[gtk/nonoverlapping-containers: 3/4] gsk: Collect opacity information




commit 38eb182947894e956e575fde36ed41275b49dc05
Author: Matthias Clasen <mclasen redhat com>
Date:   Tue Apr 5 14:55:36 2022 -0400

    gsk: Collect opacity information
    
    Collect information about whether to use offscreens
    for opacity during node construction, so we don't
    need to walk the tree repeatedly, later.

 gsk/gskrendernode.c        | 19 ++++++++++++++++---
 gsk/gskrendernodeimpl.c    | 26 ++++++++++++++++++++++++++
 gsk/gskrendernodeprivate.h |  3 +++
 3 files changed, 45 insertions(+), 3 deletions(-)
---
diff --git a/gsk/gskrendernode.c b/gsk/gskrendernode.c
index 295ddf698e..14a29c358c 100644
--- a/gsk/gskrendernode.c
+++ b/gsk/gskrendernode.c
@@ -58,14 +58,14 @@ value_render_node_init (GValue *value)
 {
   value->data[0].v_pointer = NULL;
 }
- 
+
 static void
 value_render_node_free_value (GValue *value)
 {
   if (value->data[0].v_pointer != NULL)
     gsk_render_node_unref (value->data[0].v_pointer);
 }
- 
+
 static void
 value_render_node_copy_value (const GValue *src,
                               GValue       *dst)
@@ -75,7 +75,7 @@ value_render_node_copy_value (const GValue *src,
   else
     dst->data[0].v_pointer = NULL;
 }
