summaryrefslogtreecommitdiffstats
path: root/src
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 /src
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>
Diffstat (limited to 'src')
-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
3 files changed, 39 insertions, 2 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;