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: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1538>
This commit is contained in:
Georges Basile Stavracas Neto 2020-12-10 17:21:11 -03:00 committed by Jonas Ådahl
parent 0cdddaa4a7
commit a96868d1b0
16 changed files with 398 additions and 272 deletions

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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);
}

View File

@ -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__ */

View File

@ -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);

View File

@ -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

View File

@ -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);
}
}

View File

@ -112,7 +112,6 @@ struct _StThemeNode {
CoglTexture *background_texture;
CoglPipeline *background_pipeline;
CoglPipeline *background_shadow_pipeline;
CoglPipeline *color_pipeline;
StThemeNodePaintState cached_state;

View File

@ -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

View File

@ -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);

View File

@ -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);
}

View File

@ -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);

View File

@ -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;

View File

@ -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;

View File

@ -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);