4 * An OpenGL based 'interactive canvas' library.
6 * Copyright (C) 2011 Intel Corporation.
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library. If not, see <http://www.gnu.org/licenses/>.
22 * Emmanuele Bassi <ebassi@linux.intel.com>
26 * SECTION:clutter-paint-nodes
28 * @Short_Description: ClutterPaintNode implementations
30 * Clutter provides a set of predefined #ClutterPaintNode implementations
31 * that cover all the state changes available.
38 #define CLUTTER_ENABLE_EXPERIMENTAL_API
40 #include "clutter-paint-node-private.h"
42 #include <pango/pango.h>
43 #include <cogl/cogl.h>
45 #include "clutter-actor-private.h"
46 #include "clutter-color.h"
47 #include "clutter-debug.h"
48 #include "clutter-private.h"
50 #include "clutter-paint-nodes.h"
52 static CoglPipeline *default_color_pipeline = NULL;
53 static CoglPipeline *default_texture_pipeline = NULL;
56 * _clutter_paint_node_init_types:
58 * Initializes the required types for ClutterPaintNode subclasses
61 _clutter_paint_node_init_types (void)
65 GType node_type G_GNUC_UNUSED;
67 if (G_LIKELY (default_color_pipeline != NULL))
70 ctx = clutter_backend_get_cogl_context (clutter_get_default_backend ());
72 node_type = clutter_paint_node_get_type ();
74 cogl_color_init_from_4f (&cogl_color, 1.0, 1.0, 1.0, 1.0);
76 default_color_pipeline = cogl_pipeline_new (ctx);
77 cogl_pipeline_set_color (default_color_pipeline, &cogl_color);
79 default_texture_pipeline = cogl_pipeline_new (ctx);
80 cogl_pipeline_set_layer_null_texture (default_texture_pipeline, 0,
81 COGL_TEXTURE_TYPE_2D);
82 cogl_pipeline_set_color (default_texture_pipeline, &cogl_color);
83 cogl_pipeline_set_layer_wrap_mode (default_texture_pipeline, 0,
84 COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE);
90 * any frame can only have a since RootNode instance for each
94 #define clutter_root_node_get_type _clutter_root_node_get_type
96 typedef struct _ClutterRootNode ClutterRootNode;
97 typedef struct _ClutterPaintNodeClass ClutterRootNodeClass;
99 struct _ClutterRootNode
101 ClutterPaintNode parent_instance;
103 CoglFramebuffer *framebuffer;
105 CoglBufferBit clear_flags;
106 CoglColor clear_color;
107 CoglMatrix modelview;
110 G_DEFINE_TYPE (ClutterRootNode, clutter_root_node, CLUTTER_TYPE_PAINT_NODE)
113 clutter_root_node_pre_draw (ClutterPaintNode *node)
115 ClutterRootNode *rnode = (ClutterRootNode *) node;
119 cogl_framebuffer_set_modelview_matrix (rnode->framebuffer,
122 cogl_framebuffer_clear (rnode->framebuffer,
124 &rnode->clear_color);
130 clutter_root_node_post_draw (ClutterPaintNode *node)
136 clutter_root_node_finalize (ClutterPaintNode *node)
138 ClutterRootNode *rnode = (ClutterRootNode *) node;
140 cogl_object_unref (rnode->framebuffer);
142 CLUTTER_PAINT_NODE_CLASS (clutter_root_node_parent_class)->finalize (node);
146 clutter_root_node_class_init (ClutterRootNodeClass *klass)
148 ClutterPaintNodeClass *node_class = CLUTTER_PAINT_NODE_CLASS (klass);
150 node_class->pre_draw = clutter_root_node_pre_draw;
151 node_class->post_draw = clutter_root_node_post_draw;
152 node_class->finalize = clutter_root_node_finalize;
156 clutter_root_node_init (ClutterRootNode *self)
158 cogl_matrix_init_identity (&self->modelview);
162 _clutter_root_node_new (CoglFramebuffer *framebuffer,
163 const ClutterColor *clear_color,
164 CoglBufferBit clear_flags,
165 const CoglMatrix *matrix)
167 ClutterRootNode *res;
169 res = _clutter_paint_node_create (_clutter_root_node_get_type ());
171 cogl_color_init_from_4ub (&res->clear_color,
176 cogl_color_premultiply (&res->clear_color);
178 res->framebuffer = cogl_object_ref (framebuffer);
179 res->clear_flags = clear_flags;
180 res->modelview = *matrix;
182 return (ClutterPaintNode *) res;
188 * A private PaintNode, that changes the modelview of its child
192 #define clutter_transform_node_get_type _clutter_transform_node_get_type
194 typedef struct _ClutterTransformNode {
195 ClutterPaintNode parent_instance;
197 CoglMatrix modelview;
198 } ClutterTransformNode;
200 typedef struct _ClutterPaintNodeClass ClutterTransformNodeClass;
202 G_DEFINE_TYPE (ClutterTransformNode, clutter_transform_node, CLUTTER_TYPE_PAINT_NODE)
205 clutter_transform_node_pre_draw (ClutterPaintNode *node)
207 ClutterTransformNode *tnode = (ClutterTransformNode *) node;
212 cogl_get_modelview_matrix (&matrix);
213 cogl_matrix_multiply (&matrix, &matrix, &tnode->modelview);
214 cogl_set_modelview_matrix (&matrix);
220 clutter_transform_node_post_draw (ClutterPaintNode *node)
226 clutter_transform_node_class_init (ClutterTransformNodeClass *klass)
228 ClutterPaintNodeClass *node_class;
230 node_class = CLUTTER_PAINT_NODE_CLASS (klass);
231 node_class->pre_draw = clutter_transform_node_pre_draw;
232 node_class->post_draw = clutter_transform_node_post_draw;
236 clutter_transform_node_init (ClutterTransformNode *self)
238 cogl_matrix_init_identity (&self->modelview);
242 _clutter_transform_node_new (const CoglMatrix *modelview)
244 ClutterTransformNode *res;
246 res = _clutter_paint_node_create (_clutter_transform_node_get_type ());
248 if (modelview != NULL)
249 res->modelview = *modelview;
251 return (ClutterPaintNode *) res;
255 * Dummy node, private
257 * an empty node, used temporarily until we can drop API compatibility,
258 * and we'll be able to build a full render tree for each frame.
261 #define clutter_dummy_node_get_type _clutter_dummy_node_get_type
263 typedef struct _ClutterDummyNode ClutterDummyNode;
264 typedef struct _ClutterPaintNodeClass ClutterDummyNodeClass;
266 struct _ClutterDummyNode
268 ClutterPaintNode parent_instance;
273 G_DEFINE_TYPE (ClutterDummyNode, clutter_dummy_node, CLUTTER_TYPE_PAINT_NODE)
276 clutter_dummy_node_pre_draw (ClutterPaintNode *node)
282 clutter_dummy_node_serialize (ClutterPaintNode *node)
284 ClutterDummyNode *dnode = (ClutterDummyNode *) node;
285 JsonBuilder *builder;
288 if (dnode->actor == NULL)
289 return json_node_new (JSON_NODE_NULL);
291 builder = json_builder_new ();
292 json_builder_begin_object (builder);
294 json_builder_set_member_name (builder, "actor");
295 json_builder_add_string_value (builder, _clutter_actor_get_debug_name (dnode->actor));
297 json_builder_end_object (builder);
299 res = json_builder_get_root (builder);
300 g_object_unref (builder);
306 clutter_dummy_node_class_init (ClutterDummyNodeClass *klass)
308 ClutterPaintNodeClass *node_class = CLUTTER_PAINT_NODE_CLASS (klass);
310 node_class->pre_draw = clutter_dummy_node_pre_draw;
311 node_class->serialize = clutter_dummy_node_serialize;
315 clutter_dummy_node_init (ClutterDummyNode *self)
320 _clutter_dummy_node_new (ClutterActor *actor)
322 ClutterPaintNode *res;
324 res = _clutter_paint_node_create (_clutter_dummy_node_get_type ());
326 ((ClutterDummyNode *) res)->actor = actor;
335 struct _ClutterPipelineNode
337 ClutterPaintNode parent_instance;
339 CoglPipeline *pipeline;
343 * ClutterPipelineNodeClass:
345 * The <structname>ClutterPipelineNodeClass</structname> structure is an opaque
346 * type whose members cannot be directly accessed.
350 struct _ClutterPipelineNodeClass
352 ClutterPaintNodeClass parent_class;
355 G_DEFINE_TYPE (ClutterPipelineNode, clutter_pipeline_node, CLUTTER_TYPE_PAINT_NODE)
358 clutter_pipeline_node_finalize (ClutterPaintNode *node)
360 ClutterPipelineNode *pnode = CLUTTER_PIPELINE_NODE (node);
362 if (pnode->pipeline != NULL)
363 cogl_object_unref (pnode->pipeline);
365 CLUTTER_PAINT_NODE_CLASS (clutter_pipeline_node_parent_class)->finalize (node);
369 clutter_pipeline_node_pre_draw (ClutterPaintNode *node)
371 ClutterPipelineNode *pnode = CLUTTER_PIPELINE_NODE (node);
373 if (node->operations != NULL &&
374 pnode->pipeline != NULL)
376 cogl_push_source (pnode->pipeline);
384 clutter_pipeline_node_draw (ClutterPaintNode *node)
386 ClutterPipelineNode *pnode = CLUTTER_PIPELINE_NODE (node);
389 if (pnode->pipeline == NULL)
392 if (node->operations == NULL)
395 for (i = 0; i < node->operations->len; i++)
397 const ClutterPaintOperation *op;
399 op = &g_array_index (node->operations, ClutterPaintOperation, i);
403 case PAINT_OP_INVALID:
406 case PAINT_OP_TEX_RECT:
407 cogl_rectangle_with_texture_coords (op->op.texrect[0],
418 cogl_path_fill (op->op.path);
421 case PAINT_OP_PRIMITIVE:
423 CoglFramebuffer *fb = cogl_get_draw_framebuffer ();
425 cogl_framebuffer_draw_primitive (fb, pnode->pipeline,
434 clutter_pipeline_node_post_draw (ClutterPaintNode *node)
440 clutter_pipeline_node_serialize (ClutterPaintNode *node)
442 ClutterPipelineNode *pnode = CLUTTER_PIPELINE_NODE (node);
443 JsonBuilder *builder;
447 if (pnode->pipeline == NULL)
448 return json_node_new (JSON_NODE_NULL);
450 builder = json_builder_new ();
451 json_builder_begin_object (builder);
453 cogl_pipeline_get_color (pnode->pipeline, &color);
454 json_builder_set_member_name (builder, "color");
455 json_builder_begin_array (builder);
456 json_builder_add_double_value (builder, cogl_color_get_red (&color));
457 json_builder_add_double_value (builder, cogl_color_get_green (&color));
458 json_builder_add_double_value (builder, cogl_color_get_blue (&color));
459 json_builder_add_double_value (builder, cogl_color_get_alpha (&color));
460 json_builder_end_array (builder);
463 json_builder_set_member_name (builder, "layers");
464 json_builder_begin_array (builder);
465 cogl_pipeline_foreach_layer (pnode->pipeline,
466 clutter_pipeline_node_serialize_layer,
468 json_builder_end_array (builder);
471 json_builder_end_object (builder);
473 res = json_builder_get_root (builder);
474 g_object_unref (builder);
480 clutter_pipeline_node_class_init (ClutterPipelineNodeClass *klass)
482 ClutterPaintNodeClass *node_class;
484 node_class = CLUTTER_PAINT_NODE_CLASS (klass);
485 node_class->pre_draw = clutter_pipeline_node_pre_draw;
486 node_class->draw = clutter_pipeline_node_draw;
487 node_class->post_draw = clutter_pipeline_node_post_draw;
488 node_class->finalize = clutter_pipeline_node_finalize;
489 node_class->serialize = clutter_pipeline_node_serialize;
493 clutter_pipeline_node_init (ClutterPipelineNode *self)
498 * clutter_pipeline_node_new:
499 * @pipeline: (allow-none): a Cogl pipeline state object, or %NULL
501 * Creates a new #ClutterPaintNode that will use the @pipeline to
502 * paint its contents.
504 * This function will acquire a reference on the passed @pipeline,
505 * so it is safe to call cogl_object_unref() when it returns.
507 * Return value: (transfer full): the newly created #ClutterPaintNode.
508 * Use clutter_paint_node_unref() when done.
513 clutter_pipeline_node_new (CoglPipeline *pipeline)
515 ClutterPipelineNode *res;
517 g_return_val_if_fail (pipeline == NULL || cogl_is_pipeline (pipeline), NULL);
519 res = _clutter_paint_node_create (CLUTTER_TYPE_PIPELINE_NODE);
521 if (pipeline != NULL)
522 res->pipeline = cogl_object_ref (pipeline);
524 return (ClutterPaintNode *) res;
531 struct _ClutterColorNode
533 ClutterPipelineNode parent_instance;
537 * ClutterColorNodeClass:
539 * The <structname>ClutterColorNodeClass</structname> structure is an
540 * opaque type whose members cannot be directly accessed.
544 struct _ClutterColorNodeClass
546 ClutterPipelineNodeClass parent_class;
549 G_DEFINE_TYPE (ClutterColorNode, clutter_color_node, CLUTTER_TYPE_PIPELINE_NODE)
552 clutter_color_node_class_init (ClutterColorNodeClass *klass)
558 clutter_color_node_init (ClutterColorNode *cnode)
560 ClutterPipelineNode *pnode = CLUTTER_PIPELINE_NODE (cnode);
562 g_assert (default_color_pipeline != NULL);
563 pnode->pipeline = cogl_pipeline_copy (default_color_pipeline);
567 * clutter_color_node_new:
568 * @color: (allow-none): the color to paint, or %NULL
570 * Creates a new #ClutterPaintNode that will paint a solid color
573 * Return value: (transfer full): the newly created #ClutterPaintNode. Use
574 * clutter_paint_node_unref() when done
579 clutter_color_node_new (const ClutterColor *color)
581 ClutterPipelineNode *cnode;
583 cnode = _clutter_paint_node_create (CLUTTER_TYPE_COLOR_NODE);
587 CoglColor cogl_color;
589 cogl_color_init_from_4ub (&cogl_color,
594 cogl_color_premultiply (&cogl_color);
596 cogl_pipeline_set_color (cnode->pipeline, &cogl_color);
599 return (ClutterPaintNode *) cnode;
606 struct _ClutterTextureNode
608 ClutterPipelineNode parent_instance;
612 * ClutterTextureNodeClass:
614 * The <structname>ClutterTextureNodeClass</structname> structure is an
615 * opaque type whose members cannot be directly accessed.
619 struct _ClutterTextureNodeClass
621 ClutterPipelineNodeClass parent_class;
624 G_DEFINE_TYPE (ClutterTextureNode, clutter_texture_node, CLUTTER_TYPE_PIPELINE_NODE)
627 clutter_texture_node_class_init (ClutterTextureNodeClass *klass)
632 clutter_texture_node_init (ClutterTextureNode *self)
634 ClutterPipelineNode *pnode = CLUTTER_PIPELINE_NODE (self);
636 g_assert (default_texture_pipeline != NULL);
637 pnode->pipeline = cogl_pipeline_copy (default_texture_pipeline);
640 static CoglPipelineFilter
641 clutter_scaling_filter_to_cogl_pipeline_filter (ClutterScalingFilter filter)
645 case CLUTTER_SCALING_FILTER_NEAREST:
646 return COGL_PIPELINE_FILTER_NEAREST;
648 case CLUTTER_SCALING_FILTER_LINEAR:
649 return COGL_PIPELINE_FILTER_LINEAR;
651 case CLUTTER_SCALING_FILTER_TRILINEAR:
652 return COGL_PIPELINE_FILTER_LINEAR_MIPMAP_LINEAR;
655 return COGL_PIPELINE_FILTER_LINEAR;
659 * clutter_texture_node_new:
660 * @texture: a #CoglTexture
661 * @color: a #ClutterColor
662 * @min_filter: the minification filter for the texture
663 * @mag_filter: the magnification filter for the texture
665 * Creates a new #ClutterPaintNode that will paint the passed @texture.
667 * This function will take a reference on @texture, so it is safe to
668 * call cogl_object_unref() on @texture when it returns.
670 * Return value: (transfer full): the newly created #ClutterPaintNode.
671 * Use clutter_paint_node_unref() when done
676 clutter_texture_node_new (CoglTexture *texture,
677 const ClutterColor *color,
678 ClutterScalingFilter min_filter,
679 ClutterScalingFilter mag_filter)
681 ClutterPipelineNode *tnode;
682 CoglColor cogl_color;
683 CoglPipelineFilter min_f, mag_f;
685 g_return_val_if_fail (cogl_is_texture (texture), NULL);
687 tnode = _clutter_paint_node_create (CLUTTER_TYPE_TEXTURE_NODE);
689 cogl_pipeline_set_layer_texture (tnode->pipeline, 0, texture);
691 min_f = clutter_scaling_filter_to_cogl_pipeline_filter (min_filter);
692 mag_f = clutter_scaling_filter_to_cogl_pipeline_filter (mag_filter);
693 cogl_pipeline_set_layer_filters (tnode->pipeline, 0, min_f, mag_f);
695 cogl_color_init_from_4ub (&cogl_color,
700 cogl_color_premultiply (&cogl_color);
701 cogl_pipeline_set_color (tnode->pipeline, &cogl_color);
703 return (ClutterPaintNode *) tnode;
710 struct _ClutterTextNode
712 ClutterPaintNode parent_instance;
719 * ClutterTextNodeClass:
721 * The <structname>ClutterTextNodeClass</structname> structure is an opaque
722 * type whose contents cannot be directly accessed.
726 struct _ClutterTextNodeClass
728 ClutterPaintNodeClass parent_class;
731 G_DEFINE_TYPE (ClutterTextNode, clutter_text_node, CLUTTER_TYPE_PAINT_NODE)
734 clutter_text_node_finalize (ClutterPaintNode *node)
736 ClutterTextNode *tnode = CLUTTER_TEXT_NODE (node);
738 if (tnode->layout != NULL)
739 g_object_unref (tnode->layout);
741 CLUTTER_PAINT_NODE_CLASS (clutter_text_node_parent_class)->finalize (node);
745 clutter_text_node_pre_draw (ClutterPaintNode *node)
747 ClutterTextNode *tnode = CLUTTER_TEXT_NODE (node);
749 return tnode->layout != NULL;
753 clutter_text_node_draw (ClutterPaintNode *node)
755 ClutterTextNode *tnode = CLUTTER_TEXT_NODE (node);
756 PangoRectangle extents;
759 if (node->operations == NULL)
762 pango_layout_get_pixel_extents (tnode->layout, NULL, &extents);
764 for (i = 0; i < node->operations->len; i++)
766 const ClutterPaintOperation *op;
767 float op_width, op_height;
768 gboolean clipped = FALSE;
770 op = &g_array_index (node->operations, ClutterPaintOperation, i);
774 case PAINT_OP_TEX_RECT:
775 op_width = op->op.texrect[2] - op->op.texrect[0];
776 op_height = op->op.texrect[3] - op->op.texrect[1];
778 /* if the primitive size was smaller than the layout,
779 * we clip the layout when drawin, to avoid spilling
782 if (extents.width > op_width ||
783 extents.height > op_height)
785 cogl_clip_push_rectangle (op->op.texrect[0],
792 cogl_pango_render_layout (tnode->layout,
803 case PAINT_OP_PRIMITIVE:
804 case PAINT_OP_INVALID:
811 clutter_text_node_serialize (ClutterPaintNode *node)
813 ClutterTextNode *tnode = CLUTTER_TEXT_NODE (node);
814 JsonBuilder *builder;
817 builder = json_builder_new ();
819 json_builder_begin_object (builder);
821 json_builder_set_member_name (builder, "layout");
823 #if PANGO_VERSION_CHECK (1, 30, 0)
824 if (pango_layout_get_character_count (tnode->layout) > 12)
826 const char *text = pango_layout_get_text (tnode->layout);
829 str = g_strndup (text, 12);
830 json_builder_add_string_value (builder, str);
834 #endif /* PANGO_VERSION_CHECK (1, 30, 0) */
835 json_builder_add_string_value (builder, pango_layout_get_text (tnode->layout));
837 json_builder_set_member_name (builder, "color");
838 json_builder_begin_array (builder);
839 json_builder_add_double_value (builder, cogl_color_get_red (&tnode->color));
840 json_builder_add_double_value (builder, cogl_color_get_green (&tnode->color));
841 json_builder_add_double_value (builder, cogl_color_get_blue (&tnode->color));
842 json_builder_add_double_value (builder, cogl_color_get_alpha (&tnode->color));
843 json_builder_end_array (builder);
845 json_builder_end_object (builder);
847 res = json_builder_get_root (builder);
848 g_object_unref (builder);
854 clutter_text_node_class_init (ClutterTextNodeClass *klass)
856 ClutterPaintNodeClass *node_class = CLUTTER_PAINT_NODE_CLASS (klass);
858 node_class->pre_draw = clutter_text_node_pre_draw;
859 node_class->draw = clutter_text_node_draw;
860 node_class->finalize = clutter_text_node_finalize;
861 node_class->serialize = clutter_text_node_serialize;
865 clutter_text_node_init (ClutterTextNode *self)
867 cogl_color_init_from_4f (&self->color, 0.0, 0.0, 0.0, 1.0);
871 * clutter_text_node_new:
872 * @layout: (allow-none): a #PangoLayout, or %NULL
873 * @color: (allow-none): the color used to paint the layout,
876 * Creates a new #ClutterPaintNode that will paint a #PangoLayout
877 * with the given color.
879 * This function takes a reference on the passed @layout, so it
880 * is safe to call g_object_unref() after it returns.
882 * Return value: (transfer full): the newly created #ClutterPaintNode.
883 * Use clutter_paint_node_unref() when done
888 clutter_text_node_new (PangoLayout *layout,
889 const ClutterColor *color)
891 ClutterTextNode *res;
893 g_return_val_if_fail (layout == NULL || PANGO_IS_LAYOUT (layout), NULL);
895 res = _clutter_paint_node_create (CLUTTER_TYPE_TEXT_NODE);
898 res->layout = g_object_ref (layout);
902 cogl_color_init_from_4ub (&res->color,
909 return (ClutterPaintNode *) res;
915 struct _ClutterClipNode
917 ClutterPaintNode parent_instance;
921 * ClutterClipNodeClass:
923 * The <structname>ClutterClipNodeClass</structname> structure is an opaque
924 * type whose members cannot be directly accessed.
928 struct _ClutterClipNodeClass
930 ClutterPaintNodeClass parent_class;
933 G_DEFINE_TYPE (ClutterClipNode, clutter_clip_node, CLUTTER_TYPE_PAINT_NODE)
936 clutter_clip_node_pre_draw (ClutterPaintNode *node)
938 gboolean retval = FALSE;
942 if (node->operations == NULL)
945 fb = cogl_get_draw_framebuffer ();
947 for (i = 0; i < node->operations->len; i++)
949 const ClutterPaintOperation *op;
951 op = &g_array_index (node->operations, ClutterPaintOperation, i);
955 case PAINT_OP_TEX_RECT:
956 cogl_framebuffer_push_rectangle_clip (fb,
965 cogl_framebuffer_push_path_clip (fb, op->op.path);
969 case PAINT_OP_PRIMITIVE:
970 case PAINT_OP_INVALID:
979 clutter_clip_node_post_draw (ClutterPaintNode *node)
984 if (node->operations == NULL)
987 fb = cogl_get_draw_framebuffer ();
989 for (i = 0; i < node->operations->len; i++)
991 const ClutterPaintOperation *op;
993 op = &g_array_index (node->operations, ClutterPaintOperation, i);
998 case PAINT_OP_TEX_RECT:
999 cogl_framebuffer_pop_clip (fb);
1002 case PAINT_OP_PRIMITIVE:
1003 case PAINT_OP_INVALID:
1010 clutter_clip_node_class_init (ClutterClipNodeClass *klass)
1012 ClutterPaintNodeClass *node_class;
1014 node_class = CLUTTER_PAINT_NODE_CLASS (klass);
1015 node_class->pre_draw = clutter_clip_node_pre_draw;
1016 node_class->post_draw = clutter_clip_node_post_draw;
1020 clutter_clip_node_init (ClutterClipNode *self)
1025 * clutter_clip_node_new:
1027 * Creates a new #ClutterPaintNode that will clip its child
1028 * nodes to the 2D regions added to it.
1030 * Return value: (transfer full): the newly created #ClutterPaintNode.
1031 * Use clutter_paint_node_unref() when done.
1036 clutter_clip_node_new (void)
1038 return _clutter_paint_node_create (CLUTTER_TYPE_CLIP_NODE);
1042 * ClutterLayerNode (private)
1045 #define clutter_layer_node_get_type _clutter_layer_node_get_type
1047 struct _ClutterLayerNode
1049 ClutterPaintNode parent_instance;
1051 cairo_rectangle_t viewport;
1053 CoglMatrix projection;
1058 CoglPipeline *state;
1059 CoglFramebuffer *offscreen;
1060 CoglTexture *texture;
1065 struct _ClutterLayerNodeClass
1067 ClutterPaintNodeClass parent_class;
1070 G_DEFINE_TYPE (ClutterLayerNode, clutter_layer_node, CLUTTER_TYPE_PAINT_NODE)
1073 clutter_layer_node_pre_draw (ClutterPaintNode *node)
1075 ClutterLayerNode *lnode = (ClutterLayerNode *) node;
1078 /* if we were unable to create an offscreen buffer for this node, then
1079 * we simply ignore it
1081 if (lnode->offscreen == NULL)
1084 /* if no geometry was submitted for this node then we simply ignore it */
1085 if (node->operations == NULL)
1088 /* copy the same modelview from the current framebuffer to the one we
1091 cogl_get_modelview_matrix (&matrix);
1093 cogl_push_framebuffer (lnode->offscreen);
1095 cogl_framebuffer_set_modelview_matrix (lnode->offscreen, &matrix);
1097 cogl_framebuffer_set_viewport (lnode->offscreen,
1100 lnode->viewport.width,
1101 lnode->viewport.height);
1103 cogl_framebuffer_set_projection_matrix (lnode->offscreen,
1104 &lnode->projection);
1106 /* clear out the target framebuffer */
1107 cogl_framebuffer_clear4f (lnode->offscreen,
1108 COGL_BUFFER_BIT_COLOR | COGL_BUFFER_BIT_DEPTH,
1109 0.f, 0.f, 0.f, 0.f);
1111 cogl_push_matrix ();
1113 /* every draw operation after this point will happen an offscreen
1121 clutter_layer_node_post_draw (ClutterPaintNode *node)
1123 ClutterLayerNode *lnode = CLUTTER_LAYER_NODE (node);
1124 CoglFramebuffer *fb;
1127 /* switch to the previous framebuffer */
1129 cogl_pop_framebuffer ();
1131 fb = cogl_get_draw_framebuffer ();
1133 for (i = 0; i < node->operations->len; i++)
1135 const ClutterPaintOperation *op;
1137 op = &g_array_index (node->operations, ClutterPaintOperation, i);
1140 case PAINT_OP_INVALID:
1143 case PAINT_OP_TEX_RECT:
1144 /* now we need to paint the texture */
1145 cogl_push_source (lnode->state);
1146 cogl_rectangle_with_texture_coords (op->op.texrect[0],
1158 cogl_push_source (lnode->state);
1159 cogl_path_fill (op->op.path);
1163 case PAINT_OP_PRIMITIVE:
1164 cogl_framebuffer_draw_primitive (fb, lnode->state, op->op.primitive);
1171 clutter_layer_node_finalize (ClutterPaintNode *node)
1173 ClutterLayerNode *lnode = CLUTTER_LAYER_NODE (node);
1175 if (lnode->state != NULL)
1176 cogl_object_unref (lnode->state);
1178 if (lnode->offscreen != NULL)
1179 cogl_object_unref (lnode->offscreen);
1181 CLUTTER_PAINT_NODE_CLASS (clutter_layer_node_parent_class)->finalize (node);
1185 clutter_layer_node_class_init (ClutterLayerNodeClass *klass)
1187 ClutterPaintNodeClass *node_class;
1189 node_class = CLUTTER_PAINT_NODE_CLASS (klass);
1190 node_class->pre_draw = clutter_layer_node_pre_draw;
1191 node_class->post_draw = clutter_layer_node_post_draw;
1192 node_class->finalize = clutter_layer_node_finalize;
1196 clutter_layer_node_init (ClutterLayerNode *self)
1198 cogl_matrix_init_identity (&self->projection);
1202 * clutter_layer_node_new:
1203 * @projection: the projection matrix to use to set up the layer
1204 * @viewport: (type cairo.Rectangle): the viewport to use to set up the layer
1205 * @width: the width of the layer
1206 * @height: the height of the layer
1207 * @opacity: the opacity to be used when drawing the layer
1209 * Creates a new #ClutterLayerNode.
1211 * All children of this node will be painted inside a separate
1212 * framebuffer; the framebuffer will then be painted using the
1215 * Return value: (transfer full): the newly created #ClutterLayerNode.
1216 * Use clutter_paint_node_unref() when done.
1221 _clutter_layer_node_new (const CoglMatrix *projection,
1222 const cairo_rectangle_t *viewport,
1227 ClutterLayerNode *res;
1230 res = _clutter_paint_node_create (CLUTTER_TYPE_LAYER_NODE);
1232 res->projection = *projection;
1233 res->viewport = *viewport;
1234 res->fbo_width = width;
1235 res->fbo_height = height;
1236 res->opacity = opacity;
1238 /* the texture backing the FBO */
1239 res->texture = cogl_texture_new_with_size (MAX (res->fbo_width, 1),
1240 MAX (res->fbo_height, 1),
1241 COGL_TEXTURE_NO_SLICING,
1242 COGL_PIXEL_FORMAT_RGBA_8888_PRE);
1244 res->offscreen = COGL_FRAMEBUFFER (cogl_offscreen_new_to_texture (res->texture));
1245 if (res->offscreen == NULL)
1247 g_critical ("%s: Unable to create an offscreen buffer", G_STRLOC);
1249 cogl_object_unref (res->texture);
1250 res->texture = NULL;
1255 cogl_color_init_from_4ub (&color, opacity, opacity, opacity, opacity);
1257 /* the pipeline used to paint the texture; we use nearest
1258 * interpolation filters because the texture is always
1259 * going to be painted at a 1:1 texel:pixel ratio
1261 res->state = cogl_pipeline_copy (default_texture_pipeline);
1262 cogl_pipeline_set_layer_filters (res->state, 0,
1263 COGL_PIPELINE_FILTER_NEAREST,
1264 COGL_PIPELINE_FILTER_NEAREST);
1265 cogl_pipeline_set_layer_texture (res->state, 0, res->texture);
1266 cogl_pipeline_set_color (res->state, &color);
1267 cogl_object_unref (res->texture);
1270 return (ClutterPaintNode *) res;