Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Does this Qt adopt a foreign EGL context?

The whole GPU path for in-compositor QML turned on one call. If Qt can adopt the compositor’s EGL context, it can render into a texture we sample directly. If it cannot, Qt renders on a context of its own and the only way across is a shared buffer.

Since then (2026-09-30). The answer was no: QEGLContext::fromNative returns null under both offscreen and eglfs (see the QML spike). So the GPU path was built on a shared buffer (#94), and it has been the default since #147. Whether that path works on a given machine is now answered by solium --probe-qml-gpu, which the compositor also runs in a child process at every start on the hardware under the default auto renderer (dev/README.md, QML on the GPU). This probe is for the question in its title: re-run it after a Qt update and read the fromNative: line. The exit status does not report that line; it is 0 when the GBM-paired import below worked, 2 or 3 when EGL or a context could not be set up, and 4 when the import failed. The probe opens /dev/dri/renderD128 itself rather than looking the render node up, so on a machine with two GPUs it may test the wrong one.

From dev/qtprobe:

podman run --rm --userns=keep-id --security-opt label=disable -v "$HOME:$HOME" -w "$PWD" \
    localhost/solium-build:fc44 \
    sh -c 'g++ -fPIC probe.cpp -o probe $(pkg-config --cflags --libs Qt6Gui gbm egl glesv2) -lEGL'
QT_QPA_PLATFORM=offscreen ./probe
QT_QPA_PLATFORM=eglfs ./probe

This exists because the answer has now been derived twice, and it is a property of the installed Qt rather than of anything in this repository — so it is worth re-running after a Qt update rather than reasoning about.

dmabuf round-trip

2026-09-08: yes — a GBM buffer can be imported as an EGLImage and bound to a texture, provided the importing EGLDisplay is a GBM-platform display on the same GPU as the buffer. That pairing matters: it is not the default EGLDisplay, and getting it wrong looks exactly like the feature being unsupported. Read this whole section before re-deriving it — the pairing is the part that is easy to get wrong quietly.

The probe pairs the display with the buffer’s own gbm_device, the strictest form of that rule. The first real use of the import, the same evening, measured the looser form Solium depends on: Qt’s eglfs display, opened on the card node, accepted a buffer allocated through the render node, so the pairing is per GPU, not per gbm_device object or per DRM node (the comment above import_dmabuf_texture in crates/solium/qml/host.cpp). It also means a second GPU would break it.

Solium’s own EGLDisplay (crates/solium/src/tty.rs, open_gpu) is built as EGLDisplay::new(gbm.clone()) — a GBM-platform display on a specific GbmDevice object, not eglGetDisplay(EGL_DEFAULT_DISPLAY). The probe imports the same dmabuf against both, to make the contrast impossible to miss:

dmabuf[default display]: eglCreateImageKHR failed 0x3009  (format=ARGB8888 stride=1024 modifier=0x300000000e08014)
dmabuf[gbm-paired display]: ok  texture=1 stride=1024 modifier=0x300000000e08014

Same fd, same 256×256 ARGB8888 buffer, same stride (1024), same modifier (0x300000000e08014 — vendor byte 0x03 is DRM_FORMAT_MOD_VENDOR_NVIDIA, a real tiled modifier, not DRM_FORMAT_MOD_INVALID). The default display rejects it with EGL_BAD_MATCH (0x3009); a display obtained via eglGetPlatformDisplayEXT(EGL_PLATFORM_GBM_KHR, gbm, nullptr) on the buffer’s own gbm_device* accepts it. Reproducible across three runs, both offscreen and eglfs, identical every time. EGL_EXT_image_dma_buf_import and EGL_EXT_image_dma_buf_import_modifiers are both present on both displays, and EGL_ANDROID_native_fence_sync is present — none of those were the blocker.

That run: Qt qt6-qtbase-6.11.1-1.fc44.x86_64 at run time (what the probe binary loads when run natively; it was built in the container against Qt6Gui 6.11.2 via pkg-config, the same 6.11 ABI line), on an NVIDIA GPU with NVIDIA’s proprietary driver.

Not tested by this probe: rendering into the bound texture through an FBO from a second, Qt-owned context on the same device, and fencing the hand-off to the compositor’s context — the harder half the spike named (“NVIDIA’s driver is where dmabuf round-trips and cross-context fences are least forgiving”). This result is the allocate/import/bind step only, and it works; the render-and-fence pipeline built on it is exercised end to end by dev/wirecheck (see its README). The two dmabuf[...] lines quoted above are the probe’s own output, from that run.