backends/drm: implement damage tracking for the color management shadow buffer

This significantly reduces the amount of pixels that have to be repainted in most frames
while an ICC profile is set.

BUG: 477223
This commit is contained in:
Xaver Hugl 2024-08-19 20:08:47 +02:00
parent d56dbb04e6
commit e7780f1ab3
2 changed files with 17 additions and 5 deletions

View file

@ -98,6 +98,7 @@ std::optional<OutputLayerBeginFrameInfo> EglGbmLayerSurface::startRendering(cons
if (m_surface->targetColorDescription != colorDescription || m_surface->channelFactors != channelFactors || m_surface->iccProfile != iccProfile) { if (m_surface->targetColorDescription != colorDescription || m_surface->channelFactors != channelFactors || m_surface->iccProfile != iccProfile) {
m_surface->damageJournal.clear(); m_surface->damageJournal.clear();
m_surface->shadowDamageJournal.clear();
m_surface->needsShadowBuffer = channelFactors != QVector3D(1, 1, 1) || iccProfile || colorDescription.transferFunction().type != TransferFunction::gamma22; m_surface->needsShadowBuffer = channelFactors != QVector3D(1, 1, 1) || iccProfile || colorDescription.transferFunction().type != TransferFunction::gamma22;
m_surface->targetColorDescription = colorDescription; m_surface->targetColorDescription = colorDescription;
m_surface->channelFactors = channelFactors; m_surface->channelFactors = channelFactors;
@ -120,7 +121,6 @@ std::optional<OutputLayerBeginFrameInfo> EglGbmLayerSurface::startRendering(cons
} }
} }
const QRegion repaint = bufferAgeEnabled ? m_surface->damageJournal.accumulate(slot->age(), infiniteRegion()) : infiniteRegion();
m_surface->compositingTimeQuery = std::make_unique<GLRenderTimeQuery>(m_surface->context); m_surface->compositingTimeQuery = std::make_unique<GLRenderTimeQuery>(m_surface->context);
m_surface->compositingTimeQuery->begin(); m_surface->compositingTimeQuery->begin();
if (m_surface->needsShadowBuffer) { if (m_surface->needsShadowBuffer) {
@ -173,14 +173,14 @@ std::optional<OutputLayerBeginFrameInfo> EglGbmLayerSurface::startRendering(cons
m_surface->currentShadowSlot->texture()->setContentTransform(m_surface->currentSlot->framebuffer()->colorAttachment()->contentTransform()); m_surface->currentShadowSlot->texture()->setContentTransform(m_surface->currentSlot->framebuffer()->colorAttachment()->contentTransform());
return OutputLayerBeginFrameInfo{ return OutputLayerBeginFrameInfo{
.renderTarget = RenderTarget(m_surface->currentShadowSlot->framebuffer(), m_surface->intermediaryColorDescription), .renderTarget = RenderTarget(m_surface->currentShadowSlot->framebuffer(), m_surface->intermediaryColorDescription),
.repaint = infiniteRegion(), .repaint = bufferAgeEnabled ? m_surface->shadowDamageJournal.accumulate(m_surface->currentShadowSlot->age(), infiniteRegion()) : infiniteRegion(),
}; };
} else { } else {
m_surface->shadowSwapchain.reset(); m_surface->shadowSwapchain.reset();
m_surface->currentShadowSlot.reset(); m_surface->currentShadowSlot.reset();
return OutputLayerBeginFrameInfo{ return OutputLayerBeginFrameInfo{
.renderTarget = RenderTarget(m_surface->currentSlot->framebuffer(), m_surface->intermediaryColorDescription), .renderTarget = RenderTarget(m_surface->currentSlot->framebuffer(), m_surface->intermediaryColorDescription),
.repaint = repaint, .repaint = bufferAgeEnabled ? m_surface->damageJournal.accumulate(slot->age(), infiniteRegion()) : infiniteRegion(),
}; };
} }
} }
@ -188,6 +188,14 @@ std::optional<OutputLayerBeginFrameInfo> EglGbmLayerSurface::startRendering(cons
bool EglGbmLayerSurface::endRendering(const QRegion &damagedRegion, OutputFrame *frame) bool EglGbmLayerSurface::endRendering(const QRegion &damagedRegion, OutputFrame *frame)
{ {
if (m_surface->needsShadowBuffer) { if (m_surface->needsShadowBuffer) {
const QRegion logicalRepaint = damagedRegion | m_surface->damageJournal.accumulate(m_surface->currentSlot->age(), infiniteRegion());
m_surface->damageJournal.add(damagedRegion);
m_surface->shadowDamageJournal.add(damagedRegion);
QRegion repaint;
for (const QRect &rect : logicalRepaint) {
repaint |= scaledRect(rect, m_surface->scale).toAlignedRect();
}
GLFramebuffer *fbo = m_surface->currentSlot->framebuffer(); GLFramebuffer *fbo = m_surface->currentSlot->framebuffer();
GLFramebuffer::pushFramebuffer(fbo); GLFramebuffer::pushFramebuffer(fbo);
ShaderBinder binder = m_surface->iccShader ? ShaderBinder(m_surface->iccShader->shader()) : ShaderBinder(ShaderTrait::MapTexture | ShaderTrait::TransformColorspace); ShaderBinder binder = m_surface->iccShader ? ShaderBinder(m_surface->iccShader->shader()) : ShaderBinder(ShaderTrait::MapTexture | ShaderTrait::TransformColorspace);
@ -208,12 +216,13 @@ bool EglGbmLayerSurface::endRendering(const QRegion &damagedRegion, OutputFrame
mat.ortho(QRectF(QPointF(), fbo->size())); mat.ortho(QRectF(QPointF(), fbo->size()));
binder.shader()->setUniform(GLShader::Mat4Uniform::ModelViewProjectionMatrix, mat); binder.shader()->setUniform(GLShader::Mat4Uniform::ModelViewProjectionMatrix, mat);
glDisable(GL_BLEND); glDisable(GL_BLEND);
m_surface->currentShadowSlot->texture()->render(m_surface->gbmSwapchain->size()); m_surface->currentShadowSlot->texture()->render(repaint, m_surface->gbmSwapchain->size(), true);
EGLNativeFence fence(m_surface->context->displayObject()); EGLNativeFence fence(m_surface->context->displayObject());
m_surface->shadowSwapchain->release(m_surface->currentShadowSlot, fence.takeFileDescriptor()); m_surface->shadowSwapchain->release(m_surface->currentShadowSlot, fence.takeFileDescriptor());
GLFramebuffer::popFramebuffer(); GLFramebuffer::popFramebuffer();
} } else {
m_surface->damageJournal.add(damagedRegion); m_surface->damageJournal.add(damagedRegion);
}
m_surface->compositingTimeQuery->end(); m_surface->compositingTimeQuery->end();
if (frame) { if (frame) {
frame->addRenderTimeQuery(std::move(m_surface->compositingTimeQuery)); frame->addRenderTimeQuery(std::move(m_surface->compositingTimeQuery));
@ -281,6 +290,8 @@ void EglGbmLayerSurface::forgetDamage()
{ {
if (m_surface) { if (m_surface) {
m_surface->damageJournal.clear(); m_surface->damageJournal.clear();
m_surface->importDamageJournal.clear();
m_surface->shadowDamageJournal.clear();
} }
} }

View file

@ -106,6 +106,7 @@ private:
double brightness = 1.0; double brightness = 1.0;
std::unique_ptr<IccShader> iccShader; std::unique_ptr<IccShader> iccShader;
std::shared_ptr<IccProfile> iccProfile; std::shared_ptr<IccProfile> iccProfile;
DamageJournal shadowDamageJournal;
std::unique_ptr<GLRenderTimeQuery> compositingTimeQuery; std::unique_ptr<GLRenderTimeQuery> compositingTimeQuery;
}; };