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 to use,
as this is a requirement for porting e.g. ClutterOffscreenEffect
and subclasses.

Add a new clutter_layer_node_new_with_framebuffer() API.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1340
This commit is contained in:
Georges Basile Stavracas Neto 2020-06-29 15:17:27 -03:00
parent 6f0719b3c7
commit 03be5ed9f1
2 changed files with 67 additions and 18 deletions

View File

@ -1338,6 +1338,7 @@ struct _ClutterLayerNode
CoglFramebuffer *offscreen; CoglFramebuffer *offscreen;
guint8 opacity; guint8 opacity;
gboolean update_modelview;
}; };
struct _ClutterLayerNodeClass struct _ClutterLayerNodeClass
@ -1352,8 +1353,6 @@ clutter_layer_node_pre_draw (ClutterPaintNode *node,
ClutterPaintContext *paint_context) ClutterPaintContext *paint_context)
{ {
ClutterLayerNode *lnode = (ClutterLayerNode *) node; ClutterLayerNode *lnode = (ClutterLayerNode *) node;
CoglFramebuffer *framebuffer;
CoglMatrix matrix;
/* if we were unable to create an offscreen buffer for this node, then /* if we were unable to create an offscreen buffer for this node, then
* we simply ignore it * we simply ignore it
@ -1365,25 +1364,30 @@ clutter_layer_node_pre_draw (ClutterPaintNode *node,
if (node->operations == NULL) if (node->operations == NULL)
return FALSE; return FALSE;
/* copy the same modelview from the current framebuffer to the one we if (lnode->update_modelview)
* are going to use {
*/ CoglFramebuffer *framebuffer;
framebuffer = clutter_paint_context_get_framebuffer (paint_context); CoglMatrix matrix;
cogl_framebuffer_get_modelview_matrix (framebuffer, &matrix);
/* 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); 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 */ /* clear out the target framebuffer */
cogl_framebuffer_clear4f (lnode->offscreen, cogl_framebuffer_clear4f (lnode->offscreen,
COGL_BUFFER_BIT_COLOR | COGL_BUFFER_BIT_DEPTH, COGL_BUFFER_BIT_COLOR | COGL_BUFFER_BIT_DEPTH,
@ -1521,6 +1525,7 @@ clutter_layer_node_new (const CoglMatrix *projection,
res = _clutter_paint_node_create (CLUTTER_TYPE_LAYER_NODE); res = _clutter_paint_node_create (CLUTTER_TYPE_LAYER_NODE);
res->update_modelview = TRUE;
res->projection = *projection; res->projection = *projection;
res->viewport = *viewport; res->viewport = *viewport;
res->fbo_width = width; res->fbo_width = width;
@ -1561,3 +1566,42 @@ out:
return (ClutterPaintNode *) res; return (ClutterPaintNode *) res;
} }
/**
* clutter_layer_node_new_with_framebuffer:
* @framebuffer: a #CoglFramebuffer
* @pipeline: a #CoglPipeline
* @opacity: the opacity to be used when drawing the layer
*
* Creates a new #ClutterLayerNode with @framebuffer and
* @pipeline. @framebuffer will then be painted using the
* given @opacity.
*
* When using this constructor, the caller is responsible
* for setting up the framebuffer's modelview and projection
* matrices.
*
* Return value: (transfer full)(nullable): the newly created #ClutterLayerNode.
* Use clutter_paint_node_unref() when done.
*/
ClutterPaintNode *
clutter_layer_node_new_with_framebuffer (CoglFramebuffer *framebuffer,
CoglPipeline *pipeline,
guint8 opacity)
{
ClutterLayerNode *res;
CoglColor color;
g_return_val_if_fail (cogl_is_framebuffer (framebuffer), NULL);
res = _clutter_paint_node_create (CLUTTER_TYPE_LAYER_NODE);
res->update_modelview = FALSE;
res->offscreen = cogl_object_ref (framebuffer);
res->pipeline = cogl_pipeline_copy (pipeline);
cogl_color_init_from_4ub (&color, opacity, opacity, opacity, opacity);
cogl_pipeline_set_color (res->pipeline, &color);
return (ClutterPaintNode *) res;
}

View File

@ -209,6 +209,11 @@ ClutterPaintNode * clutter_layer_node_new (const CoglMatrix
float height, float height,
guint8 opacity); guint8 opacity);
CLUTTER_EXPORT
ClutterPaintNode * clutter_layer_node_new_with_framebuffer (CoglFramebuffer *framebuffer,
CoglPipeline *pipeline,
guint8 opacity);
#define CLUTTER_TYPE_TRANSFORM_NODE (clutter_transform_node_get_type ()) #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)) #define CLUTTER_TRANSFORM_NODE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_TRANSFORM_NODE, ClutterTransformNode))