From 883acb1f5860be7a923eb01c86f47c4f1eb96c8e Mon Sep 17 00:00:00 2001 From: Vlad Zahorodnii Date: Sun, 24 Mar 2024 22:43:06 +0200 Subject: [PATCH] scene: Update surface texture in preprocess() If two items display image data, the item renderer needs to special case each item. It's not an extensible design, and my long term goal is to introduce a separate tree specifically to solve this problem and also help with computing the repaint damage automatically, instead of issuing scheduleRepaint()s manually. The first step is to refactor the item renderer so it merely takes the input data and renders it. At the moment, it's not exactly the case because surface textures are updated while painting the items, which inherently requires special casing. This change moves surface texture update code to the surface item so it's easier to refactor rendering code in the item renderer. --- .../scenes/opengl/openglsurfacetexture.h | 3 -- .../scenes/qpainter/qpaintersurfacetexture.h | 3 -- src/scene/itemrenderer_opengl.cpp | 32 ++----------------- src/scene/itemrenderer_qpainter.cpp | 6 ---- src/scene/surfaceitem.cpp | 15 +++++++++ src/scene/surfaceitem.h | 3 ++ 6 files changed, 20 insertions(+), 42 deletions(-) diff --git a/src/platformsupport/scenes/opengl/openglsurfacetexture.h b/src/platformsupport/scenes/opengl/openglsurfacetexture.h index e6815d6554..b2b26cd746 100644 --- a/src/platformsupport/scenes/opengl/openglsurfacetexture.h +++ b/src/platformsupport/scenes/opengl/openglsurfacetexture.h @@ -54,9 +54,6 @@ public: OpenGLBackend *backend() const; OpenGLSurfaceContents texture() const; - virtual bool create() = 0; - virtual void update(const QRegion ®ion) = 0; - protected: OpenGLBackend *m_backend; OpenGLSurfaceContents m_texture; diff --git a/src/platformsupport/scenes/qpainter/qpaintersurfacetexture.h b/src/platformsupport/scenes/qpainter/qpaintersurfacetexture.h index 862086cde1..710abccade 100644 --- a/src/platformsupport/scenes/qpainter/qpaintersurfacetexture.h +++ b/src/platformsupport/scenes/qpainter/qpaintersurfacetexture.h @@ -25,9 +25,6 @@ public: QPainterBackend *backend() const; QImage image() const; - virtual bool create() = 0; - virtual void update(const QRegion ®ion) = 0; - protected: QPainterBackend *m_backend; QImage m_image; diff --git a/src/scene/itemrenderer_opengl.cpp b/src/scene/itemrenderer_opengl.cpp index a2638ae1f2..541e2468e9 100644 --- a/src/scene/itemrenderer_opengl.cpp +++ b/src/scene/itemrenderer_opengl.cpp @@ -67,35 +67,6 @@ void ItemRendererOpenGL::setBlendEnabled(bool enabled) m_blendingEnabled = enabled; } -static OpenGLSurfaceContents bindSurfaceTexture(SurfaceItem *surfaceItem) -{ - SurfacePixmap *surfacePixmap = surfaceItem->pixmap(); - auto platformSurfaceTexture = - static_cast(surfacePixmap->texture()); - if (surfacePixmap->isDiscarded()) { - return platformSurfaceTexture->texture(); - } - - if (platformSurfaceTexture->texture().isValid()) { - const QRegion region = surfaceItem->damage(); - if (!region.isEmpty()) { - platformSurfaceTexture->update(region); - surfaceItem->resetDamage(); - } - } else { - if (!surfacePixmap->isValid()) { - return {}; - } - if (!platformSurfaceTexture->create()) { - qCDebug(KWIN_OPENGL) << "Failed to bind window"; - return {}; - } - surfaceItem->resetDamage(); - } - - return platformSurfaceTexture->texture(); -} - static RenderGeometry clipQuads(const Item *item, const ItemRendererOpenGL::RenderContext *context) { const WindowQuadList quads = item->quads(); @@ -201,8 +172,9 @@ void ItemRendererOpenGL::createRenderNode(Item *item, RenderContext *context) SurfacePixmap *pixmap = surfaceItem->pixmap(); if (pixmap) { if (!geometry.isEmpty()) { + OpenGLSurfaceTexture *surfaceTexture = static_cast(pixmap->texture()); context->renderNodes.append(RenderNode{ - .texture = bindSurfaceTexture(surfaceItem), + .texture = surfaceTexture->texture(), .geometry = geometry, .transformMatrix = context->transformStack.top(), .opacity = context->opacityStack.top(), diff --git a/src/scene/itemrenderer_qpainter.cpp b/src/scene/itemrenderer_qpainter.cpp index 048dbbc676..273259a53a 100644 --- a/src/scene/itemrenderer_qpainter.cpp +++ b/src/scene/itemrenderer_qpainter.cpp @@ -132,12 +132,6 @@ void ItemRendererQPainter::renderSurfaceItem(QPainter *painter, SurfaceItem *sur QPainterSurfaceTexture *platformSurfaceTexture = static_cast(surfaceTexture->texture()); - if (!platformSurfaceTexture->isValid()) { - platformSurfaceTexture->create(); - } else { - platformSurfaceTexture->update(surfaceItem->damage()); - } - surfaceItem->resetDamage(); const OutputTransform surfaceToBufferTransform = surfaceItem->bufferTransform(); const QSizeF transformedSize = surfaceToBufferTransform.map(surfaceItem->destinationSize()); diff --git a/src/scene/surfaceitem.cpp b/src/scene/surfaceitem.cpp index d62b289605..88a52a964a 100644 --- a/src/scene/surfaceitem.cpp +++ b/src/scene/surfaceitem.cpp @@ -216,6 +216,21 @@ void SurfaceItem::destroyPixmap() void SurfaceItem::preprocess() { updatePixmap(); + + if (SurfacePixmap *surfacePixmap = pixmap(); surfacePixmap && !surfacePixmap->isDiscarded()) { + SurfaceTexture *surfaceTexture = surfacePixmap->texture(); + if (surfaceTexture->isValid()) { + const QRegion region = damage(); + if (!region.isEmpty()) { + surfaceTexture->update(region); + resetDamage(); + } + } else if (surfacePixmap->isValid()) { + if (surfaceTexture->create()) { + resetDamage(); + } + } + } } WindowQuadList SurfaceItem::buildQuads() const diff --git a/src/scene/surfaceitem.h b/src/scene/surfaceitem.h index e614303c99..5b3b23729e 100644 --- a/src/scene/surfaceitem.h +++ b/src/scene/surfaceitem.h @@ -90,6 +90,9 @@ public: virtual ~SurfaceTexture(); virtual bool isValid() const = 0; + + virtual bool create() = 0; + virtual void update(const QRegion ®ion) = 0; }; class KWIN_EXPORT SurfacePixmap : public QObject