From d7ec51998bca678e7a098e646f62ff1dde3128e7 Mon Sep 17 00:00:00 2001 From: Vlad Zahorodnii Date: Fri, 13 May 2022 12:06:17 +0300 Subject: [PATCH] backends/drm: Import gbm bos using dmabuf It appears that importing gbm_bo's using eglCreateImageKHR() doesn't work on nvidia. Another issue is that Platform::createDmaBufTexture() uses gbm_bo_create(). The nvidia driver doesn't like that, it's preferred to use gbm_bo_create_with_modifiers(). In order to address those issues, this change refactors how gbm_bo objects are imported and how gbm_bo's are allocated for dmabuf textures, so the same code can be reused in EglGbmBackend::textureForOutput() and Platform::createDmaBufTexture(). --- src/backends/drm/CMakeLists.txt | 1 - src/backends/drm/drm_backend.cpp | 31 ++++++- src/backends/drm/drm_backend.h | 2 +- src/backends/drm/drm_buffer_gbm.cpp | 12 --- src/backends/drm/egl_gbm_backend.cpp | 96 +++++++++++++++++++++ src/backends/drm/egl_gbm_backend.h | 7 ++ src/backends/drm/egl_gbm_layer.cpp | 2 +- src/backends/drm/egl_gbm_layer_surface.cpp | 2 +- src/backends/drm/gbm_dmabuf.cpp | 83 ------------------ src/backends/drm/gbm_dmabuf.h | 31 +++---- src/backends/drm/virtual_egl_gbm_layer.cpp | 3 +- src/backends/wayland/CMakeLists.txt | 2 +- src/backends/wayland/wayland_backend.cpp | 10 --- src/backends/wayland/wayland_backend.h | 1 - src/dmabuftexture.cpp | 20 ++++- src/dmabuftexture.h | 29 +++++-- src/platform.cpp | 6 ++ src/platform.h | 6 +- src/plugins/screencast/screencaststream.cpp | 10 ++- 19 files changed, 204 insertions(+), 150 deletions(-) delete mode 100644 src/backends/drm/gbm_dmabuf.cpp diff --git a/src/backends/drm/CMakeLists.txt b/src/backends/drm/CMakeLists.txt index d1de7c244c..134369560d 100644 --- a/src/backends/drm/CMakeLists.txt +++ b/src/backends/drm/CMakeLists.txt @@ -24,7 +24,6 @@ set(DRM_SOURCES egl_gbm_layer.cpp drm_buffer_gbm.cpp gbm_surface.cpp - gbm_dmabuf.cpp placeholderinputeventfilter.cpp virtual_egl_gbm_layer.cpp drm_lease_egl_gbm_layer.cpp diff --git a/src/backends/drm/drm_backend.cpp b/src/backends/drm/drm_backend.cpp index 7e87bb25e7..f92cf1d845 100644 --- a/src/backends/drm/drm_backend.cpp +++ b/src/backends/drm/drm_backend.cpp @@ -13,6 +13,7 @@ #include "backends/libinput/libinputbackend.h" #include "composite.h" #include "cursor.h" +#include "drm_fourcc.h" #include "drm_gpu.h" #include "drm_object_connector.h" #include "drm_object_crtc.h" @@ -623,11 +624,37 @@ void DrmBackend::removeVirtualOutput(Output *output) primaryGpu()->removeVirtualOutput(virtualOutput); } -DmaBufTexture *DrmBackend::createDmaBufTexture(const QSize &size) +QSharedPointer DrmBackend::createDmaBufTexture(const QSize &size) { if (const auto eglBackend = dynamic_cast(m_renderBackend); eglBackend && primaryGpu()->gbmDevice()) { eglBackend->makeCurrent(); - return GbmDmaBuf::createBuffer(size, primaryGpu()->gbmDevice()); + + const int format = GBM_FORMAT_ARGB8888; + const uint64_t modifiers[] = {DRM_FORMAT_MOD_LINEAR}; + + gbm_bo *bo = gbm_bo_create_with_modifiers(primaryGpu()->gbmDevice(), + size.width(), + size.height(), + format, + modifiers, 1); + + // If modifiers are not supported fallback to gbm_bo_create(). + if (!bo && errno == ENOSYS) { + bo = gbm_bo_create(primaryGpu()->gbmDevice(), + size.width(), + size.height(), + format, + GBM_BO_USE_RENDERING | GBM_BO_USE_LINEAR); + } + if (!bo) { + return nullptr; + } + + // The bo will be kept around until the last fd is closed. + const DmaBufAttributes attributes = dmaBufAttributesForBo(bo); + gbm_bo_destroy(bo); + + return QSharedPointer::create(eglBackend->importDmaBufAsTexture(attributes), attributes); } else { return nullptr; } diff --git a/src/backends/drm/drm_backend.h b/src/backends/drm/drm_backend.h index 68232f2978..2265a752af 100644 --- a/src/backends/drm/drm_backend.h +++ b/src/backends/drm/drm_backend.h @@ -44,7 +44,7 @@ public: InputBackend *createInputBackend() override; QPainterBackend *createQPainterBackend() override; OpenGLBackend *createOpenGLBackend() override; - DmaBufTexture *createDmaBufTexture(const QSize &size) override; + QSharedPointer createDmaBufTexture(const QSize &size) override; Session *session() const override; bool initialize() override; diff --git a/src/backends/drm/drm_buffer_gbm.cpp b/src/backends/drm/drm_buffer_gbm.cpp index ee4722ad39..e2a61f8d37 100644 --- a/src/backends/drm/drm_buffer_gbm.cpp +++ b/src/backends/drm/drm_buffer_gbm.cpp @@ -12,7 +12,6 @@ #include "config-kwin.h" #include "drm_gpu.h" -#include "kwineglimagetexture.h" #include "kwineglutils_p.h" #include "logging.h" #include "wayland/clientbuffer.h" @@ -129,17 +128,6 @@ bool GbmBuffer::map(uint32_t flags) return m_data; } -QSharedPointer GbmBuffer::createTexture(EGLDisplay eglDisplay) const -{ - EGLImageKHR image = eglCreateImageKHR(eglDisplay, nullptr, EGL_NATIVE_PIXMAP_KHR, m_bo, nullptr); - if (image != EGL_NO_IMAGE_KHR) { - return QSharedPointer::create(eglDisplay, image, GL_RGBA8, QSize(gbm_bo_get_width(m_bo), gbm_bo_get_height(m_bo))); - } else { - qCWarning(KWIN_DRM) << "Failed to record frame: Error creating EGLImageKHR - " << getEglErrorString(); - return nullptr; - } -} - void GbmBuffer::createFds() { #if HAVE_GBM_BO_GET_FD_FOR_PLANE diff --git a/src/backends/drm/egl_gbm_backend.cpp b/src/backends/drm/egl_gbm_backend.cpp index f43f878716..db09cc18d2 100644 --- a/src/backends/drm/egl_gbm_backend.cpp +++ b/src/backends/drm/egl_gbm_backend.cpp @@ -22,6 +22,7 @@ #include "egl_dmabuf.h" #include "egl_gbm_cursor_layer.h" #include "egl_gbm_layer.h" +#include "gbm_dmabuf.h" #include "gbm_surface.h" #include "kwineglutils_p.h" #include "linux_dmabuf.h" @@ -267,4 +268,99 @@ bool operator==(const GbmFormat &lhs, const GbmFormat &rhs) return lhs.drmFormat == rhs.drmFormat; } +EGLImageKHR EglGbmBackend::importDmaBufAsImage(const DmaBufAttributes &dmabuf) +{ + QVector attribs; + attribs.reserve(6 + dmabuf.planeCount * 10 + 1); + + attribs + << EGL_WIDTH << dmabuf.width + << EGL_HEIGHT << dmabuf.height + << EGL_LINUX_DRM_FOURCC_EXT << dmabuf.format; + + attribs + << EGL_DMA_BUF_PLANE0_FD_EXT << dmabuf.fd[0] + << EGL_DMA_BUF_PLANE0_OFFSET_EXT << dmabuf.offset[0] + << EGL_DMA_BUF_PLANE0_PITCH_EXT << dmabuf.pitch[0]; + if (dmabuf.modifier[0] != DRM_FORMAT_MOD_INVALID) { + attribs + << EGL_DMA_BUF_PLANE0_MODIFIER_LO_EXT << EGLint(dmabuf.modifier[0] & 0xffffffff) + << EGL_DMA_BUF_PLANE0_MODIFIER_HI_EXT << EGLint(dmabuf.modifier[0] >> 32); + } + + if (dmabuf.planeCount > 1) { + attribs + << EGL_DMA_BUF_PLANE1_FD_EXT << dmabuf.fd[1] + << EGL_DMA_BUF_PLANE1_OFFSET_EXT << dmabuf.offset[1] + << EGL_DMA_BUF_PLANE1_PITCH_EXT << dmabuf.pitch[1]; + if (dmabuf.modifier[1] != DRM_FORMAT_MOD_INVALID) { + attribs + << EGL_DMA_BUF_PLANE1_MODIFIER_LO_EXT << EGLint(dmabuf.modifier[1] & 0xffffffff) + << EGL_DMA_BUF_PLANE1_MODIFIER_HI_EXT << EGLint(dmabuf.modifier[1] >> 32); + } + } + + if (dmabuf.planeCount > 2) { + attribs + << EGL_DMA_BUF_PLANE2_FD_EXT << dmabuf.fd[2] + << EGL_DMA_BUF_PLANE2_OFFSET_EXT << dmabuf.offset[2] + << EGL_DMA_BUF_PLANE2_PITCH_EXT << dmabuf.pitch[2]; + if (dmabuf.modifier[2] != DRM_FORMAT_MOD_INVALID) { + attribs + << EGL_DMA_BUF_PLANE2_MODIFIER_LO_EXT << EGLint(dmabuf.modifier[2] & 0xffffffff) + << EGL_DMA_BUF_PLANE2_MODIFIER_HI_EXT << EGLint(dmabuf.modifier[2] >> 32); + } + } + + if (dmabuf.planeCount > 3) { + attribs + << EGL_DMA_BUF_PLANE3_FD_EXT << dmabuf.fd[3] + << EGL_DMA_BUF_PLANE3_OFFSET_EXT << dmabuf.offset[3] + << EGL_DMA_BUF_PLANE3_PITCH_EXT << dmabuf.pitch[3]; + if (dmabuf.modifier[3] != DRM_FORMAT_MOD_INVALID) { + attribs + << EGL_DMA_BUF_PLANE3_MODIFIER_LO_EXT << EGLint(dmabuf.modifier[3] & 0xffffffff) + << EGL_DMA_BUF_PLANE3_MODIFIER_HI_EXT << EGLint(dmabuf.modifier[3] >> 32); + } + } + + attribs << EGL_NONE; + + return eglCreateImageKHR(eglDisplay(), EGL_NO_CONTEXT, EGL_LINUX_DMA_BUF_EXT, nullptr, attribs.data()); } + +EGLImageKHR EglGbmBackend::importDmaBufAsImage(gbm_bo *bo) +{ + const DmaBufAttributes dmabuf = dmaBufAttributesForBo(bo); + EGLImage image = importDmaBufAsImage(dmabuf); + + for (int i = 0; i < dmabuf.planeCount; ++i) { + close(dmabuf.fd[i]); + } + + return image; +} + +QSharedPointer EglGbmBackend::importDmaBufAsTexture(const DmaBufAttributes &attributes) +{ + EGLImageKHR image = importDmaBufAsImage(attributes); + if (image != EGL_NO_IMAGE_KHR) { + return QSharedPointer::create(eglDisplay(), image, GL_RGBA8, QSize(attributes.width, attributes.height)); + } else { + qCWarning(KWIN_DRM) << "Failed to record frame: Error creating EGLImageKHR - " << getEglErrorString(); + return nullptr; + } +} + +QSharedPointer EglGbmBackend::importDmaBufAsTexture(gbm_bo *bo) +{ + EGLImageKHR image = importDmaBufAsImage(bo); + if (image != EGL_NO_IMAGE_KHR) { + return QSharedPointer::create(eglDisplay(), image, GL_RGBA8, QSize(gbm_bo_get_width(bo), gbm_bo_get_height(bo))); + } else { + qCWarning(KWIN_DRM) << "Failed to record frame: Error creating EGLImageKHR - " << getEglErrorString(); + return nullptr; + } +} + +} // namespace KWin diff --git a/src/backends/drm/egl_gbm_backend.h b/src/backends/drm/egl_gbm_backend.h index 0d9deed3a9..20a1fee8a7 100644 --- a/src/backends/drm/egl_gbm_backend.h +++ b/src/backends/drm/egl_gbm_backend.h @@ -27,6 +27,8 @@ class SurfaceInterface; namespace KWin { + +struct DmaBufAttributes; class Output; class DrmAbstractOutput; class DrmBuffer; @@ -79,6 +81,11 @@ public: std::optional gbmFormatForDrmFormat(uint32_t format) const; DrmGpu *gpu() const; + EGLImageKHR importDmaBufAsImage(const DmaBufAttributes &attributes); + EGLImageKHR importDmaBufAsImage(gbm_bo *bo); + QSharedPointer importDmaBufAsTexture(const DmaBufAttributes &attributes); + QSharedPointer importDmaBufAsTexture(gbm_bo *bo); + private: bool initializeEgl(); bool initBufferConfigs(); diff --git a/src/backends/drm/egl_gbm_layer.cpp b/src/backends/drm/egl_gbm_layer.cpp index 4bb8852882..0d299c4161 100644 --- a/src/backends/drm/egl_gbm_layer.cpp +++ b/src/backends/drm/egl_gbm_layer.cpp @@ -79,7 +79,7 @@ bool EglGbmLayer::checkTestBuffer() QSharedPointer EglGbmLayer::texture() const { if (m_scanoutBuffer) { - return static_cast(m_scanoutBuffer->buffer())->createTexture(m_surface.eglBackend()->eglDisplay()); + return m_surface.eglBackend()->importDmaBufAsTexture(static_cast(m_scanoutBuffer->buffer())->bo()); } else { return m_surface.texture(); } diff --git a/src/backends/drm/egl_gbm_layer_surface.cpp b/src/backends/drm/egl_gbm_layer_surface.cpp index d8b3210fcc..1aa624d3f4 100644 --- a/src/backends/drm/egl_gbm_layer_surface.cpp +++ b/src/backends/drm/egl_gbm_layer_surface.cpp @@ -336,7 +336,7 @@ QSharedPointer EglGbmLayerSurface::texture() const qCWarning(KWIN_DRM) << "Failed to record frame: No gbm buffer!"; return nullptr; } - return m_currentBuffer->createTexture(m_eglBackend->eglDisplay()); + return m_eglBackend->importDmaBufAsTexture(m_currentBuffer->bo()); } std::shared_ptr EglGbmLayerSurface::renderTestBuffer(const QSize &bufferSize, const QMap> &formats, uint32_t additionalFlags) diff --git a/src/backends/drm/gbm_dmabuf.cpp b/src/backends/drm/gbm_dmabuf.cpp deleted file mode 100644 index 28c0a30674..0000000000 --- a/src/backends/drm/gbm_dmabuf.cpp +++ /dev/null @@ -1,83 +0,0 @@ -/* - SPDX-FileCopyrightText: 2020 Aleix Pol Gonzalez - - SPDX-License-Identifier: LGPL-2.0-or-later -*/ - -#include "gbm_dmabuf.h" -#include "drm_fourcc.h" -#include "kwineglimagetexture.h" -#include "main.h" -#include "platform.h" -#include - -namespace KWin -{ - -GbmDmaBuf::GbmDmaBuf(GLTexture *texture, gbm_bo *bo, int fd) - : DmaBufTexture(texture) - , m_bo(bo) - , m_fd(fd) -{ -} - -GbmDmaBuf::~GbmDmaBuf() -{ - m_texture.reset(nullptr); - - close(m_fd); - gbm_bo_destroy(m_bo); -} - -int GbmDmaBuf::fd() const -{ - return m_fd; -} - -quint32 GbmDmaBuf::stride() const -{ - return gbm_bo_get_stride(m_bo); -} - -GbmDmaBuf *GbmDmaBuf::createBuffer(const QSize &size, gbm_device *device) -{ - if (!device) { - return nullptr; - } - - auto bo = gbm_bo_create(device, size.width(), size.height(), GBM_FORMAT_ARGB8888, GBM_BO_USE_RENDERING | GBM_BO_USE_LINEAR); - - if (!bo) { - return nullptr; - } - - const int fd = gbm_bo_get_fd(bo); - if (fd < 0) { - gbm_bo_destroy(bo); - return nullptr; - } - - EGLint importAttributes[] = { - EGL_WIDTH, EGLint(gbm_bo_get_width(bo)), - EGL_HEIGHT, EGLint(gbm_bo_get_height(bo)), - EGL_LINUX_DRM_FOURCC_EXT, DRM_FORMAT_ARGB8888, - EGL_DMA_BUF_PLANE0_FD_EXT, fd, - EGL_DMA_BUF_PLANE0_OFFSET_EXT, EGLint(gbm_bo_get_offset(bo, 0)), - EGL_DMA_BUF_PLANE0_PITCH_EXT, EGLint(gbm_bo_get_stride(bo)), - EGL_NONE}; - - EGLDisplay display = kwinApp()->platform()->sceneEglDisplay(); - if (display == EGL_NO_DISPLAY) { - return nullptr; - } - EGLImageKHR destinationImage = eglCreateImageKHR(display, EGL_NO_CONTEXT, EGL_LINUX_DMA_BUF_EXT, nullptr, importAttributes); - if (destinationImage == EGL_NO_IMAGE_KHR) { - close(fd); - gbm_bo_destroy(bo); - return nullptr; - } - - return new GbmDmaBuf(new KWin::EGLImageTexture(display, destinationImage, GL_RGBA8, size), bo, fd); -} - -} diff --git a/src/backends/drm/gbm_dmabuf.h b/src/backends/drm/gbm_dmabuf.h index 067c46bb14..94b3bfa81b 100644 --- a/src/backends/drm/gbm_dmabuf.h +++ b/src/backends/drm/gbm_dmabuf.h @@ -7,27 +7,28 @@ #pragma once #include "dmabuftexture.h" -#include -#include + #include namespace KWin { -class GbmDmaBuf : public DmaBufTexture +inline DmaBufAttributes dmaBufAttributesForBo(gbm_bo *bo) { -public: - ~GbmDmaBuf(); + DmaBufAttributes attributes; + attributes.planeCount = gbm_bo_get_plane_count(bo); + attributes.width = gbm_bo_get_width(bo); + attributes.height = gbm_bo_get_height(bo); + attributes.format = gbm_bo_get_format(bo); - int fd() const override; - quint32 stride() const override; - - static GbmDmaBuf *createBuffer(const QSize &size, gbm_device *device); - -private: - GbmDmaBuf(GLTexture *texture, gbm_bo *bo, int fd); - struct gbm_bo *const m_bo; - const int m_fd; -}; + for (int i = 0; i < attributes.planeCount; ++i) { + attributes.fd[i] = gbm_bo_get_fd_for_plane(bo, i); + attributes.offset[i] = gbm_bo_get_offset(bo, i); + attributes.pitch[i] = gbm_bo_get_stride_for_plane(bo, i); + attributes.modifier[i] = gbm_bo_get_modifier(bo); + } + return attributes; } + +} // namespace KWin diff --git a/src/backends/drm/virtual_egl_gbm_layer.cpp b/src/backends/drm/virtual_egl_gbm_layer.cpp index 512e0a2dbb..1a488db366 100644 --- a/src/backends/drm/virtual_egl_gbm_layer.cpp +++ b/src/backends/drm/virtual_egl_gbm_layer.cpp @@ -17,7 +17,6 @@ #include "egl_dmabuf.h" #include "egl_gbm_backend.h" #include "gbm_surface.h" -#include "kwineglimagetexture.h" #include "kwineglutils_p.h" #include "logging.h" #include "shadowbuffer.h" @@ -139,7 +138,7 @@ QSharedPointer VirtualEglGbmLayer::texture() const qCWarning(KWIN_DRM) << "Failed to record frame: No gbm buffer!"; return nullptr; } - return m_currentBuffer->createTexture(m_eglBackend->eglDisplay()); + return m_eglBackend->importDmaBufAsTexture(m_currentBuffer->bo()); } bool VirtualEglGbmLayer::scanout(SurfaceItem *surfaceItem) diff --git a/src/backends/wayland/CMakeLists.txt b/src/backends/wayland/CMakeLists.txt index 6ac6ee8341..3fd9860f78 100644 --- a/src/backends/wayland/CMakeLists.txt +++ b/src/backends/wayland/CMakeLists.txt @@ -6,7 +6,7 @@ set(WAYLAND_BACKEND_SOURCES ) if (HAVE_WAYLAND_EGL) - set(WAYLAND_BACKEND_SOURCES egl_wayland_backend.cpp ${WAYLAND_BACKEND_SOURCES} ../drm/gbm_dmabuf.cpp) + set(WAYLAND_BACKEND_SOURCES egl_wayland_backend.cpp ${WAYLAND_BACKEND_SOURCES}) endif() add_library(KWinWaylandWaylandBackend MODULE ${WAYLAND_BACKEND_SOURCES}) diff --git a/src/backends/wayland/wayland_backend.cpp b/src/backends/wayland/wayland_backend.cpp index f065ccb9ad..e1c910cb93 100644 --- a/src/backends/wayland/wayland_backend.cpp +++ b/src/backends/wayland/wayland_backend.cpp @@ -10,7 +10,6 @@ #include "wayland_backend.h" #if HAVE_WAYLAND_EGL -#include "../drm/gbm_dmabuf.h" #include "egl_wayland_backend.h" #include #endif @@ -991,15 +990,6 @@ void WaylandBackend::addConfiguredOutput(WaylandOutput *output) } } -DmaBufTexture *WaylandBackend::createDmaBufTexture(const QSize &size) -{ -#if HAVE_WAYLAND_EGL - return GbmDmaBuf::createBuffer(size, m_gbmDevice); -#else - return nullptr; -#endif -} - void WaylandBackend::createDpmsFilter() { if (m_dpmsFilter) { diff --git a/src/backends/wayland/wayland_backend.h b/src/backends/wayland/wayland_backend.h index e0d2c5bd6b..318620f30b 100644 --- a/src/backends/wayland/wayland_backend.h +++ b/src/backends/wayland/wayland_backend.h @@ -260,7 +260,6 @@ public: InputBackend *createInputBackend() override; OpenGLBackend *createOpenGLBackend() override; QPainterBackend *createQPainterBackend() override; - DmaBufTexture *createDmaBufTexture(const QSize &size) override; void flush(); diff --git a/src/dmabuftexture.cpp b/src/dmabuftexture.cpp index c85f5c29e0..c83b0de2df 100644 --- a/src/dmabuftexture.cpp +++ b/src/dmabuftexture.cpp @@ -6,19 +6,31 @@ #include "dmabuftexture.h" -#include "kwineglimagetexture.h" #include "kwinglutils.h" +#include + namespace KWin { -DmaBufTexture::DmaBufTexture(KWin::GLTexture *texture) +DmaBufTexture::DmaBufTexture(QSharedPointer texture, const DmaBufAttributes &attributes) : m_texture(texture) - , m_framebuffer(new KWin::GLFramebuffer(texture)) + , m_framebuffer(new GLFramebuffer(texture.data())) + , m_attributes(attributes) { } -DmaBufTexture::~DmaBufTexture() = default; +DmaBufTexture::~DmaBufTexture() +{ + for (int i = 0; i < m_attributes.planeCount; ++i) { + ::close(m_attributes.fd[i]); + } +} + +DmaBufAttributes DmaBufTexture::attributes() const +{ + return m_attributes; +} KWin::GLTexture *DmaBufTexture::texture() const { diff --git a/src/dmabuftexture.h b/src/dmabuftexture.h index a4020604a1..4f5350a8b1 100644 --- a/src/dmabuftexture.h +++ b/src/dmabuftexture.h @@ -6,27 +6,42 @@ #pragma once #include "kwin_export.h" + #include +#include namespace KWin { class GLFramebuffer; class GLTexture; +struct DmaBufAttributes +{ + int planeCount; + int width; + int height; + int format; + + int fd[4]; + int offset[4]; + int pitch[4]; + uint64_t modifier[4]; +}; + class KWIN_EXPORT DmaBufTexture { public: - explicit DmaBufTexture(KWin::GLTexture *texture); + explicit DmaBufTexture(QSharedPointer texture, const DmaBufAttributes &attributes); virtual ~DmaBufTexture(); - virtual quint32 stride() const = 0; - virtual int fd() const = 0; - KWin::GLTexture *texture() const; - KWin::GLFramebuffer *framebuffer() const; + DmaBufAttributes attributes() const; + GLTexture *texture() const; + GLFramebuffer *framebuffer() const; protected: - QScopedPointer m_texture; - QScopedPointer m_framebuffer; + QSharedPointer m_texture; + QScopedPointer m_framebuffer; + DmaBufAttributes m_attributes; }; } diff --git a/src/platform.cpp b/src/platform.cpp index 9f4d0d5bbb..e196eb3b21 100644 --- a/src/platform.cpp +++ b/src/platform.cpp @@ -80,6 +80,12 @@ QPainterBackend *Platform::createQPainterBackend() return nullptr; } +QSharedPointer Platform::createDmaBufTexture(const QSize &size) +{ + Q_UNUSED(size) + return {}; +} + Edge *Platform::createScreenEdge(ScreenEdges *edges) { return new Edge(edges); diff --git a/src/platform.h b/src/platform.h index 306c06f133..a8c664d2cc 100644 --- a/src/platform.h +++ b/src/platform.h @@ -66,11 +66,7 @@ public: virtual InputBackend *createInputBackend(); virtual OpenGLBackend *createOpenGLBackend(); virtual QPainterBackend *createQPainterBackend(); - virtual DmaBufTexture *createDmaBufTexture(const QSize &size) - { - Q_UNUSED(size); - return nullptr; - } + virtual QSharedPointer createDmaBufTexture(const QSize &size); /** * Allows the platform to create a platform specific screen edge. diff --git a/src/plugins/screencast/screencaststream.cpp b/src/plugins/screencast/screencaststream.cpp index b5228aafbb..42bfff985a 100644 --- a/src/plugins/screencast/screencaststream.cpp +++ b/src/plugins/screencast/screencaststream.cpp @@ -142,14 +142,16 @@ void ScreenCastStream::onStreamAddBuffer(void *data, pw_buffer *buffer) spa_data->flags = SPA_DATA_FLAG_READWRITE; if (spa_data[0].type != SPA_ID_INVALID && spa_data[0].type & (1 << SPA_DATA_DmaBuf)) { - dmabuf.reset(kwinApp()->platform()->createDmaBufTexture(stream->m_resolution)); + dmabuf = kwinApp()->platform()->createDmaBufTexture(stream->m_resolution); } if (dmabuf) { + const DmaBufAttributes dmabufAttribs = dmabuf->attributes(); + spa_data->type = SPA_DATA_DmaBuf; - spa_data->fd = dmabuf->fd(); + spa_data->fd = dmabufAttribs.fd[0]; spa_data->data = nullptr; - spa_data->maxsize = dmabuf->stride() * stream->m_resolution.height(); + spa_data->maxsize = dmabufAttribs.pitch[0] * stream->m_resolution.height(); stream->m_dmabufDataForPwBuffer.insert(buffer, dmabuf); #ifdef F_SEAL_SEAL // Disable memfd on systems that don't have it, like BSD < 12 @@ -399,7 +401,7 @@ void ScreenCastStream::recordFrame(const QRegion &damagedRegion) } else { auto &buf = m_dmabufDataForPwBuffer[buffer]; - spa_data->chunk->stride = buf->stride(); + spa_data->chunk->stride = buf->attributes().pitch[0]; spa_data->chunk->size = spa_data->maxsize; m_source->render(buf->framebuffer());