From 50bc9bb1f1dfee8dcf8b7852e61bdcd8d6b41111 Mon Sep 17 00:00:00 2001 From: Vlad Zahorodnii Date: Wed, 26 Jul 2023 11:55:34 +0300 Subject: [PATCH] scene,wayland: Make tracking of the buffer source box less error prone At the moment, the SurfaceItem needs to track individual properties that may contribute to the buffer source box. That's error prone. To fix that, this change makes the SurfaceInterface indicate when the source box has changed and the SurfaceItem should sync its source box, discard quads, etc. --- src/scene/surfaceitem_wayland.cpp | 17 ++++++++++++++--- src/scene/surfaceitem_wayland.h | 2 ++ src/wayland/surface_interface.cpp | 31 +++++++++++++++++++++---------- src/wayland/surface_interface.h | 1 + src/wayland/surface_interface_p.h | 2 ++ 5 files changed, 40 insertions(+), 13 deletions(-) diff --git a/src/scene/surfaceitem_wayland.cpp b/src/scene/surfaceitem_wayland.cpp index 6303298710..8f7591ad99 100644 --- a/src/scene/surfaceitem_wayland.cpp +++ b/src/scene/surfaceitem_wayland.cpp @@ -27,6 +27,10 @@ SurfaceItemWayland::SurfaceItemWayland(KWaylandServer::SurfaceInterface *surface this, &SurfaceItemWayland::handleSurfaceSizeChanged); connect(surface, &KWaylandServer::SurfaceInterface::bufferSizeChanged, this, &SurfaceItemWayland::handleBufferSizeChanged); + connect(surface, &KWaylandServer::SurfaceInterface::bufferSourceBoxChanged, + this, &SurfaceItemWayland::handleBufferSourceBoxChanged); + connect(surface, &KWaylandServer::SurfaceInterface::bufferTransformChanged, + this, &SurfaceItemWayland::handleBufferTransformChanged); connect(surface, &KWaylandServer::SurfaceInterface::childSubSurfacesChanged, this, &SurfaceItemWayland::handleChildSubSurfacesChanged); @@ -77,8 +81,6 @@ KWaylandServer::SurfaceInterface *SurfaceItemWayland::surface() const void SurfaceItemWayland::handleSurfaceToBufferMatrixChanged() { - setBufferTransform(m_surface->bufferTransform()); - setBufferSourceBox(m_surface->bufferSourceBox()); setSurfaceToBufferMatrix(m_surface->surfaceToBufferMatrix()); discardQuads(); discardPixmap(); @@ -91,11 +93,20 @@ void SurfaceItemWayland::handleSurfaceSizeChanged() void SurfaceItemWayland::handleBufferSizeChanged() { - setBufferSourceBox(m_surface->bufferSourceBox()); setBufferSize(m_surface->bufferSize()); discardPixmap(); } +void SurfaceItemWayland::handleBufferSourceBoxChanged() +{ + setBufferSourceBox(m_surface->bufferSourceBox()); +} + +void SurfaceItemWayland::handleBufferTransformChanged() +{ + setBufferTransform(m_surface->bufferTransform()); +} + void SurfaceItemWayland::handleSurfaceCommitted() { if (m_surface->hasFrameCallbacks()) { diff --git a/src/scene/surfaceitem_wayland.h b/src/scene/surfaceitem_wayland.h index a8eeb61d29..22a5b1ff2c 100644 --- a/src/scene/surfaceitem_wayland.h +++ b/src/scene/surfaceitem_wayland.h @@ -41,6 +41,8 @@ private Q_SLOTS: void handleSurfaceCommitted(); void handleSurfaceSizeChanged(); void handleBufferSizeChanged(); + void handleBufferSourceBoxChanged(); + void handleBufferTransformChanged(); void handleChildSubSurfaceRemoved(KWaylandServer::SubSurfaceInterface *child); void handleChildSubSurfacesChanged(); diff --git a/src/wayland/surface_interface.cpp b/src/wayland/surface_interface.cpp index 94d46ef195..144ad6bde2 100644 --- a/src/wayland/surface_interface.cpp +++ b/src/wayland/surface_interface.cpp @@ -476,6 +476,20 @@ QMatrix4x4 SurfaceInterfacePrivate::buildSurfaceToBufferMatrix() return surfaceToBufferMatrix; } +QRectF SurfaceInterfacePrivate::computeBufferSourceBox() const +{ + if (!current.viewport.sourceGeometry.isValid()) { + return QRectF(0, 0, bufferSize.width(), bufferSize.height()); + } + + const QRectF box(current.viewport.sourceGeometry.x() * current.bufferScale, + current.viewport.sourceGeometry.y() * current.bufferScale, + current.viewport.sourceGeometry.width() * current.bufferScale, + current.viewport.sourceGeometry.height() * current.bufferScale); + + return current.bufferTransform.inverted().map(box, bufferSize); +} + void SurfaceState::mergeInto(SurfaceState *target) { if (bufferIsSet) { @@ -561,6 +575,7 @@ void SurfaceInterfacePrivate::applyState(SurfaceState *next) const QSizeF oldSurfaceSize = surfaceSize; const QSize oldBufferSize = bufferSize; + const QRectF oldBufferSourceBox = bufferSourceBox; const QMatrix4x4 oldSurfaceToBufferMatrix = surfaceToBufferMatrix; const QRegion oldInputRegion = inputRegion; @@ -571,6 +586,7 @@ void SurfaceInterfacePrivate::applyState(SurfaceState *next) // TODO: Refactor the state management code because it gets more clumsy. if (current.buffer) { bufferSize = current.buffer->size(); + bufferSourceBox = computeBufferSourceBox(); implicitSurfaceSize = current.buffer->size() / current.bufferScale; switch (current.bufferTransform.kind()) { @@ -617,6 +633,7 @@ void SurfaceInterfacePrivate::applyState(SurfaceState *next) surfaceSize = QSizeF(0, 0); implicitSurfaceSize = QSizeF(0, 0); bufferSize = QSize(0, 0); + bufferSourceBox = QRectF(); inputRegion = QRegion(); opaqueRegion = QRegion(); } @@ -647,6 +664,9 @@ void SurfaceInterfacePrivate::applyState(SurfaceState *next) if (surfaceToBufferMatrix != oldSurfaceToBufferMatrix) { Q_EMIT q->surfaceToBufferMatrixChanged(); } + if (bufferSourceBox != oldBufferSourceBox) { + Q_EMIT q->bufferSourceBoxChanged(); + } if (bufferSize != oldBufferSize) { Q_EMIT q->bufferSizeChanged(); } @@ -787,16 +807,7 @@ QRegion SurfaceInterface::input() const QRectF SurfaceInterface::bufferSourceBox() const { - if (!d->current.viewport.sourceGeometry.isValid()) { - return QRectF(0, 0, d->bufferSize.width(), d->bufferSize.height()); - } - - const QRectF box(d->current.viewport.sourceGeometry.x() * d->current.bufferScale, - d->current.viewport.sourceGeometry.y() * d->current.bufferScale, - d->current.viewport.sourceGeometry.width() * d->current.bufferScale, - d->current.viewport.sourceGeometry.height() * d->current.bufferScale); - - return d->current.bufferTransform.inverted().map(box, d->bufferSize); + return d->bufferSourceBox; } KWin::OutputTransform SurfaceInterface::bufferTransform() const diff --git a/src/wayland/surface_interface.h b/src/wayland/surface_interface.h index 8fc8a25964..e36f80e240 100644 --- a/src/wayland/surface_interface.h +++ b/src/wayland/surface_interface.h @@ -371,6 +371,7 @@ Q_SIGNALS: * This signal is emitted when the buffer transform has changed. */ void bufferTransformChanged(KWin::OutputTransform); + void bufferSourceBoxChanged(); /** * This signal is emitted when the size of the attached buffer has changed. */ diff --git a/src/wayland/surface_interface_p.h b/src/wayland/surface_interface_p.h index c4ce0bcdfc..799a9dae81 100644 --- a/src/wayland/surface_interface_p.h +++ b/src/wayland/surface_interface_p.h @@ -99,6 +99,7 @@ public: void commitSubSurface(); QMatrix4x4 buildSurfaceToBufferMatrix(); + QRectF computeBufferSourceBox() const; void applyState(SurfaceState *next); bool computeEffectiveMapped() const; @@ -120,6 +121,7 @@ public: SubSurfaceInterface *subSurface = nullptr; QMatrix4x4 surfaceToBufferMatrix; QSize bufferSize = QSize(0, 0); + QRectF bufferSourceBox; QSizeF implicitSurfaceSize = QSizeF(0, 0); QSizeF surfaceSize = QSizeF(0, 0);