Display and input

A virtio GPU in 2D or with virgl 3D, drawn on a canvas with WebGPU or WebGL2, and a keyboard and tablet driven by the user or by QMP.

A display

Add a virtio GPU and the guest gets a graphical console and /dev/dri/card0:

wemu-system-aarch64 ... -device virtio-gpu-pci -device virtio-keyboard-pci -device virtio-tablet-pci
DeviceWhat the guest gets
virtio-gpu-pciA 2D display: a framebuffer console, a desktop in software, a hardware cursor. Default 1280×800; set xres and yres.
virtio-gpu-gl-pciThe same, plus 3D through virgl (see below).
ramfbA plain 1024×768 framebuffer, for firmware and kernels without a virtio GPU driver.

-vga virtio is a shorthand for -device virtio-gpu-pci.

Where the picture goes

The picture reaches your code through the host's display:

  • A canvas. Pass an OffscreenCanvas and Warm64's GPU worker draws on it directly.
  • Frames. Pass a frame(width, height, pixels) callback and receive each changed frame, at up to refreshHz times a second.
  • Screenshots. screendump saves the screen as PNG or PPM, with or without a display attached.
const canvas = document.querySelector("canvas").transferControlToOffscreen();
const vm = await WEMU.launch("... -device virtio-gpu-gl-pci -device virtio-keyboard-pci", {
  ...browserWEMUHost(),
  display: { canvas },
});

In Node there's no window: use frame or screendump.

await vm.qmp("screendump", { filename: "screen.png", format: "png" });

When the page resizes, tell the guest, as a resized QEMU window does:

vm.setUIInfo({ width: 1440, height: 900 });

3D graphics

virtio-gpu-gl-pci gives the guest virgl: its stock Mesa virgl driver sends OpenGL work to Warm64, which renders it on the host's GPU.

HostRenders with
A browser with WebGPUWebGPU
A browser with WebGL2WebGL2
Neither, or -display ...,gl=offSoftware
NodeSoftware

The guest gets OpenGL 2.1 and OpenGL ES 2.0 with GLSL 1.30, enough for desktops, kmscube and glmark2. Compute, geometry and tessellation shaders, multisampling and transform feedback aren't there.

Tip Run glmark2 with --visual-config alpha=0.

Keyboard and pointer

Any one of virtio-keyboard-*, virtio-tablet-* or virtio-mouse-* adds both a keyboard and a tablet, which Linux names warm64 keyboard and warm64 tablet. The pointer is always an absolute tablet, so it follows the user's pointer exactly.

On USB instead, add a controller and the devices:

wemu-system-aarch64 ... -device wemu-xhci -device usb-kbd -device usb-tablet

Sending input from code

// type Enter
await vm.qmp("send-key", { keys: [{ type: "qcode", data: "ret" }] });
// click in the middle of the screen
await vm.qmp("input-send-event", { events: [
  { type: "abs", data: { axis: "x", value: 16384 } },
  { type: "abs", data: { axis: "y", value: 16384 } },
  { type: "btn", data: { down: true, button: "left" } },
  { type: "btn", data: { down: false, button: "left" } },
] });

Pointer positions run from 0 to 32767 across the screen. See send-key and input-send-event.

USB

The xHCI controller (-device wemu-xhci, or -usb) takes a keyboard (usb-kbd), a tablet (usb-tablet; usb-mouse becomes one) and a disk (usb-storage,drive=ID). A USB disk is read into memory and its writes aren't saved.

See also