backends/wayland: Pass linux-dmabuf buffers for cursor layer

This lets us avoid reading fbo data back.
This commit is contained in:
Vlad Zahorodnii 2023-01-03 12:44:12 +02:00
parent 9f100e8292
commit c10b35facb
5 changed files with 22 additions and 16 deletions

View file

@ -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<OutputLayerBeginFrameInfo> WaylandEglCursorLayer::beginFrame()
}
const QSize bufferSize = m_size.expandedTo(QSize(64, 64));
if (!m_texture || m_texture->size() != bufferSize) {
m_texture = std::make_unique<GLTexture>(GL_RGBA8, bufferSize);
m_framebuffer = std::make_unique<GLFramebuffer>(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<uint64_t> modifiers = dmabuf->formats().value(format);
m_swapchain = std::make_unique<WaylandEglLayerSwapchain>(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;
}

View file

@ -115,8 +115,8 @@ public:
private:
WaylandOutput *m_output;
WaylandEglBackend *m_backend;
std::unique_ptr<GLFramebuffer> m_framebuffer;
std::unique_ptr<GLTexture> m_texture;
std::unique_ptr<WaylandEglLayerSwapchain> m_swapchain;
std::shared_ptr<WaylandEglLayerBuffer> m_buffer;
QPoint m_hotspot;
QSize m_size;
qreal m_scale = 1.0;

View file

@ -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;

View file

@ -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<KWayland::Client::Surface> m_surface;
KWayland::Client::Buffer::Ptr m_buffer;
wl_buffer *m_buffer = nullptr;
QPoint m_hotspot;
qreal m_scale = 1;
bool m_enabled = true;

View file

@ -184,7 +184,7 @@ std::optional<OutputLayerBeginFrameInfo> 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;
}