This project was inspired by and uses code from jenissimo/pico8-led.
Display any graphical application on an RGB LED matrix using Raspberry Pi GPIO. This program captures the output from a virtual X server (Xvfb) and renders it in real-time on an LED matrix display.
The application:
- Creates a virtual X server display (192x128 pixels in the current run script configuration)
- Continuously captures screenshots from the X display
- Renders each frame to the RGB LED matrix via GPIO
- Supports real-time display at up to 100 FPS
- Raspberry Pi with GPIO pins (Pi 1, 2, 3, 4, or Zero - NOT Pi 5)
- RGB LED Matrix panels (connected via GPIO)
- rpi-rgb-led-matrix library (included as submodule)
Clone the repository with submodules:
git clone --recurse-submodules https://github.com/raulzanardo/xserver-screen.git
cd xserver-screenInstall dependencies:
sudo apt-get install xvfb libx11-devBuild the project:
makeInstall it:
sudo make installThis installs xserver-screen and run to /usr/local/bin.
Use the included run script to start the virtual display and run your application:
run your_applicationFor example:
run xclock -geometry 192x128
run firefox
run /usr/games/your-gameThe xserver-screen binary supports several command-line options:
sudo xserver-screen [options] [led-matrix-options]
Options:
-u, --update-interval <microseconds> Update interval in microseconds (default: 10000)
-x, --x-offset <pixels> Screenshot X offset (default: 0)
-y, --y-offset <pixels> Screenshot Y offset (default: 0)
-h, --help Show help messageScreenshot dimensions are automatically calculated from the LED matrix configuration.
Example:
sudo xserver-screen -u 20000 -x 0 -y 0 --led-rows=64 --led-cols=64Edit the run script to adjust your LED matrix configuration:
--led-rows: Number of rows in each panel (default: 64)--led-cols: Number of columns in each panel (default: 64)--led-chain: Number of panels chained horizontally (default: 3)--led-parallel: Number of parallel chains (default: 2)--led-brightness: Display brightness 0-100 (default: 60)--led-panel-type: Panel driver chip type (default: FM6126A)
For more options, see the rpi-rgb-led-matrix documentation.
The virtual X server resolution is set to 192x128 pixels to match the LED matrix configuration (3 panels × 64 columns = 192 width, 2 panels × 64 rows = 128 height). Adjust the Xvfb resolution in the run script to match your matrix setup.
You can also adjust the screenshot region using the command-line options to capture a specific portion of the virtual display.
- Retro gaming displays
- Information dashboards
- Digital signage
- Visual effects and animations
- Media players
- Any X11 application
It had to be done. Running chocolate-doom with modified chocolate-doom.cfg file.
run chocolate-doomWith the jonof's jfduke3d port I was able to configure a bunch of the screen settings to match my led matrix.
The first quake its a good FPS. This port was made by Henrique194 it is called chocolate-quake it is based on chocolate-doom and was the only one I was able to fix the resolution and make it run ok.
It is also a cool app to run in the matrix, but I couldn't fix the HUD location and it is really hard to play with the joystick, at least for me it is
This is the port of SM64 that was made for raspberry pi, it was installed via PiKISS
The port of 2s2h that the shall not be named from the company that shall not be named, also from PiKISS. This one I was not able to hard code the window size and position in the config so I had to use two commands in different ssh sessions:
# will run the game in it's location folder
run ./2s2h.elf
# will move the window to the top left and redize to the matrix size
xdotool search --class "2s2h.elf" windowsize 192 128 windowmove 0 0Another cool one from PiKISS, this one also need to use xdotool to config it's size and position
# will run the game in it's location folder
run ./xash3d
# will move the window to the top left and redize to the matrix size
xdotool search --class "xash3d" windowsize 192 128 windowmove 0 0This one is from Portmaster, it is really pretty and really hard.
# will run the game in it's location folder
run ./Celeste
# will move the window to the top left and redize to the matrix size
xdotool search --class "mono-sgen" windowsize 192 128 windowmove 0 0Stream the usb webcam with the address /dev/video0 or anything that ffplay can play.
run ffplay -vf "scale=192:128,hflip" /dev/video0Primordis is a cool particle-based life simulation. The application was modified so the screen resolution is smaller, the particle has only one pixel and a few more tweaks so it looks good in a smaller screen.
run python Primordis.pyRun the simple xclock app that comes with X11.
run xclock -geometry 192x128I was able to run a bunch of consoles using Mednafen, it has a really flexible config file.
All this examples can be seen in this youtube video.
# necessary to define the current display in the ssh session
export DISPLAY=:3.0
# this one will list active windows
xwininfo -root -tree
# and this will resize and reposition the window to your specific led matrix
xdotool search --class "2s2h.elf" windowsize 192 128 windowmove 0 0This project is based on jenissimo/pico8-led with the following enhancements:
- Generalized for any application: Works with any X11 application, not just PICO-8
- Automatic dimension detection: Screenshot size automatically matches LED matrix configuration
- Flexible capture region: Added
-xand-yoptions to capture from any screen position (default: 0,0 instead of 128,128) - Simplified run script: Single
runscript accepts any application as argument - System installation: Added
make installtarget for system-wide installation
Also see my personal LED matrix notes and hardware configuration at https://github.com/raulzanardo/my-led-matrix — with configuration snippets, photos, and other notes specific to the physical matrix used with this project.













