Skip to content

Commit 099a58a

Browse files
committed
Start X on Raspberry Pi, lazzer style
Signed-off-by: Joachim Wiberg <[email protected]>
1 parent be301be commit 099a58a

File tree

2 files changed

+77
-41
lines changed

2 files changed

+77
-41
lines changed

Dockerfile

Lines changed: 53 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,11 @@ RUN apk add --no-cache \
1313
libxmp \
1414
mesa-dri-gallium \
1515
mesa-gbm \
16+
xorg-server \
17+
xf86-video-fbdev \
18+
xf86-input-evdev \
19+
xdpyinfo \
20+
xinit \
1621
gcc \
1722
musl-dev \
1823
make \
@@ -24,8 +29,53 @@ COPY demo.c Makefile topaz-8.otf *.png music.mod* ./
2429

2530
RUN make
2631

27-
# Default to X11, but can be overridden for framebuffer
32+
# Create minimal X config for framebuffer
33+
RUN mkdir -p /etc/X11 && cat > /etc/X11/xorg.conf << 'EOF'
34+
Section "ServerFlags"
35+
Option "DontVTSwitch" "true"
36+
Option "BlankTime" "0"
37+
Option "StandbyTime" "0"
38+
Option "SuspendTime" "0"
39+
Option "OffTime" "0"
40+
EndSection
41+
42+
Section "Device"
43+
Identifier "Card0"
44+
Driver "fbdev"
45+
Option "fbdev" "/dev/fb0"
46+
EndSection
47+
48+
Section "Screen"
49+
Identifier "Screen0"
50+
Device "Card0"
51+
EndSection
52+
EOF
53+
54+
# Create startup script
55+
RUN cat > /app/start.sh << 'EOF'
56+
#!/bin/sh
57+
# Smart startup: use existing X or start our own
58+
59+
# Check if X server is already available
60+
if xdpyinfo -display "${DISPLAY:-:0}" >/dev/null 2>&1; then
61+
echo "Using existing X server on $DISPLAY"
62+
exec ./demo "$@"
63+
else
64+
echo "No X server found, starting embedded X server..."
65+
# Start X server in background and run demo
66+
Xorg -noreset +extension GLX +extension RANDR +extension RENDER -logfile /tmp/xorg.log -config /etc/X11/xorg.conf :0 &
67+
XPID=$!
68+
sleep 2
69+
DISPLAY=:0 ./demo "$@"
70+
EXITCODE=$?
71+
kill $XPID 2>/dev/null
72+
wait $XPID 2>/dev/null
73+
exit $EXITCODE
74+
fi
75+
EOF
76+
77+
RUN chmod +x /app/start.sh
78+
2879
ENV DISPLAY=:0
29-
ENV SDL_VIDEODRIVER=x11
3080

31-
CMD ["./demo"]
81+
CMD ["/app/start.sh", "-f"]

README.md

Lines changed: 24 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -70,13 +70,17 @@ No installation required! The AppImage bundles all dependencies.
7070

7171
### Run with Docker
7272

73-
**Pull and run the latest image:**
73+
The container image automatically detects whether X11 is available and adapts accordingly.
74+
75+
#### On Desktop Systems (with X11)
76+
77+
**Basic run:**
7478

7579
```bash
7680
# Allow X11 connections (run once per session)
7781
xhost +local:docker
7882

79-
# Run the demo (video only)
83+
# Run the demo
8084
docker run --rm -it \
8185
-e DISPLAY=$DISPLAY \
8286
-v /tmp/.X11-unix:/tmp/.X11-unix \
@@ -107,65 +111,47 @@ docker run --rm -it \
107111
-e PULSE_SERVER=unix:${XDG_RUNTIME_DIR}/pulse/native \
108112
-v ${XDG_RUNTIME_DIR}/pulse/native:${XDG_RUNTIME_DIR}/pulse/native \
109113
ghcr.io/kernelkit/demo:latest \
110-
./demo -w 1920x1080
111-
```
112-
113-
**Or use docker-compose:**
114-
115-
```bash
116-
docker compose up
114+
/app/start.sh -w 1920x1080
117115
```
118116

119-
### Run without X11 (Direct Framebuffer)
117+
#### On Embedded Systems (without X11)
120118

121-
For embedded systems or headless setups without X11 (e.g., Raspberry Pi, embedded Linux):
119+
For embedded systems like Raspberry Pi or Infix OS, the container starts its own X server:
122120

123-
**Using KMS/DRM (recommended for modern systems):**
121+
**Raspberry Pi 4 / Embedded Linux (fullscreen):**
124122

125123
```bash
126-
# Requires access to DRI and input devices
127124
docker run --rm -it \
128125
--privileged \
129-
-v /dev/dri:/dev/dri \
130-
-v /dev/input:/dev/input \
131-
-e SDL_VIDEODRIVER=kmsdrm \
132-
-e SDL_AUDIODRIVER=alsa \
126+
-v /dev/fb0:/dev/fb0 \
127+
-v /dev/tty1:/dev/tty1 \
133128
ghcr.io/kernelkit/demo:latest
134129
```
135130

136-
**Using legacy framebuffer:**
131+
**With custom demo options:**
137132

138133
```bash
134+
# Example: 30 seconds per scene, show scenes 0, 2, and 6
139135
docker run --rm -it \
140136
--privileged \
141137
-v /dev/fb0:/dev/fb0 \
142-
-v /dev/input:/dev/input \
143-
-e SDL_VIDEODRIVER=fbcon \
144-
-e SDL_FBDEV=/dev/fb0 \
145-
-e SDL_AUDIODRIVER=alsa \
146-
ghcr.io/kernelkit/demo:latest
138+
-v /dev/tty1:/dev/tty1 \
139+
ghcr.io/kernelkit/demo:latest \
140+
/app/start.sh -d 30 0 2 6
147141
```
148142

149-
**On Raspberry Pi 4:**
143+
#### Using docker-compose
150144

151145
```bash
152-
# KMS/DRM mode (best performance)
153-
docker run --rm -it \
154-
--privileged \
155-
-v /dev/dri:/dev/dri \
156-
-v /dev/input:/dev/input \
157-
-e SDL_VIDEODRIVER=kmsdrm \
158-
-e SDL_AUDIODRIVER=alsa \
159-
ghcr.io/kernelkit/demo:latest \
160-
./demo -f
146+
docker compose up
161147
```
162148

163149
**Notes:**
164-
- `SDL_VIDEODRIVER=kmsdrm` uses kernel mode setting (modern, hardware accelerated)
165-
- `SDL_VIDEODRIVER=fbcon` uses legacy framebuffer (fallback)
166-
- `--privileged` gives access to GPU and input devices
167-
- `-f` flag runs in fullscreen mode (recommended for framebuffer)
168-
- For audio without PulseAudio, use `SDL_AUDIODRIVER=alsa` or omit for no audio
150+
- The container automatically detects if X11 is available via `xdpyinfo`
151+
- With X11: Uses the host's X server
152+
- Without X11: Starts embedded X server using framebuffer
153+
- `--privileged` needed for framebuffer/TTY access on embedded systems
154+
- Default runs fullscreen (`-f` flag) when using embedded X server
169155

170156
## Building from Source
171157

0 commit comments

Comments
 (0)