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.
This commit is contained in:
Vlad Zahorodnii 2023-07-26 11:55:34 +03:00
parent 7d02bc17d6
commit 50bc9bb1f1
5 changed files with 40 additions and 13 deletions

View file

@ -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()) {

View file

@ -41,6 +41,8 @@ private Q_SLOTS:
void handleSurfaceCommitted();
void handleSurfaceSizeChanged();
void handleBufferSizeChanged();
void handleBufferSourceBoxChanged();
void handleBufferTransformChanged();
void handleChildSubSurfaceRemoved(KWaylandServer::SubSurfaceInterface *child);
void handleChildSubSurfacesChanged();

View file

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

View file

@ -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.
*/

View file

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