scene: Fix SurfaceItem::bufferTransform()

The wayland spec is not quite clear about the transforms, but the buffer
transform indicates a transform from wl_surface to wl_buffer or compositor
global coordinate space to composited buffer.

On the other hand, SurfaceItem assumes that the order is vice versa.
This commit is contained in:
Vlad Zahorodnii 2023-12-20 22:15:38 +02:00
parent f8df72497f
commit 6510fe6e5d
16 changed files with 85 additions and 231 deletions

View file

@ -289,7 +289,7 @@ void TestWaylandSurface::testDamage()
{
const QRegion surfaceDamage = QRegion(5, 8, 3, 6).united(QRect(10, 11, 6, 1));
const QRegion expectedDamage = QRegion(10, 16, 6, 12).united(QRect(20, 22, 12, 2));
QImage img(QSize(40, 35), QImage::Format_ARGB32_Premultiplied);
QImage img(QSize(80, 70), QImage::Format_ARGB32_Premultiplied);
img.fill(Qt::black);
auto b = m_shm->createBuffer(img);
s->attachBuffer(b);

View file

@ -143,7 +143,7 @@ void TestViewporterInterface::testCropScale()
QSignalSpy serverSurfaceMappedSpy(serverSurface, &SurfaceInterface::mapped);
QSignalSpy serverSurfaceSizeChangedSpy(serverSurface, &SurfaceInterface::sizeChanged);
QSignalSpy surfaceToBufferMatrixChangedSpy(serverSurface, &SurfaceInterface::surfaceToBufferMatrixChanged);
QSignalSpy bufferSourceBoxChangedSpy(serverSurface, &SurfaceInterface::bufferSourceBoxChanged);
// Map the surface.
QImage image(QSize(200, 100), QImage::Format_ARGB32_Premultiplied);
@ -154,9 +154,9 @@ void TestViewporterInterface::testCropScale()
clientSurface->damage(image.rect());
clientSurface->commit(KWayland::Client::Surface::CommitFlag::None);
QVERIFY(serverSurfaceMappedSpy.wait());
QCOMPARE(surfaceToBufferMatrixChangedSpy.count(), 1);
QCOMPARE(bufferSourceBoxChangedSpy.count(), 1);
QCOMPARE(serverSurface->size(), QSize(100, 50));
QCOMPARE(serverSurface->mapToBuffer(QPointF(0, 0)), QPointF(0, 0));
QCOMPARE(serverSurface->bufferSourceBox(), QRectF(0, 0, 200, 100));
// Create a viewport for the surface.
std::unique_ptr<Viewport> clientViewport(new Viewport);
@ -166,25 +166,25 @@ void TestViewporterInterface::testCropScale()
clientViewport->set_source(wl_fixed_from_double(10), wl_fixed_from_double(10), wl_fixed_from_double(30), wl_fixed_from_double(20));
clientSurface->commit(KWayland::Client::Surface::CommitFlag::None);
QVERIFY(serverSurfaceSizeChangedSpy.wait());
QCOMPARE(surfaceToBufferMatrixChangedSpy.count(), 2);
QCOMPARE(bufferSourceBoxChangedSpy.count(), 2);
QCOMPARE(serverSurface->size(), QSize(30, 20));
QCOMPARE(serverSurface->mapToBuffer(QPointF(0, 0)), QPointF(20, 20));
QCOMPARE(serverSurface->bufferSourceBox(), QRectF(20, 20, 60, 40));
// Scale the surface.
clientViewport->set_destination(500, 250);
clientSurface->commit(KWayland::Client::Surface::CommitFlag::None);
QVERIFY(serverSurfaceSizeChangedSpy.wait());
QCOMPARE(surfaceToBufferMatrixChangedSpy.count(), 3);
QCOMPARE(bufferSourceBoxChangedSpy.count(), 2);
QCOMPARE(serverSurface->size(), QSize(500, 250));
QCOMPARE(serverSurface->mapToBuffer(QPointF(0, 0)), QPointF(20, 20));
QCOMPARE(serverSurface->bufferSourceBox(), QRectF(20, 20, 60, 40));
// If the viewport is destroyed, the crop and scale state will be unset on a next commit.
clientViewport->destroy();
clientSurface->commit(KWayland::Client::Surface::CommitFlag::None);
QVERIFY(serverSurfaceSizeChangedSpy.wait());
QCOMPARE(surfaceToBufferMatrixChangedSpy.count(), 4);
QCOMPARE(bufferSourceBoxChangedSpy.count(), 3);
QCOMPARE(serverSurface->size(), QSize(100, 50));
QCOMPARE(serverSurface->mapToBuffer(QPointF(0, 0)), QPointF(0, 0));
QCOMPARE(serverSurface->bufferSourceBox(), QRectF(0, 0, 200, 100));
}
QTEST_GUILESS_MAIN(TestViewporterInterface)

