summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaul Olav Tvete <paul.tvete@qt.io>2020-07-03 14:31:17 +0200
committerPaul Olav Tvete <paul.tvete@qt.io>2020-07-07 12:55:29 +0200
commit7e412517c4fa10aad6f7bb0b691cb3335e815db0 (patch)
tree97429362065303715d519b4cd2da3bb8497449db
parent82f01cc931ef5ed0a77f389666c8071c5c0c4b59 (diff)
Support wl_surface.damage_buffer
Add compositor support for wl_surface.damage_buffer requests. This also required updating wl_compositor to version 4. Fixes: QTBUG-74927 Change-Id: I887ed04e60fe14ecce7df6a517950b0091e2ad54 Reviewed-by: Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@qt.io>
-rw-r--r--src/compositor/compositor_api/qwaylandcompositor.cpp2
-rw-r--r--src/compositor/compositor_api/qwaylandsurface.cpp37
-rw-r--r--src/compositor/compositor_api/qwaylandsurface_p.h2
-rw-r--r--tests/auto/compositor/compositor/mockclient.cpp2
-rw-r--r--tests/auto/compositor/compositor/tst_compositor.cpp8
-rw-r--r--tests/manual/scaling-compositor/main.qml47
-rw-r--r--tests/manual/scaling-compositor/scaling-compositor.pro3
7 files changed, 81 insertions, 20 deletions
diff --git a/src/compositor/compositor_api/qwaylandcompositor.cpp b/src/compositor/compositor_api/qwaylandcompositor.cpp
index 8878ce121..fb99f9413 100644
--- a/src/compositor/compositor_api/qwaylandcompositor.cpp
+++ b/src/compositor/compositor_api/qwaylandcompositor.cpp
@@ -190,7 +190,7 @@ void QWaylandCompositorPrivate::init()
if (socketArg != -1 && socketArg + 1 < arguments.size())
socket_name = arguments.at(socketArg + 1).toLocal8Bit();
}
- wl_compositor::init(display, 3);
+ wl_compositor::init(display, 4);
wl_subcompositor::init(display, 1);
#if QT_CONFIG(wayland_datadevice)
diff --git a/src/compositor/compositor_api/qwaylandsurface.cpp b/src/compositor/compositor_api/qwaylandsurface.cpp
index 2ebb04a35..efd186fc5 100644
--- a/src/compositor/compositor_api/qwaylandsurface.cpp
+++ b/src/compositor/compositor_api/qwaylandsurface.cpp
@@ -195,9 +195,26 @@ void QWaylandSurfacePrivate::surface_attach(Resource *, struct wl_resource *buff
pending.newlyAttached = true;
}
+/*
+ Note: The Wayland protocol specifies that buffer scale and damage can be interleaved, so
+ we cannot scale the damage region until commit. We assume that clients will either use
+ surface_damage or surface_damage_buffer within one frame for one surface.
+*/
+
void QWaylandSurfacePrivate::surface_damage(Resource *, int32_t x, int32_t y, int32_t width, int32_t height)
{
+ if (Q_UNLIKELY(pending.damageInBufferCoordinates && !pending.damage.isNull()))
+ qCWarning(qLcWaylandCompositor) << "Unsupported: Client is using both wl_surface.damage_buffer and wl_surface.damage.";
+ pending.damage = pending.damage.united(QRect(x, y, width, height));
+ pending.damageInBufferCoordinates = false;
+}
+
+void QWaylandSurfacePrivate::surface_damage_buffer(Resource *, int32_t x, int32_t y, int32_t width, int32_t height)
+{
+ if (Q_UNLIKELY(!pending.damageInBufferCoordinates && !pending.damage.isNull()))
+ qCWarning(qLcWaylandCompositor) << "Unsupported: Client is using both wl_surface.damage_buffer and wl_surface.damage.";
pending.damage = pending.damage.united(QRect(x, y, width, height));
+ pending.damageInBufferCoordinates = true;
}
void QWaylandSurfacePrivate::surface_frame(Resource *resource, uint32_t callback)
@@ -240,7 +257,24 @@ void QWaylandSurfacePrivate::surface_commit(Resource *)
QSize surfaceSize = bufferSize / bufferScale;
sourceGeometry = !pending.sourceGeometry.isValid() ? QRect(QPoint(), surfaceSize) : pending.sourceGeometry;
destinationSize = pending.destinationSize.isEmpty() ? sourceGeometry.size().toSize() : pending.destinationSize;
- damage = pending.damage.intersected(QRect(QPoint(), destinationSize));
+ if (!pending.damageInBufferCoordinates || pending.bufferScale == 1) {
+ // pending.damage is already in surface coordinates
+ damage = pending.damage.intersected(QRect(QPoint(), destinationSize));
+ } else {
+ // We must transform pending.damage from buffer coordinate system to surface coordinates
+ // TODO(QTBUG-85461): Also support wp_viewport setting more complex transformations
+ auto xform = [](const QRect &r, int scale) -> QRect {
+ QRect res{
+ QPoint{ r.x() / scale, r.y() / scale },
+ QPoint{ (r.right() + scale - 1) / scale, (r.bottom() + scale - 1) / scale }
+ };
+ return res;
+ };
+ damage = {};
+ for (const QRect &r : pending.damage) {
+ damage |= xform(r, bufferScale).intersected(QRect{{}, destinationSize});
+ }
+ }
hasContent = bufferRef.hasContent();
frameCallbacks << pendingFrameCallbacks;
inputRegion = pending.inputRegion.intersected(QRect(QPoint(), destinationSize));
@@ -255,6 +289,7 @@ void QWaylandSurfacePrivate::surface_commit(Resource *)
pending.offset = QPoint();
pending.newlyAttached = false;
pending.damage = QRegion();
+ pending.damageInBufferCoordinates = false;
pendingFrameCallbacks.clear();
// Notify buffers and views
diff --git a/src/compositor/compositor_api/qwaylandsurface_p.h b/src/compositor/compositor_api/qwaylandsurface_p.h
index 3f657c9d0..1150ccf91 100644
--- a/src/compositor/compositor_api/qwaylandsurface_p.h
+++ b/src/compositor/compositor_api/qwaylandsurface_p.h
@@ -116,6 +116,7 @@ protected:
struct wl_resource *buffer, int x, int y) override;
void surface_damage(Resource *resource,
int32_t x, int32_t y, int32_t width, int32_t height) override;
+ void surface_damage_buffer(Resource *resource, int32_t x, int32_t y, int32_t width, int32_t height) override;
void surface_frame(Resource *resource,
uint32_t callback) override;
void surface_set_opaque_region(Resource *resource,
@@ -141,6 +142,7 @@ public: //member variables
struct {
QWaylandBufferRef buffer;
QRegion damage;
+ bool damageInBufferCoordinates = false;
QPoint offset;
bool newlyAttached = false;
QRegion inputRegion;
diff --git a/tests/auto/compositor/compositor/mockclient.cpp b/tests/auto/compositor/compositor/mockclient.cpp
index 76ccd0c58..53e10d687 100644
--- a/tests/auto/compositor/compositor/mockclient.cpp
+++ b/tests/auto/compositor/compositor/mockclient.cpp
@@ -166,7 +166,7 @@ void MockClient::handleGlobalRemove(void *data, wl_registry *wl_registry, uint32
void MockClient::handleGlobal(uint32_t id, const QByteArray &interface)
{
if (interface == "wl_compositor") {
- compositor = static_cast<wl_compositor *>(wl_registry_bind(registry, id, &wl_compositor_interface, 3));
+ compositor = static_cast<wl_compositor *>(wl_registry_bind(registry, id, &wl_compositor_interface, 4));
} else if (interface == "wl_output") {
auto output = static_cast<wl_output *>(wl_registry_bind(registry, id, &wl_output_interface, 2));
m_outputs.insert(id, output);
diff --git a/tests/auto/compositor/compositor/tst_compositor.cpp b/tests/auto/compositor/compositor/tst_compositor.cpp
index a44aef2f3..902f420de 100644
--- a/tests/auto/compositor/compositor/tst_compositor.cpp
+++ b/tests/auto/compositor/compositor/tst_compositor.cpp
@@ -531,8 +531,6 @@ void tst_WaylandCompositor::mapSurfaceHiDpi()
};
QObject::connect(waylandSurface, &QWaylandSurface::damaged, [=] (const QRegion &damage) {
- // Currently, QWaylandSurface::size returns the size in pixels.
- // Should be fixed or removed for Qt 6.
QCOMPARE(damage, QRect(QPoint(), surfaceSize));
verifyComittedState();
});
@@ -570,6 +568,12 @@ void tst_WaylandCompositor::mapSurfaceHiDpi()
QTRY_COMPARE(destinationSizeSpy.count(), 1);
QTRY_COMPARE(bufferScaleSpy.count(), 1);
QTRY_COMPARE(offsetSpy.count(), 1);
+ QTRY_COMPARE(damagedSpy.count(), 1);
+
+ // Now verify that wl_surface_damage_buffer gets mapped properly
+ wl_surface_damage_buffer(surface, 0, 0, bufferSize.width(), bufferSize.height());
+ wl_surface_commit(surface);
+ QTRY_COMPARE(damagedSpy.count(), 2);
wl_surface_destroy(surface);
}
diff --git a/tests/manual/scaling-compositor/main.qml b/tests/manual/scaling-compositor/main.qml
index 056af4e5b..655bae1c2 100644
--- a/tests/manual/scaling-compositor/main.qml
+++ b/tests/manual/scaling-compositor/main.qml
@@ -48,10 +48,9 @@
**
****************************************************************************/
-import QtQuick 2.2
+import QtQuick 2.15
import QtQuick.Window 2.2
-import QtQuick.Controls 2.0
-import QtWayland.Compositor 1.0
+import QtWayland.Compositor 1.3
WaylandCompositor {
id: comp
@@ -66,16 +65,7 @@ WaylandCompositor {
height: 500
visible: true
title: "Scaling compositor x" + output.scaleFactor
- Button {
- id: incrementButton
- text: "+"
- onClicked: ++output.scaleFactor
- }
- Button {
- text: "-"
- onClicked: output.scaleFactor = Math.max(1, output.scaleFactor - 1)
- anchors.left: incrementButton.right
- }
+
Repeater {
model: shellSurfaces
ShellSurfaceItem {
@@ -83,6 +73,33 @@ WaylandCompositor {
onSurfaceDestroyed: shellSurfaces.remove(index);
}
}
+
+ Rectangle {
+ id: incrementButton
+ color: "#c0f0d0"
+ Text {
+ text: "+"
+ }
+ width: 100
+ height: 30
+ TapHandler {
+ onTapped: ++output.scaleFactor
+ }
+ }
+
+ Rectangle {
+ id: decrementButton
+ color: "#f0d0c0"
+ Text {
+ text: "-"
+ }
+ width: 100
+ height: 30
+ TapHandler {
+ onTapped: output.scaleFactor = Math.max(1, output.scaleFactor - 1)
+ }
+ anchors.left: incrementButton.right
+ }
}
}
@@ -91,4 +108,8 @@ WaylandCompositor {
WlShell {
onWlShellSurfaceCreated: shellSurfaces.append({shellSurface: shellSurface});
}
+ XdgShell {
+ onToplevelCreated:
+ shellSurfaces.append({shellSurface: xdgSurface});
+ }
}
diff --git a/tests/manual/scaling-compositor/scaling-compositor.pro b/tests/manual/scaling-compositor/scaling-compositor.pro
index 847e07ea7..200dc8c40 100644
--- a/tests/manual/scaling-compositor/scaling-compositor.pro
+++ b/tests/manual/scaling-compositor/scaling-compositor.pro
@@ -1,7 +1,6 @@
TEMPLATE = app
-QT += gui qml quickcontrols2
-
+QT += gui qml
SOURCES += main.cpp
RESOURCES += qml.qrc