summaryrefslogtreecommitdiff
path: root/gdk
diff options
context:
space:
mode:
authorBenjamin Otte <otte@redhat.com>2023-04-29 05:07:03 +0200
committerBenjamin Otte <otte@redhat.com>2023-04-29 05:07:03 +0200
commit11aaa29a6917458b40266bf72ecbc4ecb8295bee (patch)
treed47f72631a458d2a949321731bd19ffe4d274341 /gdk
parentb4c859c0113f8802d9c6f047dcf2b689223848da (diff)
downloadgtk+-11aaa29a6917458b40266bf72ecbc4ecb8295bee.tar.gz
wayland: Use wl_surface_damage_buffer() in Cairo
... when it is available. Also introduce the new function gdk_rectangle_transform_affine(), which looks like overkill for this purpose, but I'm about to use it elsewhere.
Diffstat (limited to 'gdk')
-rw-r--r--gdk/gdkrectangleprivate.h57
-rw-r--r--gdk/wayland/gdksurface-wayland.c18
2 files changed, 72 insertions, 3 deletions
diff --git a/gdk/gdkrectangleprivate.h b/gdk/gdkrectangleprivate.h
new file mode 100644
index 0000000000..b7857d5037
--- /dev/null
+++ b/gdk/gdkrectangleprivate.h
@@ -0,0 +1,57 @@
+#pragma once
+
+#include "gdkrectangle.h"
+
+#include <math.h>
+
+G_BEGIN_DECLS
+
+/*
+ * gdk_rectangle_transform_affine:
+ * @src: the rectangle to transform
+ * @scale_x: scale factor in the X direction. The scale factor
+ * may be negative or 0.
+ * @scale_y: scale factor in the Y direction. The scale factor
+ * may be negative or 0.
+ * @offset_x: offset of result in X direction.
+ * @offset_y: offset of result in Y direction.
+ * @dest: (out caller-allocates): destination rectangle, may be
+ * identical to @src
+ *
+ * Does an affine transform of the source rectangle and stores the
+ * result in the dest rectangle. If the destination rectangle does
+ * not fit on integer bounds, the result will be enlarged to make it
+ * fit.
+ * (Fun fact: This means with a scale of 0 and an offset of 0.5,
+ * the resulting rect will have a width of 1.)
+ *
+ * The width and height of the result will be positive, even if the
+ * src rectangle or the scale were negative.
+ *
+ * This function can be used with the output of
+ * gsk_transform_to_affine().
+ **/
+static inline void
+gdk_rectangle_transform_affine (const GdkRectangle *src,
+ float scale_x,
+ float scale_y,
+ float offset_x,
+ float offset_y,
+ GdkRectangle *dest)
+{
+ float x1, x2, y1, y2;
+
+ x1 = offset_x + src->x * scale_x;
+ x2 = offset_x + (src->x + src->width) * scale_x;
+ y1 = offset_y + src->y * scale_y;
+ y2 = offset_y + (src->y + src->height) * scale_y;
+
+ dest->x = floorf (MIN (x1, x2));
+ dest->y = floorf (MIN (y1, y2));
+ dest->width = ceilf (MAX (x1, x2)) - dest->x;
+ dest->height = ceilf (MAX (y1, y2)) - dest->y;
+}
+
+
+G_END_DECLS
+
diff --git a/gdk/wayland/gdksurface-wayland.c b/gdk/wayland/gdksurface-wayland.c
index a4049bab72..483ccec8a2 100644
--- a/gdk/wayland/gdksurface-wayland.c
+++ b/gdk/wayland/gdksurface-wayland.c
@@ -28,6 +28,7 @@
#include "gdkmonitor-wayland.h"
#include "gdkpopupprivate.h"
#include "gdkprivate-wayland.h"
+#include "gdkrectangleprivate.h"
#include "gdkseat-wayland.h"
#include "gdksurfaceprivate.h"
#include "gdktoplevelprivate.h"
@@ -468,6 +469,7 @@ gdk_wayland_surface_attach_image (GdkSurface *surface,
{
GdkWaylandSurface *impl = GDK_WAYLAND_SURFACE (surface);
cairo_rectangle_int_t rect;
+ uint32_t wl_surface_version;
int i, n;
if (GDK_SURFACE_DESTROYED (surface))
@@ -475,14 +477,15 @@ gdk_wayland_surface_attach_image (GdkSurface *surface,
g_assert (_gdk_wayland_is_shm_surface (cairo_surface));
+ wl_surface_version = wl_surface_get_version (impl->display_server.wl_surface);
+
/* Attach this new buffer to the surface */
wl_surface_attach (impl->display_server.wl_surface,
_gdk_wayland_shm_surface_get_wl_buffer (cairo_surface),
0, 0);
if ((impl->pending_buffer_offset_x || impl->pending_buffer_offset_y) &&
- wl_surface_get_version (impl->display_server.wl_surface) >=
- WL_SURFACE_OFFSET_SINCE_VERSION)
+ wl_surface_version >= WL_SURFACE_OFFSET_SINCE_VERSION)
wl_surface_offset (impl->display_server.wl_surface,
impl->pending_buffer_offset_x,
impl->pending_buffer_offset_y);
@@ -493,7 +496,16 @@ gdk_wayland_surface_attach_image (GdkSurface *surface,
for (i = 0; i < n; i++)
{
cairo_region_get_rectangle (damage, i, &rect);
- wl_surface_damage (impl->display_server.wl_surface, rect.x, rect.y, rect.width, rect.height);
+ if (wl_surface_version >= WL_SURFACE_DAMAGE_BUFFER_SINCE_VERSION)
+ {
+ float scale = gdk_surface_get_scale (surface);
+ gdk_rectangle_transform_affine (&rect, scale, scale, 0, 0, &rect);
+ wl_surface_damage_buffer (impl->display_server.wl_surface, rect.x, rect.y, rect.width, rect.height);
+ }
+ else
+ {
+ wl_surface_damage (impl->display_server.wl_surface, rect.x, rect.y, rect.width, rect.height);
+ }
}
}