diff --git a/src/backends/drm/drm_egl_layer_surface.cpp b/src/backends/drm/drm_egl_layer_surface.cpp index 31cf4701e5..ab0b51f468 100644 --- a/src/backends/drm/drm_egl_layer_surface.cpp +++ b/src/backends/drm/drm_egl_layer_surface.cpp @@ -121,23 +121,46 @@ std::optional EglGbmLayerSurface::startRendering(cons const QRegion repaint = bufferAgeEnabled ? m_surface->damageJournal.accumulate(slot->age(), infiniteRegion()) : infiniteRegion(); if (enableColormanagement) { - if (!m_surface->shadowBuffer || m_surface->shadowTexture->size() != m_surface->gbmSwapchain->size()) { - m_surface->shadowTexture = GLTexture::allocate(GL_RGBA16F, m_surface->gbmSwapchain->size()); - if (!m_surface->shadowTexture) { - return std::nullopt; + if (!m_surface->shadowSwapchain || m_surface->shadowSwapchain->size() != m_surface->gbmSwapchain->size()) { + const auto formats = m_eglBackend->eglDisplayObject()->nonExternalOnlySupportedDrmFormats(); + const auto createSwapchain = [&formats, this](bool requireAlpha) { + for (auto it = formats.begin(); it != formats.end(); it++) { + const auto info = FormatInfo::get(it.key()); + if (!info || info->bitsPerColor != 16 || !info->floatingPoint) { + continue; + } + if (requireAlpha && info->alphaBits == 0) { + continue; + } + m_surface->shadowSwapchain = EglSwapchain::create(m_eglBackend->drmDevice()->allocator(), m_eglBackend->openglContext(), m_surface->gbmSwapchain->size(), it.key(), it.value()); + if (m_surface->shadowSwapchain) { + break; + } + } + }; + createSwapchain(true); + if (!m_surface->shadowSwapchain && m_formatOption != FormatOption::RequireAlpha) { + createSwapchain(false); } - m_surface->shadowBuffer = std::make_unique(m_surface->shadowTexture.get()); } - m_surface->shadowTexture->setContentTransform(m_surface->currentSlot->framebuffer()->colorAttachment()->contentTransform()); + if (!m_surface->shadowSwapchain) { + qCCritical(KWIN_DRM) << "Failed to create shadow swapchain!"; + return std::nullopt; + } + m_surface->currentShadowSlot = m_surface->shadowSwapchain->acquire(); + if (!m_surface->currentShadowSlot) { + return std::nullopt; + } + m_surface->currentShadowSlot->texture()->setContentTransform(m_surface->currentSlot->framebuffer()->colorAttachment()->contentTransform()); m_surface->renderStart = std::chrono::steady_clock::now(); m_surface->timeQuery->begin(); return OutputLayerBeginFrameInfo{ - .renderTarget = RenderTarget(m_surface->shadowBuffer.get(), m_surface->intermediaryColorDescription), - .repaint = repaint, + .renderTarget = RenderTarget(m_surface->currentShadowSlot->framebuffer(), m_surface->intermediaryColorDescription), + .repaint = infiniteRegion(), }; } else { - m_surface->shadowTexture.reset(); - m_surface->shadowBuffer.reset(); + m_surface->shadowSwapchain.reset(); + m_surface->currentShadowSlot.reset(); m_surface->renderStart = std::chrono::steady_clock::now(); m_surface->timeQuery->begin(); return OutputLayerBeginFrameInfo{ @@ -173,7 +196,9 @@ bool EglGbmLayerSurface::endRendering(const QRegion &damagedRegion) mat.ortho(QRectF(QPointF(), fbo->size())); binder.shader()->setUniform(GLShader::Mat4Uniform::ModelViewProjectionMatrix, mat); glDisable(GL_BLEND); - m_surface->shadowTexture->render(m_surface->gbmSwapchain->size()); + m_surface->currentShadowSlot->texture()->render(m_surface->gbmSwapchain->size()); + EGLNativeFence fence(m_surface->context->displayObject()); + m_surface->shadowSwapchain->release(m_surface->currentShadowSlot, fence.fileDescriptor().duplicate()); GLFramebuffer::popFramebuffer(); } m_surface->damageJournal.add(damagedRegion); @@ -227,7 +252,7 @@ std::shared_ptr EglGbmLayerSurface::currentBuffer() const const ColorDescription &EglGbmLayerSurface::colorDescription() const { if (m_surface) { - return m_surface->shadowTexture ? m_surface->intermediaryColorDescription : m_surface->targetColorDescription; + return m_surface->currentShadowSlot ? m_surface->intermediaryColorDescription : m_surface->targetColorDescription; } else { return ColorDescription::sRGB; } @@ -241,7 +266,7 @@ bool EglGbmLayerSurface::doesSurfaceFit(const QSize &size, const QMap EglGbmLayerSurface::texture() const { if (m_surface) { - return m_surface->shadowTexture ? m_surface->shadowTexture : m_surface->currentSlot->texture(); + return m_surface->currentShadowSlot ? m_surface->currentShadowSlot->texture() : m_surface->currentSlot->texture(); } else { return nullptr; } diff --git a/src/backends/drm/drm_egl_layer_surface.h b/src/backends/drm/drm_egl_layer_surface.h index db94315b5a..c2ed18a6f4 100644 --- a/src/backends/drm/drm_egl_layer_surface.h +++ b/src/backends/drm/drm_egl_layer_surface.h @@ -99,8 +99,8 @@ private: // for color management bool colormanagementEnabled = false; - std::shared_ptr shadowTexture; - std::unique_ptr shadowBuffer; + std::shared_ptr shadowSwapchain; + std::shared_ptr currentShadowSlot; ColorDescription targetColorDescription = ColorDescription::sRGB; ColorDescription intermediaryColorDescription = ColorDescription::sRGB; QVector3D channelFactors = {1, 1, 1}; diff --git a/src/utils/drm_format_helper.cpp b/src/utils/drm_format_helper.cpp index e78f7a107d..6998da23bf 100644 --- a/src/utils/drm_format_helper.cpp +++ b/src/utils/drm_format_helper.cpp @@ -24,6 +24,7 @@ std::optional FormatInfo::get(uint32_t drmFormat) .alphaBits = 0, .bitsPerPixel = 32, .openglFormat = GL_RGBA8, + .floatingPoint = false, }; case DRM_FORMAT_ARGB8888: case DRM_FORMAT_ABGR8888: @@ -35,6 +36,7 @@ std::optional FormatInfo::get(uint32_t drmFormat) .alphaBits = 8, .bitsPerPixel = 32, .openglFormat = GL_RGBA8, + .floatingPoint = false, }; case DRM_FORMAT_XRGB2101010: case DRM_FORMAT_XBGR2101010: @@ -46,6 +48,7 @@ std::optional FormatInfo::get(uint32_t drmFormat) .alphaBits = 0, .bitsPerPixel = 32, .openglFormat = GL_RGB10_A2, + .floatingPoint = false, }; case DRM_FORMAT_ARGB2101010: case DRM_FORMAT_ABGR2101010: @@ -57,6 +60,7 @@ std::optional FormatInfo::get(uint32_t drmFormat) .alphaBits = 2, .bitsPerPixel = 32, .openglFormat = GL_RGB10_A2, + .floatingPoint = false, }; case DRM_FORMAT_XRGB16161616F: case DRM_FORMAT_XBGR16161616F: @@ -66,6 +70,7 @@ std::optional FormatInfo::get(uint32_t drmFormat) .alphaBits = 0, .bitsPerPixel = 64, .openglFormat = GL_RGBA16F, + .floatingPoint = true, }; case DRM_FORMAT_ARGB16161616F: case DRM_FORMAT_ABGR16161616F: @@ -75,6 +80,7 @@ std::optional FormatInfo::get(uint32_t drmFormat) .alphaBits = 16, .bitsPerPixel = 64, .openglFormat = GL_RGBA16F, + .floatingPoint = true, }; case DRM_FORMAT_ARGB4444: case DRM_FORMAT_ABGR4444: @@ -86,6 +92,7 @@ std::optional FormatInfo::get(uint32_t drmFormat) .alphaBits = 4, .bitsPerPixel = 16, .openglFormat = GL_RGBA4, + .floatingPoint = false, }; case DRM_FORMAT_ARGB1555: case DRM_FORMAT_ABGR1555: @@ -97,6 +104,7 @@ std::optional FormatInfo::get(uint32_t drmFormat) .alphaBits = 1, .bitsPerPixel = 16, .openglFormat = GL_RGB5_A1, + .floatingPoint = false, }; case DRM_FORMAT_NV12: return FormatInfo{ @@ -105,6 +113,7 @@ std::optional FormatInfo::get(uint32_t drmFormat) .alphaBits = 0, .bitsPerPixel = 24, .openglFormat = GL_R8, + .floatingPoint = false, }; default: return std::nullopt; diff --git a/src/utils/drm_format_helper.h b/src/utils/drm_format_helper.h index d68893609e..d6fa2ff2e7 100644 --- a/src/utils/drm_format_helper.h +++ b/src/utils/drm_format_helper.h @@ -45,6 +45,7 @@ struct KWIN_EXPORT FormatInfo uint32_t alphaBits; uint32_t bitsPerPixel; GLint openglFormat; + bool floatingPoint; std::optional yuvConversion() const {