View file

@ -139,7 +139,7 @@ void ItemRendererQPainter::renderSurfaceItem(QPainter *painter, SurfaceItem *sur
}
surfaceItem->resetDamage();
const OutputTransform surfaceToBufferTransform = surfaceItem->bufferTransform().inverted();
const OutputTransform surfaceToBufferTransform = surfaceItem->bufferTransform();
const QSizeF transformedSize = surfaceToBufferTransform.map(surfaceItem->size());
painter->save();
@ -147,34 +147,34 @@ void ItemRendererQPainter::renderSurfaceItem(QPainter *painter, SurfaceItem *sur
case OutputTransform::Normal:
break;
case OutputTransform::Rotate90:
painter->translate(0, transformedSize.width());
painter->rotate(-90);
painter->translate(transformedSize.height(), 0);
painter->rotate(90);
break;
case OutputTransform::Rotate180:
painter->translate(transformedSize.width(), transformedSize.height());
painter->rotate(-180);
painter->rotate(180);
break;
case OutputTransform::Rotate270:
painter->translate(transformedSize.height(), 0);
painter->rotate(-270);
painter->translate(0, transformedSize.width());
painter->rotate(270);
break;
case OutputTransform::FlipX:
painter->translate(transformedSize.width(), 0);
painter->scale(-1, 1);
break;
case OutputTransform::FlipX90:
painter->rotate(-90);
painter->scale(-1, 1);
painter->rotate(90);
break;
case OutputTransform::FlipX180:
painter->translate(0, transformedSize.height());
painter->rotate(-180);
painter->scale(-1, 1);
painter->rotate(180);
break;
case OutputTransform::FlipX270:
painter->translate(transformedSize.height(), transformedSize.width());
painter->rotate(-270);
painter->scale(-1, 1);
painter->rotate(270);
break;
}

View file

