qt/vulkan: replace cross-TU forward decl with PresentSink interface
`vulkan::Host` no longer reaches into `GhosttySurface.cpp` via a
namespace-scoped `extern void presentToGhosttySurface(...)`. The
trampoline path now goes through a virtual `vulkan::PresentSink`
interface declared next to `Host`:
class PresentSink {
public:
virtual void presentDmabuf(int fd, ..., bool image_backed) = 0;
};
`GhosttySurface` inherits and provides a thin override that forwards
to its existing `presentVulkanDmabuf` (kept under that name so the
extensive doc comments + cross-references in the rest of the file
don't churn). `Host::asPlatform` now takes a `PresentSink *` instead
of a `void *` — typed at the boundary; `cbPresent` does
`static_cast<PresentSink *>(ud)->presentDmabuf(...)`.
Drops the `Q_INVOKABLE` marker on `presentVulkanDmabuf` (only
`drainVulkan` is invoked by name via QMetaObject; the present method
isn't, so the marker was dead).
Step 5b of 6.
Co-Authored-By: claude-flow <ruv@ruv.net>
pull/12846/head
parent
8f47e4d117
commit
002dddc9df
|
|
@ -1836,25 +1836,10 @@ bool GhosttySurface::forceParentCommit() {
|
|||
return true;
|
||||
}
|
||||
|
||||
// Trampoline so `Host.cpp` doesn't need to include the full
|
||||
// `GhosttySurface.h`. The forward declaration lives in
|
||||
// `vulkan/Host.cpp` (namespace scope, not anonymous, so the linker
|
||||
// resolves this definition).
|
||||
namespace vulkan {
|
||||
|
||||
void presentToGhosttySurface(
|
||||
void *surface,
|
||||
int dmabuf_fd,
|
||||
uint32_t drm_format,
|
||||
uint64_t drm_modifier,
|
||||
uint32_t width,
|
||||
uint32_t height,
|
||||
uint32_t stride,
|
||||
bool image_backed) {
|
||||
if (surface == nullptr) return;
|
||||
static_cast<GhosttySurface *>(surface)->presentVulkanDmabuf(
|
||||
dmabuf_fd, drm_format, drm_modifier, width, height, stride,
|
||||
image_backed);
|
||||
}
|
||||
|
||||
} // namespace vulkan
|
||||
// (Frame delivery to GhosttySurface is now via the
|
||||
// `vulkan::PresentSink` interface declared in `vulkan/Host.h`.
|
||||
// `vulkan::Host`'s present-callback trampoline calls
|
||||
// `static_cast<vulkan::PresentSink*>(userdata)->presentDmabuf(...)`,
|
||||
// which `GhosttySurface::presentDmabuf` (inline forwarder in the
|
||||
// header) routes to `presentVulkanDmabuf` above. No cross-TU
|
||||
// `extern void presentToGhosttySurface` symbol any more.)
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@
|
|||
#include <QWidget>
|
||||
|
||||
#include "ghostty.h"
|
||||
#include "vulkan/Host.h"
|
||||
|
||||
namespace wayland {
|
||||
class SubsurfacePresenter;
|
||||
|
|
@ -62,7 +63,7 @@ class OverlayScrollbar;
|
|||
// renderer reports image_backed=false (NVIDIA Vulkan's
|
||||
// legacy_copy path on this branch), the frame goes through a
|
||||
// mmap+memcpy+QImage+QPainter::drawImage path instead.
|
||||
class GhosttySurface : public QWidget {
|
||||
class GhosttySurface : public QWidget, public vulkan::PresentSink {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
|
@ -175,7 +176,7 @@ public:
|
|||
// (zero-copy) or paints the QImage (fallback). The dropped-frame
|
||||
// counter `m_droppedFrames` makes any genuine queue-loss visible
|
||||
// (zero in the steady state).
|
||||
Q_INVOKABLE void presentVulkanDmabuf(
|
||||
void presentVulkanDmabuf(
|
||||
int dmabuf_fd,
|
||||
quint32 drm_format,
|
||||
quint64 drm_modifier,
|
||||
|
|
@ -184,6 +185,18 @@ public:
|
|||
quint32 stride,
|
||||
bool image_backed);
|
||||
|
||||
// `vulkan::PresentSink` override. Thin forward to
|
||||
// `presentVulkanDmabuf` so the existing implementation (and its
|
||||
// doc comment above) stays where it is. Called by `vulkan::Host`'s
|
||||
// present-callback trampoline on the libghostty renderer thread.
|
||||
void presentDmabuf(int dmabuf_fd, std::uint32_t drm_format,
|
||||
std::uint64_t drm_modifier, std::uint32_t width,
|
||||
std::uint32_t height, std::uint32_t stride,
|
||||
bool image_backed) override {
|
||||
presentVulkanDmabuf(dmabuf_fd, drm_format, drm_modifier, width,
|
||||
height, stride, image_backed);
|
||||
}
|
||||
|
||||
// GUI-thread drain step: hands the most recent pending frame
|
||||
// either to the SubsurfacePresenter (zero-copy path) or the
|
||||
// QImage paint pipeline (fallback). Idempotent: returns
|
||||
|
|
|
|||
|
|
@ -13,20 +13,6 @@
|
|||
|
||||
namespace vulkan {
|
||||
|
||||
// Forward declaration of the entry point in `GhosttySurface.cpp` that
|
||||
// receives a presented frame. Declared here at namespace scope (not
|
||||
// in the anonymous namespace below) so its external definition in
|
||||
// the other TU resolves at link time.
|
||||
void presentToGhosttySurface(
|
||||
void *surface,
|
||||
int dmabuf_fd,
|
||||
uint32_t drm_format,
|
||||
uint64_t drm_modifier,
|
||||
uint32_t width,
|
||||
uint32_t height,
|
||||
uint32_t stride,
|
||||
bool image_backed);
|
||||
|
||||
namespace {
|
||||
|
||||
constexpr const char *kRequiredDeviceExtensions[] = {
|
||||
|
|
@ -136,8 +122,9 @@ void cbPresent(
|
|||
uint32_t stride,
|
||||
bool image_backed) {
|
||||
if (ud == nullptr) return;
|
||||
::vulkan::presentToGhosttySurface(ud, dmabuf_fd, drm_format, drm_modifier,
|
||||
width, height, stride, image_backed);
|
||||
static_cast<PresentSink *>(ud)->presentDmabuf(
|
||||
dmabuf_fd, drm_format, drm_modifier, width, height, stride,
|
||||
image_backed);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
|
@ -238,9 +225,9 @@ Host::~Host() {
|
|||
if (m_instance != VK_NULL_HANDLE) vkDestroyInstance(m_instance, nullptr);
|
||||
}
|
||||
|
||||
ghostty_platform_vulkan_s Host::asPlatform(void *surface_userdata) const {
|
||||
ghostty_platform_vulkan_s Host::asPlatform(PresentSink *sink) const {
|
||||
ghostty_platform_vulkan_s p{};
|
||||
p.userdata = surface_userdata;
|
||||
p.userdata = sink;
|
||||
p.get_instance_proc_addr = cbGetInstanceProcAddr;
|
||||
p.instance = cbInstance;
|
||||
p.physical_device = cbPhysicalDevice;
|
||||
|
|
|
|||
|
|
@ -30,6 +30,25 @@
|
|||
|
||||
namespace vulkan {
|
||||
|
||||
/// Receiver for a presented dmabuf-backed frame. Implemented by
|
||||
/// `GhosttySurface`; abstract so `vulkan::Host` doesn't need to
|
||||
/// know about the widget type. Replaces an earlier cross-TU
|
||||
/// forward declaration of a free function `presentToGhosttySurface`
|
||||
/// that coupled `Host.cpp` directly to `GhosttySurface.cpp`.
|
||||
class PresentSink {
|
||||
public:
|
||||
virtual ~PresentSink() = default;
|
||||
/// Hand off a rendered frame. Called on the libghostty renderer
|
||||
/// thread; the implementation is responsible for marshalling to
|
||||
/// whatever thread it composites on. The fd is borrowed for the
|
||||
/// duration of the call — implementations that need to retain
|
||||
/// it must `dup()`.
|
||||
virtual void presentDmabuf(int dmabuf_fd, std::uint32_t drm_format,
|
||||
std::uint64_t drm_modifier,
|
||||
std::uint32_t width, std::uint32_t height,
|
||||
std::uint32_t stride, bool image_backed) = 0;
|
||||
};
|
||||
|
||||
/// Process-wide Vulkan setup. One per Ghastty process; threadsafe
|
||||
/// to call `instance()` from anywhere (constructs once via
|
||||
/// std::call_once on first access).
|
||||
|
|
@ -40,13 +59,13 @@ public:
|
|||
/// repeated lookups are cheap.
|
||||
static Host *instance();
|
||||
|
||||
/// Build a `ghostty_platform_vulkan_s` callback struct populated
|
||||
/// with this host's handles. `surface_userdata` is round-tripped
|
||||
/// through as the `userdata` field — used by the `present`
|
||||
/// callback to identify which `GhosttySurface` the dmabuf is for.
|
||||
/// The other handle-lookup callbacks ignore it and route through
|
||||
/// `Host::instance()`.
|
||||
ghostty_platform_vulkan_s asPlatform(void *surface_userdata) const;
|
||||
/// Build a `ghostty_platform_vulkan_s` callback struct whose
|
||||
/// `present` callback delivers frames to `sink`. `sink` must
|
||||
/// outlive the lifetime of any libghostty surface that was
|
||||
/// configured with the returned platform struct. Other callbacks
|
||||
/// (handle lookups, modifier registry) ignore `sink` and route
|
||||
/// through the process singleton.
|
||||
ghostty_platform_vulkan_s asPlatform(PresentSink *sink) const;
|
||||
|
||||
VkInstance vkInstance() const { return m_instance; }
|
||||
VkPhysicalDevice vkPhysicalDevice() const { return m_physicalDevice; }
|
||||
|
|
|
|||
Loading…
Reference in New Issue