clutter/offscreen-effect: Use paint nodes to paint target

Add a new ClutterPaintNode parameter to the paint_target() vfunc.
For now, create a temporary ClutterEffectNode that is passed to
paint_target() and immediately painted; next commits will move
this to upper layers.

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1355>
This commit is contained in:
Georges Basile Stavracas Neto 2020-07-05 17:44:38 -03:00
parent 691d31748a
commit 26c1a5eedf
5 changed files with 64 additions and 23 deletions

View File

@ -58,9 +58,12 @@
#include <cogl/cogl.h>
#include "clutter-color.h"
#include "clutter-debug.h"
#include "clutter-enum-types.h"
#include "clutter-offscreen-effect-private.h"
#include "clutter-paint-node.h"
#include "clutter-paint-nodes.h"
#include "clutter-private.h"
#define DEFAULT_N_TILES 32
@ -166,14 +169,13 @@ clutter_deform_effect_set_actor (ClutterActorMeta *meta,
static void
clutter_deform_effect_paint_target (ClutterOffscreenEffect *effect,
ClutterPaintNode *node,
ClutterPaintContext *paint_context)
{
ClutterDeformEffect *self= CLUTTER_DEFORM_EFFECT (effect);
ClutterDeformEffectPrivate *priv = self->priv;
CoglPipeline *pipeline;
CoglDepthState depth_state;
CoglFramebuffer *fb =
clutter_paint_context_get_framebuffer (paint_context);
if (priv->is_dirty)
{
@ -285,11 +287,21 @@ clutter_deform_effect_paint_target (ClutterOffscreenEffect *effect,
/* draw the front */
if (pipeline != NULL)
cogl_framebuffer_draw_primitive (fb, pipeline, priv->primitive);
{
ClutterPaintNode *front_node;
front_node = clutter_pipeline_node_new (pipeline);
clutter_paint_node_set_static_name (front_node,
"ClutterDeformEffect (front)");
clutter_paint_node_add_child (node, front_node);
clutter_paint_node_add_primitive (front_node, priv->primitive);
clutter_paint_node_unref (front_node);
}
/* draw the back */
if (priv->back_pipeline != NULL)
{
ClutterPaintNode *back_node;
CoglPipeline *back_pipeline;
/* We probably shouldn't be modifying the user's material so
@ -299,20 +311,30 @@ clutter_deform_effect_paint_target (ClutterOffscreenEffect *effect,
cogl_pipeline_set_cull_face_mode (back_pipeline,
COGL_PIPELINE_CULL_FACE_MODE_FRONT);
cogl_framebuffer_draw_primitive (fb, back_pipeline, priv->primitive);
back_node = clutter_pipeline_node_new (back_pipeline);
clutter_paint_node_set_static_name (back_node,
"ClutterDeformEffect (back)");
clutter_paint_node_add_child (node, back_node);
clutter_paint_node_add_primitive (back_node, priv->primitive);
clutter_paint_node_unref (back_node);
cogl_object_unref (back_pipeline);
}
if (G_UNLIKELY (priv->lines_primitive != NULL))
{
CoglContext *ctx =
clutter_backend_get_cogl_context (clutter_get_default_backend ());
CoglPipeline *lines_pipeline = cogl_pipeline_new (ctx);
cogl_pipeline_set_color4f (lines_pipeline, 1.0, 0, 0, 1.0);
cogl_framebuffer_draw_primitive (fb, lines_pipeline,
priv->lines_primitive);
cogl_object_unref (lines_pipeline);
const ClutterColor *red;
ClutterPaintNode *lines_node;
red = clutter_color_get_static (CLUTTER_COLOR_RED);
lines_node = clutter_color_node_new (red);
clutter_paint_node_set_static_name (lines_node,
"ClutterDeformEffect (lines)");
clutter_paint_node_add_child (node, lines_node);
clutter_paint_node_add_primitive (lines_node, priv->lines_primitive);
clutter_paint_node_unref (lines_node);
}
}

View File

@ -75,6 +75,8 @@
#include "clutter-private.h"
#include "clutter-stage-private.h"
#include "clutter-paint-context-private.h"
#include "clutter-paint-node-private.h"
#include "clutter-paint-nodes.h"
#include "clutter-paint-volume-private.h"
#include "clutter-actor-box-private.h"
@ -386,11 +388,11 @@ disable_effect:
static void
clutter_offscreen_effect_real_paint_target (ClutterOffscreenEffect *effect,
ClutterPaintNode *node,
ClutterPaintContext *paint_context)
{
ClutterOffscreenEffectPrivate *priv = effect->priv;
CoglFramebuffer *framebuffer =
clutter_paint_context_get_framebuffer (paint_context);
ClutterPaintNode *pipeline_node;
guint8 paint_opacity;
paint_opacity = clutter_actor_get_paint_opacity (priv->actor);
@ -401,18 +403,24 @@ clutter_offscreen_effect_real_paint_target (ClutterOffscreenEffect *effect,
paint_opacity,
paint_opacity);
pipeline_node = clutter_pipeline_node_new (priv->pipeline);
clutter_paint_node_set_static_name (pipeline_node,
"ClutterOffscreenEffect (pipeline)");
clutter_paint_node_add_child (node, pipeline_node);
/* At this point we are in stage coordinates translated so if
* we draw our texture using a textured quad the size of the paint
* box then we will overlay where the actor would have drawn if it
* hadn't been redirected offscreen.
*/
cogl_framebuffer_draw_textured_rectangle (framebuffer,
priv->pipeline,
0, 0,
cogl_texture_get_width (priv->texture),
cogl_texture_get_height (priv->texture),
0.0, 0.0,
1.0, 1.0);
clutter_paint_node_add_rectangle (pipeline_node,
&(ClutterActorBox) {
0.f, 0.f,
cogl_texture_get_width (priv->texture),
cogl_texture_get_height (priv->texture),
});
clutter_paint_node_unref (pipeline_node);
}
static void
@ -626,10 +634,17 @@ void
clutter_offscreen_effect_paint_target (ClutterOffscreenEffect *effect,
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);
}
/**

View File

@ -82,6 +82,7 @@ struct _ClutterOffscreenEffectClass
CoglPipeline* (* create_pipeline) (ClutterOffscreenEffect *effect,
CoglTexture *texture);
void (* paint_target) (ClutterOffscreenEffect *effect,
ClutterPaintNode *node,
ClutterPaintContext *paint_context);
/*< private >*/

View File

@ -384,6 +384,7 @@ clutter_shader_effect_try_static_source (ClutterShaderEffect *self)
static void
clutter_shader_effect_paint_target (ClutterOffscreenEffect *effect,
ClutterPaintNode *node,
ClutterPaintContext *paint_context)
{
ClutterShaderEffect *self = CLUTTER_SHADER_EFFECT (effect);
@ -414,7 +415,7 @@ clutter_shader_effect_paint_target (ClutterOffscreenEffect *effect,
out:
/* paint the offscreen buffer */
parent = CLUTTER_OFFSCREEN_EFFECT_CLASS (clutter_shader_effect_parent_class);
parent->paint_target (effect, paint_context);
parent->paint_target (effect, node, paint_context);
}

View File

@ -37,6 +37,7 @@ G_DEFINE_TYPE (FooOldShaderEffect,
static void
foo_old_shader_effect_paint_target (ClutterOffscreenEffect *effect,
ClutterPaintNode *node,
ClutterPaintContext *paint_context)
{
clutter_shader_effect_set_shader_source (CLUTTER_SHADER_EFFECT (effect),
@ -47,7 +48,7 @@ foo_old_shader_effect_paint_target (ClutterOffscreenEffect *effect,
1.0f, 0.0f, 0.0f);
CLUTTER_OFFSCREEN_EFFECT_CLASS (foo_old_shader_effect_parent_class)->
paint_target (effect, paint_context);
paint_target (effect, node, paint_context);
}
static void
@ -112,6 +113,7 @@ foo_new_shader_effect_get_static_source (ClutterShaderEffect *effect)
static void
foo_new_shader_effect_paint_target (ClutterOffscreenEffect *effect,
ClutterPaintNode *node,
ClutterPaintContext *paint_context)
{
clutter_shader_effect_set_uniform (CLUTTER_SHADER_EFFECT (effect),
@ -120,7 +122,7 @@ foo_new_shader_effect_paint_target (ClutterOffscreenEffect *effect,
0.0f, 1.0f, 0.0f);
CLUTTER_OFFSCREEN_EFFECT_CLASS (foo_new_shader_effect_parent_class)->
paint_target (effect, paint_context);
paint_target (effect, node, paint_context);
}
static void