From c10b35facb4b12e9edbacdf436b80e3a684a33c3 Mon Sep 17 00:00:00 2001 From: Vlad Zahorodnii Date: Tue, 3 Jan 2023 12:44:12 +0200 Subject: [PATCH] backends/wayland: Pass linux-dmabuf buffers for cursor layer This lets us avoid reading fbo data back. --- src/backends/wayland/wayland_egl_backend.cpp | 26 ++++++++++++------- src/backends/wayland/wayland_egl_backend.h | 4 +-- src/backends/wayland/wayland_output.cpp | 2 +- src/backends/wayland/wayland_output.h | 4 +-- .../wayland/wayland_qpainter_backend.cpp | 2 +- 5 files changed, 22 insertions(+), 16 deletions(-) diff --git a/src/backends/wayland/wayland_egl_backend.cpp b/src/backends/wayland/wayland_egl_backend.cpp index c0e131799e..b6a778fc5b 100644 --- a/src/backends/wayland/wayland_egl_backend.cpp +++ b/src/backends/wayland/wayland_egl_backend.cpp @@ -233,8 +233,6 @@ WaylandEglCursorLayer::WaylandEglCursorLayer(WaylandOutput *output, WaylandEglBa WaylandEglCursorLayer::~WaylandEglCursorLayer() { eglMakeCurrent(m_backend->eglDisplay(), EGL_NO_SURFACE, EGL_NO_SURFACE, m_backend->context()); - m_framebuffer.reset(); - m_texture.reset(); } qreal WaylandEglCursorLayer::scale() const @@ -275,24 +273,32 @@ std::optional WaylandEglCursorLayer::beginFrame() } const QSize bufferSize = m_size.expandedTo(QSize(64, 64)); - if (!m_texture || m_texture->size() != bufferSize) { - m_texture = std::make_unique(GL_RGBA8, bufferSize); - m_framebuffer = std::make_unique(m_texture.get()); + if (!m_swapchain || m_swapchain->size() != bufferSize) { + const WaylandLinuxDmabufV1 *dmabuf = m_backend->backend()->display()->linuxDmabuf(); + const uint32_t format = DRM_FORMAT_ARGB8888; + if (!dmabuf->formats().contains(format)) { + qCCritical(KWIN_WAYLAND_BACKEND) << "DRM_FORMAT_ARGB8888 is unsupported"; + return std::nullopt; + } + const QVector modifiers = dmabuf->formats().value(format); + m_swapchain = std::make_unique(bufferSize, format, modifiers, m_backend); } + m_buffer = m_swapchain->acquire(); return OutputLayerBeginFrameInfo{ - .renderTarget = RenderTarget(m_framebuffer.get()), + .renderTarget = RenderTarget(m_buffer->framebuffer()), .repaint = infiniteRegion(), }; } bool WaylandEglCursorLayer::endFrame(const QRegion &renderedRegion, const QRegion &damagedRegion) { - // Technically, we could pass a linux-dmabuf buffer, but host kwin does not support that atm. - const QImage image = m_texture->toImage().mirrored(false, true); - KWayland::Client::Buffer::Ptr buffer = m_output->backend()->display()->shmPool()->createBuffer(image); - m_output->cursor()->update(buffer, m_scale, m_hotspot); + // Flush rendering commands to the dmabuf. + glFlush(); + m_output->cursor()->update(m_buffer->buffer(), m_scale, m_hotspot); + + m_swapchain->release(m_buffer); return true; } diff --git a/src/backends/wayland/wayland_egl_backend.h b/src/backends/wayland/wayland_egl_backend.h index ef7ddc909c..0c9d93cd20 100644 --- a/src/backends/wayland/wayland_egl_backend.h +++ b/src/backends/wayland/wayland_egl_backend.h @@ -115,8 +115,8 @@ public: private: WaylandOutput *m_output; WaylandEglBackend *m_backend; - std::unique_ptr m_framebuffer; - std::unique_ptr m_texture; + std::unique_ptr m_swapchain; + std::shared_ptr m_buffer; QPoint m_hotspot; QSize m_size; qreal m_scale = 1.0; diff --git a/src/backends/wayland/wayland_output.cpp b/src/backends/wayland/wayland_output.cpp index 317046da9e..9c2c7e6db9 100644 --- a/src/backends/wayland/wayland_output.cpp +++ b/src/backends/wayland/wayland_output.cpp @@ -83,7 +83,7 @@ void WaylandCursor::disable() } } -void WaylandCursor::update(KWayland::Client::Buffer::Ptr buffer, qreal scale, const QPoint &hotspot) +void WaylandCursor::update(wl_buffer *buffer, qreal scale, const QPoint &hotspot) { if (m_buffer != buffer || m_scale != scale || m_hotspot != hotspot) { m_buffer = buffer; diff --git a/src/backends/wayland/wayland_output.h b/src/backends/wayland/wayland_output.h index e6af4883e9..c29d50627a 100644 --- a/src/backends/wayland/wayland_output.h +++ b/src/backends/wayland/wayland_output.h @@ -46,7 +46,7 @@ public: void enable(); void disable(); - void update(KWayland::Client::Buffer::Ptr buffer, qreal scale, const QPoint &hotspot); + void update(wl_buffer *buffer, qreal scale, const QPoint &hotspot); private: void sync(); @@ -54,7 +54,7 @@ private: WaylandBackend *const m_backend; KWayland::Client::Pointer *m_pointer = nullptr; std::unique_ptr m_surface; - KWayland::Client::Buffer::Ptr m_buffer; + wl_buffer *m_buffer = nullptr; QPoint m_hotspot; qreal m_scale = 1; bool m_enabled = true; diff --git a/src/backends/wayland/wayland_qpainter_backend.cpp b/src/backends/wayland/wayland_qpainter_backend.cpp index 3f4b88eb11..255566530e 100644 --- a/src/backends/wayland/wayland_qpainter_backend.cpp +++ b/src/backends/wayland/wayland_qpainter_backend.cpp @@ -184,7 +184,7 @@ std::optional WaylandQPainterCursorLayer::beginFrame( bool WaylandQPainterCursorLayer::endFrame(const QRegion &renderedRegion, const QRegion &damagedRegion) { KWayland::Client::Buffer::Ptr buffer = m_output->backend()->display()->shmPool()->createBuffer(m_backingStore); - m_output->cursor()->update(buffer, m_scale, m_hotspot); + m_output->cursor()->update(*buffer.lock(), m_scale, m_hotspot); return true; }