diff --git a/clutter/clutter/clutter-actor.c b/clutter/clutter/clutter-actor.c index fd9aab289dfdf62f4ad51f91d3800eca081d9f68..4701daab76647635701ad8741497ab39e4f8a734 100644 --- a/clutter/clutter/clutter-actor.c +++ b/clutter/clutter/clutter-actor.c @@ -3740,7 +3740,7 @@ clutter_actor_paint_node (ClutterActor *actor, if (!clutter_stage_get_no_clear_hint (CLUTTER_STAGE (actor))) clear_flags |= COGL_BUFFER_BIT_COLOR; - node = _clutter_root_node_new (fb, &bg_color, clear_flags); + node = clutter_root_node_new (fb, &bg_color, clear_flags); clutter_paint_node_set_name (node, "stageClear"); clutter_paint_node_add_rectangle (node, &box); clutter_paint_node_add_child (root, node); @@ -3779,7 +3779,7 @@ clutter_actor_paint_node (ClutterActor *actor, } #endif /* CLUTTER_ENABLE_DEBUG */ - _clutter_paint_node_paint (root); + clutter_paint_node_paint (root); return TRUE; } diff --git a/clutter/clutter/clutter-content.c b/clutter/clutter/clutter-content.c index 35419305e004e3ef2f24cb98acd0e96ceafcbe8d..b7aea04c2afd9e43d9d915f26caaf65c92c9aa85 100644 --- a/clutter/clutter/clutter-content.c +++ b/clutter/clutter/clutter-content.c @@ -38,6 +38,7 @@ #include "clutter-build-config.h" +#include "clutter-actor-private.h" #include "clutter-content-private.h" #include "clutter-debug.h" @@ -91,6 +92,11 @@ clutter_content_real_invalidate (ClutterContent *content) { } +static void +clutter_content_real_invalidate_size (ClutterContent *content) +{ +} + static void clutter_content_real_paint_content (ClutterContent *content, ClutterActor *actor, @@ -108,6 +114,7 @@ clutter_content_default_init (ClutterContentInterface *iface) iface->attached = clutter_content_real_attached; iface->detached = clutter_content_real_detached; iface->invalidate = clutter_content_real_invalidate; + iface->invalidate_size = clutter_content_real_invalidate_size; /** * ClutterContent::attached: @@ -188,6 +195,45 @@ clutter_content_invalidate (ClutterContent *content) } } +/** + * clutter_content_invalidate_size: + * @content: a #ClutterContent + * + * Signals that @content's size changed. Attached actors with request mode + * set to %CLUTTER_REQUEST_CONTENT_SIZE will have a relayout queued. + * + * Attached actors with other request modes are not redrawn. To redraw them + * too, use clutter_content_invalidate(). + */ +void +clutter_content_invalidate_size (ClutterContent *content) +{ + ClutterActor *actor; + GHashTable *actors; + GHashTableIter iter; + + g_return_if_fail (CLUTTER_IS_CONTENT (content)); + + CLUTTER_CONTENT_GET_IFACE (content)->invalidate_size (content); + + actors = g_object_get_qdata (G_OBJECT (content), quark_content_actors); + if (actors == NULL) + return; + + g_hash_table_iter_init (&iter, actors); + while (g_hash_table_iter_next (&iter, (gpointer *) &actor, NULL)) + { + ClutterRequestMode request_mode; + + g_assert (actor != NULL); + + request_mode = clutter_actor_get_request_mode (actor); + + if (request_mode == CLUTTER_REQUEST_CONTENT_SIZE) + _clutter_actor_queue_only_relayout (actor); + } +} + /*< private > * _clutter_content_attached: * @content: a #ClutterContent diff --git a/clutter/clutter/clutter-content.h b/clutter/clutter/clutter-content.h index 69836d5a1c8cdc67411cac3f8d4860f912558fe4..0b676f6e3cbcc8d323ded29e103df4287ecbd841 100644 --- a/clutter/clutter/clutter-content.h +++ b/clutter/clutter/clutter-content.h @@ -86,6 +86,8 @@ struct _ClutterContentIface ClutterActor *actor); void (* invalidate) (ClutterContent *content); + + void (* invalidate_size) (ClutterContent *content); }; CLUTTER_EXPORT @@ -98,6 +100,9 @@ gboolean clutter_content_get_preferred_size (ClutterContent *content CLUTTER_EXPORT void clutter_content_invalidate (ClutterContent *content); +CLUTTER_EXPORT +void clutter_content_invalidate_size (ClutterContent *content); + G_END_DECLS #endif /* __CLUTTER_CONTENT_H__ */ diff --git a/clutter/clutter/clutter-image.c b/clutter/clutter/clutter-image.c index d4356598b7e5838bee612b6f70e6bab198b25c1b..924626be04a84750a8a6bcbe43120bd1bf4ee96c 100644 --- a/clutter/clutter/clutter-image.c +++ b/clutter/clutter/clutter-image.c @@ -53,6 +53,8 @@ struct _ClutterImagePrivate { CoglTexture *texture; + gint width; + gint height; }; static void clutter_content_iface_init (ClutterContentIface *iface); @@ -68,6 +70,27 @@ clutter_image_error_quark (void) return g_quark_from_static_string ("clutter-image-error-quark"); } +static void +update_image_size (ClutterImage *self) +{ + gint width, height; + + if (self->priv->texture == NULL) + return; + + width = cogl_texture_get_width (self->priv->texture); + height = cogl_texture_get_height (self->priv->texture); + + if (self->priv->width == width && + self->priv->height == height) + return; + + self->priv->width = width; + self->priv->height = height; + + clutter_content_invalidate_size (CLUTTER_CONTENT (self)); +} + static void clutter_image_finalize (GObject *gobject) { @@ -238,6 +261,7 @@ clutter_image_set_data (ClutterImage *image, } clutter_content_invalidate (CLUTTER_CONTENT (image)); + update_image_size (image); return TRUE; } @@ -306,6 +330,7 @@ clutter_image_set_bytes (ClutterImage *image, } clutter_content_invalidate (CLUTTER_CONTENT (image)); + update_image_size (image); return TRUE; } @@ -399,6 +424,7 @@ clutter_image_set_area (ClutterImage *image, } clutter_content_invalidate (CLUTTER_CONTENT (image)); + update_image_size (image); return TRUE; } diff --git a/clutter/clutter/clutter-paint-node-private.h b/clutter/clutter/clutter-paint-node-private.h index 2945b78a432ae7135e928fd6c23acd2aeac2c7bd..55cf9efd2b42e1bb407a5ebfa9de73c6e32f6a97 100644 --- a/clutter/clutter/clutter-paint-node-private.h +++ b/clutter/clutter/clutter-paint-node-private.h @@ -77,6 +77,7 @@ struct _ClutterPaintNodeClass typedef enum { PAINT_OP_INVALID = 0, PAINT_OP_TEX_RECT, + PAINT_OP_MULTITEX_RECT, PAINT_OP_PATH, PAINT_OP_PRIMITIVE } PaintOpCode; @@ -85,6 +86,8 @@ struct _ClutterPaintOperation { PaintOpCode opcode; + GArray *multitex_coords; + union { float texrect[8]; @@ -94,7 +97,6 @@ struct _ClutterPaintOperation } op; }; -GType _clutter_root_node_get_type (void) G_GNUC_CONST; GType _clutter_transform_node_get_type (void) G_GNUC_CONST; GType _clutter_dummy_node_get_type (void) G_GNUC_CONST; @@ -107,13 +109,9 @@ void _clutter_paint_operation_paint_primitive (const C void _clutter_paint_node_init_types (void); gpointer _clutter_paint_node_create (GType gtype); -ClutterPaintNode * _clutter_root_node_new (CoglFramebuffer *framebuffer, - const ClutterColor *clear_color, - CoglBufferBit clear_flags); ClutterPaintNode * _clutter_transform_node_new (const CoglMatrix *matrix); ClutterPaintNode * _clutter_dummy_node_new (ClutterActor *actor); -void _clutter_paint_node_paint (ClutterPaintNode *root); void _clutter_paint_node_dump_tree (ClutterPaintNode *root); G_GNUC_INTERNAL diff --git a/clutter/clutter/clutter-paint-node.c b/clutter/clutter/clutter-paint-node.c index 3dafca0f180328a1934bdfd163a4ef0f8440c09a..e731ca60a26b4f5f2c1833542fd63d8da2a1bf45 100644 --- a/clutter/clutter/clutter-paint-node.c +++ b/clutter/clutter/clutter-paint-node.c @@ -761,6 +761,11 @@ clutter_paint_operation_clear (ClutterPaintOperation *op) case PAINT_OP_TEX_RECT: break; + case PAINT_OP_MULTITEX_RECT: + if (op->multitex_coords != NULL) + g_array_unref (op->multitex_coords); + break; + case PAINT_OP_PATH: if (op->op.path != NULL) cogl_object_unref (op->op.path); @@ -794,6 +799,27 @@ clutter_paint_op_init_tex_rect (ClutterPaintOperation *op, op->op.texrect[7] = y_2; } +static inline void +clutter_paint_op_init_multitex_rect (ClutterPaintOperation *op, + const ClutterActorBox *rect, + const float *tex_coords, + unsigned int tex_coords_len) +{ + clutter_paint_operation_clear (op); + + op->opcode = PAINT_OP_MULTITEX_RECT; + op->multitex_coords = g_array_sized_new (FALSE, FALSE, + sizeof (float), + tex_coords_len); + + g_array_append_vals (op->multitex_coords, tex_coords, tex_coords_len); + + op->op.texrect[0] = rect->x1; + op->op.texrect[1] = rect->y1; + op->op.texrect[2] = rect->x2; + op->op.texrect[3] = rect->y2; +} + static inline void clutter_paint_op_init_path (ClutterPaintOperation *op, CoglPath *path) @@ -881,6 +907,33 @@ clutter_paint_node_add_texture_rectangle (ClutterPaintNode *node, g_array_append_val (node->operations, operation); } + +/** + * clutter_paint_node_add_multitexture_rectangle: + * @node: a #ClutterPaintNode + * @rect: a #ClutterActorBox + * @text_coords: array of multitexture values + * @text_coords_len: number of items of @text_coords + * + * Adds a rectangle region to the @node, with multitexture coordinates. + */ +void +clutter_paint_node_add_multitexture_rectangle (ClutterPaintNode *node, + const ClutterActorBox *rect, + const float *text_coords, + unsigned int text_coords_len) +{ + ClutterPaintOperation operation = PAINT_OP_INIT; + + g_return_if_fail (CLUTTER_IS_PAINT_NODE (node)); + g_return_if_fail (rect != NULL); + + clutter_paint_node_maybe_init_operations (node); + + clutter_paint_op_init_multitex_rect (&operation, rect, text_coords, text_coords_len); + g_array_append_val (node->operations, operation); +} + /** * clutter_paint_node_add_path: (skip) * @node: a #ClutterPaintNode @@ -936,15 +989,15 @@ clutter_paint_node_add_primitive (ClutterPaintNode *node, g_array_append_val (node->operations, operation); } -/*< private > - * _clutter_paint_node_paint: +/** + * clutter_paint_node_paint: * @node: a #ClutterPaintNode * * Paints the @node using the class implementation, traversing * its children, if any. */ void -_clutter_paint_node_paint (ClutterPaintNode *node) +clutter_paint_node_paint (ClutterPaintNode *node) { ClutterPaintNodeClass *klass = CLUTTER_PAINT_NODE_GET_CLASS (node); ClutterPaintNode *iter; @@ -961,7 +1014,7 @@ _clutter_paint_node_paint (ClutterPaintNode *node) iter != NULL; iter = iter->next_sibling) { - _clutter_paint_node_paint (iter); + clutter_paint_node_paint (iter); } if (res) @@ -1006,7 +1059,7 @@ clutter_paint_node_to_json (ClutterPaintNode *node) if (node->operations != NULL) { - guint i; + guint i, j; for (i = 0; i < node->operations->len; i++) { @@ -1031,6 +1084,19 @@ clutter_paint_node_to_json (ClutterPaintNode *node) json_builder_end_array (builder); break; + case PAINT_OP_MULTITEX_RECT: + json_builder_set_member_name (builder, "texrect"); + json_builder_begin_array (builder); + + for (j = 0; i < op->multitex_coords->len; j++) + { + float coord = g_array_index (op->multitex_coords, float, j); + json_builder_add_double_value (builder, coord); + } + + json_builder_end_array (builder); + break; + case PAINT_OP_PATH: json_builder_set_member_name (builder, "path"); json_builder_add_int_value (builder, (gint64) op->op.path); diff --git a/clutter/clutter/clutter-paint-node.h b/clutter/clutter/clutter-paint-node.h index 779b15e35e9c1878ad3b4dcf78d17b386c5211a5..c42abbc3d8a2bc27fb921df3534bb42a3f98cd5e 100644 --- a/clutter/clutter/clutter-paint-node.h +++ b/clutter/clutter/clutter-paint-node.h @@ -49,6 +49,9 @@ ClutterPaintNode * clutter_paint_node_ref (Clutter CLUTTER_EXPORT void clutter_paint_node_unref (ClutterPaintNode *node); +CLUTTER_EXPORT +void clutter_paint_node_paint (ClutterPaintNode *node); + CLUTTER_EXPORT void clutter_paint_node_set_name (ClutterPaintNode *node, const char *name); @@ -67,6 +70,12 @@ void clutter_paint_node_add_texture_rectangle (Clutter float x_2, float y_2); +CLUTTER_EXPORT +void clutter_paint_node_add_multitexture_rectangle (ClutterPaintNode *node, + const ClutterActorBox *rect, + const float *text_coords, + unsigned int text_coords_len); + CLUTTER_EXPORT void clutter_paint_node_add_path (ClutterPaintNode *node, CoglPath *path); diff --git a/clutter/clutter/clutter-paint-nodes.c b/clutter/clutter/clutter-paint-nodes.c index 2707dcf62100f01f04d99751cf42f03f5d4ffbee..d5efd5864251249bf515a6d2291c7ca211789ba6 100644 --- a/clutter/clutter/clutter-paint-nodes.c +++ b/clutter/clutter/clutter-paint-nodes.c @@ -83,16 +83,13 @@ _clutter_paint_node_init_types (void) } /* - * Root node, private + * Root node * * any frame can only have a since RootNode instance for each * top-level actor. */ -#define clutter_root_node_get_type _clutter_root_node_get_type - -typedef struct _ClutterRootNode ClutterRootNode; -typedef struct _ClutterPaintNodeClass ClutterRootNodeClass; +#define clutter_root_node_get_type clutter_root_node_get_type struct _ClutterRootNode { @@ -111,6 +108,8 @@ clutter_root_node_pre_draw (ClutterPaintNode *node) { ClutterRootNode *rnode = (ClutterRootNode *) node; + cogl_push_framebuffer (rnode->framebuffer); + cogl_framebuffer_clear (rnode->framebuffer, rnode->clear_flags, &rnode->clear_color); @@ -121,6 +120,7 @@ clutter_root_node_pre_draw (ClutterPaintNode *node) static void clutter_root_node_post_draw (ClutterPaintNode *node) { + cogl_pop_framebuffer (); } static void @@ -158,13 +158,13 @@ clutter_root_node_init (ClutterRootNode *self) } ClutterPaintNode * -_clutter_root_node_new (CoglFramebuffer *framebuffer, - const ClutterColor *clear_color, - CoglBufferBit clear_flags) +clutter_root_node_new (CoglFramebuffer *framebuffer, + const ClutterColor *clear_color, + CoglBufferBit clear_flags) { ClutterRootNode *res; - res = _clutter_paint_node_create (_clutter_root_node_get_type ()); + res = _clutter_paint_node_create (CLUTTER_TYPE_ROOT_NODE); cogl_color_init_from_4ub (&res->clear_color, clear_color->red, @@ -431,6 +431,17 @@ clutter_pipeline_node_draw (ClutterPaintNode *node) op->op.texrect[7]); break; + case PAINT_OP_MULTITEX_RECT: + cogl_framebuffer_draw_multitextured_rectangle (cogl_get_draw_framebuffer (), + pnode->pipeline, + op->op.texrect[0], + op->op.texrect[1], + op->op.texrect[2], + op->op.texrect[3], + (float*) op->multitex_coords->data, + op->multitex_coords->len); + break; + case PAINT_OP_PATH: cogl_path_fill (op->op.path); break; @@ -827,6 +838,7 @@ clutter_text_node_draw (ClutterPaintNode *node) cogl_framebuffer_pop_clip (fb); break; + case PAINT_OP_MULTITEX_RECT: case PAINT_OP_PATH: case PAINT_OP_PRIMITIVE: case PAINT_OP_INVALID: @@ -992,6 +1004,7 @@ clutter_clip_node_pre_draw (ClutterPaintNode *node) retval = TRUE; break; + case PAINT_OP_MULTITEX_RECT: case PAINT_OP_PRIMITIVE: case PAINT_OP_INVALID: break; @@ -1025,6 +1038,7 @@ clutter_clip_node_post_draw (ClutterPaintNode *node) cogl_framebuffer_pop_clip (fb); break; + case PAINT_OP_MULTITEX_RECT: case PAINT_OP_PRIMITIVE: case PAINT_OP_INVALID: break; @@ -1180,6 +1194,17 @@ clutter_layer_node_post_draw (ClutterPaintNode *node) cogl_pop_source (); break; + case PAINT_OP_MULTITEX_RECT: + cogl_framebuffer_draw_multitextured_rectangle (cogl_get_draw_framebuffer (), + lnode->state, + op->op.texrect[0], + op->op.texrect[1], + op->op.texrect[2], + op->op.texrect[3], + (float*) op->multitex_coords->data, + op->multitex_coords->len); + break; + case PAINT_OP_PATH: cogl_push_source (lnode->state); cogl_path_fill (op->op.path); diff --git a/clutter/clutter/clutter-paint-nodes.h b/clutter/clutter/clutter-paint-nodes.h index 381c7f8a7b8cb8044e456bf9ebeca8d62147bac7..ecaae60ba9fe2960d7ffbf11ea11b0ee8d5d7814 100644 --- a/clutter/clutter/clutter-paint-nodes.h +++ b/clutter/clutter/clutter-paint-nodes.h @@ -143,6 +143,26 @@ CLUTTER_EXPORT ClutterPaintNode * clutter_text_node_new (PangoLayout *layout, const ClutterColor *color); +#define CLUTTER_TYPE_ROOT_NODE (clutter_root_node_get_type ()) +#define CLUTTER_ROOT_NODE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_ROOT_NODE, ClutterRootNode)) +#define CLUTTER_IS_ROOT_NODE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_ROOT_NODE)) + +/** + * ClutterRootNode: + * + * The #ClutterRootNode structure is an opaque + * type whose members cannot be directly accessed. + */ +typedef struct _ClutterRootNode ClutterRootNode; +typedef struct _ClutterPaintNodeClass ClutterRootNodeClass; + +CLUTTER_EXPORT +GType clutter_root_node_get_type (void) G_GNUC_CONST; + +CLUTTER_EXPORT +ClutterPaintNode * clutter_root_node_new (CoglFramebuffer *framebuffer, + const ClutterColor *clear_color, + CoglBufferBit clear_flags); G_END_DECLS #endif /* __CLUTTER_PAINT_NODES_H__ */