From abd9a3c5f875c7f6420d02cfad207ee0fc1152eb Mon Sep 17 00:00:00 2001 From: outfoxxed Date: Sun, 25 May 2025 17:47:58 -0700 Subject: [PATCH] wayland/screencopy: use all dmabuf planes and modifiers in egl image Fixes black texture on nvidia --- src/wayland/buffer/dmabuf.cpp | 78 ++++++++++++++++++++++++++++++++--- 1 file changed, 72 insertions(+), 6 deletions(-) diff --git a/src/wayland/buffer/dmabuf.cpp b/src/wayland/buffer/dmabuf.cpp index 09abc15f..d233da50 100644 --- a/src/wayland/buffer/dmabuf.cpp +++ b/src/wayland/buffer/dmabuf.cpp @@ -6,6 +6,7 @@ #include #include #include +#include #include #include @@ -555,23 +556,88 @@ WlBufferQSGTexture* WlDmaBuffer::createQsgTexture(QQuickWindow* window) const { auto* display = qEglContext->display(); + // Ref https://github.com/hyprwm/hyprlock/blob/da1d076d849fc0f298c1d287bddd04802bf7d0f9/src/renderer/Screencopy.cpp#L194 + struct AttribNameSet { + EGLAttrib fd; + EGLAttrib offset; + EGLAttrib pitch; + EGLAttrib modlo; + EGLAttrib modhi; + }; + + static auto attribNames = std::array { + AttribNameSet { + .fd = EGL_DMA_BUF_PLANE0_FD_EXT, + .offset = EGL_DMA_BUF_PLANE0_OFFSET_EXT, + .pitch = EGL_DMA_BUF_PLANE0_PITCH_EXT, + .modlo = EGL_DMA_BUF_PLANE0_MODIFIER_LO_EXT, + .modhi = EGL_DMA_BUF_PLANE0_MODIFIER_HI_EXT + }, + AttribNameSet { + .fd = EGL_DMA_BUF_PLANE1_FD_EXT, + .offset = EGL_DMA_BUF_PLANE1_OFFSET_EXT, + .pitch = EGL_DMA_BUF_PLANE1_PITCH_EXT, + .modlo = EGL_DMA_BUF_PLANE1_MODIFIER_LO_EXT, + .modhi = EGL_DMA_BUF_PLANE1_MODIFIER_HI_EXT + }, + AttribNameSet { + .fd = EGL_DMA_BUF_PLANE2_FD_EXT, + .offset = EGL_DMA_BUF_PLANE2_OFFSET_EXT, + .pitch = EGL_DMA_BUF_PLANE2_PITCH_EXT, + .modlo = EGL_DMA_BUF_PLANE2_MODIFIER_LO_EXT, + .modhi = EGL_DMA_BUF_PLANE2_MODIFIER_HI_EXT + }, + AttribNameSet { + .fd = EGL_DMA_BUF_PLANE3_FD_EXT, + .offset = EGL_DMA_BUF_PLANE3_OFFSET_EXT, + .pitch = EGL_DMA_BUF_PLANE3_PITCH_EXT, + .modlo = EGL_DMA_BUF_PLANE3_MODIFIER_LO_EXT, + .modhi = EGL_DMA_BUF_PLANE3_MODIFIER_HI_EXT + } + }; + // clang-format off - auto attribs = std::array { + auto attribs = std::vector { EGL_WIDTH, this->width, EGL_HEIGHT, this->height, EGL_LINUX_DRM_FOURCC_EXT, this->format, - EGL_DMA_BUF_PLANE0_FD_EXT, this->planes[0].fd, // NOLINT - EGL_DMA_BUF_PLANE0_OFFSET_EXT, this->planes[0].offset, // NOLINT - EGL_DMA_BUF_PLANE0_PITCH_EXT, this->planes[0].stride, // NOLINT - EGL_NONE }; // clang-format on + if (this->planeCount > 4) { + qFatal(logDmabuf) << "Could not create EGL attrib array with more than 4 planes. Count:" + << this->planeCount; + } + + for (auto i = 0; i != this->planeCount; i++) { + const auto& names = attribNames[i]; + const auto& plane = this->planes[i]; // NOLINT + + // clang-format off + attribs.insert(attribs.end(), { + names.fd, plane.fd, + names.offset, plane.offset, + names.pitch, plane.stride, + }); + // clang-format on + + // clang-format off + if (this->modifier != DRM_FORMAT_MOD_INVALID) { + attribs.insert(attribs.end(), { + names.modlo, static_cast(this->modifier & 0xFFFFFFFF), + names.modhi, static_cast(this->modifier >> 32), + }); + } + // clang-format on + } + + attribs.emplace_back(EGL_NONE); + auto* eglImage = eglCreateImage(display, EGL_NO_CONTEXT, EGL_LINUX_DMA_BUF_EXT, nullptr, attribs.data()); if (eglImage == EGL_NO_IMAGE) { - qFatal() << "failed to make egl image" << eglGetError(); + qFatal() << "Failed to create egl image" << eglGetError(); return nullptr; }