@ -5,6 +5,7 @@
*/
#include "scene/surfaceitem.h"
#include "core/pixelgrid.h"
#include "scene/scene.h"
namespace KWin
@ -15,17 +16,6 @@ SurfaceItem::SurfaceItem(Scene *scene, Item *parent)
{
}
QMatrix4x4 SurfaceItem::surfaceToBufferMatrix() const
{
return m_surfaceToBufferMatrix;
}
void SurfaceItem::setSurfaceToBufferMatrix(const QMatrix4x4 &matrix)
{
m_surfaceToBufferMatrix = matrix;
m_bufferToSurfaceMatrix = matrix.inverted();
}
QRectF SurfaceItem::bufferSourceBox() const
{
return m_bufferSourceBox;
@ -33,17 +23,24 @@ QRectF SurfaceItem::bufferSourceBox() const
void SurfaceItem::setBufferSourceBox(const QRectF &box)
{
m_bufferSourceBox = box;
if (m_bufferSourceBox != box) {
m_bufferSourceBox = box;
discardQuads();
}
}
OutputTransform SurfaceItem::bufferTransform() const
{
return m_bufferTransform;
return m_surfaceToBufferTransform;
}
void SurfaceItem::setBufferTransform(OutputTransform transform)
{
m_bufferTransform = transform;
if (m_surfaceToBufferTransform != transform) {
m_surfaceToBufferTransform = transform;
m_bufferToSurfaceTransform = transform.inverted();
discardQuads();
}
}
QSize SurfaceItem::bufferSize() const
@ -53,14 +50,23 @@ QSize SurfaceItem::bufferSize() const
void SurfaceItem::setBufferSize(const QSize &size)
{
m_bufferSize = size;
if (m_bufferSize != size) {
m_bufferSize = size;
discardPixmap();
discardQuads();
}
}
QRegion SurfaceItem::mapFromBuffer(const QRegion &region) const
{
const QRectF sourceBox = m_bufferToSurfaceTransform.map(m_bufferSourceBox, m_bufferSize);
const qreal xScale = size().width() / sourceBox.width();
const qreal yScale = size().height() / sourceBox.height();
QRegion result;
for (const QRect &rect : region) {
result += m_bufferToSurfaceMatrix.mapRect(QRectF(rect)).toAlignedRect();
for (QRectF rect : region) {
const QRectF r = m_bufferToSurfaceTransform.map(rect, m_bufferSize).translated(-sourceBox.topLeft());
result += QRectF(r.x() * xScale, r.y() * yScale, r.width() * xScale, r.height() * yScale).toAlignedRect();
}
return result;
}
@ -93,7 +99,7 @@ void SurfaceItem::addDamage(const QRegion &region)
m_lastDamage = std::chrono::steady_clock::now();
m_damage += region;
const QRectF sourceBox = m_bufferTransform.map(m_bufferSourceBox, m_bufferSize);
const QRectF sourceBox = m_bufferToSurfaceTransform.map(m_bufferSourceBox, m_bufferSize);
const qreal xScale = sourceBox.width() / size().width();
const qreal yScale = sourceBox.height() / size().height();
const QRegion logicalDamage = mapFromBuffer(region);
@ -204,27 +210,25 @@ WindowQuadList SurfaceItem::buildQuads() const
}
const QList<QRectF> region = shape();
const auto size = pixmap()->size();
WindowQuadList quads;
quads.reserve(region.count());
const QRectF sourceBox = m_bufferToSurfaceTransform.map(m_bufferSourceBox, m_bufferSize);
const qreal xScale = sourceBox.width() / size().width();
const qreal yScale = sourceBox.height() / size().height();
for (const QRectF rect : region) {
WindowQuad quad;
// Use toPoint to round the device position to match what we eventually
// do for the geometry, otherwise we end up with mismatched UV
// coordinates as the texture size is going to be in (rounded) device
// coordinates as well.
const QPointF bufferTopLeft = m_surfaceToBufferMatrix.map(rect.topLeft()).toPoint();
const QPointF bufferTopRight = m_surfaceToBufferMatrix.map(rect.topRight()).toPoint();
const QPointF bufferBottomRight = m_surfaceToBufferMatrix.map(rect.bottomRight()).toPoint();
const QPointF bufferBottomLeft = m_surfaceToBufferMatrix.map(rect.bottomLeft()).toPoint();
const QPointF bufferTopLeft = snapToPixelGridF(m_bufferSourceBox.topLeft() + m_surfaceToBufferTransform.map(QPointF(rect.left() * xScale, rect.top() * yScale), sourceBox.size()));
const QPointF bufferTopRight = snapToPixelGridF(m_bufferSourceBox.topLeft() + m_surfaceToBufferTransform.map(QPointF(rect.right() * xScale, rect.top() * yScale), sourceBox.size()));
const QPointF bufferBottomRight = snapToPixelGridF(m_bufferSourceBox.topLeft() + m_surfaceToBufferTransform.map(QPointF(rect.right() * xScale, rect.bottom() * yScale), sourceBox.size()));
const QPointF bufferBottomLeft = snapToPixelGridF(m_bufferSourceBox.topLeft() + m_surfaceToBufferTransform.map(QPointF(rect.left() * xScale, rect.bottom() * yScale), sourceBox.size()));
quad[0] = WindowVertex(rect.topLeft(), QPointF{bufferTopLeft.x() / size.width(), bufferTopLeft.y() / size.height()});
quad[1] = WindowVertex(rect.topRight(), QPointF{bufferTopRight.x() / size.width(), bufferTopRight.y() / size.height()});
quad[2] = WindowVertex(rect.bottomRight(), QPointF{bufferBottomRight.x() / size.width(), bufferBottomRight.y() / size.height()});
quad[3] = WindowVertex(rect.bottomLeft(), QPointF{bufferBottomLeft.x() / size.width(), bufferBottomLeft.y() / size.height()});
quad[0] = WindowVertex(rect.topLeft(), QPointF{bufferTopLeft.x() / m_bufferSize.width(), bufferTopLeft.y() / m_bufferSize.height()});
quad[1] = WindowVertex(rect.topRight(), QPointF{bufferTopRight.x() / m_bufferSize.width(), bufferTopRight.y() / m_bufferSize.height()});
quad[2] = WindowVertex(rect.bottomRight(), QPointF{bufferBottomRight.x() / m_bufferSize.width(), bufferBottomRight.y() / m_bufferSize.height()});
quad[3] = WindowVertex(rect.bottomLeft(), QPointF{bufferBottomLeft.x() / m_bufferSize.width(), bufferBottomLeft.y() / m_bufferSize.height()});
quads << quad;
}

View file

@ -26,9 +26,6 @@ class KWIN_EXPORT SurfaceItem : public Item
Q_OBJECT
public:
QMatrix4x4 surfaceToBufferMatrix() const;
void setSurfaceToBufferMatrix(const QMatrix4x4 &matrix);
QRectF bufferSourceBox() const;
void setBufferSourceBox(const QRectF &box);
@ -71,13 +68,12 @@ protected:
WindowQuadList buildQuads() const override;
QRegion m_damage;
OutputTransform m_bufferTransform;
OutputTransform m_bufferToSurfaceTransform;
OutputTransform m_surfaceToBufferTransform;
QRectF m_bufferSourceBox;
QSize m_bufferSize;
std::unique_ptr<SurfacePixmap> m_pixmap;
std::unique_ptr<SurfacePixmap> m_previousPixmap;
QMatrix4x4 m_surfaceToBufferMatrix;
QMatrix4x4 m_bufferToSurfaceMatrix;
int m_referencePixmapCounter = 0;
std::deque<std::chrono::nanoseconds> m_lastDamageTimeDiffs;
std::optional<std::chrono::steady_clock::time_point> m_lastDamage;

View file

@ -20,13 +20,8 @@ SurfaceItemInternal::SurfaceItemInternal(InternalWindow *window, Scene *scene, I
this, &SurfaceItemInternal::handleBufferGeometryChanged);
setSize(window->bufferGeometry().size());
setBufferSourceBox(QRectF(QPointF(0, 0), window->bufferGeometry().size()));
setBufferSourceBox(QRectF(QPointF(0, 0), window->bufferGeometry().size() * window->bufferScale()));
setBufferSize((window->bufferGeometry().size() * window->bufferScale()).toSize());
// The device pixel ratio of the internal window is static.
QMatrix4x4 surfaceToBufferMatrix;
surfaceToBufferMatrix.scale(window->bufferScale());
setSurfaceToBufferMatrix(surfaceToBufferMatrix);
}
InternalWindow *SurfaceItemInternal::window() const
@ -44,13 +39,10 @@ std::unique_ptr<SurfacePixmap> SurfaceItemInternal::createPixmap()
return std::make_unique<SurfacePixmapInternal>(this);
}
void SurfaceItemInternal::handleBufferGeometryChanged(const QRectF &old)
void SurfaceItemInternal::handleBufferGeometryChanged()
{
if (m_window->bufferGeometry().size() != old.size()) {
discardPixmap();
}
setSize(m_window->bufferGeometry().size());
setBufferSourceBox(QRectF(QPointF(0, 0), m_window->bufferGeometry().size()));
setBufferSourceBox(QRectF(QPointF(0, 0), m_window->bufferGeometry().size() * m_window->bufferScale()));
setBufferSize((m_window->bufferGeometry().size() * m_window->bufferScale()).toSize());
}

