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_layout_get_character_count (tnode->layout) > 12)
825 const char *text = pango_layout_get_text (tnode->layout);
828 str = g_strndup (text, 12);
829 json_builder_add_string_value (builder, str);
833 json_builder_add_string_value (builder, pango_layout_get_text (tnode->layout));
835 json_builder_set_member_name (builder, "color");
836 json_builder_begin_array (builder);
837 json_builder_add_double_value (builder, cogl_color_get_red (&tnode->color));
838 json_builder_add_double_value (builder, cogl_color_get_green (&tnode->color));
839 json_builder_add_double_value (builder, cogl_color_get_blue (&tnode->color));
840 json_builder_add_double_value (builder, cogl_color_get_alpha (&tnode->color));
841 json_builder_end_array (builder);
843 json_builder_end_object (builder);
845 res = json_builder_get_root (builder);
846 g_object_unref (builder);
852 clutter_text_node_class_init (ClutterTextNodeClass *klass)
854 ClutterPaintNodeClass *node_class = CLUTTER_PAINT_NODE_CLASS (klass);
856 node_class->pre_draw = clutter_text_node_pre_draw;
857 node_class->draw = clutter_text_node_draw;
858 node_class->finalize = clutter_text_node_finalize;
859 node_class->serialize = clutter_text_node_serialize;
863 clutter_text_node_init (ClutterTextNode *self)
865 cogl_color_init_from_4f (&self->color, 0.0, 0.0, 0.0, 1.0);
869 * clutter_text_node_new:
870 * @layout: (allow-none): a #PangoLayout, or %NULL
871 * @color: (allow-none): the color used to paint the layout,
874 * Creates a new #ClutterPaintNode that will paint a #PangoLayout
875 * with the given color.
877 * This function takes a reference on the passed @layout, so it
878 * is safe to call g_object_unref() after it returns.
880 * Return value: (transfer full): the newly created #ClutterPaintNode.
881 * Use clutter_paint_node_unref() when done
886 clutter_text_node_new (PangoLayout *layout,
887 const ClutterColor *color)
889 ClutterTextNode *res;
891 g_return_val_if_fail (layout == NULL || PANGO_IS_LAYOUT (layout), NULL);
893 res = _clutter_paint_node_create (CLUTTER_TYPE_TEXT_NODE);
896 res->layout = g_object_ref (layout);
900 cogl_color_init_from_4ub (&res->color,
907 return (ClutterPaintNode *) res;
913 struct _ClutterClipNode
915 ClutterPaintNode parent_instance;
919 * ClutterClipNodeClass:
921 * The <structname>ClutterClipNodeClass</structname> structure is an opaque
922 * type whose members cannot be directly accessed.
926 struct _ClutterClipNodeClass
928 ClutterPaintNodeClass parent_class;
931 G_DEFINE_TYPE (ClutterClipNode, clutter_clip_node, CLUTTER_TYPE_PAINT_NODE)
934 clutter_clip_node_pre_draw (ClutterPaintNode *node)
936 gboolean retval = FALSE;
940 if (node->operations == NULL)
943 fb = cogl_get_draw_framebuffer ();
945 for (i = 0; i < node->operations->len; i++)
947 const ClutterPaintOperation *op;
949 op = &g_array_index (node->operations, ClutterPaintOperation, i);
953 case PAINT_OP_TEX_RECT:
954 cogl_framebuffer_push_rectangle_clip (fb,
963 cogl_framebuffer_push_path_clip (fb, op->op.path);
967 case PAINT_OP_PRIMITIVE:
968 case PAINT_OP_INVALID:
977 clutter_clip_node_post_draw (ClutterPaintNode *node)
982 if (node->operations == NULL)
985 fb = cogl_get_draw_framebuffer ();
987 for (i = 0; i < node->operations->len; i++)
989 const ClutterPaintOperation *op;
991 op = &g_array_index (node->operations, ClutterPaintOperation, i);
996 case PAINT_OP_TEX_RECT:
997 cogl_framebuffer_pop_clip (fb);
1000 case PAINT_OP_PRIMITIVE:
1001 case PAINT_OP_INVALID:
1008 clutter_clip_node_class_init (ClutterClipNodeClass *klass)
1010 ClutterPaintNodeClass *node_class;
1012 node_class = CLUTTER_PAINT_NODE_CLASS (klass);
1013 node_class->pre_draw = clutter_clip_node_pre_draw;
1014 node_class->post_draw = clutter_clip_node_post_draw;
1018 clutter_clip_node_init (ClutterClipNode *self)
1023 * clutter_clip_node_new:
1025 * Creates a new #ClutterPaintNode that will clip its child
1026 * nodes to the 2D regions added to it.
1028 * Return value: (transfer full): the newly created #ClutterPaintNode.
1029 * Use clutter_paint_node_unref() when done.
1034 clutter_clip_node_new (void)
1036 return _clutter_paint_node_create (CLUTTER_TYPE_CLIP_NODE);
1040 * ClutterLayerNode (private)
1043 #define clutter_layer_node_get_type _clutter_layer_node_get_type
1045 struct _ClutterLayerNode
1047 ClutterPaintNode parent_instance;
1049 cairo_rectangle_t viewport;
1051 CoglMatrix projection;
1056 CoglPipeline *state;
1057 CoglFramebuffer *offscreen;
1058 CoglTexture *texture;
1063 struct _ClutterLayerNodeClass
1065 ClutterPaintNodeClass parent_class;
1068 G_DEFINE_TYPE (ClutterLayerNode, clutter_layer_node, CLUTTER_TYPE_PAINT_NODE)
1071 clutter_layer_node_pre_draw (ClutterPaintNode *node)
1073 ClutterLayerNode *lnode = (ClutterLayerNode *) node;
1076 /* if we were unable to create an offscreen buffer for this node, then
1077 * we simply ignore it
1079 if (lnode->offscreen == NULL)
1082 /* if no geometry was submitted for this node then we simply ignore it */
1083 if (node->operations == NULL)
1086 /* copy the same modelview from the current framebuffer to the one we
1089 cogl_get_modelview_matrix (&matrix);
1091 cogl_push_framebuffer (lnode->offscreen);
1093 cogl_framebuffer_set_modelview_matrix (lnode->offscreen, &matrix);
1095 cogl_framebuffer_set_viewport (lnode->offscreen,
1098 lnode->viewport.width,
1099 lnode->viewport.height);
1101 cogl_framebuffer_set_projection_matrix (lnode->offscreen,
1102 &lnode->projection);
1104 /* clear out the target framebuffer */
1105 cogl_framebuffer_clear4f (lnode->offscreen,
1106 COGL_BUFFER_BIT_COLOR | COGL_BUFFER_BIT_DEPTH,
1107 0.f, 0.f, 0.f, 0.f);
1109 cogl_push_matrix ();
1111 /* every draw operation after this point will happen an offscreen
1119 clutter_layer_node_post_draw (ClutterPaintNode *node)
1121 ClutterLayerNode *lnode = CLUTTER_LAYER_NODE (node);
1122 CoglFramebuffer *fb;
1125 /* switch to the previous framebuffer */
1127 cogl_pop_framebuffer ();
1129 fb = cogl_get_draw_framebuffer ();
1131 for (i = 0; i < node->operations->len; i++)
1133 const ClutterPaintOperation *op;
1135 op = &g_array_index (node->operations, ClutterPaintOperation, i);
1138 case PAINT_OP_INVALID:
1141 case PAINT_OP_TEX_RECT:
1142 /* now we need to paint the texture */
1143 cogl_push_source (lnode->state);
1144 cogl_rectangle_with_texture_coords (op->op.texrect[0],
1156 cogl_push_source (lnode->state);
1157 cogl_path_fill (op->op.path);
1161 case PAINT_OP_PRIMITIVE:
1162 cogl_framebuffer_draw_primitive (fb, lnode->state, op->op.primitive);
1169 clutter_layer_node_finalize (ClutterPaintNode *node)
1171 ClutterLayerNode *lnode = CLUTTER_LAYER_NODE (node);
1173 if (lnode->state != NULL)
1174 cogl_object_unref (lnode->state);
1176 if (lnode->offscreen != NULL)
1177 cogl_object_unref (lnode->offscreen);
1179 CLUTTER_PAINT_NODE_CLASS (clutter_layer_node_parent_class)->finalize (node);
1183 clutter_layer_node_class_init (ClutterLayerNodeClass *klass)
1185 ClutterPaintNodeClass *node_class;
1187 node_class = CLUTTER_PAINT_NODE_CLASS (klass);
1188 node_class->pre_draw = clutter_layer_node_pre_draw;
1189 node_class->post_draw = clutter_layer_node_post_draw;
1190 node_class->finalize = clutter_layer_node_finalize;
1194 clutter_layer_node_init (ClutterLayerNode *self)
1196 cogl_matrix_init_identity (&self->projection);
1200 * clutter_layer_node_new:
1201 * @projection: the projection matrix to use to set up the layer
1202 * @viewport: (type cairo.Rectangle): the viewport to use to set up the layer
1203 * @width: the width of the layer
1204 * @height: the height of the layer
1205 * @opacity: the opacity to be used when drawing the layer
1207 * Creates a new #ClutterLayerNode.
1209 * All children of this node will be painted inside a separate
1210 * framebuffer; the framebuffer will then be painted using the
1213 * Return value: (transfer full): the newly created #ClutterLayerNode.
1214 * Use clutter_paint_node_unref() when done.
1219 _clutter_layer_node_new (const CoglMatrix *projection,
1220 const cairo_rectangle_t *viewport,
1225 ClutterLayerNode *res;
1228 res = _clutter_paint_node_create (CLUTTER_TYPE_LAYER_NODE);
1230 res->projection = *projection;
1231 res->viewport = *viewport;
1232 res->fbo_width = width;
1233 res->fbo_height = height;
1234 res->opacity = opacity;
1236 /* the texture backing the FBO */
1237 res->texture = cogl_texture_new_with_size (MAX (res->fbo_width, 1),
1238 MAX (res->fbo_height, 1),
1239 COGL_TEXTURE_NO_SLICING,
1240 COGL_PIXEL_FORMAT_RGBA_8888_PRE);
1242 res->offscreen = COGL_FRAMEBUFFER (cogl_offscreen_new_to_texture (res->texture));
1243 if (res->offscreen == NULL)
1245 g_critical ("%s: Unable to create an offscreen buffer", G_STRLOC);
1247 cogl_object_unref (res->texture);
1248 res->texture = NULL;
1253 cogl_color_init_from_4ub (&color, opacity, opacity, opacity, opacity);
1255 /* the pipeline used to paint the texture; we use nearest
1256 * interpolation filters because the texture is always
1257 * going to be painted at a 1:1 texel:pixel ratio
1259 res->state = cogl_pipeline_copy (default_texture_pipeline);
1260 cogl_pipeline_set_layer_filters (res->state, 0,
1261 COGL_PIPELINE_FILTER_NEAREST,
1262 COGL_PIPELINE_FILTER_NEAREST);
1263 cogl_pipeline_set_layer_texture (res->state, 0, res->texture);
1264 cogl_pipeline_set_color (res->state, &color);
1265 cogl_object_unref (res->texture);
1268 return (ClutterPaintNode *) res;