From 87c4262bd924b7b1de368effaad8ce1d9d9dc09b Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Tue, 9 Apr 2024 17:13:42 -0400 Subject: [PATCH] wip: Add lightboxes to graphics offload Add GTK_GRAHPICS_OFFLOAD_ENABLED_WITH_LIGHTBOX, and pass that on to the subsurface. --- gdk/gdksubsurface.c | 10 ++++- gdk/gdksubsurfaceprivate.h | 4 ++ gdk/wayland/gdksubsurface-wayland-private.h | 1 + gdk/wayland/gdksubsurface-wayland.c | 11 +++++ gsk/gskoffload.c | 49 ++++++++++++++++----- gsk/gskoffloadprivate.h | 1 + gtk/gtkgraphicsoffload.c | 7 +++ gtk/gtkgraphicsoffload.h | 1 + testsuite/gdk/subsurface.c | 10 ++--- 9 files changed, 77 insertions(+), 17 deletions(-) diff --git a/gdk/gdksubsurface.c b/gdk/gdksubsurface.c index 5f0a26f62e..b47c9a9d97 100644 --- a/gdk/gdksubsurface.c +++ b/gdk/gdksubsurface.c @@ -114,6 +114,7 @@ gdk_subsurface_attach (GdkSubsurface *subsurface, const graphene_rect_t *source, const graphene_rect_t *dest, GdkTextureTransform transform, + gboolean lightbox, gboolean above, GdkSubsurface *sibling) { @@ -156,7 +157,7 @@ gdk_subsurface_attach (GdkSubsurface *subsurface, } } - return GDK_SUBSURFACE_GET_CLASS (subsurface)->attach (subsurface, texture, source, dest, transform, above, sibling); + return GDK_SUBSURFACE_GET_CLASS (subsurface)->attach (subsurface, texture, source, dest, transform, lightbox, above, sibling); } void @@ -213,3 +214,10 @@ gdk_subsurface_get_transform (GdkSubsurface *subsurface) return GDK_SUBSURFACE_GET_CLASS (subsurface)->get_transform (subsurface); } +gboolean +gdk_subsurface_get_lightbox (GdkSubsurface *subsurface) +{ + g_return_val_if_fail (GDK_IS_SUBSURFACE (subsurface), FALSE); + + return GDK_SUBSURFACE_GET_CLASS (subsurface)->get_lightbox (subsurface); +} diff --git a/gdk/gdksubsurfaceprivate.h b/gdk/gdksubsurfaceprivate.h index ea36af1bf5..3ca9cd3d89 100644 --- a/gdk/gdksubsurfaceprivate.h +++ b/gdk/gdksubsurfaceprivate.h @@ -67,6 +67,7 @@ struct _GdkSubsurfaceClass const graphene_rect_t *source, const graphene_rect_t *dest, GdkTextureTransform transform, + gboolean lightbox, gboolean above, GdkSubsurface *sibling); void (* detach) (GdkSubsurface *subsurface); @@ -77,6 +78,7 @@ struct _GdkSubsurfaceClass graphene_rect_t *dest); GdkTextureTransform (* get_transform) (GdkSubsurface *subsurface); + gboolean (* get_lightbox) (GdkSubsurface *subsurface); }; GType gdk_subsurface_get_type (void) G_GNUC_CONST; @@ -88,6 +90,7 @@ gboolean gdk_subsurface_attach (GdkSubsurface *subsurfac const graphene_rect_t *source, const graphene_rect_t *dest, GdkTextureTransform transform, + gboolean lightbox, gboolean above, GdkSubsurface *sibling); void gdk_subsurface_detach (GdkSubsurface *subsurface); @@ -99,6 +102,7 @@ void gdk_subsurface_get_dest (GdkSubsurface *subsurfac gboolean gdk_subsurface_is_above_parent (GdkSubsurface *subsurface); GdkTextureTransform gdk_subsurface_get_transform (GdkSubsurface *subsurface); +gboolean gdk_subsurface_get_lightbox (GdkSubsurface *subsurface); G_END_DECLS diff --git a/gdk/wayland/gdksubsurface-wayland-private.h b/gdk/wayland/gdksubsurface-wayland-private.h index fb5c98a85a..024b238ed5 100644 --- a/gdk/wayland/gdksubsurface-wayland-private.h +++ b/gdk/wayland/gdksubsurface-wayland-private.h @@ -25,6 +25,7 @@ struct _GdkWaylandSubsurface cairo_rectangle_int_t dest; graphene_rect_t source; enum wl_output_transform transform; + gboolean lightbox; struct wl_region *opaque_region; diff --git a/gdk/wayland/gdksubsurface-wayland.c b/gdk/wayland/gdksubsurface-wayland.c index 3e72234e85..bd43e2cd9d 100644 --- a/gdk/wayland/gdksubsurface-wayland.c +++ b/gdk/wayland/gdksubsurface-wayland.c @@ -168,6 +168,7 @@ gdk_wayland_subsurface_attach (GdkSubsurface *sub, const graphene_rect_t *dest, GdkTextureTransform transform, gboolean above, + gboolean lightbox, GdkSubsurface *sibling) { GdkWaylandSubsurface *self = GDK_WAYLAND_SUBSURFACE (sub); @@ -202,6 +203,7 @@ gdk_wayland_subsurface_attach (GdkSubsurface *sub, self->source.size.height = source->size.height; self->transform = gdk_texture_transform_to_wl (transform); + self->lightbox = lightbox; scale = gdk_fractional_scale_to_double (&parent->scale); @@ -430,6 +432,14 @@ gdk_wayland_subsurface_get_transform (GdkSubsurface *sub) return wl_output_transform_to_gdk (self->transform); } +static gboolean +gdk_wayland_subsurface_get_lightbox (GdkSubsurface *sub) +{ + GdkWaylandSubsurface *self = GDK_WAYLAND_SUBSURFACE (sub); + + return self->lightbox; +} + static void gdk_wayland_subsurface_class_init (GdkWaylandSubsurfaceClass *class) { @@ -444,6 +454,7 @@ gdk_wayland_subsurface_class_init (GdkWaylandSubsurfaceClass *class) subsurface_class->get_source = gdk_wayland_subsurface_get_source; subsurface_class->get_dest = gdk_wayland_subsurface_get_dest; subsurface_class->get_transform = gdk_wayland_subsurface_get_transform; + subsurface_class->get_lightbox = gdk_wayland_subsurface_get_lightbox; }; static void diff --git a/gsk/gskoffload.c b/gsk/gskoffload.c index 0ef9323a7c..cbf9bf61ab 100644 --- a/gsk/gskoffload.c +++ b/gsk/gskoffload.c @@ -82,34 +82,59 @@ find_texture_transform (GskTransform *transform) static GdkTexture * find_texture_to_attach (GskOffload *self, - GdkSubsurface *subsurface, - const GskRenderNode *node, + const GskRenderNode *subsurface_node, graphene_rect_t *out_clip, - GdkTextureTransform *out_texture_transform) + GdkTextureTransform *out_texture_transform, + gboolean *out_lightbox) { + GdkSubsurface *subsurface; + const GskRenderNode *node; gboolean has_clip = FALSE; graphene_rect_t clip; GskTransform *transform = NULL; GdkTexture *ret = NULL; + *out_texture_transform = GDK_TEXTURE_TRANSFORM_NORMAL; + *out_lightbox = FALSE; + + subsurface = gsk_subsurface_node_get_subsurface (subsurface_node); + node = subsurface_node; + for (;;) { switch ((int) GSK_RENDER_NODE_TYPE (node)) { case GSK_DEBUG_NODE: + case GSK_SUBSURFACE_NODE: node = gsk_debug_node_get_child (node); break; case GSK_CONTAINER_NODE: - if (gsk_container_node_get_n_children (node) != 1) + if (gsk_container_node_get_n_children (node) == 1) { - GDK_DISPLAY_DEBUG (gdk_surface_get_display (self->surface), OFFLOAD, - "Can't offload subsurface %p: too much content, container with %d children", - subsurface, gsk_container_node_get_n_children (node)); - goto out; + node = gsk_container_node_get_child (node, 0); + break; } - node = gsk_container_node_get_child (node, 0); - break; + else if (gsk_container_node_get_n_children (node) == 2) + { + GskRenderNode *child; + + child = gsk_container_node_get_child (node, 0); + if (GSK_RENDER_NODE_TYPE (child) == GSK_COLOR_NODE && + gsk_rect_equal (&child->bounds, &subsurface_node->bounds) && + gdk_rgba_equal (gsk_color_node_get_color (child), &(GdkRGBA) { 0, 0, 0, 1 })) + { + g_print ("found lightbox\n"); + *out_lightbox = TRUE; + node = gsk_container_node_get_child (node, 1); + break; + } + } + + GDK_DISPLAY_DEBUG (gdk_surface_get_display (self->surface), OFFLOAD, + "Can't offload subsurface %p: too much content, container with %d children", + subsurface, gsk_container_node_get_n_children (node)); + goto out; case GSK_TRANSFORM_NODE: { @@ -615,7 +640,7 @@ complex_clip: } else { - info->texture = find_texture_to_attach (self, subsurface, gsk_subsurface_node_get_child (node), &info->source, &info->transform); + info->texture = find_texture_to_attach (self, node, &info->source, &info->transform, &info->lightbox); if (info->texture) { info->can_offload = TRUE; @@ -691,6 +716,7 @@ gsk_offload_new (GdkSurface *surface, &info->source, &info->dest, info->transform, + info->lightbox, TRUE, NULL); else info->is_offloaded = gdk_subsurface_attach (info->subsurface, @@ -698,6 +724,7 @@ gsk_offload_new (GdkSurface *surface, &info->source, &info->dest, info->transform, + info->lightbox, info->place_above != NULL, info->place_above); } diff --git a/gsk/gskoffloadprivate.h b/gsk/gskoffloadprivate.h index c4c604179a..b021eab773 100644 --- a/gsk/gskoffloadprivate.h +++ b/gsk/gskoffloadprivate.h @@ -34,6 +34,7 @@ typedef struct graphene_rect_t dest; graphene_rect_t source; GdkTextureTransform transform; + gboolean lightbox; guint was_offloaded : 1; guint can_offload : 1; diff --git a/gtk/gtkgraphicsoffload.c b/gtk/gtkgraphicsoffload.c index ca19828c5c..46a658a275 100644 --- a/gtk/gtkgraphicsoffload.c +++ b/gtk/gtkgraphicsoffload.c @@ -208,6 +208,13 @@ gtk_graphics_offload_snapshot (GtkWidget *widget, if (self->subsurface) gtk_snapshot_push_subsurface (snapshot, self->subsurface); + if (self->enabled == GTK_GRAPHICS_OFFLOAD_ENABLED_WITH_LIGHTBOX) + gtk_snapshot_append_color (snapshot, + &(GdkRGBA) { 0, 0, 0, 1 }, + &GRAPHENE_RECT_INIT (0, 0, + gtk_widget_get_width (widget), + gtk_widget_get_height (widget))); + gtk_widget_snapshot_child (widget, self->child, snapshot); if (self->subsurface) diff --git a/gtk/gtkgraphicsoffload.h b/gtk/gtkgraphicsoffload.h index 6e30da6f84..d39d7611e8 100644 --- a/gtk/gtkgraphicsoffload.h +++ b/gtk/gtkgraphicsoffload.h @@ -57,6 +57,7 @@ typedef enum { GTK_GRAPHICS_OFFLOAD_ENABLED, GTK_GRAPHICS_OFFLOAD_DISABLED, + GTK_GRAPHICS_OFFLOAD_ENABLED_WITH_LIGHTBOX, } GtkGraphicsOffloadEnabled; GDK_AVAILABLE_IN_4_14 diff --git a/testsuite/gdk/subsurface.c b/testsuite/gdk/subsurface.c index 37657e8049..dce870e54e 100644 --- a/testsuite/gdk/subsurface.c +++ b/testsuite/gdk/subsurface.c @@ -42,9 +42,9 @@ test_subsurface_stacking (void) texture = gdk_texture_new_from_resource ("/org/gtk/libgtk/icons/16x16/actions/media-eject.png"); - gdk_subsurface_attach (sub0, texture, &TEXTURE_RECT (texture), &GRAPHENE_RECT_INIT (0, 0, 10, 10), GDK_TEXTURE_TRANSFORM_NORMAL, TRUE, NULL); - gdk_subsurface_attach (sub1, texture, &TEXTURE_RECT (texture), &GRAPHENE_RECT_INIT (0, 0, 10, 10), GDK_TEXTURE_TRANSFORM_NORMAL, TRUE, NULL); - gdk_subsurface_attach (sub2, texture, &TEXTURE_RECT (texture), &GRAPHENE_RECT_INIT (0, 0, 10, 10), GDK_TEXTURE_TRANSFORM_NORMAL, TRUE, NULL); + gdk_subsurface_attach (sub0, texture, &TEXTURE_RECT (texture), &GRAPHENE_RECT_INIT (0, 0, 10, 10), GDK_TEXTURE_TRANSFORM_NORMAL, FALSE, TRUE, NULL); + gdk_subsurface_attach (sub1, texture, &TEXTURE_RECT (texture), &GRAPHENE_RECT_INIT (0, 0, 10, 10), GDK_TEXTURE_TRANSFORM_NORMAL, FALSE, TRUE, NULL); + gdk_subsurface_attach (sub2, texture, &TEXTURE_RECT (texture), &GRAPHENE_RECT_INIT (0, 0, 10, 10), GDK_TEXTURE_TRANSFORM_NORMAL, FALSE, TRUE, NULL); g_assert_true (surface->subsurfaces_above == sub2); g_assert_true (sub2->sibling_below == NULL); @@ -67,7 +67,7 @@ test_subsurface_stacking (void) g_assert_true (sub0->sibling_above == NULL); g_assert_true (sub0->above_parent); - gdk_subsurface_attach (sub2, texture, &TEXTURE_RECT (texture), &GRAPHENE_RECT_INIT (0, 0, 10, 10), GDK_TEXTURE_TRANSFORM_NORMAL, FALSE, NULL); + gdk_subsurface_attach (sub2, texture, &TEXTURE_RECT (texture), &GRAPHENE_RECT_INIT (0, 0, 10, 10), GDK_TEXTURE_TRANSFORM_NORMAL, FALSE, FALSE, NULL); g_assert_true (surface->subsurfaces_above == sub0); g_assert_true (sub0->sibling_below == NULL); @@ -79,7 +79,7 @@ test_subsurface_stacking (void) g_assert_true (sub2->sibling_above == NULL); g_assert_false (sub2->above_parent); - gdk_subsurface_attach (sub1, texture, &TEXTURE_RECT (texture), &GRAPHENE_RECT_INIT (0, 0, 10, 10), GDK_TEXTURE_TRANSFORM_NORMAL, TRUE, sub2); + gdk_subsurface_attach (sub1, texture, &TEXTURE_RECT (texture), &GRAPHENE_RECT_INIT (0, 0, 10, 10), GDK_TEXTURE_TRANSFORM_NORMAL, FALSE, TRUE, sub2); g_assert_true (surface->subsurfaces_below == sub1); g_assert_true (sub1->sibling_above == NULL);