qt/wayland: split DmabufRegistry header out of SubsurfacePresenter
`SubsurfacePresenter.h` used to expose two unrelated APIs: the per-widget presenter class AND the process-wide registry free functions (`primeDmabufModifierRegistry`, `supportedDmabufModifiers`). Moves the latter pair into `qt/src/wayland/DmabufRegistry.h` so each header owns one concern. Implementations stay in `SubsurfacePresenter.cpp` — they share the `globalState()` machinery for Wayland-globals discovery, and tearing that apart would be deeper surgery without a payoff. The split is header-only on the public API side, which is what the review called for: presenter is per-widget, registry is process-wide and read-only, the headers should reflect that. Also: the dmabuf registry priming moves out of `vulkan::Host::instance` and into `GhosttySurface`'s ctor (still on the GUI thread, still called once before the renderer thread is spawned). `Host` is a Vulkan-side singleton and shouldn't be responsible for a Wayland priming concern that's only loosely related. Step 5c of 6. Co-Authored-By: claude-flow <ruv@ruv.net>pull/12846/head
parent
002dddc9df
commit
85ebee27ce
|
|
@ -12,6 +12,7 @@
|
|||
#include "vulkan/Host.h"
|
||||
#endif
|
||||
#include "opengl/EglDmabufTarget.h"
|
||||
#include "wayland/DmabufRegistry.h"
|
||||
#include "wayland/SubsurfacePresenter.h"
|
||||
|
||||
// Qt private Wayland headers — give us QtWaylandClient::QWaylandWindow,
|
||||
|
|
@ -138,6 +139,14 @@ GhosttySurface::GhosttySurface(ghostty_app_t app, MainWindow *owner,
|
|||
"of libghostty has no OpenGL fallback — exiting.\n");
|
||||
std::abort();
|
||||
}
|
||||
// Prime the compositor dmabuf modifier registry on THIS thread
|
||||
// (the GUI thread — surface ctors run there). The renderer
|
||||
// thread will read it lock-free via the
|
||||
// `get_supported_modifiers` platform callback. Idempotent if
|
||||
// another surface already primed it. Same lifetime guarantee
|
||||
// we used to achieve inside `Host::instance`'s `call_once`,
|
||||
// but kept on the wayland side of the layering boundary.
|
||||
::wayland::primeDmabufModifierRegistry();
|
||||
m_useVulkan = true;
|
||||
sc.platform_tag = GHOSTTY_PLATFORM_VULKAN;
|
||||
sc.platform.vulkan = vk_host->asPlatform(this);
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@
|
|||
#include <optional>
|
||||
#include <vector>
|
||||
|
||||
#include "../wayland/SubsurfacePresenter.h"
|
||||
#include "../wayland/DmabufRegistry.h"
|
||||
|
||||
namespace vulkan {
|
||||
|
||||
|
|
@ -249,15 +249,13 @@ Host *Host::instance() {
|
|||
}
|
||||
// candidate's destructor runs on init failure and cleans up
|
||||
// any partial state.
|
||||
|
||||
// Eagerly prime the dmabuf modifier registry while we're
|
||||
// guaranteed to be on the GUI thread (Host::instance is called
|
||||
// from GhosttySurface's ctor before the renderer thread spawns).
|
||||
// From here on, `wayland::supportedDmabufModifiers` is a
|
||||
// lock-free read of an immutable table, safe to call from the
|
||||
// renderer thread via `cbGetSupportedModifiers`.
|
||||
::wayland::primeDmabufModifierRegistry();
|
||||
});
|
||||
// The dmabuf modifier registry priming used to happen here too,
|
||||
// inside this `call_once`. It moved out to `GhosttySurface`'s
|
||||
// ctor: registry priming is a Wayland-protocol concern, not a
|
||||
// Vulkan one, and `Host::instance()` is logically about Vulkan
|
||||
// setup. Co-locating both in one trampoline coupled `Host` to a
|
||||
// wayland-side concern that doesn't need it.
|
||||
return host.get();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -14,10 +14,14 @@
|
|||
// dmabuf-as-importable-image export path libghostty's Vulkan
|
||||
// renderer uses to hand frames back to the host.
|
||||
//
|
||||
// On first use Host::instance() also primes the process-wide
|
||||
// Wayland dmabuf modifier registry (see SubsurfacePresenter) on
|
||||
// the calling thread, so the renderer-thread `get_supported_modifiers`
|
||||
// callback can read it without further synchronization.
|
||||
// The compositor dmabuf modifier registry that this host's
|
||||
// `get_supported_modifiers` callback reads is primed elsewhere
|
||||
// (in `GhosttySurface`'s ctor on the GUI thread, via
|
||||
// `wayland::primeDmabufModifierRegistry` from
|
||||
// `qt/src/wayland/DmabufRegistry.h`). That priming is a Wayland
|
||||
// concern and used to leak into `Host::instance`'s `call_once` —
|
||||
// which made `Host` (a Vulkan object) responsible for a
|
||||
// Wayland-protocol concern it doesn't otherwise touch.
|
||||
|
||||
#pragma once
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,55 @@
|
|||
// Compositor dmabuf modifier registry.
|
||||
//
|
||||
// Process-wide read-only table of `(drm_format, [modifier])` pairs the
|
||||
// compositor advertises via `zwp_linux_dmabuf_v1`. libghostty's Vulkan
|
||||
// renderer queries this through the
|
||||
// `ghostty_platform_vulkan_s.get_supported_modifiers` callback when
|
||||
// picking a modifier the compositor will accept on attach — without
|
||||
// that intersection, drivers that don't expose `COLOR_ATTACHMENT_BIT`
|
||||
// for `LINEAR` (NVIDIA) can't get into Target's direct-export mode at
|
||||
// all and have to fall back to the legacy CPU-readback path.
|
||||
//
|
||||
// Why a header of its own instead of living on
|
||||
// `wayland::SubsurfacePresenter`? The presenter is per-widget; the
|
||||
// registry is process-wide and read-only after a one-shot prime. They
|
||||
// share `globalState()` machinery internally
|
||||
// (`SubsurfacePresenter.cpp`) but their public surfaces are unrelated
|
||||
// concerns.
|
||||
//
|
||||
// Wayland-only by project decision (the Qt frontend is Wayland-only;
|
||||
// see `feedback-qt-no-x11` memory). On non-Wayland QPA both functions
|
||||
// are no-ops — `primeDmabufModifierRegistry` returns immediately and
|
||||
// `supportedDmabufModifiers` returns 0 — so callers can stay
|
||||
// runtime-agnostic.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
|
||||
namespace wayland {
|
||||
|
||||
// Eagerly discover the compositor's dmabuf modifier list on the
|
||||
// CALLING THREAD. MUST be called from the GUI thread before any
|
||||
// `supportedDmabufModifiers` reader runs (typically the libghostty
|
||||
// renderer thread). Safe to call multiple times — discovery happens
|
||||
// exactly once via the underlying `globalState`'s latched `searched`
|
||||
// flag.
|
||||
//
|
||||
// Idempotent no-op if the QPA isn't Wayland or the
|
||||
// QPlatformNativeInterface lookup fails.
|
||||
void primeDmabufModifierRegistry();
|
||||
|
||||
// Read the cached compositor-supported DRM modifiers for the given
|
||||
// DRM_FORMAT_* fourcc. Returns the number of modifiers actually
|
||||
// written to `out` (capped at `capacity`). Pass `out=nullptr,
|
||||
// capacity=0` to query the total count.
|
||||
//
|
||||
// Thread-safe for readers once `primeDmabufModifierRegistry` has
|
||||
// returned. Returns 0 if the registry hasn't been primed yet or the
|
||||
// format isn't advertised.
|
||||
std::size_t supportedDmabufModifiers(std::uint32_t drm_format,
|
||||
std::uint64_t *out,
|
||||
std::size_t capacity);
|
||||
|
||||
} // namespace wayland
|
||||
|
|
@ -1,4 +1,5 @@
|
|||
#include "SubsurfacePresenter.h"
|
||||
#include "DmabufRegistry.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstdio>
|
||||
|
|
|
|||
|
|
@ -6,14 +6,11 @@
|
|||
// subsurface. The compositor scans the buffers out directly — no
|
||||
// mmap, no memcpy, no QImage, no QPainter blit on the present path.
|
||||
//
|
||||
// Also exposes the process-wide compositor modifier registry
|
||||
// (`primeDmabufModifierRegistry` / `supportedDmabufModifiers`)
|
||||
// learned from zwp_linux_dmabuf_v1's format/modifier events.
|
||||
// libghostty's Vulkan renderer queries this via the
|
||||
// `get_supported_modifiers` platform callback to pick a modifier
|
||||
// the compositor will actually accept — without that intersection,
|
||||
// drivers that don't expose COLOR_ATTACHMENT for LINEAR (NVIDIA)
|
||||
// can't get into Target's direct-export mode at all.
|
||||
// The process-wide compositor modifier registry that used to share
|
||||
// this header now lives in `DmabufRegistry.h`. The implementations
|
||||
// share `globalState()` machinery in `SubsurfacePresenter.cpp` but
|
||||
// the API surfaces are disjoint: presenter is per-widget, registry
|
||||
// is process-wide and read-only.
|
||||
//
|
||||
// Wayland-only by project decision (the Qt frontend is Wayland-only;
|
||||
// see `feedback-qt-no-x11` memory). If the host isn't on a Wayland
|
||||
|
|
@ -37,28 +34,6 @@ class QWindow;
|
|||
|
||||
namespace wayland {
|
||||
|
||||
// Eagerly discover the compositor's globals (incl. the
|
||||
// zwp_linux_dmabuf_v1 format/modifier list) on the calling thread.
|
||||
// MUST be called from the GUI thread before any
|
||||
// `supportedDmabufModifiers` reader runs (the renderer thread). Safe
|
||||
// to call multiple times — discovery happens exactly once.
|
||||
//
|
||||
// Idempotent no-op if the QPA isn't Wayland or the
|
||||
// QPlatformNativeInterface lookup fails.
|
||||
void primeDmabufModifierRegistry();
|
||||
|
||||
// Read the cached compositor-supported DRM modifiers for the given
|
||||
// DRM_FORMAT_* fourcc. Returns the number of modifiers actually
|
||||
// written to `out` (capped at `capacity`). Pass `out=nullptr,
|
||||
// capacity=0` to query the total count.
|
||||
//
|
||||
// Thread-safe for readers once `primeDmabufModifierRegistry` has
|
||||
// returned. Returns 0 if the registry hasn't been primed yet or the
|
||||
// format isn't advertised.
|
||||
std::size_t supportedDmabufModifiers(std::uint32_t drm_format,
|
||||
std::uint64_t *out,
|
||||
std::size_t capacity);
|
||||
|
||||
class SubsurfacePresenter {
|
||||
public:
|
||||
// Build a subsurface parented to `topLevel`'s native `wl_surface`,
|
||||
|
|
|
|||
Loading…
Reference in New Issue