diff options
author | Benjamin Otte <otte.benjamin@googlemail.com> | 2023-04-29 03:43:45 +0000 |
---|---|---|
committer | Benjamin Otte <otte.benjamin@googlemail.com> | 2023-04-29 03:43:45 +0000 |
commit | c542351a73538b42bb820324c6590350b14a48b7 (patch) | |
tree | 1db6cda423f86d5a5779e07241c0eb8dafb3c19b | |
parent | d1a25178fdda26946441cbc733bdd51d431a5c39 (diff) | |
parent | 31983301883d2a17bc5c43819102dec659298265 (diff) | |
download | gtk+-c542351a73538b42bb820324c6590350b14a48b7.tar.gz |
Merge branch 'wip/otte/for-main' into 'main'
wayland: Use wl_surface_damage_buffer() in Cairo
See merge request GNOME/gtk!5886
-rw-r--r-- | gdk/gdkrectangleprivate.h | 57 | ||||
-rw-r--r-- | gdk/wayland/gdksurface-wayland.c | 18 | ||||
-rw-r--r-- | gsk/gskrendernodeimpl.c | 33 |
3 files changed, 104 insertions, 4 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); + } } } diff --git a/gsk/gskrendernodeimpl.c b/gsk/gskrendernodeimpl.c index bde92c1edc..ef31f459c7 100644 --- a/gsk/gskrendernodeimpl.c +++ b/gsk/gskrendernodeimpl.c @@ -32,6 +32,7 @@ #include "gdk/gdktextureprivate.h" #include "gdk/gdkmemoryformatprivate.h" #include "gdk/gdkprivate.h" +#include "gdk/gdkrectangleprivate.h" #include <cairo.h> #ifdef CAIRO_HAS_SVG_SURFACE @@ -74,6 +75,25 @@ _graphene_rect_init_from_clip_extents (graphene_rect_t *rect, graphene_rect_init (rect, x1c, y1c, x2c - x1c, y2c - y1c); } +static void +region_union_region_affine (cairo_region_t *region, + const cairo_region_t *sub, + float scale_x, + float scale_y, + float offset_x, + float offset_y) +{ + cairo_rectangle_int_t rect; + int i; + + for (i = 0; i < cairo_region_num_rectangles (sub); i++) + { + cairo_region_get_rectangle (sub, i, &rect); + gdk_rectangle_transform_affine (&rect, scale_x, scale_y, offset_x, offset_y, &rect); + cairo_region_union_rectangle (region, &rect); + } +} + /* {{{ GSK_COLOR_NODE */ /** @@ -3354,11 +3374,22 @@ gsk_transform_node_diff (GskRenderNode *node1, } break; + case GSK_TRANSFORM_CATEGORY_2D_AFFINE: + { + cairo_region_t *sub; + float scale_x, scale_y, dx, dy; + gsk_transform_to_affine (self1->transform, &scale_x, &scale_y, &dx, &dy); + sub = cairo_region_create (); + gsk_render_node_diff (self1->child, self2->child, sub); + region_union_region_affine (region, sub, scale_x, scale_y, dx, dy); + cairo_region_destroy (sub); + } + break; + case GSK_TRANSFORM_CATEGORY_UNKNOWN: case GSK_TRANSFORM_CATEGORY_ANY: case GSK_TRANSFORM_CATEGORY_3D: case GSK_TRANSFORM_CATEGORY_2D: - case GSK_TRANSFORM_CATEGORY_2D_AFFINE: default: gsk_render_node_diff_impossible (node1, node2, region); break; |