A Picasso96 RTG graphics driver for AmigaOS 4.1 Final Edition on the QEMU VirtIO GPU.
Status: Beta (v53.209) — Workbench-ready on QEMU Pegasos2 and AmigaOne; Sam460 planned.
⚠️ Beta — actively under development. Expect bugs and rough edges; do not rely on it for anything important. Use at your own risk.
virtiogpu.chip drives the VirtIO GPU (PCI 1AF4:1050) provided by
QEMU, giving AmigaOS 4.1 FE full RTG support: 8/16/32-bit screen
modes, EDID-based native resolution detection, dynamic mode switching,
screen dragging, and Virgl 2D/3D GPU acceleration.
Recent releases added an experimental Warp3D V5 hardware backend
(3D rendering through the stock Warp3D.library via Virgl), a
dedicated GPU I/O server task so the desktop, pointer and 3D clients no
longer block each other, and a set of opt-in Virgl performance paths —
see docs/VERSIONS.md for the full history.
| Phase | Description | Status |
|---|---|---|
| Phase 1 | Basic 32bpp framebuffer at boot | Complete |
| Phase 2 | Flush command + hardware cursor | Complete |
| Phase 3 | RTG chip driver — Workbench on GPU | Complete |
| Phase 4 | EDID, screen modes, 16bpp, DPMS, mode switching | Complete |
| Phase 5 | Virgl 2D acceleration (CLEAR/BLIT) | Working |
| Phase 5b | Virgl 3D rendering (DRAW_VBO) | Working |
| Phase 5c | Double-buffering (tear-free) | Working |
| Phase 5d | Compositing (CompositeTags) | Working |
| Phase 6 | Virgl 3D draw path for Warp3D | Working |
| Phase 7 | Performance (write-through, Virgl scanout, blob) | Opt-in |
| Phase 8 | GPU I/O server + Warp3D V5 hardware backend | In progress |
- 8/16/32-bit colour — CLUT8, R5G6B5, and B8G8R8X8 pixel formats.
- Screen modes — standard SVGA/HD modes plus the EDID native resolution; the framebuffer resource is recreated to match the active mode on each screen-mode change.
- Screen dragging — full support for AmigaOS dragged-screen composition.
- Pointer — OS-drawn soft sprite, so the rendered cursor always matches the click position under QEMU's relative mouse input. The VirtIO hardware-cursor plane is implemented but disabled by default (host-rendered cursors drift from the guest pointer position).
- EDID support —
GET_EDIDfor native resolution detection. - DPMS — display power management.
- Virgl 2D acceleration — FillRect via
CLEAR, BlitRect viaBLIT(GPU-side), when QEMU exposes Virgl (virtio-gpu-gl-pci). - Hardware compositing —
CompositeTagshook with Porter-Duff blend states. - Warp3D V5 (experimental) —
W3D_VirtIOGPU.libraryhardware backend plusW3D_VirtIO.libraryGFX driver, loaded by the stockWarp3D.libraryfront-end; renders through Virgl on the host GPU. See Warp3D (experimental).
- AmigaOS 4.1 Final Edition.
- QEMU with
-M pegasos2or-M amigaoneand a VirtIO GPU display device (see below).
-M pegasos2 -device virtio-gpu-pci
or, for Virgl GPU acceleration:
-M pegasos2 -device virtio-gpu-gl-pci -display sdl,gl=on
The Pegasos2 MV64361 bridge transparently maps PCI BAR addresses into
the CPU address space, allowing direct MMIO access via
lwbrx/stwbrx.
QEMU AmigaOne works the same way:
-M amigaone -device virtio-gpu-pci
AmigaOS's AmigaOne PCI enumeration leaves the high dword of 64-bit BARs unprogrammed (the "AmigaOne PCI probe bug"); the driver repairs the BAR before its scan, after which direct MMIO works. This applies to the QEMU machine only — real Articia S silicon does not forward PCI MMIO, so real-hardware support would need the scaffolded PCI_CFG fallback (untested).
Sam460 is a planned future target. On an unsupported machine the driver fails cleanly at init with a diagnostic message rather than crashing.
Copy build/virtiogpu.chip into SYS:Kickstart/ on your AmigaOS
volume, then add it to SYS:Kickstart/Kicklayout after
PCIGraphics.card:
MODULE Kickstart/PCIGraphics.card
MODULE Kickstart/virtiogpu.chip
(Module order in Kicklayout does not affect driver init order — the chip's board resident runs by priority — but listing the card first is the canonical layout.)
No configuration is required for the 2D driver. The driver queries QEMU for the active
display via GET_DISPLAY_INFO and EDID, and registers screen modes
automatically.
Note that bboot-based setups load Kickstart from kickstart.zip, not
from SYS:Kickstart/Kicklayout — on those, add the chip and the
Kicklayout line to the zip instead.
Virgl acceleration paths are opt-in and read once at startup. Create
the variable in ENVARC: (any value) and reboot; they require
virtio-gpu-gl-pci with gl=on:
| Variable | Effect |
|---|---|
virtiogpu_virgl2d |
Bring up the Virgl 3D scanout, the CompositeTags hook and the 3D transport used by Warp3D |
virtiogpu_gpuaccel |
Draw large FillRect operations on the GPU (with virtiogpu_virgl2d) |
virtiogpu_zerocopy, virtiogpu_dirtyrect |
Experimental presentation paths; not recommended |
virtiogpu_tritest |
Diagnostic: draw a test triangle over the display each frame |
3D support uses the stock AmigaOS Warp3D.library 53.27 front-end with two drivers built from this repository:
W3D_VirtIOGPU.library→LIBS:Warp3D/HWdrivers/W3D_VirtIO.library→LIBS:Warp3D/GFXdrivers/
The stock W3D_Picasso96.library GFX driver does not recognise the
VirtIO board and must be moved out of LIBS:Warp3D/GFXdrivers/.
ENVARC:virtiogpu_virgl2d must be set and QEMU must run with
virtio-gpu-gl-pci and gl=on. The CoW3D demo renders correctly
(geometry, textures, depth, blending); texture-environment combine
modes, backface culling and several state operations are not yet
implemented.
make dist stages an AmigaOS Installation Utility drawer under
build/dist/VirtIOGPU/ (chip + installer script + readme);
make dist-lha packs it into build/VirtIOGPU.lha.
The bundled install.py targets the Python-based Installation Utility
shipped with every AmigaOS 4.1 Final Edition: it copies the chip to
SYS:Kickstart/, inserts the MODULE line into Kicklayout (backing
up Kicklayout.bak first, idempotently), and offers a reboot.
Launch it from inside the extracted drawer — the script uses
drawer-relative content/ paths, like the OS's own update installers.
The archive ships without icons (see installer/README.md),
so run it from a shell with the drawer as the current directory:
"SYS:Utilities/Installation Utility" PACKAGE=install.py
One QEMU quirk: the "Reboot now" option on the finish page may power the virtual machine off instead of restarting it — simply start QEMU again.
installer/install.py is pre-generated from
installer/virtiogpu_installer_fixture.py and committed, so building
the archive needs no extra tooling.
Requires the walkero/amigagccondocker:os4-gcc11 Docker image
(provides ppc-amigaos-gcc, GCC 11).
Run clean and all as separate Docker invocations — a combined
parallel build races (clean deletes the build dir while compilation
runs):
docker run --rm -v "$(pwd):/src" -w /src \
walkero/amigagccondocker:os4-gcc11 make clean
docker run --rm -v "$(pwd):/src" -w /src \
walkero/amigagccondocker:os4-gcc11 sh -c 'make -j$(nproc) all'Outputs in build/:
virtiogpu.chip— the Picasso96 chip driver (primary artefact)W3D_VirtIOGPU.library— Warp3D V5 hardware backend (experimental)W3D_VirtIO.library— Warp3D GFX driver (experimental; not part ofall, build withmake build/W3D_VirtIO.library)warp3d.library— earlier standalone Warp3D implementation (superseded by the backend above)minigl.library— MiniGL stub (placeholder)test_composite,virtiogpu_info,w3dtri— helper / diagnostic tools
src/chip/
├── chip_lib.c — Library boilerplate, ROM tags, _start asm
├── chip_board.c — VirtIOGPUBoard resident (pri 65), SetMethod hooks
├── chip_init.c — PCI/VirtIO init, chip_InitCard_C, framebuffer resize
├── chip_gpu_cmds.c — Shared 2D GPU command wrappers + virtqueue I/O
├── chip_gpu_3d.c — GPU 3D commands (CTX, SUBMIT_3D, RESOURCE_BLOB)
├── chip_irq.c — IRQ install + ISR (signals waiters; polling fallback)
├── chip_flush.c — Framebuffer convert + signal-driven flush task
├── chip_p96.c — P96 BoardInfo vtable: display cfg, sprite, vsync
├── chip_alloc.c — P96 bitmap alloc/free + AllocCardMem
├── chip_blit.c — P96 FillRect / BlitRect / Template / Pattern / etc.
├── chip_modes.c — Screen mode table + registration
├── chip_virgl.c — Virgl capability query, feature negotiation
├── chip_virgl_2d.c — Virgl 2D acceleration (CLEAR/BLIT, 3D scanout)
├── chip_composite.c — CompositeTags hook + Porter-Duff blend states
├── chip_gpu_srv.c — GPU I/O server task (prioritised control-queue access)
├── chip_v3d.c — "v3d" transport interface for the Warp3D drivers
├── chip_vram.c — GPU render-target bookkeeping for bitmaps
└── chip_perf.c — ENV-gated performance options
src/w3d_virtio/ — W3D_VirtIOGPU.library (Warp3D V5 hardware backend)
src/w3d_virtio_gfx/ — W3D_VirtIO.library (Warp3D GFX driver)
src/warp3d/ — Warp3D-to-Virgl translation (GPL; also built as warp3d.library)
src/minigl/ — MiniGL stub
src/tools/ — diagnostic tools
src/virtio/ — virtqueue implementation
src/linux/, src/compat/ — work-in-progress port of the Linux virtio-gpu
virtqueue code (not yet built)
installer/ — Installation Utility script
legacy/ — archived hand-written VirtIO layer (reference only)
docs/reference/ — upstream Linux virtio-gpu driver sources (reference only)
include/chip/chip_state.h — ChipGPUState struct, MMIO inlines, macros
include/chip/gpu_srv.h — GPU I/O server request interface
include/v3d/v3d_iface.h — chip ⇄ Warp3D transport ABI
include/virgl/virgl_cmd.h — Virgl command buffer builder API
include/p96/boardinfo.h — Picasso96 BoardInfo / chip vtable definitions
The chip binary contains two AmigaOS residents:
- VirtIOGPUBoard (
NT_RESOURCE, pri 65) — runs before graphics.library and hooksPCIGraphics.card'sFindCard/InitBoardmethods viaSetMethod. - virtiogpu.chip (
NT_LIBRARY, pri -128) — loaded on demand for GPU init and the Picasso96 BoardInfo vtable.
Key constraints: the chip is built with -mcrt=newlib; only the
modern VirtIO transport exists for device 0x1050; MMIO uses
stwbrx/lwbrx inline assembly; two virtqueues (control + cursor).
Command flow — 2D mode:
RESOURCE_CREATE_2D → ATTACH_BACKING → SET_SCANOUT
TRANSFER_TO_HOST_2D + RESOURCE_FLUSH (signal-driven flush task)
Virgl 2D mode (GPU-accelerated):
CTX_CREATE → RESOURCE_CREATE_3D → ATTACH_BACKING → SET_SCANOUT
Virgl CLEAR (FillRect) / Virgl BLIT (BlitRect) + RESOURCE_FLUSH
TRANSFER_TO_HOST_3D + RESOURCE_FLUSH (periodic flush for GRANTDIRECTACCESS)
Control-queue commands are submitted through a dedicated GPU I/O server task: clients post per-request messages to a high-priority port (presentation, pointer) or a low-priority port (bulk 3D draws) and wait for the reply, so a long 3D submission cannot stall the desktop or the pointer.
- docs/VERSIONS.md — version history and release notes.
This project was created with help from Claude (Anthropic) — writing the C code, designing the architecture, and debugging hardware-level issues against the AmigaOS 4.1 SDK — with a human developer directing, reviewing, and testing the result.
Copyright © 2026 Richard Gibbs. Released under the MIT License.
Exceptions (each file carries an SPDX-License-Identifier line):
src/warp3d/— GPL-2.0-or-later.warp3d_main.cis also linked intoW3D_VirtIOGPU.library, so bothwarp3d.libraryandW3D_VirtIOGPU.libraryare GPL as built.virtiogpu.chipcontains no GPL code.- Linux virtio-gpu driver code from Red Hat (
src/linux/virtgpu_vq.c,docs/reference/linux-virtio-gpu/) — MIT, original notices retained;virtio_gpu.hprotocol headers — BSD-3-Clause;docs/reference/linux-virtio-gpu/virtgpu_vram.c— GPL-2.0 (reference only, not built).