From 63ea2dacc41d15e8a926f0844c25b22855c68a06 Mon Sep 17 00:00:00 2001 From: Georges Basile Stavracas Neto Date: Mon, 29 Jun 2020 15:17:27 -0300 Subject: [PATCH] clutter/paint-nodes: Add new ClutterLayerNode API ClutterLayerNode is the "offscreen framebuffer" node, that paints it's child nodes in a separate framebuffer, and then copies that framebuffer to the parent one. It'll be useful to hand ClutterLayerNode which framebuffer and pipeline to use, as this is a requirement for porting e.g. ClutterOffscreenEffect and subclasses. Add a new clutter_layer_node_new_to_framebuffer() API. Part-of: --- clutter/clutter/clutter-paint-nodes.c | 73 +++++++++++++++++++++------ clutter/clutter/clutter-paint-nodes.h | 4 ++ 2 files changed, 61 insertions(+), 16 deletions(-) diff --git a/clutter/clutter/clutter-paint-nodes.c b/clutter/clutter/clutter-paint-nodes.c index e70946667..652141c4b 100644 --- a/clutter/clutter/clutter-paint-nodes.c +++ b/clutter/clutter/clutter-paint-nodes.c @@ -1338,6 +1338,8 @@ struct _ClutterLayerNode CoglFramebuffer *offscreen; guint8 opacity; + + gboolean needs_fbo_setup : 1; }; struct _ClutterLayerNodeClass @@ -1365,25 +1367,27 @@ clutter_layer_node_pre_draw (ClutterPaintNode *node, if (node->operations == NULL) return FALSE; - /* copy the same modelview from the current framebuffer to the one we - * are going to use - */ - framebuffer = clutter_paint_context_get_framebuffer (paint_context); - cogl_framebuffer_get_modelview_matrix (framebuffer, &matrix); + if (lnode->needs_fbo_setup) + { + /* copy the same modelview from the current framebuffer to the one we + * are going to use + */ + framebuffer = clutter_paint_context_get_framebuffer (paint_context); + cogl_framebuffer_get_modelview_matrix (framebuffer, &matrix); + cogl_framebuffer_set_modelview_matrix (lnode->offscreen, &matrix); + + cogl_framebuffer_set_viewport (lnode->offscreen, + lnode->viewport.x, + lnode->viewport.y, + lnode->viewport.width, + lnode->viewport.height); + + cogl_framebuffer_set_projection_matrix (lnode->offscreen, + &lnode->projection); + } clutter_paint_context_push_framebuffer (paint_context, lnode->offscreen); - cogl_framebuffer_set_modelview_matrix (lnode->offscreen, &matrix); - - cogl_framebuffer_set_viewport (lnode->offscreen, - lnode->viewport.x, - lnode->viewport.y, - lnode->viewport.width, - lnode->viewport.height); - - cogl_framebuffer_set_projection_matrix (lnode->offscreen, - &lnode->projection); - /* clear out the target framebuffer */ cogl_framebuffer_clear4f (lnode->offscreen, COGL_BUFFER_BIT_COLOR | COGL_BUFFER_BIT_DEPTH, @@ -1522,6 +1526,7 @@ clutter_layer_node_new (const graphene_matrix_t *projection, res = _clutter_paint_node_create (CLUTTER_TYPE_LAYER_NODE); + res->needs_fbo_setup = TRUE; res->projection = *projection; res->viewport = *viewport; res->fbo_width = width; @@ -1566,3 +1571,39 @@ out: return (ClutterPaintNode *) res; } + +/** + * clutter_layer_node_new_to_framebuffer: + * @framebuffer: a #CoglFramebuffer + * @pipeline: a #CoglPipeline + * + * Creates a new #ClutterLayerNode that will redirect drawing at + * @framebuffer. It will then use @pipeline to paint the stored + * operations. + * + * When using this constructor, the caller is reponsible for setting + * up @framebuffer, including its modelview and projection matrices, + * and the viewport, and the @pipeline as well. + * + * Return value: (transfer full): the newly created #ClutterLayerNode. + * Use clutter_paint_node_unref() when done. + */ +ClutterPaintNode * +clutter_layer_node_new_to_framebuffer (CoglFramebuffer *framebuffer, + CoglPipeline *pipeline) +{ + ClutterLayerNode *res; + + g_return_val_if_fail (COGL_IS_FRAMEBUFFER (framebuffer), NULL); + g_return_val_if_fail (cogl_is_pipeline (pipeline), NULL); + + res = _clutter_paint_node_create (CLUTTER_TYPE_LAYER_NODE); + + res->needs_fbo_setup = FALSE; + res->fbo_width = cogl_framebuffer_get_width (framebuffer); + res->fbo_height = cogl_framebuffer_get_height (framebuffer); + res->offscreen = g_object_ref (framebuffer); + res->pipeline = cogl_pipeline_copy (pipeline); + + return (ClutterPaintNode *) res; +} diff --git a/clutter/clutter/clutter-paint-nodes.h b/clutter/clutter/clutter-paint-nodes.h index 32b56a8d3..082419af8 100644 --- a/clutter/clutter/clutter-paint-nodes.h +++ b/clutter/clutter/clutter-paint-nodes.h @@ -209,6 +209,10 @@ ClutterPaintNode * clutter_layer_node_new (const graphene_matrix_t float height, guint8 opacity); +CLUTTER_EXPORT +ClutterPaintNode * clutter_layer_node_new_to_framebuffer (CoglFramebuffer *framebuffer, + CoglPipeline *pipeline); + #define CLUTTER_TYPE_TRANSFORM_NODE (clutter_transform_node_get_type ()) #define CLUTTER_TRANSFORM_NODE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_TRANSFORM_NODE, ClutterTransformNode))