View file

@ -28,7 +28,7 @@ public:
QList<QRectF> shape() const override;
private Q_SLOTS:
void handleBufferGeometryChanged(const QRectF &old);
void handleBufferGeometryChanged();
protected:
std::unique_ptr<SurfacePixmap> createPixmap() override;

View file

@ -20,9 +20,6 @@ SurfaceItemWayland::SurfaceItemWayland(SurfaceInterface *surface, Scene *scene,
: SurfaceItem(scene, parent)
, m_surface(surface)
{
connect(surface, &SurfaceInterface::surfaceToBufferMatrixChanged,
this, &SurfaceItemWayland::handleSurfaceToBufferMatrixChanged);
connect(surface, &SurfaceInterface::sizeChanged,
this, &SurfaceItemWayland::handleSurfaceSizeChanged);
connect(surface, &SurfaceInterface::bufferSizeChanged,
@ -62,7 +59,6 @@ SurfaceItemWayland::SurfaceItemWayland(SurfaceInterface *surface, Scene *scene,
setBufferTransform(surface->bufferTransform());
setBufferSourceBox(surface->bufferSourceBox());
setBufferSize(surface->bufferSize());
setSurfaceToBufferMatrix(surface->surfaceToBufferMatrix());
setColorDescription(surface->colorDescription());
}
@ -84,22 +80,15 @@ SurfaceInterface *SurfaceItemWayland::surface() const
return m_surface;
}
void SurfaceItemWayland::handleSurfaceToBufferMatrixChanged()
{
setSurfaceToBufferMatrix(m_surface->surfaceToBufferMatrix());
discardQuads();
discardPixmap();
}
void SurfaceItemWayland::handleSurfaceSizeChanged()
{
setSize(m_surface->size());
discardQuads();
}
void SurfaceItemWayland::handleBufferSizeChanged()
{
setBufferSize(m_surface->bufferSize());
discardPixmap();
}
void SurfaceItemWayland::handleBufferSourceBoxChanged()

View file

@ -36,7 +36,6 @@ public:
SurfaceInterface *surface() const;
private Q_SLOTS:
void handleSurfaceToBufferMatrixChanged();
void handleSurfaceCommitted();
void handleSurfaceSizeChanged();
void handleBufferSizeChanged();

View file

@ -140,11 +140,8 @@ void SurfaceItemX11::destroyDamage()
}
}
void SurfaceItemX11::handleBufferGeometryChanged(const QRectF &old)
void SurfaceItemX11::handleBufferGeometryChanged()
{
if (m_window->bufferGeometry().size() != old.size()) {
discardPixmap();
}
setSize(m_window->bufferGeometry().size());
setBufferSourceBox(QRectF(QPointF(0, 0), m_window->bufferGeometry().size()));
setBufferSize(m_window->bufferGeometry().size().toSize());

View file

@ -41,7 +41,7 @@ public:
QRegion opaque() const override;
private Q_SLOTS:
void handleBufferGeometryChanged(const QRectF &old);
void handleBufferGeometryChanged();
void handleShapeChanged();
protected:

View file

@ -33,8 +33,6 @@ void SubSurfaceMonitor::registerSubSurface(SubSurfaceInterface *subSurface)
this, &SubSurfaceMonitor::subSurfaceMapped);
connect(surface, &SurfaceInterface::unmapped,
this, &SubSurfaceMonitor::subSurfaceUnmapped);
connect(surface, &SurfaceInterface::surfaceToBufferMatrixChanged,
this, &SubSurfaceMonitor::subSurfaceSurfaceToBufferMatrixChanged);
connect(surface, &SurfaceInterface::bufferSizeChanged,
this, &SubSurfaceMonitor::subSurfaceBufferSizeChanged);
connect(surface, &SurfaceInterface::committed,

View file

@ -59,11 +59,6 @@ Q_SIGNALS:
* This signal is emitted when a sub-surface is unmapped.
*/
void subSurfaceUnmapped();
/**
* This signal is emitted when the mapping between the surface-local coordinate space
* and the buffer coordinate space for a sub-surface has changed.
*/
void subSurfaceSurfaceToBufferMatrixChanged();
/**
* This signal is emitted when the buffer size of a subsurface has changed.
*/

View file

@ -482,73 +482,6 @@ bool SurfaceInterface::hasFrameCallbacks() const
return !wl_list_empty(&d->current->frameCallbacks);
}
QMatrix4x4 SurfaceInterfacePrivate::buildSurfaceToBufferMatrix()
{
// The order of transforms is reversed, i.e. the viewport transform is the first one.
QMatrix4x4 surfaceToBufferMatrix;
if (!current->buffer) {
return surfaceToBufferMatrix;
}
surfaceToBufferMatrix.scale(current->bufferScale, current->bufferScale);
surfaceToBufferMatrix.scale(scaleOverride, scaleOverride);
switch (current->bufferTransform.kind()) {
case OutputTransform::Normal:
case OutputTransform::FlipX:
break;
case OutputTransform::Rotate90:
case OutputTransform::FlipX90:
surfaceToBufferMatrix.translate(0, bufferSize.height() / current->bufferScale);
surfaceToBufferMatrix.rotate(-90, 0, 0, 1);
break;
case OutputTransform::Rotate180:
case OutputTransform::FlipX180:
surfaceToBufferMatrix.translate(bufferSize.width() / current->bufferScale, bufferSize.height() / current->bufferScale);
surfaceToBufferMatrix.rotate(-180, 0, 0, 1);
break;
case OutputTransform::Rotate270:
case OutputTransform::FlipX270:
surfaceToBufferMatrix.translate(bufferSize.width() / current->bufferScale, 0);
surfaceToBufferMatrix.rotate(-270, 0, 0, 1);
break;
}
switch (current->bufferTransform.kind()) {
case OutputTransform::FlipX:
case OutputTransform::FlipX180:
surfaceToBufferMatrix.translate(bufferSize.width() / current->bufferScale, 0);
surfaceToBufferMatrix.scale(-1, 1);
break;
case OutputTransform::FlipX90:
case OutputTransform::FlipX270:
surfaceToBufferMatrix.translate(bufferSize.height() / current->bufferScale, 0);
surfaceToBufferMatrix.scale(-1, 1);
break;
default:
break;
}
if (current->viewport.sourceGeometry.isValid()) {
surfaceToBufferMatrix.translate(current->viewport.sourceGeometry.x(), current->viewport.sourceGeometry.y());
}
QSizeF sourceSize;
if (current->viewport.sourceGeometry.isValid()) {
sourceSize = current->viewport.sourceGeometry.size();
} else {
sourceSize = implicitSurfaceSize;
}
if (sourceSize != surfaceSize) {
surfaceToBufferMatrix.scale(sourceSize.width() / surfaceSize.width(), sourceSize.height() / surfaceSize.height());
}
return surfaceToBufferMatrix;
}
QRectF SurfaceInterfacePrivate::computeBufferSourceBox() const
{
if (!current->viewport.sourceGeometry.isValid()) {
@ -561,7 +494,7 @@ QRectF SurfaceInterfacePrivate::computeBufferSourceBox() const
current->viewport.sourceGeometry.width() * current->bufferScale,
current->viewport.sourceGeometry.height() * current->bufferScale);
return current->bufferTransform.inverted().map(box, bounds);
return current->bufferTransform.map(box, bounds);
}
SurfaceState::SurfaceState()
@ -676,7 +609,6 @@ 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;
if (!next->damage.isEmpty() || !next->bufferDamage.isEmpty()) {
@ -689,14 +621,13 @@ void SurfaceInterfacePrivate::applyState(SurfaceState *next)
if (current->buffer) {
bufferSize = current->buffer->size();
bufferSourceBox = computeBufferSourceBox();
implicitSurfaceSize = current->bufferTransform.map(current->buffer->size() / current->bufferScale);
if (current->viewport.destinationSize.isValid()) {
surfaceSize = current->viewport.destinationSize;
} else if (current->viewport.sourceGeometry.isValid()) {
surfaceSize = current->viewport.sourceGeometry.size();
} else {
surfaceSize = implicitSurfaceSize;
surfaceSize = current->bufferTransform.map(current->buffer->size() / current->bufferScale);
}
const QRectF surfaceRect(QPoint(0, 0), surfaceSize);
@ -716,18 +647,14 @@ void SurfaceInterfacePrivate::applyState(SurfaceState *next)
opaqueRegion = map_helper(scaleOverrideMatrix, opaqueRegion);
inputRegion = map_helper(scaleOverrideMatrix, inputRegion);
surfaceSize = surfaceSize / scaleOverride;
implicitSurfaceSize = implicitSurfaceSize / scaleOverride;
} else {
surfaceSize = QSizeF(0, 0);
implicitSurfaceSize = QSizeF(0, 0);
bufferSize = QSize(0, 0);
bufferSourceBox = QRectF();
inputRegion = QRegion();
opaqueRegion = QRegion();
}
surfaceToBufferMatrix = buildSurfaceToBufferMatrix();
if (opaqueRegionChanged) {
Q_EMIT q->opaqueChanged(opaqueRegion);
}
@ -740,9 +667,6 @@ void SurfaceInterfacePrivate::applyState(SurfaceState *next)
if (visibilityChanged) {
updateEffectiveMapped();
}
if (surfaceToBufferMatrix != oldSurfaceToBufferMatrix) {
Q_EMIT q->surfaceToBufferMatrixChanged();
}
if (bufferSourceBox != oldBufferSourceBox) {
Q_EMIT q->bufferSourceBoxChanged();
}
@ -778,7 +702,7 @@ void SurfaceInterfacePrivate::applyState(SurfaceState *next)
if (current->buffer && (!current->damage.isEmpty() || !current->bufferDamage.isEmpty())) {
const QRect bufferRect = QRect(QPoint(0, 0), current->buffer->size());
bufferDamage = current->bufferDamage
.united(q->mapToBuffer(current->damage))
.united(mapToBuffer(current->damage))
.intersected(bufferRect);
Q_EMIT q->damaged(bufferDamage);
}
@ -846,6 +770,23 @@ bool SurfaceInterfacePrivate::inputContains(const QPointF &position) const
return contains(position) && inputRegion.contains(QPoint(std::floor(position.x()), std::floor(position.y())));
}
QRegion SurfaceInterfacePrivate::mapToBuffer(const QRegion &region) const
{
if (region.isEmpty()) {
return QRegion();
}
const QRectF sourceBox = current->bufferTransform.inverted().map(bufferSourceBox, bufferSize);
const qreal xScale = sourceBox.width() / surfaceSize.width();
const qreal yScale = sourceBox.height() / surfaceSize.height();
QRegion result;
for (QRectF rect : region) {
result += current->bufferTransform.map(QRectF(rect.x() * xScale, rect.y() * yScale, rect.width() * xScale, rect.height() * yScale), sourceBox.size()).translated(bufferSourceBox.topLeft()).toAlignedRect();
}
return result;
}
QRegion SurfaceInterface::bufferDamage() const
{
return d->bufferDamage;
@ -1101,21 +1042,6 @@ ContentType SurfaceInterface::contentType() const
return d->current->contentType;
}
QPointF SurfaceInterface::mapToBuffer(const QPointF &point) const
{
return d->surfaceToBufferMatrix.map(point);
}
QRegion SurfaceInterface::mapToBuffer(const QRegion &region) const
{
return map_helper(d->surfaceToBufferMatrix, region);
}
QMatrix4x4 SurfaceInterface::surfaceToBufferMatrix() const
{
return d->surfaceToBufferMatrix;
}
QPointF SurfaceInterface::mapToChild(SurfaceInterface *child, const QPointF &point) const
{
QPointF local = point;

View file

@ -10,7 +10,6 @@
#include "core/output.h"
#include "core/renderbackend.h"
#include <QMatrix4x4>
#include <QObject>
#include <QRegion>
@ -118,37 +117,6 @@ public:
SurfaceRole *role() const;
void setRole(SurfaceRole *role);
/**
* Maps the specified @a point from the surface-local coordinates to buffer pixel coordinates.
*
* Note that there is no direct connection between points in the surface-local coordinates
* and points in the buffer pixel coordinates. In order to map points between the two spaces,
* one has to use mapToBuffer() and mapFromBuffer().
*
* The returned value will become invalid when the surfaceToBufferMatrixChanged() signal is emitted.
*
* @see surfaceToBufferMatrix(), surfaceToBufferMatrixChanged()
*/
QPointF mapToBuffer(const QPointF &point) const;
/**
* Maps the specified @a region from the surface-local coordinates to buffer pixel coordinates.
*
* Note that there is no direct connection between regions in the surface-local coordinates
* and regions in the buffer pixel coordinates. In order to map regions between the two spaces,
* one has to use mapToBuffer() and mapFromBuffer().
*
* The returned value will become invalid when the surfaceToBufferMatrixChanged() signal is emitted.
*
* @see surfaceToBufferMatrix(), surfaceToBufferMatrixChanged()
*/
QRegion mapToBuffer(const QRegion &region) const;
/**
* Returns the projection matrix from the surface-local coordinates to buffer coordinates.
*
* @see surfaceToBufferMatrixChanged()
*/
QMatrix4x4 surfaceToBufferMatrix() const;
/**
* Maps the specified @a point in this surface's coordinate system to the equivalent point
* within the @a child's coordinate system, and returns the mapped point.
@ -390,14 +358,6 @@ Q_SIGNALS:
* signal is emitted.
*/
void aboutToBeDestroyed();
/**
* This signal is emitted when the projection matrix from the surface-local coordinate space
* to the buffer coordinate space has been changed.
*
* Note that the compositor will most likely need to re-compute the texture coordinates after
* the surface-to-buffer matrix has been changed.
*/
void surfaceToBufferMatrixChanged();
/**
* Emitted whenever the SurfaceInterface got damaged.
* The signal is only emitted during the commit of state.

View file

@ -114,7 +114,6 @@ public:
void installPointerConstraint(ConfinedPointerV1Interface *confinement);
void installIdleInhibitor(IdleInhibitorV1Interface *inhibitor);
QMatrix4x4 buildSurfaceToBufferMatrix();
QRectF computeBufferSourceBox() const;
void applyState(SurfaceState *next);
@ -127,16 +126,15 @@ public:
*/
bool contains(const QPointF &position) const;
bool inputContains(const QPointF &position) const;
QRegion mapToBuffer(const QRegion &region) const;
CompositorInterface *compositor;
SurfaceInterface *q;
SurfaceRole *role = nullptr;
std::unique_ptr<SurfaceState> current;
std::unique_ptr<SurfaceState> pending;
QMatrix4x4 surfaceToBufferMatrix;
QSize bufferSize = QSize(0, 0);
QRectF bufferSourceBox;
QSizeF implicitSurfaceSize = QSizeF(0, 0);
QSizeF surfaceSize = QSizeF(0, 0);
QRegion inputRegion;