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.
This commit is contained in:
Vlad Zahorodnii 2024-03-24 22:43:06 +02:00
parent fdd338f02b
commit 883acb1f58
6 changed files with 20 additions and 42 deletions

View file

@ -54,9 +54,6 @@ public:
OpenGLBackend *backend() const;
OpenGLSurfaceContents texture() const;
virtual bool create() = 0;
virtual void update(const QRegion &region) = 0;
protected:
OpenGLBackend *m_backend;
OpenGLSurfaceContents m_texture;

View file

@ -25,9 +25,6 @@ public:
QPainterBackend *backend() const;
QImage image() const;
virtual bool create() = 0;
virtual void update(const QRegion &region) = 0;
protected:
QPainterBackend *m_backend;
QImage m_image;

View file

@ -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<OpenGLSurfaceTexture *>(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<OpenGLSurfaceTexture *>(pixmap->texture());
context->renderNodes.append(RenderNode{
.texture = bindSurfaceTexture(surfaceItem),
.texture = surfaceTexture->texture(),
.geometry = geometry,
.transformMatrix = context->transformStack.top(),
.opacity = context->opacityStack.top(),

View file

@ -132,12 +132,6 @@ void ItemRendererQPainter::renderSurfaceItem(QPainter *painter, SurfaceItem *sur
QPainterSurfaceTexture *platformSurfaceTexture =
static_cast<QPainterSurfaceTexture *>(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());

View file

@ -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

View file

@ -90,6 +90,9 @@ public:
virtual ~SurfaceTexture();
virtual bool isValid() const = 0;
virtual bool create() = 0;
virtual void update(const QRegion &region) = 0;
};
class KWIN_EXPORT SurfacePixmap : public QObject