summaryrefslogtreecommitdiff
path: root/docs/chapter31/graphics.md
blob: 2394a40158ebf6c41373f65943b023f578da3c73 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
# Optional graphics

Simple owns the pixel array and drawing code. [MiniFB](https://github.com/emoon/minifb)
provides a window, input, and pixel presentation. The first interface is
`sys.gfx`: one fixed-size window, operated on the main thread. The
[Graphics example](examples/Graphics.smp) draws a color gradient in Simple.
The [drawing library and graphical tic-tac-toe](drawing.md) build on this pixel
interface. `make run-graphical-tictactoe CTAGS=` builds the optional backend and
opens the game; `make graphical-tictactoe CTAGS=` only builds its executable.
The game run target also builds optional [background audio](audio.md).

## Default: no graphics dependency

From `chapter31`, the usual `make release`, `make tests`, and `make tictactoe`
need no MiniFB, graphics headers, OpenGL, CMake, or running display. Nothing
downloads dependencies unless you explicitly request `make libs` or `make init`
(`make lib` remains a setup alias). Build and run targets never use the network.

`make tests_nographics CTAGS=` runs the entire ordinary suite with
`SIMPLE_MINIFB=off`. This includes the missing-backend tests, which never open
windows. It excludes the interactive `run-graphics` target.

The runtime contains a small loader using the OS dynamic-library facilities.
It does nothing until `sys.gfx.open`. Without a configured backend, `open`
prints a diagnostic to stderr and returns `sys.gfx.ERROR` (-1). Programs can
return a nonzero status or fall back to text; the library does not terminate
the process. Non-graphics programs ignore even a broken graphics configuration.

## Build the optional backend

From `chapter31`:

```sh
make libs CTAGS=       # Once while online; fills the persistent lib/ cache.
make graphics graphics-example CTAGS=
make run-graphics CTAGS=
```

`libs` downloads the revision pinned in [graphics.mk](../graphics.mk) into
ignored `lib/minifb-<revision>.tar.gz` and extracts it under `lib/`.
`graphics` builds only its C framebuffer backend from these local sources. Windows
uses the MinGW-w64 GCC compiler (`x86_64-w64-mingw32-gcc`) and GDI; the rest of
Simple still uses the existing Cygwin GCC. Linux uses GCC and X11 (`libx11-dev`
on Ubuntu), including XWayland on a Wayland desktop. OpenGL, the C++ callback
wrappers, and upstream example programs are omitted. Native Wayland and macOS
builds are not provided here yet.

Outputs:

| Platform | Backend | Example |
| --- | --- | --- |
| Windows | `build/release/x86_64_v2_win64/simple_minifb.dll` | `build/examples/x86_64_v2_win64/Graphics.exe` |
| Linux | `build/release/x86_64_v2_SystemV/libsimple_minifb.so` | `build/examples/x86_64_v2_SystemV/Graphics` |

`MiniFB-LICENSE` is copied alongside the backend; include it when distributing
the library. MiniFB sources remain outside the tracked Simple sources.
The cache survives `make clean`. Editing a makefile or rebuilding a backend
does not fetch or check GitHub. Missing dependencies fail promptly with
instructions to run `make libs` while online.

`graphics-example` alone builds the executable without requiring MiniFB. It
also demonstrates the diagnostic and exit status 1 when graphics is absent.
`run-graphics` builds both, sets the backend path, and opens a window. Close it
or release Escape to exit. Passing any argument to the executable makes it
close after five polling iterations, for a quick smoke test.

To run directly from PowerShell:

```powershell
$env:SIMPLE_MINIFB = (Resolve-Path build/release/x86_64_v2_win64/simple_minifb.dll).Path
.\build\examples\x86_64_v2_win64\Graphics.exe
```

From Cygwin bash:

```sh
export SIMPLE_MINIFB="$PWD/build/release/x86_64_v2_win64/simple_minifb.dll"
./build/examples/x86_64_v2_win64/Graphics.exe
```

For WSL, from the repository root:

```sh
wsl -d Ubuntu-24.04 -- bash -lc 'cd chapter31 && make graphics graphics-example CLZDIR=build/classes-linux CTAGS='
```

Inside WSL, set `SIMPLE_MINIFB` to the full path of the Linux `.so`, then run
the Linux example with a working X11 display. For an automated virtual display:

```sh
SIMPLE_MINIFB="$PWD/build/release/x86_64_v2_SystemV/libsimple_minifb.so" \
    xvfb-run -a build/examples/x86_64_v2_SystemV/Graphics smoke
```

The backend path is explicit: a DLL installed elsewhere or a different working
directory cannot silently select the wrong version. `SIMPLE_MINIFB=off` disables
graphics; an absent, unloadable, or incompatible backend produces a diagnostic.
A backend that loads but cannot create a window also reports an error cleanly.

## Initial interface

| Operation | Meaning |
| --- | --- |
| `open(title,width,height)` | Open one window; returns `OK` or `ERROR`. |
| `present(pixels)` | Present a `u32[~]` of exactly `width*height` pixels, packed `0x00RRGGBB`. |
| `poll(wait)` | Process input; `true` waits about 17ms first to avoid a busy loop. |
| `mouseX()`, `mouseY()` | Current mouse position, origin at upper left. |
| `button(LEFT)`, `key(code)` | Current pressed state; printable keys use uppercase ASCII. |
| `close()` | Release native window and pixel storage; safe to repeat. |

`present` and `poll` return `OK` (0), `CLOSED` (1, normal close/Escape), or
`ERROR` (-1). Stop polling after either terminal result and call `close`.
The initial input API samples held state; it is not a queue of every transition.

MiniFB retains its last framebuffer for repaint events. The adapter copies the
Simple array into native-owned storage before presenting; it never retains a
Simple heap pointer. Framebuffer allocation, the copy, and window/input calls
are the only native work here. Drawing primitives and the games can be built
in Simple on top of this boundary.