- 
+
 static gpointer
 value_render_node_peek_pointer (const GValue *value)
 {
@@ -738,3 +738,16 @@ gsk_render_node_prefers_high_depth (const GskRenderNode *node)
 {
   return node->prefers_high_depth;
 }
+
+/* Whether we need an offscreen to handle opacity correctly for this node.
+ * We don't if there is only one drawing node inside (could be child
+ * node, or grandchild, or...).
+ *
+ * For containers with multiple children, we can avoid the offscreen if
+ * the children are known not to overlap.
+ */
+gboolean
+gsk_render_node_use_offscreen_for_opacity (const GskRenderNode *node)
+{
+  return node->offscreen_for_opacity;
+}
diff --git a/gsk/gskrendernodeimpl.c b/gsk/gskrendernodeimpl.c
index 53b7d35f9d..175c458848 100644
--- a/gsk/gskrendernodeimpl.c
+++ b/gsk/gskrendernodeimpl.c
@@ -139,6 +139,7 @@ gsk_color_node_new (const GdkRGBA         *rgba,
 
   self = gsk_render_node_alloc (GSK_COLOR_NODE);
   node = (GskRenderNode *) self;
+  node->offscreen_for_opacity = FALSE;
 
   self->color = *rgba;
   graphene_rect_init_from_rect (&node->bounds, bounds);
@@ -284,6 +285,7 @@ gsk_linear_gradient_node_new (const graphene_rect_t  *bounds,
 
   self = gsk_render_node_alloc (GSK_LINEAR_GRADIENT_NODE);
   node = (GskRenderNode *) self;
+  node->offscreen_for_opacity = FALSE;
 
   graphene_rect_init_from_rect (&node->bounds, bounds);
   graphene_point_init_from_point (&self->start, start);
@@ -336,6 +338,7 @@ gsk_repeating_linear_gradient_node_new (const graphene_rect_t  *bounds,
 
   self = gsk_render_node_alloc (GSK_REPEATING_LINEAR_GRADIENT_NODE);
   node = (GskRenderNode *) self;
+  node->offscreen_for_opacity = FALSE;
 
   graphene_rect_init_from_rect (&node->bounds, bounds);
   graphene_point_init_from_point (&self->start, start);
@@ -584,6 +587,7 @@ gsk_radial_gradient_node_new (const graphene_rect_t  *bounds,
 
   self = gsk_render_node_alloc (GSK_RADIAL_GRADIENT_NODE);
   node = (GskRenderNode *) self;
+  node->offscreen_for_opacity = FALSE;
 
   graphene_rect_init_from_rect (&node->bounds, bounds);
   graphene_point_init_from_point (&self->center, center);
@@ -652,6 +656,7 @@ gsk_repeating_radial_gradient_node_new (const graphene_rect_t  *bounds,
 
   self = gsk_render_node_alloc (GSK_REPEATING_RADIAL_GRADIENT_NODE);
   node = (GskRenderNode *) self;
+  node->offscreen_for_opacity = FALSE;
 
   graphene_rect_init_from_rect (&node->bounds, bounds);
   graphene_point_init_from_point (&self->center, center);
@@ -1030,6 +1035,7 @@ gsk_conic_gradient_node_new (const graphene_rect_t  *bounds,
 
   self = gsk_render_node_alloc (GSK_CONIC_GRADIENT_NODE);
   node = (GskRenderNode *) self;
+  node->offscreen_for_opacity = FALSE;
 
   graphene_rect_init_from_rect (&node->bounds, bounds);
   graphene_point_init_from_point (&self->center, center);
@@ -1413,6 +1419,7 @@ gsk_border_node_new (const GskRoundedRect *outline,
 
   self = gsk_render_node_alloc (GSK_BORDER_NODE);
   node = (GskRenderNode *) self;
+  node->offscreen_for_opacity = FALSE;
 
   gsk_rounded_rect_init_copy (&self->outline, outline);
   memcpy (self->border_width, border_width, sizeof (self->border_width));
@@ -1559,6 +1566,7 @@ gsk_texture_node_new (GdkTexture            *texture,
 
   self = gsk_render_node_alloc (GSK_TEXTURE_NODE);
   node = (GskRenderNode *) self;
+  node->offscreen_for_opacity = FALSE;
 
   self->texture = g_object_ref (texture);
   graphene_rect_init_from_rect (&node->bounds, bounds);
@@ -2014,6 +2022,7 @@ gsk_inset_shadow_node_new (const GskRoundedRect *outline,
 
   self = gsk_render_node_alloc (GSK_INSET_SHADOW_NODE);
   node = (GskRenderNode *) self;
+  node->offscreen_for_opacity = FALSE;
 
   gsk_rounded_rect_init_copy (&self->outline, outline);
   self->color = *color;
@@ -2313,6 +2322,7 @@ gsk_outset_shadow_node_new (const GskRoundedRect *outline,
 
   self = gsk_render_node_alloc (GSK_OUTSET_SHADOW_NODE);
   node = (GskRenderNode *) self;
+  node->offscreen_for_opacity = FALSE;
 
   gsk_rounded_rect_init_copy (&self->outline, outline);
   self->color = *color;
@@ -2506,6 +2516,7 @@ gsk_cairo_node_new (const graphene_rect_t *bounds)
 
   self = gsk_render_node_alloc (GSK_CAIRO_NODE);
   node = (GskRenderNode *) self;
+  node->offscreen_for_opacity = FALSE;
 
   graphene_rect_init_from_rect (&node->bounds, bounds);
 
@@ -2748,9 +2759,11 @@ gsk_container_node_new (GskRenderNode **children,
           self->disjoint &= !graphene_rect_intersection (&bounds, &(children[i]->bounds), NULL);
           graphene_rect_union (&bounds, &(children[i]->bounds), &bounds);
           node->prefers_high_depth |= gsk_render_node_prefers_high_depth (children[i]);
+          node->offscreen_for_opacity |= children[i]->offscreen_for_opacity;
         }
 
       graphene_rect_init_from_rect (&node->bounds, &bounds);
+      node->offscreen_for_opacity |= !self->disjoint;
     }
 
   return node;
@@ -2983,6 +2996,7 @@ gsk_transform_node_new (GskRenderNode *child,
 
   self = gsk_render_node_alloc (GSK_TRANSFORM_NODE);
   node = (GskRenderNode *) self;
+  node->offscreen_for_opacity = child->offscreen_for_opacity;
 
   self->child = gsk_render_node_ref (child);
   self->transform = gsk_transform_ref (transform);
@@ -3127,6 +3141,7 @@ gsk_opacity_node_new (GskRenderNode *child,
 
   self = gsk_render_node_alloc (GSK_OPACITY_NODE);
   node = (GskRenderNode *) self;
+  node->offscreen_for_opacity = child->offscreen_for_opacity;
 
   self->child = gsk_render_node_ref (child);
   self->opacity = CLAMP (opacity, 0.0, 1.0);
@@ -3330,6 +3345,7 @@ gsk_color_matrix_node_new (GskRenderNode           *child,
 
   self = gsk_render_node_alloc (GSK_COLOR_MATRIX_NODE);
   node = (GskRenderNode *) self;
+  node->offscreen_for_opacity = child->offscreen_for_opacity;
 
   self->child = gsk_render_node_ref (child);
   graphene_matrix_init_from_matrix (&self->color_matrix, color_matrix);
@@ -3478,6 +3494,7 @@ gsk_repeat_node_new (const graphene_rect_t *bounds,
 
   self = gsk_render_node_alloc (GSK_REPEAT_NODE);
   node = (GskRenderNode *) self;
+  node->offscreen_for_opacity = TRUE;
 
   graphene_rect_init_from_rect (&node->bounds, bounds);
 
@@ -3615,6 +3632,7 @@ gsk_clip_node_new (GskRenderNode         *child,
 
   self = gsk_render_node_alloc (GSK_CLIP_NODE);
   node = (GskRenderNode *) self;
+  node->offscreen_for_opacity = child->offscreen_for_opacity;
 
   self->child = gsk_render_node_ref (child);
   graphene_rect_normalize_r (clip, &self->clip);
@@ -3748,6 +3766,7 @@ gsk_rounded_clip_node_new (GskRenderNode         *child,
 
   self = gsk_render_node_alloc (GSK_ROUNDED_CLIP_NODE);
   node = (GskRenderNode *) self;
+  node->offscreen_for_opacity = child->offscreen_for_opacity;
 
   self->child = gsk_render_node_ref (child);
   gsk_rounded_rect_init_copy (&self->clip, clip);
@@ -3967,6 +3986,7 @@ gsk_shadow_node_new (GskRenderNode   *child,
 
   self = gsk_render_node_alloc (GSK_SHADOW_NODE);
   node = (GskRenderNode *) self;
+  node->offscreen_for_opacity = child->offscreen_for_opacity;
 
   self->child = gsk_render_node_ref (child);
   self->n_shadows = n_shadows;
@@ -4163,6 +4183,7 @@ gsk_blend_node_new (GskRenderNode *bottom,
 
   self = gsk_render_node_alloc (GSK_BLEND_NODE);
   node = (GskRenderNode *) self;
+  node->offscreen_for_opacity = TRUE;
 
   self->bottom = gsk_render_node_ref (bottom);
   self->top = gsk_render_node_ref (top);
@@ -4313,6 +4334,7 @@ gsk_cross_fade_node_new (GskRenderNode *start,
 
   self = gsk_render_node_alloc (GSK_CROSS_FADE_NODE);
   node = (GskRenderNode *) self;
+  node->offscreen_for_opacity = TRUE;
 
   self->start = gsk_render_node_ref (start);
   self->end = gsk_render_node_ref (end);
@@ -4499,6 +4521,7 @@ gsk_text_node_new (PangoFont              *font,
 
   self = gsk_render_node_alloc (GSK_TEXT_NODE);
   node = (GskRenderNode *) self;
+  node->offscreen_for_opacity = FALSE;
 
   self->font = g_object_ref (font);
   self->color = *color;
@@ -4905,6 +4928,7 @@ gsk_blur_node_new (GskRenderNode *child,
 
   self = gsk_render_node_alloc (GSK_BLUR_NODE);
   node = (GskRenderNode *) self;
+  node->offscreen_for_opacity = child->offscreen_for_opacity;
 
   self->child = gsk_render_node_ref (child);
   self->radius = radius;
@@ -5034,6 +5058,7 @@ gsk_debug_node_new (GskRenderNode *child,
 
   self = gsk_render_node_alloc (GSK_DEBUG_NODE);
   node = (GskRenderNode *) self;
+  node->offscreen_for_opacity = child->offscreen_for_opacity;
 
   self->child = gsk_render_node_ref (child);
   self->message = message;
@@ -5195,6 +5220,7 @@ gsk_gl_shader_node_new (GskGLShader           *shader,
 
   self = gsk_render_node_alloc (GSK_GL_SHADER_NODE);
   node = (GskRenderNode *) self;
+  node->offscreen_for_opacity = TRUE;
 
   graphene_rect_init_from_rect (&node->bounds, bounds);
   self->shader = g_object_ref (shader);
diff --git a/gsk/gskrendernodeprivate.h b/gsk/gskrendernodeprivate.h
index 637e6cb4fd..02bd846979 100644
--- a/gsk/gskrendernodeprivate.h
+++ b/gsk/gskrendernodeprivate.h
@@ -29,6 +29,7 @@ struct _GskRenderNode
   graphene_rect_t bounds;
 
   guint prefers_high_depth : 1;
+  guint offscreen_for_opacity : 1;
 };
 
 struct _GskRenderNodeClass
@@ -115,6 +116,8 @@ gboolean       gsk_render_node_prefers_high_depth       (const GskRenderNode *no
 
 gboolean       gsk_container_node_is_disjoint           (const GskRenderNode *node);
 
+gboolean       gsk_render_node_use_offscreen_for_opacity (const GskRenderNode *node);
+
 
 G_END_DECLS
 


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]