From a96868d1b0abae1f546153f8d8d921bd40d2f209 Mon Sep 17 00:00:00 2001 From: Georges Basile Stavracas Neto Date: Thu, 10 Dec 2020 17:21:11 -0300 Subject: [PATCH] st: Switch to render nodes Switch to render nodes. Most of the changes follow the pattern of replacing a cogl_framebuffer_draw_*() call by (1) creating a paint node, and (2) calling the corresponding clutter_paint_node_add_*() API. StWidget now overrides ClutterActor.paint_node(), instead of paint. All subclasses that overrided the paint vfunc also are changed to override paint_node. The entry point for CSS rendering, st_widget_paint_background(), now receives a root ClutterPaintNode, and propagates it to the rendering machinery. Part-of: --- src/st/st-entry.c | 21 +- src/st/st-icon.c | 14 +- src/st/st-label.c | 16 +- src/st/st-private.c | 19 +- src/st/st-private.h | 10 +- src/st/st-shadow.c | 12 +- src/st/st-shadow.h | 8 +- src/st/st-theme-node-drawing.c | 455 +++++++++++++++++++----------- src/st/st-theme-node-private.h | 1 - src/st/st-theme-node-transition.c | 44 +-- src/st/st-theme-node-transition.h | 2 +- src/st/st-theme-node.c | 1 - src/st/st-theme-node.h | 2 +- src/st/st-viewport.c | 40 ++- src/st/st-widget.c | 21 +- src/st/st-widget.h | 4 +- 16 files changed, 398 insertions(+), 272 deletions(-) diff --git a/src/st/st-entry.c b/src/st/st-entry.c index d90d4da6b..ccd6e3f9a 100644 --- a/src/st/st-entry.c +++ b/src/st/st-entry.c @@ -817,13 +817,12 @@ st_entry_leave_event (ClutterActor *actor, } static void -st_entry_paint (ClutterActor *actor, - ClutterPaintContext *paint_context) +st_entry_paint_node (ClutterActor *actor, + ClutterPaintNode *node) { StEntryPrivate *priv = ST_ENTRY_PRIV (actor); - ClutterActorClass *parent_class; - st_widget_paint_background (ST_WIDGET (actor), paint_context); + st_widget_paint_background (ST_WIDGET (actor), node); if (priv->shadow_spec) { @@ -851,23 +850,13 @@ st_entry_paint (ClutterActor *actor, if (priv->text_shadow_material != NULL) { - CoglFramebuffer *framebuffer = - clutter_paint_context_get_framebuffer (paint_context); - _st_paint_shadow_with_opacity (priv->shadow_spec, - framebuffer, + node, priv->text_shadow_material, &allocation, clutter_actor_get_paint_opacity (priv->entry)); } } - - /* Since we paint the background ourselves, chain to the parent class - * of StWidget, to avoid painting it twice. - * This is needed as we still want to paint children. - */ - parent_class = g_type_class_peek_parent (st_entry_parent_class); - parent_class->paint (actor, paint_context); } static void @@ -901,7 +890,7 @@ st_entry_class_init (StEntryClass *klass) actor_class->get_preferred_width = st_entry_get_preferred_width; actor_class->get_preferred_height = st_entry_get_preferred_height; actor_class->allocate = st_entry_allocate; - actor_class->paint = st_entry_paint; + actor_class->paint_node = st_entry_paint_node; actor_class->unmap = st_entry_unmap; actor_class->get_paint_volume = st_entry_get_paint_volume; diff --git a/src/st/st-icon.c b/src/st/st-icon.c index 122999893..c02ab493c 100644 --- a/src/st/st-icon.c +++ b/src/st/st-icon.c @@ -200,13 +200,13 @@ st_icon_dispose (GObject *gobject) } static void -st_icon_paint (ClutterActor *actor, - ClutterPaintContext *paint_context) +st_icon_paint_node (ClutterActor *actor, + ClutterPaintNode *node) { StIcon *icon = ST_ICON (actor); StIconPrivate *priv = icon->priv; - st_widget_paint_background (ST_WIDGET (actor), paint_context); + st_widget_paint_background (ST_WIDGET (actor), node); if (priv->icon_texture) { @@ -215,18 +215,14 @@ st_icon_paint (ClutterActor *actor, if (priv->shadow_pipeline) { ClutterActorBox allocation; - CoglFramebuffer *framebuffer; clutter_actor_get_allocation_box (priv->icon_texture, &allocation); - framebuffer = clutter_paint_context_get_framebuffer (paint_context); _st_paint_shadow_with_opacity (priv->shadow_spec, - framebuffer, + node, priv->shadow_pipeline, &allocation, clutter_actor_get_paint_opacity (priv->icon_texture)); } - - clutter_actor_paint (priv->icon_texture, paint_context); } } @@ -300,7 +296,7 @@ st_icon_class_init (StIconClass *klass) object_class->set_property = st_icon_set_property; object_class->dispose = st_icon_dispose; - actor_class->paint = st_icon_paint; + actor_class->paint_node = st_icon_paint_node; widget_class->style_changed = st_icon_style_changed; actor_class->resource_scale_changed = st_icon_resource_scale_changed; diff --git a/src/st/st-label.c b/src/st/st-label.c index 71cadb58d..d53dc588f 100644 --- a/src/st/st-label.c +++ b/src/st/st-label.c @@ -205,12 +205,12 @@ st_label_dispose (GObject *object) } static void -st_label_paint (ClutterActor *actor, - ClutterPaintContext *paint_context) +st_label_paint_node (ClutterActor *actor, + ClutterPaintNode *node) { StLabelPrivate *priv = ST_LABEL (actor)->priv; - st_widget_paint_background (ST_WIDGET (actor), paint_context); + st_widget_paint_background (ST_WIDGET (actor), node); if (priv->shadow_spec) { @@ -241,19 +241,13 @@ st_label_paint (ClutterActor *actor, if (priv->text_shadow_pipeline != NULL) { - CoglFramebuffer *framebuffer; - - framebuffer = - clutter_paint_context_get_framebuffer (paint_context); _st_paint_shadow_with_opacity (priv->shadow_spec, - framebuffer, + node, priv->text_shadow_pipeline, &allocation, clutter_actor_get_paint_opacity (priv->label)); } } - - clutter_actor_paint (priv->label, paint_context); } static void @@ -278,7 +272,7 @@ st_label_class_init (StLabelClass *klass) gobject_class->get_property = st_label_get_property; gobject_class->dispose = st_label_dispose; - actor_class->paint = st_label_paint; + actor_class->paint_node = st_label_paint_node; actor_class->allocate = st_label_allocate; actor_class->get_preferred_width = st_label_get_preferred_width; actor_class->get_preferred_height = st_label_get_preferred_height; diff --git a/src/st/st-private.c b/src/st/st-private.c index 38b2c9c5c..5caabcd07 100644 --- a/src/st/st-private.c +++ b/src/st/st-private.c @@ -773,12 +773,13 @@ _st_create_shadow_cairo_pattern (StShadow *shadow_spec_in, } void -_st_paint_shadow_with_opacity (StShadow *shadow_spec, - CoglFramebuffer *framebuffer, - CoglPipeline *shadow_pipeline, - ClutterActorBox *box, - guint8 paint_opacity) +_st_paint_shadow_with_opacity (StShadow *shadow_spec, + ClutterPaintNode *node, + CoglPipeline *shadow_pipeline, + ClutterActorBox *box, + guint8 paint_opacity) { + g_autoptr (ClutterPaintNode) pipeline_node = NULL; ClutterActorBox shadow_box; CoglColor color; @@ -794,8 +795,8 @@ _st_paint_shadow_with_opacity (StShadow *shadow_spec, shadow_spec->color.alpha / 255.0 * paint_opacity / 255.0); cogl_color_premultiply (&color); cogl_pipeline_set_layer_combine_constant (shadow_pipeline, 0, &color); - cogl_framebuffer_draw_rectangle (framebuffer, - shadow_pipeline, - shadow_box.x1, shadow_box.y1, - shadow_box.x2, shadow_box.y2); + + pipeline_node = clutter_pipeline_node_new (shadow_pipeline); + clutter_paint_node_add_child (node, pipeline_node); + clutter_paint_node_add_rectangle (pipeline_node, &shadow_box); } diff --git a/src/st/st-private.h b/src/st/st-private.h index 3f1fd1295..6e5c1197a 100644 --- a/src/st/st-private.h +++ b/src/st/st-private.h @@ -66,10 +66,10 @@ CoglPipeline * _st_create_shadow_pipeline_from_actor (StShadow *shadow_spec, cairo_pattern_t *_st_create_shadow_cairo_pattern (StShadow *shadow_spec, cairo_pattern_t *src_pattern); -void _st_paint_shadow_with_opacity (StShadow *shadow_spec, - CoglFramebuffer *framebuffer, - CoglPipeline *shadow_pipeline, - ClutterActorBox *box, - guint8 paint_opacity); +void _st_paint_shadow_with_opacity (StShadow *shadow_spec, + ClutterPaintNode *node, + CoglPipeline *shadow_pipeline, + ClutterActorBox *box, + guint8 paint_opacity); #endif /* __ST_PRIVATE_H__ */ diff --git a/src/st/st-shadow.c b/src/st/st-shadow.c index 7239241b4..a406b6153 100644 --- a/src/st/st-shadow.c +++ b/src/st/st-shadow.c @@ -281,7 +281,7 @@ st_shadow_helper_free (StShadowHelper *helper) /** * st_shadow_helper_paint: * @helper: a #StShadowHelper - * @framebuffer: a #CoglFramebuffer + * @node: a #ClutterPaintNode * @actor_box: the bounding box of the shadow * @paint_opacity: the opacity at which the shadow is painted * @@ -289,13 +289,13 @@ st_shadow_helper_free (StShadowHelper *helper) * be called from the implementation of ClutterActor::paint(). */ void -st_shadow_helper_paint (StShadowHelper *helper, - CoglFramebuffer *framebuffer, - ClutterActorBox *actor_box, - guint8 paint_opacity) +st_shadow_helper_paint (StShadowHelper *helper, + ClutterPaintNode *node, + ClutterActorBox *actor_box, + uint8_t paint_opacity) { _st_paint_shadow_with_opacity (helper->shadow, - framebuffer, + node, helper->pipeline, actor_box, paint_opacity); diff --git a/src/st/st-shadow.h b/src/st/st-shadow.h index b24ab9b04..f7703f943 100644 --- a/src/st/st-shadow.h +++ b/src/st/st-shadow.h @@ -84,10 +84,10 @@ void st_shadow_helper_free (StShadowHelper *helper); void st_shadow_helper_update (StShadowHelper *helper, ClutterActor *source); -void st_shadow_helper_paint (StShadowHelper *helper, - CoglFramebuffer *framebuffer, - ClutterActorBox *actor_box, - guint8 paint_opacity); +void st_shadow_helper_paint (StShadowHelper *helper, + ClutterPaintNode *node, + ClutterActorBox *actor_box, + uint8_t paint_opacity); G_END_DECLS diff --git a/src/st/st-theme-node-drawing.c b/src/st/st-theme-node-drawing.c index b938558d1..774544cc0 100644 --- a/src/st/st-theme-node-drawing.c +++ b/src/st/st-theme-node-drawing.c @@ -1363,7 +1363,7 @@ st_theme_node_prerender_background (StThemeNode *node, } static void st_theme_node_paint_borders (StThemeNodePaintState *state, - CoglFramebuffer *framebuffer, + ClutterPaintNode *node, const ClutterActorBox *box, StPaintBordersMode mode, guint8 paint_opacity); @@ -1667,12 +1667,13 @@ st_theme_node_update_resources (StThemeNodePaintState *state, } static void -paint_material_with_opacity (CoglPipeline *material, - CoglFramebuffer *framebuffer, - ClutterActorBox *box, - ClutterActorBox *coords, - guint8 paint_opacity) +paint_material_with_opacity (ClutterPaintNode *node, + CoglPipeline *material, + ClutterActorBox *box, + ClutterActorBox *coords, + guint8 paint_opacity) { + g_autoptr (ClutterPaintNode) pipeline_node = NULL; CoglColor color; cogl_color_init_from_4f (&color, @@ -1680,37 +1681,20 @@ paint_material_with_opacity (CoglPipeline *material, paint_opacity / 255.0, paint_opacity / 255.0); cogl_pipeline_set_color (material, &color); + pipeline_node = clutter_pipeline_node_new (material); + clutter_paint_node_add_child (node, pipeline_node); + if (coords) - cogl_framebuffer_draw_textured_rectangle (framebuffer, material, - box->x1, box->y1, box->x2, box->y2, - coords->x1, coords->y1, coords->x2, coords->y2); + clutter_paint_node_add_texture_rectangle (pipeline_node, box, + coords->x1, coords->y1, + coords->x2, coords->y2); else - cogl_framebuffer_draw_rectangle (framebuffer, material, - box->x1, box->y1, box->x2, box->y2); -} - -static void -st_theme_node_ensure_color_pipeline (StThemeNode *node) -{ - static CoglPipeline *color_pipeline_template = NULL; - - if (node->color_pipeline != NULL) - return; - - if (G_UNLIKELY (color_pipeline_template == NULL)) - { - CoglContext *ctx = - clutter_backend_get_cogl_context (clutter_get_default_backend ()); - - color_pipeline_template = cogl_pipeline_new (ctx); - } - - node->color_pipeline = cogl_pipeline_copy (color_pipeline_template); + clutter_paint_node_add_rectangle (pipeline_node, box); } static void st_theme_node_paint_borders (StThemeNodePaintState *state, - CoglFramebuffer *framebuffer, + ClutterPaintNode *root, const ClutterActorBox *box, StPaintBordersMode mode, guint8 paint_opacity) @@ -1766,13 +1750,14 @@ st_theme_node_paint_borders (StThemeNodePaintState *state, if (alpha > 0) { - st_theme_node_ensure_color_pipeline (node); - cogl_color_init_from_4f (&pipeline_color, - effective_border.red / 255.0 * alpha / 255.0, - effective_border.green / 255.0 * alpha / 255.0, - effective_border.blue / 255.0 * alpha / 255.0, - alpha / 255.0); - cogl_pipeline_set_color (node->color_pipeline, &pipeline_color); + g_autoptr (ClutterPaintNode) border_color_node = NULL; + CoglColor color; + + cogl_color_init_from_4f (&color, + effective_border.red / 255.0f, + effective_border.green / 255.0f, + effective_border.blue / 255.0f, + alpha / 255.0f); /* NORTH */ skip_corner_1 = border_radius[ST_CORNER_TOPLEFT] > 0; @@ -1815,9 +1800,11 @@ st_theme_node_paint_borders (StThemeNodePaintState *state, rects[15] = skip_corner_2 ? height - max_width_radius[ST_CORNER_BOTTOMLEFT] : height - border_width[ST_SIDE_BOTTOM]; - cogl_framebuffer_draw_rectangles (framebuffer, - node->color_pipeline, - rects, 4); + border_color_node = clutter_color_node_new (&color); + clutter_paint_node_set_static_name (border_color_node, + "StThemeNode (CSS borders)"); + clutter_paint_node_add_child (root, border_color_node); + clutter_paint_node_add_rectangles (border_color_node, rects, 4); } } @@ -1833,44 +1820,67 @@ st_theme_node_paint_borders (StThemeNodePaintState *state, { for (corner_id = 0; corner_id < 4; corner_id++) { + g_autoptr (ClutterPaintNode) corners_node = NULL; + if (state->corner_material[corner_id] == NULL) continue; cogl_pipeline_set_color (state->corner_material[corner_id], &pipeline_color); + corners_node = + clutter_pipeline_node_new (state->corner_material[corner_id]); + clutter_paint_node_set_static_name (corners_node, + "StThemeNode (CSS border corners)"); + clutter_paint_node_add_child (root, corners_node); + switch (corner_id) { - case ST_CORNER_TOPLEFT: - cogl_framebuffer_draw_textured_rectangle (framebuffer, - state->corner_material[corner_id], 0, 0, - max_width_radius[ST_CORNER_TOPLEFT], max_width_radius[ST_CORNER_TOPLEFT], - 0, 0, 0.5, 0.5); - break; - case ST_CORNER_TOPRIGHT: - cogl_framebuffer_draw_textured_rectangle (framebuffer, - state->corner_material[corner_id], - width - max_width_radius[ST_CORNER_TOPRIGHT], 0, - width, max_width_radius[ST_CORNER_TOPRIGHT], - 0.5, 0, 1, 0.5); - break; - case ST_CORNER_BOTTOMRIGHT: - cogl_framebuffer_draw_textured_rectangle (framebuffer, - state->corner_material[corner_id], - width - max_width_radius[ST_CORNER_BOTTOMRIGHT], - height - max_width_radius[ST_CORNER_BOTTOMRIGHT], - width, height, - 0.5, 0.5, 1, 1); - break; - case ST_CORNER_BOTTOMLEFT: - cogl_framebuffer_draw_textured_rectangle (framebuffer, - state->corner_material[corner_id], - 0, height - max_width_radius[ST_CORNER_BOTTOMLEFT], - max_width_radius[ST_CORNER_BOTTOMLEFT], height, - 0, 0.5, 0.5, 1); - break; - default: - g_assert_not_reached(); - break; + case ST_CORNER_TOPLEFT: + clutter_paint_node_add_texture_rectangle (corners_node, + &(ClutterActorBox) { + 0, 0, + max_width_radius[ST_CORNER_TOPLEFT], + max_width_radius[ST_CORNER_TOPLEFT], + }, + 0.0, 0.0, + 0.5, 0.5); + break; + case ST_CORNER_TOPRIGHT: + clutter_paint_node_add_texture_rectangle (corners_node, + &(ClutterActorBox) { + width - max_width_radius[ST_CORNER_TOPRIGHT], + 0, + width, + max_width_radius[ST_CORNER_TOPRIGHT], + }, + 0.5, 0.0, + 1.0, 0.5); + break; + case ST_CORNER_BOTTOMRIGHT: + clutter_paint_node_add_texture_rectangle (corners_node, + &(ClutterActorBox) { + width - max_width_radius[ST_CORNER_BOTTOMRIGHT], + height - max_width_radius[ST_CORNER_BOTTOMRIGHT], + width, + height, + }, + 0.5, 0.5, + 1.0, 1.0); + break; + case ST_CORNER_BOTTOMLEFT: + clutter_paint_node_add_texture_rectangle (corners_node, + &(ClutterActorBox) { + 0, + height - max_width_radius[ST_CORNER_BOTTOMLEFT], + max_width_radius[ST_CORNER_BOTTOMLEFT], + height, + }, + 0.0, 0.5, + 0.5, 1.0); + break; + default: + g_assert_not_reached(); + break; } } } @@ -1881,13 +1891,20 @@ st_theme_node_paint_borders (StThemeNodePaintState *state, paint_opacity * node->background_color.alpha / 255; if (alpha > 0) { - st_theme_node_ensure_color_pipeline (node); - cogl_color_init_from_4f (&pipeline_color, - node->background_color.red / 255.0 * alpha / 255.0, - node->background_color.green / 255.0 * alpha / 255.0, - node->background_color.blue / 255.0 * alpha / 255.0, - alpha / 255.0); - cogl_pipeline_set_color (node->color_pipeline, &pipeline_color); + g_autoptr (ClutterPaintNode) background_color_node = NULL; + CoglColor color; + + cogl_color_init_from_4f (&color, + node->background_color.red / 255.0f, + node->background_color.green / 255.0f, + node->background_color.blue / 255.0f, + alpha / 255.0f); + + background_color_node = clutter_color_node_new (&color); + clutter_paint_node_set_static_name (background_color_node, + "StThemeNode (CSS background color)"); + clutter_paint_node_add_child (root, background_color_node); + /* We add padding to each corner, so that all corners end up as if they * had a border-radius of max_border_radius, which allows us to treat * corners as uniform further on. @@ -1973,9 +1990,10 @@ st_theme_node_paint_borders (StThemeNodePaintState *state, g_assert_not_reached(); break; } - cogl_framebuffer_draw_rectangles (framebuffer, - node->color_pipeline, - verts, n_rects); + + clutter_paint_node_add_rectangles (background_color_node, + verts, + n_rects); } /* Once we've drawn the borders and corners, if the corners are bigger @@ -1990,32 +2008,44 @@ st_theme_node_paint_borders (StThemeNodePaintState *state, * necessary, then the main rectangle */ if (max_border_radius > border_width[ST_SIDE_TOP]) - cogl_framebuffer_draw_rectangle (framebuffer, node->color_pipeline, - MAX(max_border_radius, border_width[ST_SIDE_LEFT]), - border_width[ST_SIDE_TOP], - width - MAX(max_border_radius, border_width[ST_SIDE_RIGHT]), - max_border_radius); - if (max_border_radius > border_width[ST_SIDE_BOTTOM]) - cogl_framebuffer_draw_rectangle (framebuffer, node->color_pipeline, - MAX(max_border_radius, border_width[ST_SIDE_LEFT]), - height - max_border_radius, - width - MAX(max_border_radius, border_width[ST_SIDE_RIGHT]), - height - border_width[ST_SIDE_BOTTOM]); + { + clutter_paint_node_add_rectangle (background_color_node, + &(ClutterActorBox) { + MAX (max_border_radius, border_width[ST_SIDE_LEFT]), + border_width[ST_SIDE_TOP], + width - MAX (max_border_radius, border_width[ST_SIDE_RIGHT]), + max_border_radius, + }); + } - cogl_framebuffer_draw_rectangle (framebuffer, node->color_pipeline, - border_width[ST_SIDE_LEFT], - MAX(border_width[ST_SIDE_TOP], max_border_radius), - width - border_width[ST_SIDE_RIGHT], - height - MAX(border_width[ST_SIDE_BOTTOM], max_border_radius)); + if (max_border_radius > border_width[ST_SIDE_BOTTOM]) + { + clutter_paint_node_add_rectangle (background_color_node, + &(ClutterActorBox) { + MAX (max_border_radius, border_width[ST_SIDE_LEFT]), + height - max_border_radius, + width - MAX (max_border_radius, border_width[ST_SIDE_RIGHT]), + height - border_width[ST_SIDE_BOTTOM], + }); + } + + clutter_paint_node_add_rectangle (background_color_node, + &(ClutterActorBox) { + border_width[ST_SIDE_LEFT], + MAX (border_width[ST_SIDE_TOP], max_border_radius), + width - border_width[ST_SIDE_RIGHT], + height - MAX (border_width[ST_SIDE_BOTTOM], max_border_radius) + }); } } static void st_theme_node_paint_sliced_shadow (StThemeNodePaintState *state, - CoglFramebuffer *framebuffer, + ClutterPaintNode *root, const ClutterActorBox *box, guint8 paint_opacity) { + g_autoptr (ClutterPaintNode) pipeline_node = NULL; StThemeNode *node = state->node; guint border_radius[4]; CoglColor color; @@ -2261,50 +2291,118 @@ st_theme_node_paint_sliced_shadow (StThemeNodePaintState *state, } } - cogl_framebuffer_draw_textured_rectangles (framebuffer, state->box_shadow_pipeline, - rectangles, idx / 8); + pipeline_node = clutter_pipeline_node_new (state->box_shadow_pipeline); + clutter_paint_node_set_static_name (pipeline_node, + "StThemeNode (CSS box-shadow)"); + clutter_paint_node_add_child (root, pipeline_node); + clutter_paint_node_add_texture_rectangles (pipeline_node, + rectangles, + idx / 8); #if 0 + g_autoptr (ClutterPaintNode) color_node = NULL; + CoglColor red; + /* Visual feedback on shadow's 9-slice and original offscreen buffer, for debug purposes */ - cogl_framebuffer_draw_rectangle (framebuffer, state->box_shadow_pipeline, - xend, yoffset, xend + shadow_width, yoffset + shadow_height); + clutter_paint_node_add_rectangle (pipeline_node, + &(ClutterActorBox) { + xend, + yoffset, + xend + shadow_width, + yoffset + shadow_height, + }); - st_theme_node_ensure_color_pipeline (node); - cogl_color_init_from_4f (&color, 1.0, 0.0, 0.0, 1.0); - cogl_pipeline_set_color (node->color_pipeline, &color); + cogl_color_init_from_4f (&red, 1.0, 0.0, 0.0, 1.0); + cogl_pipeline_set_color (node->color_pipeline, &red); + color_node = clutter_color_node_new (&red); + clutter_paint_node_set_static_name (color_node, + "StThemeNode (CSS box-shadow - debug)"); + clutter_paint_node_add_child (root, color_node); - cogl_framebuffer_draw_rectangle (framebuffer, node->color_pipeline, - xoffset, top, xend, top + 1); - cogl_framebuffer_draw_rectangle (framebuffer, node->color_pipeline, - xoffset, bottom, xend, bottom + 1); - cogl_framebuffer_draw_rectangle (framebuffer, node->color_pipeline, - left, yoffset, left + 1, yend); - cogl_framebuffer_draw_rectangle (framebuffer, node->color_pipeline, - right, yoffset, right + 1, yend); + clutter_paint_node_add_rectangle (color_node, + &(ClutterActorBox) { + xoffset, + top, + xend, + top + 1, + }); + clutter_paint_node_add_rectangle (color_node, + &(ClutterActorBox) { + xoffset, + bottom, + xend, + bottom + 1, + }); + clutter_paint_node_add_rectangle (color_node, + &(ClutterActorBox) { + left, + yoffset, + left + 1, + yend, + }); + clutter_paint_node_add_rectangle (color_node, + &(ClutterActorBox) { + right, + yoffset, + right + 1, + yend, + }); - cogl_framebuffer_draw_rectangle (framebuffer, node->color_pipeline, - xend, yoffset, xend + shadow_width, yoffset + 1); - cogl_framebuffer_draw_rectangle (framebuffer, node->color_pipeline, - xend, yoffset + shadow_height, xend + shadow_width, yoffset + shadow_height + 1); - cogl_framebuffer_draw_rectangle (framebuffer, node->color_pipeline, - xend, yoffset, xend + 1, yoffset + shadow_height); - cogl_framebuffer_draw_rectangle (framebuffer, node->color_pipeline, - xend + shadow_width, yoffset, xend + shadow_width + 1, yoffset + shadow_height); + clutter_paint_node_add_rectangle (color_node, + &(ClutterActorBox) { + xend, + yoffset, + xend + shadow_width, + yoffset + 1, + }); + clutter_paint_node_add_rectangle (color_node, + &(ClutterActorBox) { + xend, + yoffset + shadow_height, + xend + shadow_width, + yoffset + shadow_height + 1, + }); + clutter_paint_node_add_rectangle (color_node, + &(ClutterActorBox) { + xend, + yoffset, + xend + 1, + yoffset + shadow_height, + }); + clutter_paint_node_add_rectangle (color_node, + &(ClutterActorBox) { + xend + shadow_width, + yoffset, + xend + shadow_width + 1, + yoffset + shadow_height, + }); s_top *= shadow_height; s_bottom *= shadow_height; s_left *= shadow_width; s_right *= shadow_width; - cogl_framebuffer_draw_rectangle (framebuffer, node->color_pipeline, - xend, yoffset + s_top, xend + shadow_width, yoffset + s_top + 1); - cogl_framebuffer_draw_rectangle (framebuffer, node->color_pipeline, - xend, yoffset + s_bottom, xend + shadow_width, yoffset + s_bottom + 1); - cogl_framebuffer_draw_rectangle (framebuffer, node->color_pipeline, - xend + s_left, yoffset, xend + s_left + 1, yoffset + shadow_height); - cogl_framebuffer_draw_rectangle (framebuffer, node->color_pipeline, - xend + s_right, yoffset, xend + s_right + 1, yoffset + shadow_height); + clutter_paint_node_add_rectangle (color_node, + &(ClutterActorBox) { + xend, yoffset + s_top, + xend + shadow_width, yoffset + s_top + 1, + }); + clutter_paint_node_add_rectangle (color_node, + &(ClutterActorBox) { + xend, yoffset + s_bottom, + xend + shadow_width, yoffset + s_bottom + 1, + }); + clutter_paint_node_add_rectangle (color_node, + &(ClutterActorBox) { + xend + s_left, yoffset, + xend + s_left + 1, yoffset + shadow_height, + }); + clutter_paint_node_add_rectangle (color_node, + &(ClutterActorBox) { + xend + s_right, yoffset, + xend + s_right + 1, yoffset + shadow_height, + }); #endif } @@ -2334,6 +2432,9 @@ st_theme_node_prerender_shadow (StThemeNodePaintState *state) if (cogl_framebuffer_allocate (framebuffer, &error)) { + g_autoptr (ClutterPaintNode) root_node = NULL; + ClutterPaintContext *paint_context; + CoglColor clear_color; ClutterActorBox box = { 0, 0, state->box_shadow_width, state->box_shadow_height}; cogl_framebuffer_orthographic (framebuffer, 0, 0, @@ -2341,9 +2442,21 @@ st_theme_node_prerender_shadow (StThemeNodePaintState *state) cogl_framebuffer_scale (framebuffer, state->resource_scale, state->resource_scale, 1); - cogl_framebuffer_clear4f (framebuffer, COGL_BUFFER_BIT_COLOR, 0, 0, 0, 0); - st_theme_node_paint_borders (state, framebuffer, &box, ST_PAINT_BORDERS_MODE_SILHOUETTE, 0xFF); + cogl_color_init_from_4f (&clear_color, 0, 0, 0, 0); + root_node = clutter_root_node_new (framebuffer, + &clear_color, + COGL_BUFFER_BIT_COLOR); + + st_theme_node_paint_borders (state, root_node, &box, + ST_PAINT_BORDERS_MODE_SILHOUETTE, 0xff); + + paint_context = + clutter_paint_context_new_for_framebuffer (framebuffer, + NULL, + CLUTTER_PAINT_FLAG_NONE); + clutter_paint_node_paint (root_node, paint_context); + clutter_paint_context_destroy (paint_context); state->box_shadow_pipeline = _st_create_shadow_pipeline (st_theme_node_get_box_shadow (node), buffer, state->resource_scale); @@ -2388,12 +2501,13 @@ st_theme_node_compute_maximum_borders (StThemeNodePaintState *state) } static void -st_theme_node_paint_sliced_border_image (StThemeNode *node, - CoglFramebuffer *framebuffer, - float width, - float height, - guint8 paint_opacity) +st_theme_node_paint_sliced_border_image (StThemeNode *node, + ClutterPaintNode *root, + float width, + float height, + guint8 paint_opacity) { + g_autoptr (ClutterPaintNode) pipeline_node = NULL; gfloat ex, ey; gfloat tx1, ty1, tx2, ty2; gint border_left, border_right, border_top, border_bottom; @@ -2479,21 +2593,27 @@ st_theme_node_paint_sliced_border_image (StThemeNode *node, 1.0, 1.0 }; - cogl_framebuffer_draw_textured_rectangles (framebuffer, pipeline, rectangles, 9); + pipeline_node = clutter_pipeline_node_new (pipeline); + clutter_paint_node_set_static_name (pipeline_node, + "StThemeNode (CSS border image)"); + clutter_paint_node_add_child (root, pipeline_node); + clutter_paint_node_add_texture_rectangles (pipeline_node, rectangles, 9); } } static void st_theme_node_paint_outline (StThemeNode *node, - CoglFramebuffer *framebuffer, + ClutterPaintNode *root, const ClutterActorBox *box, guint8 paint_opacity) { + g_autoptr (ClutterPaintNode) outline_node = NULL; + CoglColor color; float width, height; int outline_width; float rects[16]; - CoglColor outline_color, effective_outline, pipeline_color; + CoglColor outline_color, effective_outline; guint8 alpha; width = box->x2 - box->x1; @@ -2508,13 +2628,11 @@ st_theme_node_paint_outline (StThemeNode *node, alpha = paint_opacity * outline_color.alpha / 255; - st_theme_node_ensure_color_pipeline (node); - cogl_color_init_from_4f (&pipeline_color, - effective_outline.red / 255.0 * alpha / 255.0, - effective_outline.green / 255.0 * alpha / 255.0, - effective_outline.blue / 255.0 * alpha / 255.0, - alpha / 255.0); - cogl_pipeline_set_color (node->color_pipeline, &pipeline_color); + cogl_color_init_from_4f (&color, + effective_outline.red / 255.0f, + effective_outline.green / 255.0f, + effective_outline.blue / 255.0f, + alpha / 255.0f); /* The outline is drawn just outside the border, which means just * outside the allocation box. This means that in some situations @@ -2546,7 +2664,11 @@ st_theme_node_paint_outline (StThemeNode *node, rects[14] = 0; rects[15] = height; - cogl_framebuffer_draw_rectangles (framebuffer, node->color_pipeline, rects, 4); + outline_node = clutter_color_node_new (&color); + clutter_paint_node_set_static_name (outline_node, + "StThemeNode (CSS outline)"); + clutter_paint_node_add_child (root, outline_node); + clutter_paint_node_add_rectangles (outline_node, rects, 4); } static gboolean @@ -2594,7 +2716,7 @@ st_theme_node_needs_new_box_shadow_for_size (StThemeNodePaintState *state, void st_theme_node_paint (StThemeNode *node, StThemeNodePaintState *state, - CoglFramebuffer *framebuffer, + ClutterPaintNode *root, const ClutterActorBox *box, guint8 paint_opacity, float resource_scale) @@ -2669,13 +2791,13 @@ st_theme_node_paint (StThemeNode *node, if (state->alloc_width < node->box_shadow_min_width || state->alloc_height < node->box_shadow_min_height) _st_paint_shadow_with_opacity (node->box_shadow, - framebuffer, + root, state->box_shadow_pipeline, &allocation, paint_opacity); else st_theme_node_paint_sliced_shadow (state, - framebuffer, + root, &allocation, paint_opacity); } @@ -2691,22 +2813,22 @@ st_theme_node_paint (StThemeNode *node, &allocation, &paint_box); - paint_material_with_opacity (state->prerendered_pipeline, - framebuffer, + paint_material_with_opacity (root, + state->prerendered_pipeline, &paint_box, NULL, paint_opacity); } if (node->border_slices_pipeline != NULL) - st_theme_node_paint_sliced_border_image (node, framebuffer, width, height, paint_opacity); + st_theme_node_paint_sliced_border_image (node, root, width, height, paint_opacity); } else { - st_theme_node_paint_borders (state, framebuffer, box, ST_PAINT_BORDERS_MODE_COLOR, paint_opacity); + st_theme_node_paint_borders (state, root, box, ST_PAINT_BORDERS_MODE_COLOR, paint_opacity); } - st_theme_node_paint_outline (node, framebuffer, box, paint_opacity); + st_theme_node_paint_outline (node, root, box, paint_opacity); if (state->prerendered_pipeline == NULL && st_theme_node_load_background_image (node, resource_scale)) @@ -2725,9 +2847,15 @@ st_theme_node_paint (StThemeNode *node, &background_box, &texture_coords); if (has_visible_outline || node->background_repeat) - cogl_framebuffer_push_rectangle_clip (framebuffer, - allocation.x1, allocation.y1, - allocation.x2, allocation.y2); + { + g_autoptr (ClutterPaintNode) clip_node = NULL; + + clip_node = clutter_clip_node_new (); + clutter_paint_node_add_child (root, clip_node); + clutter_paint_node_add_rectangle (clip_node, &allocation); + + root = clip_node; + } /* CSS based drop shadows * @@ -2744,19 +2872,16 @@ st_theme_node_paint (StThemeNode *node, */ if (node->background_shadow_pipeline != NULL) _st_paint_shadow_with_opacity (node->background_image_shadow, - framebuffer, + root, node->background_shadow_pipeline, &background_box, paint_opacity); - paint_material_with_opacity (node->background_pipeline, - framebuffer, + paint_material_with_opacity (root, + node->background_pipeline, &background_box, &texture_coords, paint_opacity); - - if (has_visible_outline || node->background_repeat) - cogl_framebuffer_pop_clip (framebuffer); } } diff --git a/src/st/st-theme-node-private.h b/src/st/st-theme-node-private.h index 82ca88763..9a910089c 100644 --- a/src/st/st-theme-node-private.h +++ b/src/st/st-theme-node-private.h @@ -112,7 +112,6 @@ struct _StThemeNode { CoglTexture *background_texture; CoglPipeline *background_pipeline; CoglPipeline *background_shadow_pipeline; - CoglPipeline *color_pipeline; StThemeNodePaintState cached_state; diff --git a/src/st/st-theme-node-transition.c b/src/st/st-theme-node-transition.c index f7932cd6f..19e90e822 100644 --- a/src/st/st-theme-node-transition.c +++ b/src/st/st-theme-node-transition.c @@ -244,10 +244,14 @@ st_theme_node_transition_get_paint_box (StThemeNodeTransition *transition, static gboolean setup_framebuffers (StThemeNodeTransition *transition, + ClutterPaintNode *node, const ClutterActorBox *allocation, float resource_scale) { StThemeNodeTransitionPrivate *priv = transition->priv; + g_autoptr (ClutterPaintNode) old_layer_node = NULL; + g_autoptr (ClutterPaintNode) new_layer_node = NULL; + CoglPipeline *noop_pipeline; CoglContext *ctx; guint width, height; GError *catch_error = NULL; @@ -319,38 +323,45 @@ setup_framebuffers (StThemeNodeTransition *transition, cogl_pipeline_set_layer_texture (priv->material, 0, priv->new_texture); cogl_pipeline_set_layer_texture (priv->material, 1, priv->old_texture); - cogl_framebuffer_clear4f (priv->old_offscreen, COGL_BUFFER_BIT_COLOR, - 0, 0, 0, 0); + noop_pipeline = cogl_pipeline_new (ctx); cogl_framebuffer_orthographic (priv->old_offscreen, priv->offscreen_box.x1, priv->offscreen_box.y1, priv->offscreen_box.x2, priv->offscreen_box.y2, 0.0, 1.0); - st_theme_node_paint (priv->old_theme_node, &priv->old_paint_state, - priv->old_offscreen, allocation, 255, resource_scale); + old_layer_node = clutter_layer_node_new_to_framebuffer (priv->old_offscreen, + noop_pipeline); + clutter_paint_node_add_child (node, old_layer_node); - cogl_framebuffer_clear4f (priv->new_offscreen, COGL_BUFFER_BIT_COLOR, - 0, 0, 0, 0); + st_theme_node_paint (priv->old_theme_node, &priv->old_paint_state, + old_layer_node, allocation, 255, resource_scale); + + new_layer_node = clutter_layer_node_new_to_framebuffer (priv->new_offscreen, + noop_pipeline); + clutter_paint_node_add_child (node, new_layer_node); cogl_framebuffer_orthographic (priv->new_offscreen, priv->offscreen_box.x1, priv->offscreen_box.y1, priv->offscreen_box.x2, priv->offscreen_box.y2, 0.0, 1.0); st_theme_node_paint (priv->new_theme_node, &priv->new_paint_state, - priv->new_offscreen, allocation, 255, resource_scale); + new_layer_node, allocation, 255, resource_scale); + + g_clear_object (&noop_pipeline); return TRUE; } void st_theme_node_transition_paint (StThemeNodeTransition *transition, - CoglFramebuffer *framebuffer, + ClutterPaintNode *node, ClutterActorBox *allocation, guint8 paint_opacity, float resource_scale) { StThemeNodeTransitionPrivate *priv = transition->priv; + g_autoptr (ClutterPaintNode) pipeline_node = NULL; CoglColor constant, pipeline_color; float tex_coords[] = { @@ -370,7 +381,9 @@ st_theme_node_transition_paint (StThemeNodeTransition *transition, calculate_offscreen_box (transition, allocation); priv->needs_setup = clutter_actor_box_get_area (&priv->offscreen_box) == 0 || - !setup_framebuffers (transition, allocation, + !setup_framebuffers (transition, + node, + allocation, resource_scale); if (priv->needs_setup) /* setting up framebuffers failed */ @@ -386,13 +399,12 @@ st_theme_node_transition_paint (StThemeNodeTransition *transition, paint_opacity / 255.0, paint_opacity / 255.0); cogl_pipeline_set_color (priv->material, &pipeline_color); - cogl_framebuffer_draw_multitextured_rectangle (framebuffer, - priv->material, - priv->offscreen_box.x1, - priv->offscreen_box.y1, - priv->offscreen_box.x2, - priv->offscreen_box.y2, - tex_coords, 8); + pipeline_node = clutter_pipeline_node_new (priv->material); + clutter_paint_node_add_child (node, pipeline_node); + clutter_paint_node_add_multitexture_rectangle (pipeline_node, + &priv->offscreen_box, + tex_coords, + 8); } static void diff --git a/src/st/st-theme-node-transition.h b/src/st/st-theme-node-transition.h index e7420e6d5..e5eff47fb 100644 --- a/src/st/st-theme-node-transition.h +++ b/src/st/st-theme-node-transition.h @@ -42,7 +42,7 @@ void st_theme_node_transition_update (StThemeNodeTransition *transition, StThemeNode *new_node); void st_theme_node_transition_paint (StThemeNodeTransition *transition, - CoglFramebuffer *framebuffer, + ClutterPaintNode *node, ClutterActorBox *allocation, guint8 paint_opacity, float resource_scale); diff --git a/src/st/st-theme-node.c b/src/st/st-theme-node.c index 1c7fb72fc..04f0966f1 100644 --- a/src/st/st-theme-node.c +++ b/src/st/st-theme-node.c @@ -132,7 +132,6 @@ st_theme_node_finalize (GObject *object) g_clear_object (&node->background_shadow_pipeline); g_clear_object (&node->border_slices_texture); g_clear_object (&node->border_slices_pipeline); - g_clear_object (&node->color_pipeline); G_OBJECT_CLASS (st_theme_node_parent_class)->finalize (object); } diff --git a/src/st/st-theme-node.h b/src/st/st-theme-node.h index 63945d559..3227a8f11 100644 --- a/src/st/st-theme-node.h +++ b/src/st/st-theme-node.h @@ -342,7 +342,7 @@ gboolean st_theme_node_paint_equal (StThemeNode *node, */ void st_theme_node_paint (StThemeNode *node, StThemeNodePaintState *state, - CoglFramebuffer *framebuffer, + ClutterPaintNode *root, const ClutterActorBox *box, guint8 paint_opacity, float resource_scale); diff --git a/src/st/st-viewport.c b/src/st/st-viewport.c index c87c0c2b1..a8bd6668c 100644 --- a/src/st/st-viewport.c +++ b/src/st/st-viewport.c @@ -398,6 +398,31 @@ get_border_paint_offsets (StViewport *viewport, } +static void +st_viewport_paint_node (ClutterActor *actor, + ClutterPaintNode *node) +{ + StViewport *viewport = ST_VIEWPORT (actor); + int x, y; + + get_border_paint_offsets (viewport, &x, &y); + if (x != 0 || y != 0) + { + g_autoptr (ClutterPaintNode) transform_node = NULL; + graphene_matrix_t transform; + + graphene_matrix_init_translate (&transform, + &GRAPHENE_POINT3D_INIT (x, y, 0)); + + transform_node = clutter_transform_node_new (&transform); + clutter_paint_node_add_child (node, transform_node); + + node = transform_node; + } + + st_widget_paint_background (ST_WIDGET (actor), node); +} + static void st_viewport_paint (ClutterActor *actor, ClutterPaintContext *paint_context) @@ -411,24 +436,14 @@ st_viewport_paint (ClutterActor *actor, ClutterActor *child; CoglFramebuffer *fb = clutter_paint_context_get_framebuffer (paint_context); - get_border_paint_offsets (viewport, &x, &y); - if (x != 0 || y != 0) - { - cogl_framebuffer_push_matrix (fb); - cogl_framebuffer_translate (fb, x, y, 0); - } - - st_widget_paint_background (ST_WIDGET (actor), paint_context); - - if (x != 0 || y != 0) - cogl_framebuffer_pop_matrix (fb); - if (clutter_actor_get_n_children (actor) == 0) return; clutter_actor_get_allocation_box (actor, &allocation_box); st_theme_node_get_content_box (theme_node, &allocation_box, &content_box); + get_border_paint_offsets (viewport, &x, &y); + content_box.x1 += x; content_box.y1 += y; content_box.x2 += x; @@ -564,6 +579,7 @@ st_viewport_class_init (StViewportClass *klass) actor_class->allocate = st_viewport_allocate; actor_class->apply_transform = st_viewport_apply_transform; + actor_class->paint_node = st_viewport_paint_node; actor_class->paint = st_viewport_paint; actor_class->get_paint_volume = st_viewport_get_paint_volume; actor_class->pick = st_viewport_pick; diff --git a/src/st/st-widget.c b/src/st/st-widget.c index 807d8d0eb..8dba0ce98 100644 --- a/src/st/st-widget.c +++ b/src/st/st-widget.c @@ -418,11 +418,10 @@ st_widget_allocate (ClutterActor *actor, * painting children. */ void -st_widget_paint_background (StWidget *widget, - ClutterPaintContext *paint_context) +st_widget_paint_background (StWidget *widget, + ClutterPaintNode *node) { StWidgetPrivate *priv = st_widget_get_instance_private (widget); - CoglFramebuffer *framebuffer; StThemeNode *theme_node; ClutterActorBox allocation; float resource_scale; @@ -430,7 +429,6 @@ st_widget_paint_background (StWidget *widget, resource_scale = clutter_actor_get_resource_scale (CLUTTER_ACTOR (widget)); - framebuffer = clutter_paint_context_get_framebuffer (paint_context); theme_node = st_widget_get_theme_node (widget); clutter_actor_get_allocation_box (CLUTTER_ACTOR (widget), &allocation); @@ -439,27 +437,24 @@ st_widget_paint_background (StWidget *widget, if (priv->transition_animation) st_theme_node_transition_paint (priv->transition_animation, - framebuffer, + node, &allocation, opacity, resource_scale); else st_theme_node_paint (theme_node, current_paint_state (widget), - framebuffer, + node, &allocation, opacity, resource_scale); } static void -st_widget_paint (ClutterActor *actor, - ClutterPaintContext *paint_context) +st_widget_paint_node (ClutterActor *actor, + ClutterPaintNode *node) { - st_widget_paint_background (ST_WIDGET (actor), paint_context); - - /* Chain up so we paint children. */ - CLUTTER_ACTOR_CLASS (st_widget_parent_class)->paint (actor, paint_context); + st_widget_paint_background (ST_WIDGET (actor), node); } static void @@ -892,7 +887,7 @@ st_widget_class_init (StWidgetClass *klass) actor_class->get_preferred_width = st_widget_get_preferred_width; actor_class->get_preferred_height = st_widget_get_preferred_height; actor_class->allocate = st_widget_allocate; - actor_class->paint = st_widget_paint; + actor_class->paint_node = st_widget_paint_node; actor_class->get_paint_volume = st_widget_get_paint_volume; actor_class->parent_set = st_widget_parent_set; actor_class->map = st_widget_map; diff --git a/src/st/st-widget.h b/src/st/st-widget.h index f00c98733..40866357d 100644 --- a/src/st/st-widget.h +++ b/src/st/st-widget.h @@ -143,8 +143,8 @@ StThemeNode * st_widget_get_theme_node (StWidget *widg StThemeNode * st_widget_peek_theme_node (StWidget *widget); GList * st_widget_get_focus_chain (StWidget *widget); -void st_widget_paint_background (StWidget *widget, - ClutterPaintContext *paint_context); +void st_widget_paint_background (StWidget *widget, + ClutterPaintNode *node); /* debug methods */ char *st_describe_actor (ClutterActor *actor);