backends/drm: use a swapchain instead of an OpenGL texture for the shadow buffer(s)

This seems to have better performance on Intel GPUs, and allows us to implement damage
tracking for the shadow "buffer" in the future

CCBUG: 477223
This commit is contained in:
Xaver Hugl 2024-01-16 22:47:18 +01:00
parent 786dc09704
commit c26101a9fe
4 changed files with 50 additions and 15 deletions

View file

@ -121,23 +121,46 @@ std::optional<OutputLayerBeginFrameInfo> 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<GLFramebuffer>(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<DrmFramebuffer> 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<uint32_t,
std::shared_ptr<GLTexture> 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;
}

View file

@ -99,8 +99,8 @@ private:
// for color management
bool colormanagementEnabled = false;
std::shared_ptr<GLTexture> shadowTexture;
std::unique_ptr<GLFramebuffer> shadowBuffer;
std::shared_ptr<EglSwapchain> shadowSwapchain;
std::shared_ptr<EglSwapchainSlot> currentShadowSlot;
ColorDescription targetColorDescription = ColorDescription::sRGB;
ColorDescription intermediaryColorDescription = ColorDescription::sRGB;
QVector3D channelFactors = {1, 1, 1};

View file

@ -24,6 +24,7 @@ std::optional<FormatInfo> 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> 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> 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> 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> 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> 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> 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> 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> FormatInfo::get(uint32_t drmFormat)
.alphaBits = 0,
.bitsPerPixel = 24,
.openglFormat = GL_R8,
.floatingPoint = false,
};
default:
return std::nullopt;

View file

@ -45,6 +45,7 @@ struct KWIN_EXPORT FormatInfo
uint32_t alphaBits;
uint32_t bitsPerPixel;
GLint openglFormat;
bool floatingPoint;
std::optional<YuvConversion> yuvConversion() const
{