From 489840840468be15b73151ddb260430244e74329 Mon Sep 17 00:00:00 2001 From: Georges Basile Stavracas Neto Date: Sun, 5 Jul 2020 18:45:03 -0300 Subject: [PATCH] clutter/effect: Add paint nodes to all paint vfuncs In the purely paint node based rendering future, ClutterEffects simply add more paint nodes to the tree when painting the actor. This is the leap to achieve that future. Add paint nodes to pre_paint, paint, and post_paint, and move the ClutterEffectNode creation to _clutter_effect_paint(). Part-of: --- clutter/clutter/clutter-blur-effect.c | 3 +- .../clutter-brightness-contrast-effect.c | 3 +- clutter/clutter/clutter-colorize-effect.c | 3 +- clutter/clutter/clutter-desaturate-effect.c | 3 +- clutter/clutter/clutter-effect.c | 25 +++-- clutter/clutter/clutter-effect.h | 3 + clutter/clutter/clutter-offscreen-effect.c | 93 +++++++------------ clutter/clutter/clutter-offscreen-effect.h | 1 + 8 files changed, 59 insertions(+), 75 deletions(-) diff --git a/clutter/clutter/clutter-blur-effect.c b/clutter/clutter/clutter-blur-effect.c index 99331dce2..92aeca697 100644 --- a/clutter/clutter/clutter-blur-effect.c +++ b/clutter/clutter/clutter-blur-effect.c @@ -126,6 +126,7 @@ clutter_blur_effect_create_pipeline (ClutterOffscreenEffect *effect, static gboolean clutter_blur_effect_pre_paint (ClutterEffect *effect, + ClutterPaintNode *node, ClutterPaintContext *paint_context) { ClutterEffectClass *parent_class; @@ -143,7 +144,7 @@ clutter_blur_effect_pre_paint (ClutterEffect *effect, } parent_class = CLUTTER_EFFECT_CLASS (clutter_blur_effect_parent_class); - return parent_class->pre_paint (effect, paint_context); + return parent_class->pre_paint (effect, node, paint_context); } static gboolean diff --git a/clutter/clutter/clutter-brightness-contrast-effect.c b/clutter/clutter/clutter-brightness-contrast-effect.c index aa196fa20..4942b8772 100644 --- a/clutter/clutter/clutter-brightness-contrast-effect.c +++ b/clutter/clutter/clutter-brightness-contrast-effect.c @@ -140,6 +140,7 @@ clutter_brightness_contrast_effect_create_pipeline (ClutterOffscreenEffect *effe static gboolean clutter_brightness_contrast_effect_pre_paint (ClutterEffect *effect, + ClutterPaintNode *node, ClutterPaintContext *paint_context) { ClutterBrightnessContrastEffect *self = CLUTTER_BRIGHTNESS_CONTRAST_EFFECT (effect); @@ -164,7 +165,7 @@ clutter_brightness_contrast_effect_pre_paint (ClutterEffect *effect, parent_class = CLUTTER_EFFECT_CLASS (clutter_brightness_contrast_effect_parent_class); - return parent_class->pre_paint (effect, paint_context); + return parent_class->pre_paint (effect, node, paint_context); } static void diff --git a/clutter/clutter/clutter-colorize-effect.c b/clutter/clutter/clutter-colorize-effect.c index 8b8aba1d7..d73a0524f 100644 --- a/clutter/clutter/clutter-colorize-effect.c +++ b/clutter/clutter/clutter-colorize-effect.c @@ -114,6 +114,7 @@ clutter_colorize_effect_create_pipeline (ClutterOffscreenEffect *effect, static gboolean clutter_colorize_effect_pre_paint (ClutterEffect *effect, + ClutterPaintNode *node, ClutterPaintContext *paint_context) { ClutterEffectClass *parent_class; @@ -131,7 +132,7 @@ clutter_colorize_effect_pre_paint (ClutterEffect *effect, } parent_class = CLUTTER_EFFECT_CLASS (clutter_colorize_effect_parent_class); - return parent_class->pre_paint (effect, paint_context); + return parent_class->pre_paint (effect, node, paint_context); } static void diff --git a/clutter/clutter/clutter-desaturate-effect.c b/clutter/clutter/clutter-desaturate-effect.c index 4e4ea8213..d7035b679 100644 --- a/clutter/clutter/clutter-desaturate-effect.c +++ b/clutter/clutter/clutter-desaturate-effect.c @@ -125,6 +125,7 @@ clutter_desaturate_effect_create_pipeline (ClutterOffscreenEffect *effect, static gboolean clutter_desaturate_effect_pre_paint (ClutterEffect *effect, + ClutterPaintNode *node, ClutterPaintContext *paint_context) { ClutterEffectClass *parent_class; @@ -142,7 +143,7 @@ clutter_desaturate_effect_pre_paint (ClutterEffect *effect, } parent_class = CLUTTER_EFFECT_CLASS (clutter_desaturate_effect_parent_class); - return parent_class->pre_paint (effect, paint_context); + return parent_class->pre_paint (effect, node, paint_context); } static void diff --git a/clutter/clutter/clutter-effect.c b/clutter/clutter/clutter-effect.c index 1df651f20..4e33cca45 100644 --- a/clutter/clutter/clutter-effect.c +++ b/clutter/clutter/clutter-effect.c @@ -180,6 +180,7 @@ G_DEFINE_ABSTRACT_TYPE (ClutterEffect, static gboolean clutter_effect_real_pre_paint (ClutterEffect *effect, + ClutterPaintNode *node, ClutterPaintContext *paint_context) { return TRUE; @@ -187,6 +188,7 @@ clutter_effect_real_pre_paint (ClutterEffect *effect, static void clutter_effect_real_post_paint (ClutterEffect *effect, + ClutterPaintNode *node, ClutterPaintContext *paint_context) { } @@ -216,28 +218,23 @@ clutter_effect_real_paint_node (ClutterEffect *effect, static void clutter_effect_real_paint (ClutterEffect *effect, + ClutterPaintNode *node, ClutterPaintContext *paint_context, ClutterEffectPaintFlags flags) { ClutterEffectClass *effect_class = CLUTTER_EFFECT_GET_CLASS (effect); - ClutterPaintNode *node; gboolean pre_paint_succeeded; /* The default implementation provides a compatibility wrapper for effects that haven't migrated to use the 'paint' virtual yet. This just calls the old pre and post virtuals before chaining on */ - pre_paint_succeeded = effect_class->pre_paint (effect, paint_context); - - node = clutter_effect_node_new (effect); + pre_paint_succeeded = effect_class->pre_paint (effect, node,paint_context); effect_class->paint_node (effect, node, paint_context, flags); - clutter_paint_node_paint (node, paint_context); if (pre_paint_succeeded) - effect_class->post_paint (effect, paint_context); - - clutter_paint_node_unref (node); + effect_class->post_paint (effect, node, paint_context); } static void @@ -291,9 +288,19 @@ _clutter_effect_paint (ClutterEffect *effect, ClutterPaintContext *paint_context, ClutterEffectPaintFlags flags) { + ClutterPaintNode *node; + g_return_if_fail (CLUTTER_IS_EFFECT (effect)); - CLUTTER_EFFECT_GET_CLASS (effect)->paint (effect, paint_context, flags); + node = clutter_effect_node_new (effect); + + CLUTTER_EFFECT_GET_CLASS (effect)->paint (effect, + node, + paint_context, + flags); + + clutter_paint_node_paint (node, paint_context); + clutter_paint_node_unref (node); } void diff --git a/clutter/clutter/clutter-effect.h b/clutter/clutter/clutter-effect.h index d15015cf9..8969fcd78 100644 --- a/clutter/clutter/clutter-effect.h +++ b/clutter/clutter/clutter-effect.h @@ -77,14 +77,17 @@ struct _ClutterEffectClass /*< public >*/ gboolean (* pre_paint) (ClutterEffect *effect, + ClutterPaintNode *node, ClutterPaintContext *paint_context); void (* post_paint) (ClutterEffect *effect, + ClutterPaintNode *node, ClutterPaintContext *paint_context); gboolean (* modify_paint_volume) (ClutterEffect *effect, ClutterPaintVolume *volume); void (* paint) (ClutterEffect *effect, + ClutterPaintNode *node, ClutterPaintContext *paint_context, ClutterEffectPaintFlags flags); void (* paint_node) (ClutterEffect *effect, diff --git a/clutter/clutter/clutter-offscreen-effect.c b/clutter/clutter/clutter-offscreen-effect.c index 4871562b7..598adb316 100644 --- a/clutter/clutter/clutter-offscreen-effect.c +++ b/clutter/clutter/clutter-offscreen-effect.c @@ -99,8 +99,6 @@ struct _ClutterOffscreenEffectPrivate int target_width; int target_height; - gint old_opacity_override; - gulong purge_handler_id; }; @@ -270,6 +268,7 @@ update_fbo (ClutterEffect *effect, static gboolean clutter_offscreen_effect_pre_paint (ClutterEffect *effect, + ClutterPaintNode *node, ClutterPaintContext *paint_context) { ClutterOffscreenEffect *self = CLUTTER_OFFSCREEN_EFFECT (effect); @@ -279,7 +278,6 @@ clutter_offscreen_effect_pre_paint (ClutterEffect *effect, ClutterActor *stage; graphene_matrix_t projection, modelview; const ClutterPaintVolume *volume; - CoglColor transparent; gfloat stage_width, stage_height; gfloat target_width = -1, target_height = -1; float resource_scale; @@ -336,7 +334,6 @@ clutter_offscreen_effect_pre_paint (ClutterEffect *effect, goto disable_effect; offscreen = COGL_FRAMEBUFFER (priv->offscreen); - clutter_paint_context_push_framebuffer (paint_context, offscreen); /* We don't want the FBO contents to be transformed. That could waste memory * (e.g. during zoom), or result in something that's not rectangular (clipped @@ -363,22 +360,6 @@ clutter_offscreen_effect_pre_paint (ClutterEffect *effect, cogl_framebuffer_set_projection_matrix (offscreen, &projection); - cogl_color_init_from_4ub (&transparent, 0, 0, 0, 0); - cogl_framebuffer_clear (offscreen, - COGL_BUFFER_BIT_COLOR | - COGL_BUFFER_BIT_DEPTH, - &transparent); - - cogl_framebuffer_push_matrix (offscreen); - - /* Override the actor's opacity to fully opaque - we paint the offscreen - * texture with the actor's paint opacity, so we need to do this to avoid - * multiplying the opacity twice. - */ - priv->old_opacity_override = - clutter_actor_get_opacity_override (priv->actor); - clutter_actor_set_opacity_override (priv->actor, 0xff); - return TRUE; disable_effect: @@ -425,63 +406,57 @@ clutter_offscreen_effect_real_paint_target (ClutterOffscreenEffect *effect, static void clutter_offscreen_effect_paint_texture (ClutterOffscreenEffect *effect, + ClutterPaintNode *node, ClutterPaintContext *paint_context) { ClutterOffscreenEffectPrivate *priv = effect->priv; - CoglFramebuffer *framebuffer = - clutter_paint_context_get_framebuffer (paint_context); + graphene_matrix_t transform; float resource_scale; - cogl_framebuffer_push_matrix (framebuffer); + graphene_matrix_init_translate (&transform, + &GRAPHENE_POINT3D_INIT (priv->fbo_offset_x, + priv->fbo_offset_y, + 0.0f)); - /* The current modelview matrix is *almost* perfect already. It's only - * missing a correction for the expanded FBO and offset rendering within... - */ resource_scale = clutter_actor_get_resource_scale (priv->actor); - if (resource_scale != 1.0f) { float paint_scale = 1.0f / resource_scale; - cogl_framebuffer_scale (framebuffer, paint_scale, paint_scale, 1.f); + graphene_matrix_scale (&transform, paint_scale, paint_scale, 1.f); } - cogl_framebuffer_translate (framebuffer, - priv->fbo_offset_x, - priv->fbo_offset_y, - 0.0f); + if (!graphene_matrix_is_identity (&transform)) + { + ClutterPaintNode *transform_node; + + transform_node = clutter_transform_node_new (&transform); + clutter_paint_node_set_static_name (transform_node, + "ClutterOffscreenEffect (transform)"); + clutter_paint_node_add_child (node, transform_node); + clutter_paint_node_unref (transform_node); + + node = transform_node; + } /* paint the target material; this is virtualized for * sub-classes that require special hand-holding */ - clutter_offscreen_effect_paint_target (effect, paint_context); - - cogl_framebuffer_pop_matrix (framebuffer); + clutter_offscreen_effect_paint_target (effect, node, paint_context); } static void clutter_offscreen_effect_post_paint (ClutterEffect *effect, + ClutterPaintNode *node, ClutterPaintContext *paint_context) { ClutterOffscreenEffect *self = CLUTTER_OFFSCREEN_EFFECT (effect); ClutterOffscreenEffectPrivate *priv = self->priv; - CoglFramebuffer *framebuffer; g_warn_if_fail (priv->offscreen); g_warn_if_fail (priv->pipeline); g_warn_if_fail (priv->actor); - /* Restore the previous opacity override */ - if (priv->actor) - { - clutter_actor_set_opacity_override (priv->actor, - priv->old_opacity_override); - } - - framebuffer = clutter_paint_context_get_framebuffer (paint_context); - cogl_framebuffer_pop_matrix (framebuffer); - clutter_paint_context_pop_framebuffer (paint_context); - - clutter_offscreen_effect_paint_texture (self, paint_context); + clutter_offscreen_effect_paint_texture (self, node, paint_context); } static void @@ -520,15 +495,18 @@ clutter_offscreen_effect_paint_node (ClutterEffect *effect, static void clutter_offscreen_effect_paint (ClutterEffect *effect, + ClutterPaintNode *node, ClutterPaintContext *paint_context, ClutterEffectPaintFlags flags) { ClutterOffscreenEffect *self = CLUTTER_OFFSCREEN_EFFECT (effect); ClutterOffscreenEffectPrivate *priv = self->priv; + ClutterEffectClass *parent_class = + CLUTTER_EFFECT_CLASS (clutter_offscreen_effect_parent_class); if (flags & CLUTTER_EFFECT_PAINT_BYPASS_EFFECT) { - clutter_actor_continue_paint (priv->actor, paint_context); + add_actor_node (self, node, -1); g_clear_object (&priv->offscreen); return; } @@ -537,14 +515,9 @@ clutter_offscreen_effect_paint (ClutterEffect *effect, * then we can just use the cached image in the FBO. */ if (priv->offscreen == NULL || (flags & CLUTTER_EFFECT_PAINT_ACTOR_DIRTY)) - { - ClutterEffectClass *parent_class = - CLUTTER_EFFECT_CLASS (clutter_offscreen_effect_parent_class); - - parent_class->paint (effect, paint_context, flags); - } + parent_class->paint (effect, node, paint_context, flags); else - clutter_offscreen_effect_paint_texture (self, paint_context); + clutter_offscreen_effect_paint_texture (self, node, paint_context); } static void @@ -659,6 +632,7 @@ clutter_offscreen_effect_get_pipeline (ClutterOffscreenEffect *effect) /** * clutter_offscreen_effect_paint_target: * @effect: a #ClutterOffscreenEffect + * @node: a #ClutterPaintNode * @paint_context: a #ClutterPaintContext * * Calls the paint_target() virtual function of the @effect @@ -667,19 +641,14 @@ clutter_offscreen_effect_get_pipeline (ClutterOffscreenEffect *effect) */ void clutter_offscreen_effect_paint_target (ClutterOffscreenEffect *effect, + ClutterPaintNode *node, ClutterPaintContext *paint_context) { - ClutterPaintNode *node; - g_return_if_fail (CLUTTER_IS_OFFSCREEN_EFFECT (effect)); - node = clutter_effect_node_new (CLUTTER_EFFECT (effect)); - CLUTTER_OFFSCREEN_EFFECT_GET_CLASS (effect)->paint_target (effect, node, paint_context); - clutter_paint_node_paint (node, paint_context); - clutter_paint_node_unref (node); } /** diff --git a/clutter/clutter/clutter-offscreen-effect.h b/clutter/clutter/clutter-offscreen-effect.h index a53c269ff..b06bc34ed 100644 --- a/clutter/clutter/clutter-offscreen-effect.h +++ b/clutter/clutter/clutter-offscreen-effect.h @@ -106,6 +106,7 @@ CoglHandle clutter_offscreen_effect_get_texture (ClutterOffscree CLUTTER_EXPORT void clutter_offscreen_effect_paint_target (ClutterOffscreenEffect *effect, + ClutterPaintNode *node, ClutterPaintContext *paint_context); CLUTTER_EXPORT CoglHandle clutter_offscreen_effect_create_texture (ClutterOffscreenEffect *effect,