summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthias Clasen <mclasen@redhat.com>2022-04-05 14:55:36 -0400
committerMatthias Clasen <mclasen@redhat.com>2022-04-05 14:57:38 -0400
commit38eb182947894e956e575fde36ed41275b49dc05 (patch)
tree7546dea1caa515c6c22baa84e571281ff90eef0d
parent0eba21b2b58593599829732c5556f0a15ed75a06 (diff)
downloadgtk+-38eb182947894e956e575fde36ed41275b49dc05.tar.gz
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.
-rw-r--r--gsk/gskrendernode.c19
-rw-r--r--gsk/gskrendernodeimpl.c26
-rw-r--r--gsk/gskrendernodeprivate.h3
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