From 854cf5d49916c8b4eb7218c340db2f95dca81d24 Mon Sep 17 00:00:00 2001 From: Emmanuele Bassi Date: Tue, 6 Jan 2009 12:53:30 +0000 Subject: [PATCH 01/43] Animate ClutterColor properties We can animate a ClutterColor-based property between an interval of two colors by simply applying the factor to each color component. --- clutter/clutter-interval.c | 21 ++++++++++++++++++++- tests/interactive/test-animation.c | 17 ++++++++++++----- 2 files changed, 32 insertions(+), 6 deletions(-) diff --git a/clutter/clutter-interval.c b/clutter/clutter-interval.c index 5f2924d09..a3be68c71 100644 --- a/clutter/clutter-interval.c +++ b/clutter/clutter-interval.c @@ -57,9 +57,10 @@ #include #include +#include "clutter-color.h" +#include "clutter-fixed.h" #include "clutter-interval.h" #include "clutter-units.h" -#include "clutter-fixed.h" enum { @@ -249,6 +250,24 @@ clutter_interval_real_compute_value (ClutterInterval *interval, g_value_set_boolean (value, FALSE); break; + case G_TYPE_BOXED: + if (value_type == CLUTTER_TYPE_COLOR) + { + const ClutterColor *ia, *ib; + ClutterColor res = { 0, }; + + ia = clutter_value_get_color (initial); + ib = clutter_value_get_color (final); + + res.red = (factor * (ib->red - (gdouble) ia->red)) + ia->red; + res.green = (factor * (ib->green - (gdouble) ia->green)) + ia->green; + res.blue = (factor * (ib->blue - (gdouble) ia->blue)) + ia->blue; + res.alpha = (factor * (ib->alpha - (gdouble) ia->alpha)) + ia->alpha; + + clutter_value_set_color (value, &res); + } + break; + default: break; } diff --git a/tests/interactive/test-animation.c b/tests/interactive/test-animation.c index 000e02bd8..ee0ff7337 100644 --- a/tests/interactive/test-animation.c +++ b/tests/interactive/test-animation.c @@ -23,13 +23,12 @@ on_button_press (ClutterActor *actor, ClutterAnimation *animation; gint old_x, old_y, new_x, new_y; guint old_width, old_height, new_width, new_height; - guint8 old_op, new_op; gdouble new_angle; ClutterVertex vertex = { 0, }; + ClutterColor new_color = { 0, }; clutter_actor_get_position (actor, &old_x, &old_y); clutter_actor_get_size (actor, &old_width, &old_height); - old_op = clutter_actor_get_opacity (actor); /* determine the final state of the animation depending on * the state of the actor @@ -40,8 +39,12 @@ on_button_press (ClutterActor *actor, new_y = old_y - 100; new_width = old_width + 200; new_height = old_height + 200; - new_op = 255; new_angle = 360.0; + + new_color.red = 0xdd; + new_color.green = 0x44; + new_color.blue = 0xdd; + new_color.alpha = 0xff; } else { @@ -49,8 +52,12 @@ on_button_press (ClutterActor *actor, new_y = old_y + 100; new_width = old_width - 200; new_height = old_height - 200; - new_op = 128; new_angle = 0.0; + + new_color.red = 0x44; + new_color.green = 0xdd; + new_color.blue = 0x44; + new_color.alpha = 0x88; } vertex.x = CLUTTER_UNITS_FROM_FLOAT ((float) new_width / 2); @@ -62,7 +69,7 @@ on_button_press (ClutterActor *actor, "y", new_y, "width", new_width, "height", new_height, - "opacity", new_op, + "color", &new_color, "rotation-angle-z", new_angle, "fixed::rotation-center-z", &vertex, "fixed::reactive", FALSE, From 2cea22e6a05e13c32c2f13ee1d369a5806605866 Mon Sep 17 00:00:00 2001 From: Chris Lord Date: Wed, 7 Jan 2009 17:02:43 +0000 Subject: [PATCH 02/43] Update/clean and apply the async-texture patch from bug #1144 --- clutter/clutter-texture.c | 152 +++++++++++++++++++++++++++++- clutter/clutter-texture.h | 3 +- clutter/cogl/cogl-texture.h | 42 +++++++++ clutter/cogl/cogl-types.h | 7 ++ clutter/cogl/common/cogl-bitmap.c | 31 ++++++ clutter/cogl/common/cogl-bitmap.h | 2 - clutter/cogl/gl/cogl-texture.c | 52 +++++----- 7 files changed, 262 insertions(+), 27 deletions(-) diff --git a/clutter/clutter-texture.c b/clutter/clutter-texture.c index 086a5134c..10cb2172c 100644 --- a/clutter/clutter-texture.c +++ b/clutter/clutter-texture.c @@ -96,6 +96,13 @@ struct _ClutterTexturePrivate guint repeat_y : 1; guint in_dispose : 1; guint keep_aspect_ratio : 1; + guint load_async : 1; + + GThread *load_thread; + gchar *load_filename; + CoglBitmap *load_bitmap; + GError *load_error; + guint load_source; }; enum @@ -110,13 +117,17 @@ enum PROP_FILTER_QUALITY, PROP_COGL_TEXTURE, PROP_FILENAME, - PROP_KEEP_ASPECT_RATIO + PROP_KEEP_ASPECT_RATIO, + PROP_LOAD_ASYNC }; enum { SIZE_CHANGE, PIXBUF_CHANGE, + LOAD_SUCCESS, + LOAD_FINISHED, + LAST_SIGNAL }; @@ -601,6 +612,35 @@ clutter_texture_paint (ClutterActor *self) 0, 0, t_w, t_h); } +static void +clutter_texture_thread_cancel (ClutterTexture *texture) +{ + ClutterTexturePrivate *priv = texture->priv; + + if (priv->load_thread) + { + g_thread_join (priv->load_thread); + priv->load_thread = NULL; + } + + if (priv->load_source) + { + g_source_remove (priv->load_source); + priv->load_source = 0; + + if (priv->load_error) + { + g_error_free (priv->load_error); + priv->load_error = NULL; + } + else + { + cogl_bitmap_free (priv->load_bitmap); + priv->load_bitmap = NULL; + } + } +} + static void clutter_texture_dispose (GObject *object) { @@ -625,7 +665,9 @@ clutter_texture_dispose (GObject *object) g_free (priv->local_data); priv->local_data = NULL; } - + + clutter_texture_thread_cancel (texture); + G_OBJECT_CLASS (clutter_texture_parent_class)->dispose (object); } @@ -686,6 +728,11 @@ clutter_texture_set_property (GObject *object, case PROP_KEEP_ASPECT_RATIO: priv->keep_aspect_ratio = g_value_get_boolean (value); break; + case PROP_LOAD_ASYNC: + priv->load_async = g_value_get_boolean (value); + if (priv->load_async && !g_thread_supported()) + priv->load_async = FALSE; + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -736,6 +783,9 @@ clutter_texture_get_property (GObject *object, case PROP_KEEP_ASPECT_RATIO: g_value_set_boolean (value, priv->keep_aspect_ratio); break; + case PROP_LOAD_ASYNC: + g_value_set_boolean (value, priv->load_async); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -861,6 +911,15 @@ clutter_texture_class_init (ClutterTextureClass *klass) FALSE, CLUTTER_PARAM_READWRITE)); + g_object_class_install_property + (gobject_class, PROP_LOAD_ASYNC, + g_param_spec_boolean ("load-async", + "Load asynchronously", + "Load files inside a thread to avoid blocking when " + "loading images.", + FALSE, + CLUTTER_PARAM_READWRITE)); + /** * ClutterTexture::size-change: * @texture: the texture which received the signal @@ -896,6 +955,25 @@ clutter_texture_class_init (ClutterTextureClass *klass) g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); + /** + * ClutterTexture::load-finished: + * @texture: the texture which received the signal + * @error: A set error, or %NULL + * + * The ::load-finished signal is emitted when asynchronous texture + * load has completed. If there was an error during loading, @error will + * be set. + */ + texture_signals[LOAD_FINISHED] = + g_signal_new ("load-finished", + G_TYPE_FROM_CLASS (gobject_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (ClutterTextureClass, load_finished), + NULL, NULL, + g_cclosure_marshal_VOID__POINTER, + G_TYPE_NONE, + 1, + G_TYPE_POINTER); } static ClutterScriptableIface *parent_scriptable_iface = NULL; @@ -1301,6 +1379,65 @@ clutter_texture_set_from_yuv_data (ClutterTexture *texture, error); } +static gboolean +clutter_texture_thread_cb (ClutterTexture *self) +{ + ClutterTexturePrivate *priv = self->priv; + + priv->load_source = 0; + + if (priv->load_thread) + { + g_thread_join (priv->load_thread); + priv->load_thread = NULL; + } + else + return FALSE; + + if (!priv->load_error) + { + CoglHandle handle; + + handle = cogl_texture_new_from_bitmap (priv->load_bitmap, + priv->no_slice ? + -1 : priv->max_tile_waste, + priv->filter_quality == + CLUTTER_TEXTURE_QUALITY_HIGH, + COGL_PIXEL_FORMAT_ANY); + clutter_texture_set_cogl_texture (self, handle); + cogl_texture_unref (handle); + + cogl_bitmap_free (priv->load_bitmap); + priv->load_bitmap = NULL; + } + + g_signal_emit (self, texture_signals[LOAD_FINISHED], 0, priv->load_error); + + if (priv->load_error) + { + g_error_free (priv->load_error); + priv->load_error = NULL; + } + + return FALSE; +} + +static gpointer +clutter_texture_thread_func (ClutterTexture *self) +{ + ClutterTexturePrivate *priv = self->priv; + + /* Try loading with imaging backend */ + priv->load_bitmap = cogl_bitmap_new_from_file (priv->load_filename, + &priv->load_error); + g_free (priv->load_filename); + priv->load_filename = NULL; + + clutter_threads_add_idle ((GSourceFunc)clutter_texture_thread_cb, self); + + return NULL; +} + /** * clutter_texture_set_from_file: * @texture: A #ClutterTexture @@ -1326,6 +1463,17 @@ clutter_texture_set_from_file (ClutterTexture *texture, g_return_val_if_fail (error == NULL || *error == NULL, FALSE); + if (priv->load_async) + { + clutter_texture_thread_cancel (texture); + + priv->load_filename = g_strdup (filename); + priv->load_thread = g_thread_create ((GThreadFunc) + clutter_texture_thread_func, + texture, TRUE, error); + return priv->load_thread ? TRUE : FALSE; + } + if ((new_texture = cogl_texture_new_from_file (filename, priv->no_slice ? -1 : priv->max_tile_waste, diff --git a/clutter/clutter-texture.h b/clutter/clutter-texture.h index e15f798b1..3f20413e8 100644 --- a/clutter/clutter-texture.h +++ b/clutter/clutter-texture.h @@ -84,6 +84,8 @@ struct _ClutterTextureClass gint width, gint height); void (*pixbuf_change) (ClutterTexture *texture); + void (*load_finished) (ClutterTexture *texture, + GError *error); /*< private >*/ /* padding, for future expansion */ @@ -92,7 +94,6 @@ struct _ClutterTextureClass void (*_clutter_texture3) (void); void (*_clutter_texture4) (void); void (*_clutter_texture5) (void); - void (*_clutter_texture6) (void); }; /** diff --git a/clutter/cogl/cogl-texture.h b/clutter/cogl/cogl-texture.h index 07cec1ce1..7c1dd9c9f 100644 --- a/clutter/cogl/cogl-texture.h +++ b/clutter/cogl/cogl-texture.h @@ -134,6 +134,26 @@ CoglHandle cogl_texture_new_from_foreign (GLuint gl_handle, GLuint y_pot_waste, CoglPixelFormat format); +/** + * cogl_texture_new_from_bitmap: + * @handle: handle of the preloaded texture. + * @max_waste: maximum extra horizontal and|or vertical margin pixels to make + * texture fit GPU limitations. + * @auto_mipmap: enable or disable automatic generation of mipmap pyramid + * from the base level image whenever it is updated. + * @internal_format: the #CoglPixelFormat to use for the GPU storage of the + * texture. + * + * Create a cogl texture from a #CoglBitmap. + * + * Returns: a #CoglHandle to the newly created texture or COGL_INVALID_HANDLE + * if creating the texture failed. + */ +CoglHandle cogl_texture_new_from_bitmap (CoglBitmap *bitmap, + gint max_waste, + gboolean auto_mipmap, + CoglPixelFormat internal_format); + /** * cogl_is_texture: * @handle: A CoglHandle @@ -385,6 +405,28 @@ void cogl_texture_polygon (CoglHandle handle, CoglTextureVertex *vertices, gboolean use_color); +/** + * cogl_bitmap_new_from_file: + * @filename: the file to load. + * @error: a #GError or %NULL. + * + * Load an image file from disk. This function can be safely called from + * within a thread. + * + * Returns: A #CoglBitmap to the new loaded image data, or %NULL if loading + * the image failed. + */ +CoglBitmap * cogl_bitmap_new_from_file (const gchar *filename, + GError **error); + +/** + * cogl_bitmap_free: + * @bmp: a #CoglBitmap. + * + * Frees a #CoglBitmap. + */ +void cogl_bitmap_free (CoglBitmap *bmp); + G_END_DECLS #endif /* __COGL_TEXTURE_H__ */ diff --git a/clutter/cogl/cogl-types.h b/clutter/cogl/cogl-types.h index 4fb69953a..6818d1393 100644 --- a/clutter/cogl/cogl-types.h +++ b/clutter/cogl/cogl-types.h @@ -28,6 +28,13 @@ G_BEGIN_DECLS +/** + * CoglBitmap: + * + * Type used for storing image data. + */ +typedef struct _CoglBitmap CoglBitmap; + /** * CoglHandle: * diff --git a/clutter/cogl/common/cogl-bitmap.c b/clutter/cogl/common/cogl-bitmap.c index 39341e0b0..6f31ebb5c 100644 --- a/clutter/cogl/common/cogl-bitmap.c +++ b/clutter/cogl/common/cogl-bitmap.c @@ -148,3 +148,34 @@ _cogl_bitmap_copy_subregion (CoglBitmap *src, dstdata += dst->rowstride; } } + +CoglBitmap * +cogl_bitmap_new_from_file (const gchar *filename, + GError **error) +{ + CoglBitmap bmp; + + g_return_val_if_fail (error == NULL || *error == NULL, COGL_INVALID_HANDLE); + + /* Try loading with imaging backend */ + if (!_cogl_bitmap_from_file (&bmp, filename, error)) + { + /* Try fallback */ + if (!_cogl_bitmap_fallback_from_file (&bmp, filename)) + return NULL; + else if (error && *error) + { + g_error_free (*error); + *error = NULL; + } + } + + return (CoglBitmap *) g_memdup (&bmp, sizeof (CoglBitmap)); +} + +void +cogl_bitmap_free (CoglBitmap *bmp) +{ + g_free (bmp->data); + g_free (bmp); +} diff --git a/clutter/cogl/common/cogl-bitmap.h b/clutter/cogl/common/cogl-bitmap.h index ca9f8a9c3..9baec8170 100644 --- a/clutter/cogl/common/cogl-bitmap.h +++ b/clutter/cogl/common/cogl-bitmap.h @@ -28,8 +28,6 @@ #include -typedef struct _CoglBitmap CoglBitmap; - struct _CoglBitmap { guchar *data; diff --git a/clutter/cogl/gl/cogl-texture.c b/clutter/cogl/gl/cogl-texture.c index 12caf7c58..ec4f17d32 100644 --- a/clutter/cogl/gl/cogl-texture.c +++ b/clutter/cogl/gl/cogl-texture.c @@ -1323,30 +1323,13 @@ cogl_texture_new_from_data (guint width, } CoglHandle -cogl_texture_new_from_file (const gchar *filename, - gint max_waste, - gboolean auto_mipmap, - CoglPixelFormat internal_format, - GError **error) +cogl_texture_new_from_bitmap (CoglBitmap *bmp, + gint max_waste, + gboolean auto_mipmap, + CoglPixelFormat internal_format) { - CoglBitmap bmp; CoglTexture *tex; - g_return_val_if_fail (error == NULL || *error == NULL, COGL_INVALID_HANDLE); - - /* Try loading with imaging backend */ - if (!_cogl_bitmap_from_file (&bmp, filename, error)) - { - /* Try fallback */ - if (!_cogl_bitmap_fallback_from_file (&bmp, filename)) - return COGL_INVALID_HANDLE; - else if (error && *error) - { - g_error_free (*error); - *error = NULL; - } - } - /* Create new texture and fill with loaded data */ tex = (CoglTexture*) g_malloc ( sizeof (CoglTexture)); @@ -1356,8 +1339,9 @@ cogl_texture_new_from_file (const gchar *filename, tex->is_foreign = FALSE; tex->auto_mipmap = auto_mipmap; - tex->bitmap = bmp; + tex->bitmap = *bmp; tex->bitmap_owner = TRUE; + bmp->data = NULL; tex->slice_x_spans = NULL; tex->slice_y_spans = NULL; @@ -1398,6 +1382,30 @@ cogl_texture_new_from_file (const gchar *filename, return _cogl_texture_handle_new (tex); } +CoglHandle +cogl_texture_new_from_file (const gchar *filename, + gint max_waste, + gboolean auto_mipmap, + CoglPixelFormat internal_format, + GError **error) +{ + CoglBitmap *bmp; + CoglHandle handle; + + g_return_val_if_fail (error == NULL || *error == NULL, COGL_INVALID_HANDLE); + + if (!(bmp = cogl_bitmap_new_from_file (filename, error))) + return COGL_INVALID_HANDLE; + + handle = cogl_texture_new_from_bitmap (bmp, + max_waste, + auto_mipmap, + internal_format); + cogl_bitmap_free (bmp); + + return handle; +} + CoglHandle cogl_texture_new_from_foreign (GLuint gl_handle, GLenum gl_target, From ff48c3ef7c05de41e087645deb845b4d9bb66ae6 Mon Sep 17 00:00:00 2001 From: Emmanuele Bassi Date: Wed, 7 Jan 2009 18:18:59 +0000 Subject: [PATCH 03/43] [animation] Interval::compute_value should return a boolean If the computation of the interval value depending on the progress was not successful, ClutterInterval::compute_value() should return this information to the caller. --- clutter/clutter-animation.c | 4 ++-- clutter/clutter-interval.c | 31 ++++++++++++++++++++++++------- clutter/clutter-interval.h | 4 ++-- 3 files changed, 28 insertions(+), 11 deletions(-) diff --git a/clutter/clutter-animation.c b/clutter/clutter-animation.c index eae81250d..f27d9da3e 100644 --- a/clutter/clutter-animation.c +++ b/clutter/clutter-animation.c @@ -683,9 +683,9 @@ on_alpha_notify (GObject *gobject, g_value_init (&value, clutter_interval_get_value_type (interval)); factor = (gdouble) alpha_value / CLUTTER_ALPHA_MAX_ALPHA; - clutter_interval_compute_value (interval, factor, &value); - g_object_set_property (G_OBJECT (priv->actor), p_name, &value); + if (clutter_interval_compute_value (interval, factor, &value)) + g_object_set_property (G_OBJECT (priv->actor), p_name, &value); g_value_unset (&value); } diff --git a/clutter/clutter-interval.c b/clutter/clutter-interval.c index a3be68c71..0b74e3d96 100644 --- a/clutter/clutter-interval.c +++ b/clutter/clutter-interval.c @@ -172,13 +172,14 @@ clutter_interval_real_validate (ClutterInterval *interval, return TRUE; } -static void +static gboolean clutter_interval_real_compute_value (ClutterInterval *interval, gdouble factor, GValue *value) { GValue *initial, *final; GType value_type; + gboolean retval = FALSE; initial = clutter_interval_peek_initial_value (interval); final = clutter_interval_peek_final_value (interval); @@ -197,6 +198,8 @@ clutter_interval_real_compute_value (ClutterInterval *interval, res = (factor * (ib - ia)) + ia; g_value_set_int (value, res); + + retval = TRUE; } break; @@ -210,6 +213,8 @@ clutter_interval_real_compute_value (ClutterInterval *interval, res = (factor * (ib - (gdouble) ia)) + ia; g_value_set_uint (value, res); + + retval = TRUE; } break; @@ -223,6 +228,8 @@ clutter_interval_real_compute_value (ClutterInterval *interval, res = (factor * (ib - (gdouble) ia)) + ia; g_value_set_uchar (value, res); + + retval = TRUE; } break; @@ -240,6 +247,8 @@ clutter_interval_real_compute_value (ClutterInterval *interval, g_value_set_double (value, res); else g_value_set_float (value, res); + + retval = TRUE; } break; @@ -248,6 +257,8 @@ clutter_interval_real_compute_value (ClutterInterval *interval, g_value_set_boolean (value, TRUE); else g_value_set_boolean (value, FALSE); + + retval = TRUE; break; case G_TYPE_BOXED: @@ -265,12 +276,16 @@ clutter_interval_real_compute_value (ClutterInterval *interval, res.alpha = (factor * (ib->alpha - (gdouble) ia->alpha)) + ia->alpha; clutter_value_set_color (value, &res); + + retval = TRUE; } break; default: break; } + + return retval; } static void @@ -837,19 +852,21 @@ clutter_interval_validate (ClutterInterval *interval, * Computes the value between the @interval boundaries given the * progress @factor and puts it into @value. * + * Return value: %TRUE if the operation was successful + * * Since: 1.0 */ -void +gboolean clutter_interval_compute_value (ClutterInterval *interval, gdouble factor, GValue *value) { - g_return_if_fail (CLUTTER_IS_INTERVAL (interval)); - g_return_if_fail (value != NULL); + g_return_val_if_fail (CLUTTER_IS_INTERVAL (interval), FALSE); + g_return_val_if_fail (value != NULL, FALSE); factor = CLAMP (factor, 0.0, 1.0); - CLUTTER_INTERVAL_GET_CLASS (interval)->compute_value (interval, - factor, - value); + return CLUTTER_INTERVAL_GET_CLASS (interval)->compute_value (interval, + factor, + value); } diff --git a/clutter/clutter-interval.h b/clutter/clutter-interval.h index 56d155f28..919369bb8 100644 --- a/clutter/clutter-interval.h +++ b/clutter/clutter-interval.h @@ -79,7 +79,7 @@ struct _ClutterIntervalClass /*< public >*/ gboolean (* validate) (ClutterInterval *interval, GParamSpec *pspec); - void (* compute_value) (ClutterInterval *interval, + gboolean (* compute_value) (ClutterInterval *interval, gdouble factor, GValue *value); @@ -122,7 +122,7 @@ void clutter_interval_get_interval (ClutterInterval *interval, gboolean clutter_interval_validate (ClutterInterval *interval, GParamSpec *pspec); -void clutter_interval_compute_value (ClutterInterval *interval, +gboolean clutter_interval_compute_value (ClutterInterval *interval, gdouble factor, GValue *value); From 28b0f432b78f9db0c36d3b286cc8928d12b3b1f3 Mon Sep 17 00:00:00 2001 From: Emmanuele Bassi Date: Thu, 8 Jan 2009 11:15:09 +0000 Subject: [PATCH 04/43] [animation] Allow registering custom progress function A ClutterInterval can change the way the progress is computed by subclassing and overriding the ::compute_value() virtual function. It should also be possible to register a custom progress function in the same way it is possible to register a custom transformation function between two GValues. This commit adds an internal, global hash table that maintains a GType <-> progress function association; each ClutterInterval will check if there is a progress function registered for the GType of the initial and final values of the interval and, if it has been found, it will call it to compute the value of the interval depending on the progress factor. --- clutter/clutter-interval.c | 105 +++++++++++++++++++++++++++++++++++++ clutter/clutter-interval.h | 31 +++++++++++ 2 files changed, 136 insertions(+) diff --git a/clutter/clutter-interval.c b/clutter/clutter-interval.c index 0b74e3d96..efdf58dff 100644 --- a/clutter/clutter-interval.c +++ b/clutter/clutter-interval.c @@ -62,6 +62,14 @@ #include "clutter-interval.h" #include "clutter-units.h" +typedef struct +{ + GType value_type; + ClutterProgressFunc func; +} ProgressData; + +static GHashTable *progress_funcs = NULL; + enum { PROP_0, @@ -186,6 +194,25 @@ clutter_interval_real_compute_value (ClutterInterval *interval, value_type = clutter_interval_get_value_type (interval); + if (G_UNLIKELY (progress_funcs != NULL)) + { + ProgressData *p_data; + + p_data = + g_hash_table_lookup (progress_funcs, GUINT_TO_POINTER (value_type)); + + /* if we have a progress function, and that function was + * successful in computing the progress, then we bail out + * as fast as we can + */ + if (p_data != NULL) + { + retval = p_data->func (initial, final, factor, value); + if (retval) + return retval; + } + } + switch (G_TYPE_FUNDAMENTAL (value_type)) { case G_TYPE_INT: @@ -870,3 +897,81 @@ clutter_interval_compute_value (ClutterInterval *interval, factor, value); } + +/** + * clutter_interval_register_progress_func: + * @value_type: a #GType + * @func: a #ClutterProgressFunc, or %NULL to unset a previously + * set progress function + * + * Sets the progress function for a given @value_type, like: + * + * |[ + * clutter_interval_register_progress_func (MY_TYPE_FOO, + * my_foo_progress); + * ]| + * + * Whenever a #ClutterInterval instance using the default + * #ClutterInterval::compute_value implementation is set as an + * interval between two #GValue of type @value_type, it will call + * @func to establish the value depending on the given progress, + * for instance: + * + * |[ + * static gboolean + * my_int_progress (const GValue *a, + * const GValue *b, + * gdouble progress, + * GValue *retval) + * { + * gint ia = g_value_get_int (a); + * gint ib = g_value_get_int (b); + * gint res = factor * (ib - ia) + ia; + * + * g_value_set_int (retval, res); + * + * return TRUE; + * } + * + * clutter_interval_register_progress_func (G_TYPE_INT, my_int_progress); + * ]| + * + * To unset a previously set progress function of a #GType, pass %NULL + * for @func. + * + * Since: 1.0 + */ +void +clutter_interval_register_progress_func (GType value_type, + ClutterProgressFunc func) +{ + ProgressData *progress_func; + + g_return_if_fail (value_type != G_TYPE_INVALID); + + if (G_UNLIKELY (progress_funcs == NULL)) + progress_funcs = g_hash_table_new (NULL, NULL); + + progress_func = + g_hash_table_lookup (progress_funcs, GUINT_TO_POINTER (value_type)); + if (G_UNLIKELY (progress_func)) + { + if (func == NULL) + { + g_hash_table_remove (progress_funcs, GUINT_TO_POINTER (value_type)); + g_slice_free (ProgressData, progress_func); + } + else + progress_func->func = func; + } + else + { + progress_func = g_slice_new (ProgressData); + progress_func->value_type = value_type; + progress_func->func = func; + + g_hash_table_replace (progress_funcs, + GUINT_TO_POINTER (value_type), + progress_func); + } +} diff --git a/clutter/clutter-interval.h b/clutter/clutter-interval.h index 919369bb8..72ae5304c 100644 --- a/clutter/clutter-interval.h +++ b/clutter/clutter-interval.h @@ -44,6 +44,34 @@ typedef struct _ClutterInterval ClutterInterval; typedef struct _ClutterIntervalPrivate ClutterIntervalPrivate; typedef struct _ClutterIntervalClass ClutterIntervalClass; +/** + * ClutterProgressFunc: + * @a: the initial value of an interval + * @b: the final value of an interval + * @progress: the progress factor, between 0 and 1 + * @retval: the value used to store the progress + * + * Prototype of the progress function used to compute the value + * between the two ends @a and @b of an interval depending on + * the value of @progress. + * + * The #GValue in @retval is already initialized with the same + * type as @a and @b. + * + * This function will be called by #ClutterInterval if the + * type of the values of the interval was registered using + * clutter_interval_register_progress_func(). + * + * Return value: %TRUE if the function successfully computed + * the value and stored it inside @retval + * + * Since: 1.0 + */ +typedef gboolean (* ClutterProgressFunc) (const GValue *a, + const GValue *b, + gdouble progress, + GValue *retval); + /** * ClutterInterval: * @@ -126,6 +154,9 @@ gboolean clutter_interval_compute_value (ClutterInterval *interval, gdouble factor, GValue *value); +void clutter_interval_register_progress_func (GType value_type, + ClutterProgressFunc func); + G_END_DECLS #endif /* __CLUTTER_INTERVAL_H__ */ From 24808e20b3c190ef79a88f958e4ff2617b7c155f Mon Sep 17 00:00:00 2001 From: Emmanuele Bassi Date: Thu, 8 Jan 2009 12:56:46 +0000 Subject: [PATCH 05/43] [animation] Add ClutterAnimatable The ClutterAnimatable interface is meant to be used by GObject classes to override the value computation for an animatable property within the boundaries of an interval. It is composed of a single virtual function, animate_property(); its implementation will receive the ClutterAnimation used to animate the object; the property name; the initial and final interval values; and the progress factor as retrieved by the Alpha object bound to the Animation instance. --- clutter/Makefile.am | 2 + clutter/clutter-animatable.c | 93 ++++++++++++++++++++++++++++++++++++ clutter/clutter-animatable.h | 56 ++++++++++++++++++++++ clutter/clutter.h | 1 + 4 files changed, 152 insertions(+) create mode 100644 clutter/clutter-animatable.c create mode 100644 clutter/clutter-animatable.h diff --git a/clutter/Makefile.am b/clutter/Makefile.am index 4db7c9fe2..ca54bfae2 100644 --- a/clutter/Makefile.am +++ b/clutter/Makefile.am @@ -47,6 +47,7 @@ BUILT_SOURCES = $(MARSHALFILES) $(ENUMFILES) source_h = \ $(srcdir)/clutter-actor.h \ $(srcdir)/clutter-alpha.h \ + $(srcdir)/clutter-animatable.h \ $(srcdir)/clutter-animation.h \ $(srcdir)/clutter-backend.h \ $(srcdir)/clutter-behaviour.h \ @@ -138,6 +139,7 @@ CLEANFILES = $(STAMPFILES) source_c = \ clutter-actor.c \ clutter-alpha.c \ + clutter-animatable.c \ clutter-animation.c \ clutter-backend.c \ clutter-behaviour.c \ diff --git a/clutter/clutter-animatable.c b/clutter/clutter-animatable.c new file mode 100644 index 000000000..e7876e2a6 --- /dev/null +++ b/clutter/clutter-animatable.c @@ -0,0 +1,93 @@ +/** + * SECTION:clutter-animatable + * @short_description: Interface for animatable classes + * + * #ClutterAnimatable is an interface that allows a #GObject class + * to control how a #ClutterAnimation will animate a property. + * + * Each #ClutterAnimatable should implement the animate_property() + * virtual function of the interface to compute the animation state + * between two values of an interval depending on a progress factor, + * expressed as a floating point value. + * + * If a #ClutterAnimatable is animated by a #ClutterAnimation + * instance, the #ClutterAnimation will call + * clutter_animatable_animate_property() passing the name of the + * currently animated property; the initial and final values of + * the animation interval; the progress factor. The #ClutterAnimatable + * implementation should return the computed value for the animated + * property. + * + * #ClutterAnimatable is available since Clutter 1.0 + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "clutter-animatable.h" +#include "clutter-debug.h" +#include "clutter-private.h" + +GType +clutter_animatable_get_type (void) +{ + static GType a_type = 0; + + if (G_UNLIKELY (a_type == 0)) + a_type = g_type_register_static_simple (G_TYPE_INTERFACE, + I_("ClutterAnimatable"), + sizeof (ClutterAnimatableIface), + NULL, 0, NULL, 0); + + return a_type; +} + +/** + * clutter_animatable_animate_property: + * @animatable: a #ClutterAnimatable + * @animation: a #ClutterAnimation + * @property_name: the name of the animated property + * @initial_value: the initial value of the animation interval + * @final_value: the final value of the animation interval + * @progress: the progress factor + * @value: return location for the animation value + * + * Calls the animate_property() virtual function for @animatable. + * + * The @initial_value and @final_value #GValues must contain + * the same type; @value must have been initialized to the same + * type of @initial_value and @final_value. + * + * All implementation of the #ClutterAnimatable interface must + * implement this function. + * + * Since: 1.0 + */ +void +clutter_animatable_animate_property (ClutterAnimatable *animatable, + ClutterAnimation *animation, + const gchar *property_name, + const GValue *initial_value, + const GValue *final_value, + gdouble progress, + GValue *value) +{ + g_return_if_fail (CLUTTER_IS_ANIMATABLE (animatable)); + g_return_if_fail (CLUTTER_IS_ANIMATION (animation)); + g_return_if_fail (property_name != NULL); + g_return_if_fail (initial_value != NULL && final_value != NULL); + g_return_if_fail (G_VALUE_TYPE (initial_value) != G_TYPE_INVALID); + g_return_if_fail (G_VALUE_TYPE (final_value) != G_TYPE_INVALID); + g_return_if_fail (value != NULL); + g_return_if_fail (G_VALUE_TYPE (value) == G_VALUE_TYPE (initial_value) && + G_VALUE_TYPE (value) == G_VALUE_TYPE (final_value)); + + CLUTTER_ANIMATABLE_GET_IFACE (animatable)->animate_property (animatable, + animation, + property_name, + initial_value, + final_value, + progress, + value); +} diff --git a/clutter/clutter-animatable.h b/clutter/clutter-animatable.h new file mode 100644 index 000000000..073ec3f66 --- /dev/null +++ b/clutter/clutter-animatable.h @@ -0,0 +1,56 @@ +#ifndef __CLUTTER_ANIMATABLE_H__ +#define __CLUTTER_ANIMATABLE_H__ + +#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION) +#error "Only can be included directly." +#endif + +#include + +G_BEGIN_DECLS + +#define CLUTTER_TYPE_ANIMATABLE (clutter_animatable_get_type ()) +#define CLUTTER_ANIMATABLE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_ANIMATABLE, ClutterAnimatable)) +#define CLUTTER_IS_ANIMATABLE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_ANIMATABLE)) +#define CLUTTER_ANIMATABLE_GET_IFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), CLUTTER_TYPE_ANIMATABLE, ClutterAnimatableIface)) + +typedef struct _ClutterAnimatable ClutterAnimatable; /* dummy typedef */ +typedef struct _ClutterAnimatableIface ClutterAnimatableIface; + +/** + * ClutterAnimatableIface: + * @animate_property: virtual function for animating a property + * + * Base interface for #GObjects that can be animated by a + * a #ClutterAnimation. + * + * Since: 1.0 + */ +struct _ClutterAnimatableIface +{ + /*< private >*/ + GTypeInterface parent_iface; + + /*< public >*/ + void (* animate_property) (ClutterAnimatable *animatable, + ClutterAnimation *animation, + const gchar *property_name, + const GValue *initial_value, + const GValue *final_value, + gdouble progress, + GValue *value); +}; + +GType clutter_animatable_get_type (void) G_GNUC_CONST; + +void clutter_animatable_animate_property (ClutterAnimatable *animatable, + ClutterAnimation *animation, + const gchar *property_name, + const GValue *initial_value, + const GValue *final_value, + gdouble progress, + GValue *value); + +G_END_DECLS + +#endif /* __CLUTTER_ANIMATABLE_H__ */ diff --git a/clutter/clutter.h b/clutter/clutter.h index 15208ce17..e7a8c5b3f 100644 --- a/clutter/clutter.h +++ b/clutter/clutter.h @@ -30,6 +30,7 @@ #include "clutter-actor.h" #include "clutter-alpha.h" +#include "clutter-animatable.h" #include "clutter-animation.h" #include "clutter-backend.h" #include "clutter-behaviour-depth.h" From 60cfa5edb241a4115e36d4d67374f3e87a4bb688 Mon Sep 17 00:00:00 2001 From: Emmanuele Bassi Date: Thu, 8 Jan 2009 12:59:16 +0000 Subject: [PATCH 06/43] [animation] Use ClutterAnimatable inside Animation ClutterAnimation should check if the object is implementing the Animatable interface, and if so delegate to it the computation of the value along the interval initial and final value, depending on the progress. --- clutter/clutter-animation.c | 34 ++++++++++++++++++++++++++++++++-- 1 file changed, 32 insertions(+), 2 deletions(-) diff --git a/clutter/clutter-animation.c b/clutter/clutter-animation.c index f27d9da3e..9cff31d07 100644 --- a/clutter/clutter-animation.c +++ b/clutter/clutter-animation.c @@ -50,6 +50,7 @@ #include #include "clutter-alpha.h" +#include "clutter-animatable.h" #include "clutter-animation.h" #include "clutter-debug.h" #include "clutter-enum-types.h" @@ -664,9 +665,17 @@ on_alpha_notify (GObject *gobject, ClutterAnimationPrivate *priv = animation->priv; GList *properties, *p; guint32 alpha_value; + gboolean is_animatable = FALSE; + ClutterAnimatable *animatable = NULL; alpha_value = clutter_alpha_get_alpha (CLUTTER_ALPHA (gobject)); + if (CLUTTER_IS_ANIMATABLE (priv->actor)) + { + animatable = CLUTTER_ANIMATABLE (priv->actor); + is_animatable = TRUE; + } + g_object_freeze_notify (G_OBJECT (priv->actor)); properties = g_hash_table_get_keys (priv->properties); @@ -684,8 +693,29 @@ on_alpha_notify (GObject *gobject, factor = (gdouble) alpha_value / CLUTTER_ALPHA_MAX_ALPHA; - if (clutter_interval_compute_value (interval, factor, &value)) - g_object_set_property (G_OBJECT (priv->actor), p_name, &value); + if (is_animatable) + { + const GValue *initial, *final; + + initial = clutter_interval_peek_initial_value (interval); + final = clutter_interval_peek_final_value (interval); + + CLUTTER_NOTE (ANIMATION, "Animatable property `%s'", p_name); + clutter_animatable_animate_property (animatable, animation, + p_name, + initial, final, + factor, + &value); + + g_object_set_property (G_OBJECT (priv->actor), p_name, &value); + } + else + { + CLUTTER_NOTE (ANIMATION, "Standard property `%s'", p_name); + + if (clutter_interval_compute_value (interval, factor, &value)) + g_object_set_property (G_OBJECT (priv->actor), p_name, &value); + } g_value_unset (&value); } From 068ba1caf04a952f2d0eec9eb1a9f72e72a8d000 Mon Sep 17 00:00:00 2001 From: Emmanuele Bassi Date: Thu, 8 Jan 2009 13:13:39 +0000 Subject: [PATCH 07/43] [animation] Extend ClutterAnimation support to all objects Instead of limiting the use of ClutterAnimation to ClutterActor instances, relax the constraint to include all GObject classes. ClutterAnimation is not using actor-specific API, since it is only using properties. The only actor-based API is the clutter_actor_animate() family of functions. --- clutter/clutter-animation.c | 148 +++++++++++++++++------------------- clutter/clutter-animation.h | 6 +- 2 files changed, 74 insertions(+), 80 deletions(-) diff --git a/clutter/clutter-animation.c b/clutter/clutter-animation.c index f27d9da3e..d2e4f9c13 100644 --- a/clutter/clutter-animation.c +++ b/clutter/clutter-animation.c @@ -27,12 +27,12 @@ * @short_description: Simple implicit animations * * #ClutterAnimation is an object providing simple, implicit animations - * for #ClutterActors. + * for #GObjects. * * #ClutterAnimation instances will bind a #GObject property belonging - * to a #ClutterActor to a #ClutterInterval, and will then use a - * #ClutterTimeline to interpolate the property between the initial - * and final values of the interval. + * to a #GObject to a #ClutterInterval, and will then use a #ClutterTimeline + * to interpolate the property between the initial and final values of the + * interval. * * For convenience, it is possible to use the clutter_actor_animate() * function call which will take care of setting up and tearing down @@ -60,7 +60,7 @@ enum { PROP_0, - PROP_ACTOR, + PROP_OBJECT, PROP_MODE, PROP_DURATION, PROP_LOOP, @@ -79,7 +79,7 @@ enum struct _ClutterAnimationPrivate { - ClutterActor *actor; + GObject *object; GHashTable *properties; @@ -96,7 +96,7 @@ struct _ClutterAnimationPrivate static guint animation_signals[LAST_SIGNAL] = { 0, }; -static GQuark quark_actor_animation = 0; +static GQuark quark_object_animation = 0; G_DEFINE_TYPE (ClutterAnimation, clutter_animation, G_TYPE_INITIALLY_UNOWNED); @@ -118,16 +118,14 @@ clutter_animation_dispose (GObject *gobject) { ClutterAnimationPrivate *priv = CLUTTER_ANIMATION (gobject)->priv; - if (priv->actor) + if (priv->object) { g_object_weak_unref (G_OBJECT (gobject), on_animation_weak_notify, - priv->actor); - g_object_set_qdata (G_OBJECT (priv->actor), - quark_actor_animation, - NULL); - g_object_unref (priv->actor); - priv->actor = NULL; + priv->object); + g_object_set_qdata (priv->object, quark_object_animation, NULL); + g_object_unref (priv->object); + priv->object = NULL; } if (priv->timeline) @@ -168,8 +166,8 @@ clutter_animation_set_property (GObject *gobject, switch (prop_id) { - case PROP_ACTOR: - clutter_animation_set_actor (animation, g_value_get_object (value)); + case PROP_OBJECT: + clutter_animation_set_object (animation, g_value_get_object (value)); break; case PROP_MODE: @@ -208,8 +206,8 @@ clutter_animation_get_property (GObject *gobject, switch (prop_id) { - case PROP_ACTOR: - g_value_set_object (value, priv->actor); + case PROP_OBJECT: + g_value_set_object (value, priv->object); break; case PROP_MODE: @@ -253,7 +251,7 @@ clutter_animation_class_init (ClutterAnimationClass *klass) GObjectClass *gobject_class = G_OBJECT_CLASS (klass); GParamSpec *pspec; - quark_actor_animation = + quark_object_animation = g_quark_from_static_string ("clutter-actor-animation"); g_type_class_add_private (klass, sizeof (ClutterAnimationPrivate)); @@ -266,18 +264,18 @@ clutter_animation_class_init (ClutterAnimationClass *klass) gobject_class->finalize = clutter_animation_finalize; /** - * ClutterAnimation:actor: + * ClutterAnimation:objct: * - * The actor to which the animation applies. + * The #GObject to which the animation applies. * * Since: 1.0 */ - pspec = g_param_spec_object ("actor", - "Actor", - "Actor to which the animation applies", - CLUTTER_TYPE_ACTOR, + pspec = g_param_spec_object ("object", + "Object", + "Object to which the animation applies", + G_TYPE_OBJECT, CLUTTER_PARAM_READWRITE); - g_object_class_install_property (gobject_class, PROP_ACTOR, pspec); + g_object_class_install_property (gobject_class, PROP_OBJECT, pspec); /** * ClutterAnimation:mode: @@ -427,7 +425,7 @@ clutter_animation_update_property_internal (ClutterAnimation *animation, * @property_name: the property to control * @interval: a #ClutterInterval * - * Binds @interval to the @property_name of the #ClutterActor + * Binds @interval to the @property_name of the #GObject * attached to @animation. The #ClutterAnimation will take * ownership of the passed #ClutterInterval. * @@ -451,10 +449,10 @@ clutter_animation_bind_property (ClutterAnimation *animation, priv = animation->priv; - if (G_UNLIKELY (!priv->actor)) + if (G_UNLIKELY (!priv->object)) { g_warning ("Cannot bind property `%s': the animation has no " - "actor set. You need to call clutter_animation_set_actor() " + "object set. You need to call clutter_animation_set_object() " "first to be able to bind a property", property_name); return; @@ -468,14 +466,14 @@ clutter_animation_bind_property (ClutterAnimation *animation, return; } - klass = G_OBJECT_GET_CLASS (priv->actor); + klass = G_OBJECT_GET_CLASS (priv->object); pspec = g_object_class_find_property (klass, property_name); if (!pspec) { - g_warning ("Cannot bind property `%s': actors of type `%s' have " + g_warning ("Cannot bind property `%s': objects of type `%s' have " "no such property", property_name, - g_type_name (G_OBJECT_TYPE (priv->actor))); + g_type_name (G_OBJECT_TYPE (priv->object))); return; } @@ -592,14 +590,14 @@ clutter_animation_update_property (ClutterAnimation *animation, return; } - klass = G_OBJECT_GET_CLASS (priv->actor); + klass = G_OBJECT_GET_CLASS (priv->object); pspec = g_object_class_find_property (klass, property_name); if (!pspec) { - g_warning ("Cannot bind property `%s': actors of type `%s' have " + g_warning ("Cannot bind property `%s': objects of type `%s' have " "no such property", property_name, - g_type_name (G_OBJECT_TYPE (priv->actor))); + g_type_name (G_OBJECT_TYPE (priv->object))); return; } @@ -667,7 +665,7 @@ on_alpha_notify (GObject *gobject, alpha_value = clutter_alpha_get_alpha (CLUTTER_ALPHA (gobject)); - g_object_freeze_notify (G_OBJECT (priv->actor)); + g_object_freeze_notify (priv->object); properties = g_hash_table_get_keys (priv->properties); for (p = properties; p != NULL; p = p->next) @@ -685,14 +683,14 @@ on_alpha_notify (GObject *gobject, factor = (gdouble) alpha_value / CLUTTER_ALPHA_MAX_ALPHA; if (clutter_interval_compute_value (interval, factor, &value)) - g_object_set_property (G_OBJECT (priv->actor), p_name, &value); + g_object_set_property (priv->object, p_name, &value); g_value_unset (&value); } g_list_free (properties); - g_object_thaw_notify (G_OBJECT (priv->actor)); + g_object_thaw_notify (priv->object); } /* @@ -709,7 +707,7 @@ on_animation_weak_notify (gpointer data, clutter_actor_get_gid (CLUTTER_ACTOR (actor)), actor); - g_object_set_qdata (actor, quark_actor_animation, NULL); + g_object_set_qdata (actor, quark_object_animation, NULL); } ClutterAnimation * @@ -719,66 +717,64 @@ clutter_animation_new (void) } /** - * clutter_animation_set_actor: + * clutter_animation_set_object: * @animation: a #ClutterAnimation - * @actor: a #ClutterActor + * @object: a #GObject * - * Attaches @animation to @actor. The #ClutterAnimation will take a - * reference on @actor. + * Attaches @animation to @object. The #ClutterAnimation will take a + * reference on @object. * * Since: 1.0 */ void -clutter_animation_set_actor (ClutterAnimation *animation, - ClutterActor *actor) +clutter_animation_set_object (ClutterAnimation *animation, + GObject *object) { ClutterAnimationPrivate *priv; g_return_if_fail (CLUTTER_IS_ANIMATION (animation)); - g_return_if_fail (CLUTTER_IS_ACTOR (actor)); + g_return_if_fail (G_IS_OBJECT (object)); priv = animation->priv; - g_object_ref (actor); + g_object_ref (object); - if (priv->actor) + if (priv->object) { g_object_weak_unref (G_OBJECT (animation), on_animation_weak_notify, - priv->actor); - g_object_set_qdata (G_OBJECT (priv->actor), - quark_actor_animation, - NULL); - g_object_unref (priv->actor); + priv->object); + g_object_set_qdata (priv->object, quark_object_animation, NULL); + g_object_unref (priv->object); } - priv->actor = actor; + priv->object = object; g_object_weak_ref (G_OBJECT (animation), on_animation_weak_notify, - priv->actor); - g_object_set_qdata (G_OBJECT (priv->actor), - quark_actor_animation, + priv->object); + g_object_set_qdata (G_OBJECT (priv->object), + quark_object_animation, animation); - g_object_notify (G_OBJECT (animation), "actor"); + g_object_notify (G_OBJECT (animation), "object"); } /** - * clutter_animation_get_actor: + * clutter_animation_get_object: * @animation: a #ClutterAnimation * - * Retrieves the #ClutterActor attached to @animation. + * Retrieves the #GObject attached to @animation. * - * Return value: a #ClutterActor + * Return value: a #GObject * * Since: 1.0 */ -ClutterActor * -clutter_animation_get_actor (ClutterAnimation *animation) +GObject * +clutter_animation_get_object (ClutterAnimation *animation) { g_return_val_if_fail (CLUTTER_IS_ANIMATION (animation), NULL); - return animation->priv->actor; + return animation->priv->object; } static inline void @@ -1125,7 +1121,7 @@ clutter_animation_setup_valist (ClutterAnimation *animation, GObjectClass *klass; const gchar *property_name; - klass = G_OBJECT_GET_CLASS (priv->actor); + klass = G_OBJECT_GET_CLASS (priv->object); property_name = first_property_name; while (property_name != NULL) @@ -1145,10 +1141,10 @@ clutter_animation_setup_valist (ClutterAnimation *animation, pspec = g_object_class_find_property (klass, property_name); if (!pspec) { - g_warning ("Cannot bind property `%s': actors of type `%s' do " + g_warning ("Cannot bind property `%s': objects of type `%s' do " "not have this property", property_name, - g_type_name (G_OBJECT_TYPE (priv->actor))); + g_type_name (G_OBJECT_TYPE (priv->object))); break; } @@ -1178,9 +1174,7 @@ clutter_animation_setup_valist (ClutterAnimation *animation, GValue initial = { 0, }; g_value_init (&initial, G_PARAM_SPEC_VALUE_TYPE (pspec)); - g_object_get_property (G_OBJECT (priv->actor), - property_name, - &initial); + g_object_get_property (priv->object, property_name, &initial); interval = clutter_interval_new_with_values (G_PARAM_SPEC_VALUE_TYPE (pspec), @@ -1199,7 +1193,7 @@ clutter_animation_setup_valist (ClutterAnimation *animation, g_value_unset (&initial); } else - g_object_set_property (G_OBJECT (priv->actor), property_name, &final); + g_object_set_property (priv->object, property_name, &final); g_value_unset (&final); @@ -1254,7 +1248,7 @@ clutter_actor_animate_with_alpha (ClutterActor *actor, return NULL; } - animation = g_object_get_qdata (G_OBJECT (actor), quark_actor_animation); + animation = g_object_get_qdata (G_OBJECT (actor), quark_object_animation); if (G_LIKELY (!animation)) { animation = clutter_animation_new (); @@ -1265,7 +1259,7 @@ clutter_actor_animate_with_alpha (ClutterActor *actor, clutter_animation_set_timeline (animation, timeline); clutter_animation_set_alpha (animation, alpha); - clutter_animation_set_actor (animation, actor); + clutter_animation_set_object (animation, G_OBJECT (actor)); va_start (args, first_property_name); clutter_animation_setup_valist (animation, first_property_name, args); @@ -1311,7 +1305,7 @@ clutter_actor_animate_with_timeline (ClutterActor *actor, g_return_val_if_fail (CLUTTER_IS_TIMELINE (timeline), NULL); g_return_val_if_fail (first_property_name != NULL, NULL); - animation = g_object_get_qdata (G_OBJECT (actor), quark_actor_animation); + animation = g_object_get_qdata (G_OBJECT (actor), quark_object_animation); if (G_LIKELY (!animation)) { animation = clutter_animation_new (); @@ -1323,7 +1317,7 @@ clutter_actor_animate_with_timeline (ClutterActor *actor, clutter_animation_set_timeline (animation, timeline); clutter_animation_set_alpha (animation, NULL); clutter_animation_set_mode (animation, mode); - clutter_animation_set_actor (animation, actor); + clutter_animation_set_object (animation, G_OBJECT (actor)); va_start (args, first_property_name); clutter_animation_setup_valist (animation, first_property_name, args); @@ -1406,7 +1400,7 @@ clutter_actor_animate (ClutterActor *actor, g_return_val_if_fail (duration > 0, NULL); g_return_val_if_fail (first_property_name != NULL, NULL); - animation = g_object_get_qdata (G_OBJECT (actor), quark_actor_animation); + animation = g_object_get_qdata (G_OBJECT (actor), quark_object_animation); if (G_LIKELY (!animation)) { /* if there is no animation already attached to the actor, @@ -1416,7 +1410,7 @@ clutter_actor_animate (ClutterActor *actor, animation = clutter_animation_new (); clutter_animation_set_timeline (animation, NULL); clutter_animation_set_alpha (animation, NULL); - clutter_animation_set_actor (animation, actor); + clutter_animation_set_object (animation, G_OBJECT (actor)); CLUTTER_NOTE (ANIMATION, "Created new Animation [%p]", animation); } diff --git a/clutter/clutter-animation.h b/clutter/clutter-animation.h index 115e0a0b5..061d4e439 100644 --- a/clutter/clutter-animation.h +++ b/clutter/clutter-animation.h @@ -97,9 +97,9 @@ GType clutter_animation_get_type (void) G_GNUC_CONST; ClutterAnimation * clutter_animation_new (void); -void clutter_animation_set_actor (ClutterAnimation *animation, - ClutterActor *actor); -ClutterActor * clutter_animation_get_actor (ClutterAnimation *animation); +void clutter_animation_set_object (ClutterAnimation *animation, + GObject *object); +GObject * clutter_animation_get_object (ClutterAnimation *animation); void clutter_animation_set_mode (ClutterAnimation *animation, ClutterAnimationMode mode); ClutterAnimationMode clutter_animation_get_mode (ClutterAnimation *animation); From 986c18d260bb24261e155b096aa5e53e14c65411 Mon Sep 17 00:00:00 2001 From: Emmanuele Bassi Date: Thu, 8 Jan 2009 13:16:20 +0000 Subject: [PATCH 08/43] [docs] Update the ClutterAnimation section --- doc/reference/clutter/clutter-sections.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/reference/clutter/clutter-sections.txt b/doc/reference/clutter/clutter-sections.txt index 5948dd14a..9fd95bf4f 100644 --- a/doc/reference/clutter/clutter-sections.txt +++ b/doc/reference/clutter/clutter-sections.txt @@ -1581,8 +1581,8 @@ ClutterAnimation ClutterAnimationClass ClutterAnimationMode clutter_animation_new -clutter_animation_set_actor -clutter_animation_get_actor +clutter_animation_set_object +clutter_animation_get_object clutter_animation_set_mode clutter_animation_get_mode clutter_animation_set_duration From d340de8e00b5de125ed94b2b26b9bcaa08a19675 Mon Sep 17 00:00:00 2001 From: Emmanuele Bassi Date: Thu, 8 Jan 2009 13:18:00 +0000 Subject: [PATCH 09/43] Add license notice to ClutterAnimation files --- clutter/clutter-animatable.c | 24 ++++++++++++++++++++++++ clutter/clutter-animatable.h | 24 ++++++++++++++++++++++++ 2 files changed, 48 insertions(+) diff --git a/clutter/clutter-animatable.c b/clutter/clutter-animatable.c index e7876e2a6..fb2b88b19 100644 --- a/clutter/clutter-animatable.c +++ b/clutter/clutter-animatable.c @@ -1,3 +1,27 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Copyright (C) 2009 Intel Corporation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + * + * Author: + * Emmanuele Bassi + */ + /** * SECTION:clutter-animatable * @short_description: Interface for animatable classes diff --git a/clutter/clutter-animatable.h b/clutter/clutter-animatable.h index 073ec3f66..aee717ac4 100644 --- a/clutter/clutter-animatable.h +++ b/clutter/clutter-animatable.h @@ -1,3 +1,27 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Copyright (C) 2009 Intel Corporation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + * + * Author: + * Emmanuele Bassi + */ + #ifndef __CLUTTER_ANIMATABLE_H__ #define __CLUTTER_ANIMATABLE_H__ From 628ccaf4a855dc2477a5bb579bf49c414a80249e Mon Sep 17 00:00:00 2001 From: Emmanuele Bassi Date: Thu, 8 Jan 2009 13:31:27 +0000 Subject: [PATCH 10/43] [docs] Add ClutterAnimatable to the API reference --- doc/reference/clutter/clutter-docs.xml | 1 + doc/reference/clutter/clutter-sections.txt | 79 ++++++++++++++-------- doc/reference/clutter/clutter.types | 1 + 3 files changed, 52 insertions(+), 29 deletions(-) diff --git a/doc/reference/clutter/clutter-docs.xml b/doc/reference/clutter/clutter-docs.xml index ffd06a561..3c7011827 100644 --- a/doc/reference/clutter/clutter-docs.xml +++ b/doc/reference/clutter/clutter-docs.xml @@ -106,6 +106,7 @@ + diff --git a/doc/reference/clutter/clutter-sections.txt b/doc/reference/clutter/clutter-sections.txt index 5948dd14a..771f86ba7 100644 --- a/doc/reference/clutter/clutter-sections.txt +++ b/doc/reference/clutter/clutter-sections.txt @@ -210,6 +210,35 @@ ClutterCloneTexturePrivate clutter_clone_texture_get_type +
+clutter-cairo-texture +ClutterCairoTexture +ClutterCairoTexture +ClutterCairoTextureClass +clutter_cairo_texture_new +clutter_cairo_texture_set_surface_size +clutter_cairo_texture_get_surface_size + + +clutter_cairo_texture_create +clutter_cairo_texture_create_region + + +clutter_cairo_set_source_color + + +CLUTTER_TYPE_CAIRO_TEXTURE +CLUTTER_CAIRO_TEXTURE +CLUTTER_IS_CAIRO_TEXTURE +CLUTTER_CAIRO_TEXTURE_CLASS +CLUTTER_IS_CAIRO_TEXTURE_CLASS +CLUTTER_CAIRO_TEXTURE_GET_CLASS + + +ClutterCairoTexturePrivate +clutter_cairo_texture_get_type +
+
clutter-group ClutterGroup @@ -1641,6 +1670,10 @@ clutter_interval_get_interval clutter_interval_validate clutter_interval_compute_value + +ClutterProgressFunc +clutter_interval_register_progress_func + CLUTTER_TYPE_INTERVAL CLUTTER_INTERVAL @@ -1654,6 +1687,23 @@ ClutterIntervalPrivate clutter_interval_get_type
+
+clutter-animatable +ClutterAnimatable +ClutterAnimatable +ClutterAnimatableIface +clutter_animatable_animate_property + + +CLUTTER_TYPE_ANIMATABLE +CLUTTER_ANIMATABLE +CLUTTER_IS_ANIMATABLE +CLUTTER_ANIMATABLE_GET_IFACE + + +clutter_animatable_get_type +
+
Key Bindings clutter-binding-pool @@ -1677,32 +1727,3 @@ clutter_binding_pool_unblock_action clutter_binding_pool_activate
- -
-ClutterCairoTexture -clutter-cairo-texture -ClutterCairoTexture -ClutterCairoTextureClass -clutter_cairo_texture_new -clutter_cairo_texture_set_surface_size -clutter_cairo_texture_get_surface_size - - -clutter_cairo_texture_create -clutter_cairo_texture_create_region - - -clutter_cairo_set_source_color - - -CLUTTER_TYPE_CAIRO_TEXTURE -CLUTTER_CAIRO_TEXTURE -CLUTTER_IS_CAIRO_TEXTURE -CLUTTER_CAIRO_TEXTURE_CLASS -CLUTTER_IS_CAIRO_TEXTURE_CLASS -CLUTTER_CAIRO_TEXTURE_GET_CLASS - - -ClutterCairoTexturePrivate -clutter_cairo_texture_get_type -
diff --git a/doc/reference/clutter/clutter.types b/doc/reference/clutter/clutter.types index 2bac85c6e..ac7d68ccc 100644 --- a/doc/reference/clutter/clutter.types +++ b/doc/reference/clutter/clutter.types @@ -29,3 +29,4 @@ clutter_score_get_type clutter_shader_get_type clutter_child_meta_get_type clutter_cairo_texture_get_type +clutter_animatable_get_type From e9ee7f049d51c5d3a273385dae0d073c373ca51c Mon Sep 17 00:00:00 2001 From: Emmanuele Bassi Date: Thu, 8 Jan 2009 15:45:22 +0000 Subject: [PATCH 11/43] Fix last improper usage of ClutterUnits ClutterUnits should not be used interchangeably as, or with ClutterFixed values. ClutterUnits should also not be assumed to be integers. This commit fixes the last few improper usages of ClutterUnit values, and adds a CLUTTER_UNITS_FORMAT macro for safely printing ClutterUnit values with printf(). --- clutter/clutter-actor.c | 44 ++++++++++++--------- clutter/clutter-units.h | 2 + tests/interactive/test-project.c | 65 +++++++++++++++----------------- 3 files changed, 59 insertions(+), 52 deletions(-) diff --git a/clutter/clutter-actor.c b/clutter/clutter-actor.c index 7d616266e..2f39c4f0c 100644 --- a/clutter/clutter-actor.c +++ b/clutter/clutter-actor.c @@ -1013,7 +1013,8 @@ clutter_actor_apply_relative_transform_to_point (ClutterActor *self, ClutterVertex *vertex) { ClutterFixed v[4]; - ClutterFixed x, y, z, w; + ClutterUnit x, y, z, w; + fixed_vertex_t tmp; g_return_if_fail (CLUTTER_IS_ACTOR (self)); g_return_if_fail (ancestor == NULL || CLUTTER_IS_ACTOR (ancestor)); @@ -1026,8 +1027,7 @@ clutter_actor_apply_relative_transform_to_point (ClutterActor *self, w = COGL_FIXED_1; /* First we tranform the point using the OpenGL modelview matrix */ - clutter_actor_transform_point_relative (self, ancestor, - &x, &y, &z, &w); + clutter_actor_transform_point_relative (self, ancestor, &x, &y, &z, &w); cogl_get_viewport (v); @@ -1035,12 +1035,12 @@ clutter_actor_apply_relative_transform_to_point (ClutterActor *self, * The w[3] parameter should always be 1.0 here, so we ignore it; otherwise * we would have to divide the original verts with it. */ - vertex->x = - CLUTTER_UNITS_FROM_FIXED (COGL_FIXED_MUL ((x + COGL_FIXED_0_5), v[2])); - vertex->y = - CLUTTER_UNITS_FROM_FIXED (COGL_FIXED_MUL ((COGL_FIXED_0_5 - y), v[3])); - vertex->z = - CLUTTER_UNITS_FROM_FIXED (COGL_FIXED_MUL ((z + COGL_FIXED_0_5), v[2])); + tmp.x = COGL_FIXED_MUL (CLUTTER_UNITS_TO_FIXED (x) + COGL_FIXED_0_5, v[2]); + tmp.y = COGL_FIXED_MUL (COGL_FIXED_0_5 - CLUTTER_UNITS_TO_FIXED (y), v[3]); + tmp.z = COGL_FIXED_MUL (CLUTTER_UNITS_TO_FIXED (z) + COGL_FIXED_0_5, v[2]); + tmp.w = 0; + + fixed_vertex_to_units (&tmp, vertex); } /** @@ -1060,6 +1060,7 @@ clutter_actor_apply_transform_to_point (ClutterActor *self, const ClutterVertex *point, ClutterVertex *vertex) { + ClutterUnit x, y, z, w; ClutterFixed mtx_p[16]; ClutterFixed v[4]; fixed_vertex_t tmp = { 0, }; @@ -1068,13 +1069,18 @@ clutter_actor_apply_transform_to_point (ClutterActor *self, g_return_if_fail (point != NULL); g_return_if_fail (vertex != NULL); - tmp.x = CLUTTER_UNITS_TO_FIXED (vertex->x); - tmp.y = CLUTTER_UNITS_TO_FIXED (vertex->y); - tmp.z = CLUTTER_UNITS_TO_FIXED (vertex->z); - tmp.w = COGL_FIXED_1; + x = point->x; + y = point->y; + z = point->z; + w = CLUTTER_UNITS_FROM_INT (1); /* First we tranform the point using the OpenGL modelview matrix */ - clutter_actor_transform_point (self, &tmp.x, &tmp.y, &tmp.z, &tmp.w); + clutter_actor_transform_point (self, &x, &y, &z, &w); + + tmp.x = CLUTTER_UNITS_TO_FIXED (x); + tmp.y = CLUTTER_UNITS_TO_FIXED (y); + tmp.z = CLUTTER_UNITS_TO_FIXED (z); + tmp.w = CLUTTER_UNITS_TO_FIXED (w); cogl_get_projection_matrix (mtx_p); cogl_get_viewport (v); @@ -3244,8 +3250,9 @@ clutter_actor_get_preferred_width (ClutterActor *self, if (natural_width < min_width) { - g_warning ("Actor of type %s reported a natural width of %d (%d px) " - "lower than min width %d (%d px)", + g_warning ("Actor of type %s reported a natural width " + "of %" CLUTTER_UNITS_FORMAT " (%d px) lower " + "than min width %" CLUTTER_UNITS_FORMAT " (%d px)", G_OBJECT_TYPE_NAME (self), natural_width, CLUTTER_UNITS_TO_DEVICE (natural_width), min_width, CLUTTER_UNITS_TO_DEVICE (min_width)); @@ -3314,8 +3321,9 @@ clutter_actor_get_preferred_height (ClutterActor *self, if (natural_height < min_height) { - g_warning ("Actor of type %s reported a natural height of %d " - "(%d px) lower than min height %d (%d px)", + g_warning ("Actor of type %s reported a natural height " + "of %" CLUTTER_UNITS_FORMAT " (%d px) lower than " + "min height %" CLUTTER_UNITS_FORMAT " (%d px)", G_OBJECT_TYPE_NAME (self), natural_height, CLUTTER_UNITS_TO_DEVICE (natural_height), min_height, CLUTTER_UNITS_TO_DEVICE (min_height)); diff --git a/clutter/clutter-units.h b/clutter/clutter-units.h index 8337d19ff..b85375a98 100644 --- a/clutter/clutter-units.h +++ b/clutter/clutter-units.h @@ -59,6 +59,8 @@ typedef gint32 ClutterUnit; #define CLUTTER_UNITS_FROM_FIXED(x) (x) #define CLUTTER_UNITS_TO_FIXED(x) (x) +#define CLUTTER_UNITS_FORMAT "d" + /** * CLUTTER_UNITS_FROM_DEVICE: * @x: value in pixels diff --git a/tests/interactive/test-project.c b/tests/interactive/test-project.c index 33560df0b..7c9403014 100644 --- a/tests/interactive/test-project.c +++ b/tests/interactive/test-project.c @@ -21,19 +21,19 @@ init_handles () clutter_actor_set_position (p[i], 0, 0); clutter_group_add (CLUTTER_GROUP (main_stage), p[i]); - clutter_actor_set_position (p[i], - CLUTTER_FIXED_TO_INT (v[i].x) - - clutter_actor_get_width (p[i])/2, - CLUTTER_FIXED_TO_INT (v[i].y) - - clutter_actor_get_height (p[i])/2); + clutter_actor_set_positionu (p[i], + v[i].x - + clutter_actor_get_widthu (p[i])/2, + v[i].y - + clutter_actor_get_heightu (p[i])/2); clutter_actor_raise_top (p[i]); clutter_actor_show (p[i]); } - v1.x = CLUTTER_INT_TO_FIXED (clutter_actor_get_width (rect)/2); - v1.y = CLUTTER_INT_TO_FIXED (clutter_actor_get_height (rect)/2); + v1.x = clutter_actor_get_widthu (rect) / 2; + v1.y = clutter_actor_get_heightu (rect) / 2; v1.z = 0; clutter_actor_apply_transform_to_point (rect, &v1, &v2); @@ -41,11 +41,11 @@ init_handles () clutter_actor_set_size (p[4], 5, 5); clutter_actor_set_position (p[4], 0, 0); clutter_group_add (CLUTTER_GROUP (main_stage), p[4]); - clutter_actor_set_position (p[4], - CLUTTER_FIXED_TO_INT (v2.x) - - clutter_actor_get_width (p[4])/2, - CLUTTER_FIXED_TO_INT (v2.y) - - clutter_actor_get_height (p[4])/2); + clutter_actor_set_positionu (p[4], + v2.x - + clutter_actor_get_widthu (p[4])/2, + v2.y - + clutter_actor_get_heightu (p[4])/2); clutter_actor_raise_top (p[4]); @@ -62,23 +62,21 @@ place_handles () clutter_actor_get_abs_allocation_vertices (rect, v); for (i = 0; i < 4; ++i) { - clutter_actor_set_position (p[i], - CLUTTER_FIXED_TO_INT (v[i].x) - - clutter_actor_get_width (p[i])/2, - CLUTTER_FIXED_TO_INT (v[i].y) - - clutter_actor_get_height (p[i])/2); + clutter_actor_set_positionu (p[i], + v[i].x - + clutter_actor_get_widthu (p[i])/2, + v[i].y - + clutter_actor_get_heightu (p[i])/2); } - v1.x = CLUTTER_INT_TO_FIXED (clutter_actor_get_width (rect)/2); - v1.y = CLUTTER_INT_TO_FIXED (clutter_actor_get_height (rect)/2); + v1.x = clutter_actor_get_widthu (rect)/2; + v1.y = clutter_actor_get_heightu (rect)/2; v1.z = 0; clutter_actor_apply_transform_to_point (rect, &v1, &v2); - clutter_actor_set_position (p[4], - CLUTTER_FIXED_TO_INT (v2.x) - - clutter_actor_get_width (p[4])/2, - CLUTTER_FIXED_TO_INT (v2.y) - - clutter_actor_get_height (p[4])/2); + clutter_actor_set_positionu (p[4], + v2.x - clutter_actor_get_widthu (p[4])/2, + v2.y - clutter_actor_get_heightu (p[4])/2); } #define M(m,row,col) (m)[col*4+row] @@ -127,7 +125,7 @@ on_event (ClutterStage *stage, gint x, y; gint i; ClutterActorBox box1, box2; - ClutterFixed xp, yp; + ClutterUnit xp, yp; i = find_handle_index (dragging); @@ -139,25 +137,24 @@ on_event (ClutterStage *stage, clutter_actor_get_allocation_box (dragging, &box1); clutter_actor_get_allocation_box (rect, &box2); - xp = CLUTTER_INT_TO_FIXED (x-3) - box1.x1; - yp = CLUTTER_INT_TO_FIXED (y-3) - box1.y1; + xp = CLUTTER_UNITS_FROM_DEVICE (x - 3) - box1.x1; + yp = CLUTTER_UNITS_FROM_DEVICE (y - 3) - box1.y1; if (i == 4) { g_debug ("moving box by %f, %f", - CLUTTER_FIXED_TO_FLOAT (xp), - CLUTTER_FIXED_TO_FLOAT (yp)); + CLUTTER_UNITS_TO_FLOAT (xp), + CLUTTER_UNITS_TO_FLOAT (yp)); - clutter_actor_move_by (rect, - CLUTTER_FIXED_TO_INT(xp), - CLUTTER_FIXED_TO_INT(yp)); + clutter_actor_move_byu (rect, xp, yp); } else { g_debug ("adjusting box by %f, %f, handle %d", - CLUTTER_FIXED_TO_FLOAT (xp), - CLUTTER_FIXED_TO_FLOAT (yp), + CLUTTER_UNITS_TO_FLOAT (xp), + CLUTTER_UNITS_TO_FLOAT (yp), i); + switch (i) { case 0: From efd7ad7e55357e3f656a9158c911521646898a2e Mon Sep 17 00:00:00 2001 From: Emmanuele Bassi Date: Thu, 8 Jan 2009 17:06:04 +0000 Subject: [PATCH 12/43] [text] Fix GObject properties in ClutterText Some of the read-write properties of ClutterText were missing an implementation in clutter_text_get_property(), as well as the :position and :selection-bound properties being wrongly converted from fixed point to integer, passing through floating point values. --- clutter/clutter-text.c | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/clutter/clutter-text.c b/clutter/clutter-text.c index 4b7ae3f13..76721a6d2 100644 --- a/clutter/clutter-text.c +++ b/clutter/clutter-text.c @@ -688,11 +688,11 @@ clutter_text_get_property (GObject *gobject, break; case PROP_POSITION: - g_value_set_int (value, CLUTTER_FIXED_TO_FLOAT (priv->position)); + g_value_set_int (value, priv->position); break; case PROP_SELECTION_BOUND: - g_value_set_int (value, CLUTTER_FIXED_TO_FLOAT (priv->selection_bound)); + g_value_set_int (value, priv->selection_bound); break; case PROP_EDITABLE: @@ -719,6 +719,30 @@ clutter_text_get_property (GObject *gobject, g_value_set_boolean (value, priv->single_line_mode); break; + case PROP_ELLIPSIZE: + g_value_set_enum (value, priv->ellipsize); + break; + + case PROP_LINE_WRAP: + g_value_set_boolean (value, priv->wrap); + break; + + case PROP_LINE_WRAP_MODE: + g_value_set_enum (value, priv->wrap_mode); + break; + + case PROP_ALIGNMENT: + g_value_set_enum (value, priv->alignment); + break; + + case PROP_JUSTIFY: + g_value_set_boolean (value, priv->justify); + break; + + case PROP_ATTRIBUTES: + g_value_set_boxed (value, priv->attrs); + break; + default: G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); } From 00a3c698686f25e193d0311ad25c903f0ad71e8b Mon Sep 17 00:00:00 2001 From: Emmanuele Bassi Date: Fri, 9 Jan 2009 12:06:46 +0000 Subject: [PATCH 13/43] [x11] Fix a race condition when resizing a stage There is a race condition when we resize a stage before showing it on X11. The race goes like this: - clutter_init() creates the default stage and realize it, which will cause a 640x480 Window to be created - call set_size(800, 600) on the stage will cause the Window to be resized to 800x600 - call show() on the stage for the first time will cause COGL to set up an 800 by 600 GL viewport - the Window will be mapped, which will cause X to notify the window manager that the Window should be resized to 800x600 - the window manager will approve the resize - X resizes the drawable to 800x600 To fix the race, we need to defer COGL from setting up the viewport until we receive a ConfigureNotify event and the X server has resized the Drawable. In order to defer the call to cogl_setup_viewport() we add a new private flag, CLUTTER_STAGE_IN_RESIZE; the flag is checked whenever we need to change the viewport size along with the SYNC_MATRICES private flag. Thus, cogl_setup_viewport() will be called only if SYNC_MATRICES is set and IN_RESIZE is not set. --- clutter/clutter-main.c | 3 ++- clutter/clutter-private.h | 3 ++- clutter/x11/clutter-event-x11.c | 6 ++++++ clutter/x11/clutter-stage-x11.c | 35 ++++++++++++++++++++++----------- 4 files changed, 34 insertions(+), 13 deletions(-) diff --git a/clutter/clutter-main.c b/clutter/clutter-main.c index 745fcbbd7..edcb44cf0 100644 --- a/clutter/clutter-main.c +++ b/clutter/clutter-main.c @@ -147,7 +147,8 @@ _clutter_stage_maybe_relayout (ClutterActor *stage) void _clutter_stage_maybe_setup_viewport (ClutterStage *stage) { - if (CLUTTER_PRIVATE_FLAGS (stage) & CLUTTER_ACTOR_SYNC_MATRICES) + if ((CLUTTER_PRIVATE_FLAGS (stage) & CLUTTER_ACTOR_SYNC_MATRICES) && + !(CLUTTER_PRIVATE_FLAGS (stage) & CLUTTER_STAGE_IN_RESIZE)) { ClutterPerspective perspective; guint width, height; diff --git a/clutter/clutter-private.h b/clutter/clutter-private.h index c65bfb066..b1f141bf7 100644 --- a/clutter/clutter-private.h +++ b/clutter/clutter-private.h @@ -62,7 +62,8 @@ typedef enum { */ CLUTTER_ACTOR_IN_PAINT = 1 << 4, /* Used to avoid recursion */ CLUTTER_ACTOR_IN_RELAYOUT = 1 << 5, /* Used to avoid recursion */ - CLUTTER_TEXTURE_IN_CLONE_PAINT = 1 << 6 /* Used for safety in clones */ + CLUTTER_TEXTURE_IN_CLONE_PAINT = 1 << 6, /* Used for safety in clones */ + CLUTTER_STAGE_IN_RESIZE = 1 << 7 /* Used to mark stage resizes */ } ClutterPrivateFlags; typedef enum { diff --git a/clutter/x11/clutter-event-x11.c b/clutter/x11/clutter-event-x11.c index 06e27e766..090e2c28c 100644 --- a/clutter/x11/clutter-event-x11.c +++ b/clutter/x11/clutter-event-x11.c @@ -438,6 +438,12 @@ event_translate (ClutterBackend *backend, xevent->xconfigure.height); stage_x11->handling_configure = FALSE; + + /* the resize process is complete, so we can remove the + * in-resize flag and allow the viewport to be resized + */ + CLUTTER_UNSET_PRIVATE_FLAGS (CLUTTER_ACTOR (stage_x11->wrapper), + CLUTTER_STAGE_IN_RESIZE); } res = FALSE; break; diff --git a/clutter/x11/clutter-stage-x11.c b/clutter/x11/clutter-stage-x11.c index 010063951..bfc86ba9f 100644 --- a/clutter/x11/clutter-stage-x11.c +++ b/clutter/x11/clutter-stage-x11.c @@ -282,13 +282,30 @@ clutter_stage_x11_allocate (ClutterActor *self, queue. Handling the first event will undo the work of setting the second property which will cause it to keep generating events in an infinite loop. See bug #810 */ - if (stage_x11->xwin != None - && !stage_x11->is_foreign_xwin - && !stage_x11->handling_configure) - XResizeWindow (stage_x11->xdpy, - stage_x11->xwin, - stage_x11->xwin_width, - stage_x11->xwin_height); + if (stage_x11->xwin != None && + !stage_x11->is_foreign_xwin && + !stage_x11->handling_configure) + { + XResizeWindow (stage_x11->xdpy, + stage_x11->xwin, + stage_x11->xwin_width, + stage_x11->xwin_height); + + /* resizing is an asynchronous process; to avoid races + * with the window manager, we flag the wrapper as being + * "in resize", so that the SYNC_MATRICES flag will not + * cause a call to cogl_get_viewport(). + * + * the flag is unset inside clutter-event-x11.c, after + * we receive a ConfigureNotify event. XXX - need to + * check what happens when running without a window manager + */ + CLUTTER_SET_PRIVATE_FLAGS (CLUTTER_ACTOR (stage_x11->wrapper), + CLUTTER_STAGE_IN_RESIZE); + } + + CLUTTER_SET_PRIVATE_FLAGS (CLUTTER_ACTOR (stage_x11->wrapper), + CLUTTER_ACTOR_SYNC_MATRICES); clutter_stage_x11_fix_window_size (stage_x11); @@ -298,9 +315,6 @@ clutter_stage_x11_allocate (ClutterActor *self, clutter_actor_unrealize (self); clutter_actor_realize (self); } - - CLUTTER_SET_PRIVATE_FLAGS (CLUTTER_ACTOR (stage_x11->wrapper), - CLUTTER_ACTOR_SYNC_MATRICES); } /* chain up to fill in actor->priv->allocation */ @@ -769,4 +783,3 @@ clutter_stage_x11_unmap (ClutterStageX11 *stage_x11) CLUTTER_ACTOR_UNSET_FLAGS (stage_x11, CLUTTER_ACTOR_MAPPED); CLUTTER_ACTOR_UNSET_FLAGS (stage_x11->wrapper, CLUTTER_ACTOR_MAPPED); } - From 2693ea3ddc4f7a70109a56c425280b6836ca9924 Mon Sep 17 00:00:00 2001 From: Emmanuele Bassi Date: Fri, 9 Jan 2009 14:26:35 +0000 Subject: [PATCH 14/43] [docs] Documentation warnings Fix the various warnings issued by gtk-doc when enabling the API reference generation for both COGL and Clutter. --- clutter/clutter-cairo-texture.h | 14 +++++ clutter/cogl/cogl-types.h | 72 ++++++++++++---------- clutter/cogl/common/cogl-mesh.c | 2 + doc/reference/clutter/clutter-docs.xml | 2 +- doc/reference/clutter/clutter-sections.txt | 55 ++++++++--------- 5 files changed, 83 insertions(+), 62 deletions(-) diff --git a/clutter/clutter-cairo-texture.h b/clutter/clutter-cairo-texture.h index a5cca866c..b7816fef6 100644 --- a/clutter/clutter-cairo-texture.h +++ b/clutter/clutter-cairo-texture.h @@ -49,6 +49,13 @@ typedef struct _ClutterCairoTexture ClutterCairoTexture; typedef struct _ClutterCairoTextureClass ClutterCairoTextureClass; typedef struct _ClutterCairoTexturePrivate ClutterCairoTexturePrivate; +/** + * ClutterCairoTexture: + * + * The #ClutterCairoTexture struct contains only private data. + * + * Since: 1.0 + */ struct _ClutterCairoTexture { /*< private >*/ @@ -57,6 +64,13 @@ struct _ClutterCairoTexture ClutterCairoTexturePrivate *priv; }; +/** + * ClutterCairoTextureClass: + * + * The #ClutterCairoTextureClass struct contains only private data. + * + * Since: 1.0 + */ struct _ClutterCairoTextureClass { /*< private >*/ diff --git a/clutter/cogl/cogl-types.h b/clutter/cogl/cogl-types.h index 4fb69953a..3ae0d9caa 100644 --- a/clutter/cogl/cogl-types.h +++ b/clutter/cogl/cogl-types.h @@ -86,27 +86,29 @@ typedef struct _CoglTextureVertex CoglTextureVertex; /** * CoglPixelFormat: - * @COGL_PIXEL_FORMAT_ANY: - * @COGL_PIXEL_FORMAT_A_8: - * @COGL_PIXEL_FORMAT_RGB_888: - * @COGL_PIXEL_FORMAT_BGR_888: - * @COGL_PIXEL_FORMAT_RGBA_8888: - * @COGL_PIXEL_FORMAT_BGRA_8888: - * @COGL_PIXEL_FORMAT_ARGB_8888: - * @COGL_PIXEL_FORMAT_ABGR_8888: - * @COGL_PIXEL_FORMAT_RGBA_8888_PRE: - * @COGL_PIXEL_FORMAT_BGRA_8888_PRE: - * @COGL_PIXEL_FORMAT_ARGB_8888_PRE: - * @COGL_PIXEL_FORMAT_ABGR_8888_PRE: - * @COGL_PIXEL_FORMAT_RGB_565: - * @COGL_PIXEL_FORMAT_RGBA_4444: - * @COGL_PIXEL_FORMAT_RGBA_5551: - * @COGL_PIXEL_FORMAT_RGBA_4444_PRE: - * @COGL_PIXEL_FORMAT_RGBA_5551_PRE: - * @COGL_PIXEL_FORMAT_YUV: - * @COGL_PIXEL_FORMAT_G_8: + * @COGL_PIXEL_FORMAT_ANY: Any format + * @COGL_PIXEL_FORMAT_A_8: 8 bits alpha mask + * @COGL_PIXEL_FORMAT_RGB_565: RGB, 16 bits + * @COGL_PIXEL_FORMAT_RGBA_4444: RGBA, 16 bits + * @COGL_PIXEL_FORMAT_RGBA_5551: RGBA, 16 bits + * @COGL_PIXEL_FORMAT_YUV: FIXME + * @COGL_PIXEL_FORMAT_G_8: FIXME + * @COGL_PIXEL_FORMAT_RGB_888: RGB, 24 bits + * @COGL_PIXEL_FORMAT_BGR_888: BGR, 24 bits + * @COGL_PIXEL_FORMAT_RGBA_8888: RGBA, 32 bits + * @COGL_PIXEL_FORMAT_BGRA_8888: BGRA, 32 bits + * @COGL_PIXEL_FORMAT_ARGB_8888: ARGB, 32 bits + * @COGL_PIXEL_FORMAT_ABGR_8888: ABGR, 32 bits + * @COGL_PIXEL_FORMAT_RGBA_8888_PRE: Premultiplied RGBA, 32 bits + * @COGL_PIXEL_FORMAT_BGRA_8888_PRE: Premultiplied BGRA, 32 bits + * @COGL_PIXEL_FORMAT_ARGB_8888_PRE: Premultiplied ARGB, 32 bits + * @COGL_PIXEL_FORMAT_ABGR_8888_PRE: Premultiplied ABGR, 32 bits + * @COGL_PIXEL_FORMAT_RGBA_4444_PRE: Premultiplied RGBA, 16 bits + * @COGL_PIXEL_FORMAT_RGBA_5551_PRE: Premultiplied RGBA, 16 bits * * Pixel formats used by COGL. + * + * Since: 0.8 */ typedef enum { @@ -173,19 +175,21 @@ typedef enum /** * CoglFeatureFlags: - * @COGL_FEATURE_TEXTURE_RECTANGLE: - * @COGL_FEATURE_TEXTURE_NPOT: - * @COGL_FEATURE_TEXTURE_YUV: - * @COGL_FEATURE_TEXTURE_READ_PIXELS: - * @COGL_FEATURE_SHADERS_GLSL: - * @COGL_FEATURE_OFFSCREEN: - * @COGL_FEATURE_OFFSCREEN_MULTISAMPLE: - * @COGL_FEATURE_OFFSCREEN_BLIT: - * @COGL_FEATURE_FOUR_CLIP_PLANES: - * @COGL_FEATURE_STENCIL_BUFFER: - * @COGL_FEATURE_VBOS: + * @COGL_FEATURE_TEXTURE_RECTANGLE: ARB_texture_rectangle support + * @COGL_FEATURE_TEXTURE_NPOT: ARB_texture_non_power_of_two support + * @COGL_FEATURE_TEXTURE_YUV: ycbcr conversion support + * @COGL_FEATURE_TEXTURE_READ_PIXELS: glReadPixels() support + * @COGL_FEATURE_SHADERS_GLSL: GLSL support + * @COGL_FEATURE_OFFSCREEN: FBO support + * @COGL_FEATURE_OFFSCREEN_MULTISAMPLE: Multisample support on FBOs + * @COGL_FEATURE_OFFSCREEN_BLIT: Blit support on FBOs + * @COGL_FEATURE_FOUR_CLIP_PLANES: At least 4 clip planes available + * @COGL_FEATURE_STENCIL_BUFFER: Stencil buffer support + * @COGL_FEATURE_VBOS: VBO support * * Flags for the supported features. + * + * Since: 0.8 */ typedef enum { @@ -204,11 +208,13 @@ typedef enum /** * CoglBufferTarget: - * @COGL_WINDOW_BUFFER: - * @COGL_MASK_BUFFER: - * @COGL_OFFSCREEN_BUFFER: + * @COGL_WINDOW_BUFFER: FIXME + * @COGL_MASK_BUFFER: FIXME + * @COGL_OFFSCREEN_BUFFER: FIXME * + * Target flags for FBOs. * + * Since: 0.8 */ typedef enum { diff --git a/clutter/cogl/common/cogl-mesh.c b/clutter/cogl/common/cogl-mesh.c index 88a0ba473..f7287f953 100644 --- a/clutter/cogl/common/cogl-mesh.c +++ b/clutter/cogl/common/cogl-mesh.c @@ -209,6 +209,8 @@ COGL_HANDLE_DEFINE (Mesh, mesh, mesh_handles); * * This creates a Cogl handle for a new mesh that you can then start to add * attributes too. + * + * Return value: a new #CoglHandle */ CoglHandle cogl_mesh_new (guint n_vertices) diff --git a/doc/reference/clutter/clutter-docs.xml b/doc/reference/clutter/clutter-docs.xml index e29317036..baeb0b5bf 100644 --- a/doc/reference/clutter/clutter-docs.xml +++ b/doc/reference/clutter/clutter-docs.xml @@ -57,8 +57,8 @@ - + diff --git a/doc/reference/clutter/clutter-sections.txt b/doc/reference/clutter/clutter-sections.txt index 7c9ed607b..3f0a8429f 100644 --- a/doc/reference/clutter/clutter-sections.txt +++ b/doc/reference/clutter/clutter-sections.txt @@ -28,6 +28,7 @@ clutter_media_get_type clutter-units Unit conversion ClutterUnit +CLUTTER_UNITS_FORMAT CLUTTER_UNITS_FROM_DEVICE CLUTTER_UNITS_TO_DEVICE CLUTTER_UNITS_FROM_FIXED @@ -1497,9 +1498,6 @@ clutter_shader_float_get_type clutter_shader_int_get_type clutter_shader_matrix_get_type clutter_shader_error_quark -clutter_shader_float_get_type -clutter_shader_int_get_type -clutter_shader_matrix_get_type
@@ -1582,31 +1580,6 @@ ClutterIntervalPrivate clutter_interval_get_type
-
-Key Bindings -clutter-binding-pool -ClutterBindingPool -ClutterBindingActionFunc - - -clutter_binding_pool_new -clutter_binding_pool_get_for_class -clutter_binding_pool_find - - -clutter_binding_pool_install_action -clutter_binding_pool_install_closure -clutter_binding_pool_override_action -clutter_binding_pool_override_closure -clutter_binding_pool_find_action -clutter_binding_pool_remove_action -clutter_binding_pool_block_action -clutter_binding_pool_unblock_action - - -clutter_binding_pool_activate -
-
clutter-cairo-texture ClutterCairoTexture @@ -1634,6 +1607,7 @@ CLUTTER_CAIRO_TEXTURE_GET_CLASS ClutterCairoTexturePrivate clutter_cairo_texture_get_type +
ClutterText @@ -1713,3 +1687,28 @@ CLUTTER_TYPE_TEXT ClutterTextPrivate clutter_text_get_type
+ +
+Key Bindings +clutter-binding-pool +ClutterBindingPool +ClutterBindingActionFunc + + +clutter_binding_pool_new +clutter_binding_pool_get_for_class +clutter_binding_pool_find + + +clutter_binding_pool_install_action +clutter_binding_pool_install_closure +clutter_binding_pool_override_action +clutter_binding_pool_override_closure +clutter_binding_pool_find_action +clutter_binding_pool_remove_action +clutter_binding_pool_block_action +clutter_binding_pool_unblock_action + + +clutter_binding_pool_activate +
From 4f6cc0b25f958ea720604db09b43896a985e1f50 Mon Sep 17 00:00:00 2001 From: Emmanuele Bassi Date: Mon, 12 Jan 2009 11:15:41 +0000 Subject: [PATCH 15/43] [x11] Proper fix for the ClutterStage resize race Continuation of the fix in commit 00a3c698686f25e193d0311ad25c903f0ad71e8b. Instead of using a separate flag for the resize process, just delay the setting of the CLUTTER_ACTOR_SYNC_MATRICES flag on the stage to the point when we receive a ConfigureNotify event from X11. This commit will break the stage embedding into other toolkits. --- clutter/clutter-backend.c | 3 --- clutter/clutter-main.c | 3 +-- clutter/clutter-private.h | 3 +-- clutter/x11/clutter-event-x11.c | 14 ++++++++++---- clutter/x11/clutter-stage-x11.c | 27 ++++++++++----------------- 5 files changed, 22 insertions(+), 28 deletions(-) diff --git a/clutter/clutter-backend.c b/clutter/clutter-backend.c index 4c60d40ff..efeeac185 100644 --- a/clutter/clutter-backend.c +++ b/clutter/clutter-backend.c @@ -251,9 +251,6 @@ _clutter_backend_ensure_context (ClutterBackend *backend, * potential issue of GL calls with no context) */ current_context_stage = stage; - - if (stage) - CLUTTER_SET_PRIVATE_FLAGS (stage, CLUTTER_ACTOR_SYNC_MATRICES); } else CLUTTER_NOTE (MULTISTAGE, "Stage is the same"); diff --git a/clutter/clutter-main.c b/clutter/clutter-main.c index edcb44cf0..745fcbbd7 100644 --- a/clutter/clutter-main.c +++ b/clutter/clutter-main.c @@ -147,8 +147,7 @@ _clutter_stage_maybe_relayout (ClutterActor *stage) void _clutter_stage_maybe_setup_viewport (ClutterStage *stage) { - if ((CLUTTER_PRIVATE_FLAGS (stage) & CLUTTER_ACTOR_SYNC_MATRICES) && - !(CLUTTER_PRIVATE_FLAGS (stage) & CLUTTER_STAGE_IN_RESIZE)) + if (CLUTTER_PRIVATE_FLAGS (stage) & CLUTTER_ACTOR_SYNC_MATRICES) { ClutterPerspective perspective; guint width, height; diff --git a/clutter/clutter-private.h b/clutter/clutter-private.h index b1f141bf7..c65bfb066 100644 --- a/clutter/clutter-private.h +++ b/clutter/clutter-private.h @@ -62,8 +62,7 @@ typedef enum { */ CLUTTER_ACTOR_IN_PAINT = 1 << 4, /* Used to avoid recursion */ CLUTTER_ACTOR_IN_RELAYOUT = 1 << 5, /* Used to avoid recursion */ - CLUTTER_TEXTURE_IN_CLONE_PAINT = 1 << 6, /* Used for safety in clones */ - CLUTTER_STAGE_IN_RESIZE = 1 << 7 /* Used to mark stage resizes */ + CLUTTER_TEXTURE_IN_CLONE_PAINT = 1 << 6 /* Used for safety in clones */ } ClutterPrivateFlags; typedef enum { diff --git a/clutter/x11/clutter-event-x11.c b/clutter/x11/clutter-event-x11.c index 090e2c28c..b83a0b2f3 100644 --- a/clutter/x11/clutter-event-x11.c +++ b/clutter/x11/clutter-event-x11.c @@ -433,17 +433,23 @@ event_translate (ClutterBackend *backend, it from trying to resize the window again */ stage_x11->handling_configure = TRUE; + CLUTTER_NOTE (BACKEND, "%s: ConfigureNotify[%x] (%d, %d)", + G_STRLOC, + (unsigned int) stage_x11->xwin, + xevent->xconfigure.width, + xevent->xconfigure.height); + clutter_actor_set_size (CLUTTER_ACTOR (stage), xevent->xconfigure.width, xevent->xconfigure.height); stage_x11->handling_configure = FALSE; - /* the resize process is complete, so we can remove the - * in-resize flag and allow the viewport to be resized + /* the resize process is complete, so we can ask the stage + * to set up the GL viewport with the new size */ - CLUTTER_UNSET_PRIVATE_FLAGS (CLUTTER_ACTOR (stage_x11->wrapper), - CLUTTER_STAGE_IN_RESIZE); + CLUTTER_SET_PRIVATE_FLAGS (CLUTTER_ACTOR (stage_x11->wrapper), + CLUTTER_ACTOR_SYNC_MATRICES); } res = FALSE; break; diff --git a/clutter/x11/clutter-stage-x11.c b/clutter/x11/clutter-stage-x11.c index bfc86ba9f..d01d8e2b1 100644 --- a/clutter/x11/clutter-stage-x11.c +++ b/clutter/x11/clutter-stage-x11.c @@ -286,27 +286,18 @@ clutter_stage_x11_allocate (ClutterActor *self, !stage_x11->is_foreign_xwin && !stage_x11->handling_configure) { + CLUTTER_NOTE (BACKEND, "%s: XResizeWindow[%x] (%d, %d)", + G_STRLOC, + (unsigned int) stage_x11->xwin, + stage_x11->xwin_width, + stage_x11->xwin_height); + XResizeWindow (stage_x11->xdpy, stage_x11->xwin, stage_x11->xwin_width, stage_x11->xwin_height); - - /* resizing is an asynchronous process; to avoid races - * with the window manager, we flag the wrapper as being - * "in resize", so that the SYNC_MATRICES flag will not - * cause a call to cogl_get_viewport(). - * - * the flag is unset inside clutter-event-x11.c, after - * we receive a ConfigureNotify event. XXX - need to - * check what happens when running without a window manager - */ - CLUTTER_SET_PRIVATE_FLAGS (CLUTTER_ACTOR (stage_x11->wrapper), - CLUTTER_STAGE_IN_RESIZE); } - CLUTTER_SET_PRIVATE_FLAGS (CLUTTER_ACTOR (stage_x11->wrapper), - CLUTTER_ACTOR_SYNC_MATRICES); - clutter_stage_x11_fix_window_size (stage_x11); if (stage_x11->xpixmap != None) @@ -411,6 +402,8 @@ clutter_stage_x11_set_fullscreen (ClutterStageWindow *stage_window, if (!stage) return; + CLUTTER_SET_PRIVATE_FLAGS (stage, CLUTTER_ACTOR_SYNC_MATRICES); + if (is_fullscreen) { int width, height; @@ -493,8 +486,6 @@ clutter_stage_x11_set_fullscreen (ClutterStageWindow *stage_window, stage_x11->fullscreen_on_map = FALSE; } } - - CLUTTER_SET_PRIVATE_FLAGS (stage, CLUTTER_ACTOR_SYNC_MATRICES); } static void @@ -754,6 +745,8 @@ clutter_x11_set_stage_foreign (ClutterStage *stage, clutter_actor_set_geometry (actor, &geom); clutter_actor_realize (actor); + CLUTTER_SET_PRIVATE_FLAGS (actor, CLUTTER_ACTOR_SYNC_MATRICES); + return TRUE; } From f911a3a7a13a778b44fedb4760ea55105d6bcd46 Mon Sep 17 00:00:00 2001 From: Emmanuele Bassi Date: Mon, 12 Jan 2009 11:18:11 +0000 Subject: [PATCH 16/43] Allow ensuring that a stage viewport is updated Since we only update the GL viewport when we receive a ConfigureNotify event on X11, we also need a function to allow other toolkits to tell a stage that the viewport should be updated. This commit adds clutter_stage_ensure_viewport(), a function that simply sets the private SYNC_MATRICES flag on the stage and then queues a redraw. This function should be called by libraries integrating Clutter with other toolkits, like clutter-gtk or clutter-qt. --- clutter/clutter-stage.c | 25 +++++++++++++++++++++++++ clutter/clutter-stage.h | 1 + 2 files changed, 26 insertions(+) diff --git a/clutter/clutter-stage.c b/clutter/clutter-stage.c index f6d42288f..3b312df2f 100644 --- a/clutter/clutter-stage.c +++ b/clutter/clutter-stage.c @@ -1801,6 +1801,31 @@ clutter_stage_ensure_current (ClutterStage *stage) _clutter_backend_ensure_context (ctx->backend, stage); } +/** + * clutter_stage_ensure_viewport: + * @stage: a #ClutterStage + * + * Ensures that the GL viewport is updated with the current + * stage window size. + * + * This function will queue a redraw of @stage. + * + * This function should not be called by applications; it is used + * when embedding a #ClutterStage into a toolkit with another + * windowing system, like GTK+. + * + * Since: 1.0 + */ +void +clutter_stage_ensure_viewport (ClutterStage *stage) +{ + g_return_if_fail (CLUTTER_IS_STAGE (stage)); + + CLUTTER_SET_PRIVATE_FLAGS (stage, CLUTTER_ACTOR_SYNC_MATRICES); + + clutter_stage_queue_redraw (stage); +} + static gboolean redraw_update_idle (gpointer user_data) { diff --git a/clutter/clutter-stage.h b/clutter/clutter-stage.h index cb8ca9063..7b174ee30 100644 --- a/clutter/clutter-stage.h +++ b/clutter/clutter-stage.h @@ -229,6 +229,7 @@ ClutterActor * clutter_stage_get_key_focus (ClutterStage *stage); void clutter_stage_ensure_current (ClutterStage *stage); void clutter_stage_queue_redraw (ClutterStage *stage); gboolean clutter_stage_is_default (ClutterStage *stage); +void clutter_stage_ensure_viewport (ClutterStage *stage); /* Commodity macro */ #define clutter_stage_add(stage,actor) G_STMT_START { \ From ed991fe3c5558bb2bb9058ec0bdeef2071236056 Mon Sep 17 00:00:00 2001 From: Emmanuele Bassi Date: Mon, 12 Jan 2009 11:21:06 +0000 Subject: [PATCH 17/43] Declare G_LOG_DOMAIN for COGL In order to get properly namespaced debug and warning messages inside COGL code we need to define the G_LOG_DOMAIN macro. --- clutter/cogl/common/Makefile.am | 1 + clutter/cogl/gl/Makefile.am | 1 + clutter/cogl/gles/Makefile.am | 1 + 3 files changed, 3 insertions(+) diff --git a/clutter/cogl/common/Makefile.am b/clutter/cogl/common/Makefile.am index db0f0b42d..fb2adf28f 100644 --- a/clutter/cogl/common/Makefile.am +++ b/clutter/cogl/common/Makefile.am @@ -5,6 +5,7 @@ INCLUDES = \ -I$(top_srcdir)/clutter/cogl/$(CLUTTER_COGL) \ -I$(top_builddir)/clutter \ -I$(top_builddir)/clutter/cogl \ + -DG_LOG_DOMAIN=\"Cogl-Common\" \ -DCLUTTER_COMPILATION \ $(CLUTTER_CFLAGS) \ $(CLUTTER_DEBUG_CFLAGS) \ diff --git a/clutter/cogl/gl/Makefile.am b/clutter/cogl/gl/Makefile.am index 2d90ba9c0..7635b1b90 100644 --- a/clutter/cogl/gl/Makefile.am +++ b/clutter/cogl/gl/Makefile.am @@ -20,6 +20,7 @@ INCLUDES = \ -I$(top_srcdir)/clutter/cogl/$(CLUTTER_COGL) \ -I$(top_builddir)/clutter \ -I$(top_builddir)/clutter/cogl \ + -DG_LOG_DOMAIN=\"Cogl-GL\" \ -DCLUTTER_COMPILATION \ $(CLUTTER_CFLAGS) \ $(CLUTTER_DEBUG_CFLAGS) \ diff --git a/clutter/cogl/gles/Makefile.am b/clutter/cogl/gles/Makefile.am index 19cf0a0d7..1731d2cb5 100644 --- a/clutter/cogl/gles/Makefile.am +++ b/clutter/cogl/gles/Makefile.am @@ -20,6 +20,7 @@ INCLUDES = \ -I$(top_srcdir)/clutter/cogl/$(CLUTTER_COGL) \ -I$(top_builddir)/clutter \ -I$(top_builddir)/clutter/cogl \ + -DG_LOG_DOMAIN=\"Cogl-GLES\" \ -DCLUTTER_COMPILATION \ $(CLUTTER_CFLAGS) \ $(CLUTTER_DEBUG_CFLAGS) \ From f09b221ade120c16a4696f3160509ea98adfada3 Mon Sep 17 00:00:00 2001 From: Robert Bragg Date: Mon, 12 Jan 2009 13:02:19 +0000 Subject: [PATCH 18/43] [ClutterGLXTexturePixmap] Use an RGB texture (not ARGB) for 24bpp pixmaps By creating an ARGB texture for 24bpp pixmaps we were exposing an undefined alpha channel to the blending and texture combine stages which resulted in nasty artefacts. (This issue was seen on i945 + DRI2) --- clutter/glx/clutter-glx-texture-pixmap.c | 30 ++++++++++++++++++------ 1 file changed, 23 insertions(+), 7 deletions(-) diff --git a/clutter/glx/clutter-glx-texture-pixmap.c b/clutter/glx/clutter-glx-texture-pixmap.c index 280f34216..0dfe23941 100644 --- a/clutter/glx/clutter-glx-texture-pixmap.c +++ b/clutter/glx/clutter-glx-texture-pixmap.c @@ -317,8 +317,25 @@ create_cogl_texture (ClutterTexture *texture, { ClutterGLXTexturePixmap *texture_glx = CLUTTER_GLX_TEXTURE_PIXMAP (texture); ClutterGLXTexturePixmapPrivate *priv = texture_glx->priv; - CoglHandle handle; - gboolean using_rectangle; + CoglHandle handle; + gboolean using_rectangle; + GLint gl_format; + CoglPixelFormat cogl_format; + guint depth; + + g_object_get (G_OBJECT (texture_glx), "pixmap-depth", &depth, NULL); + if (depth == 32) + { + gl_format = GL_RGBA; + cogl_format = COGL_PIXEL_FORMAT_RGBA_8888; + } + else if (depth == 24) + { + gl_format = GL_RGB; + cogl_format = COGL_PIXEL_FORMAT_RGB_888; + } + else + g_critical ("Can't create a TFP cogl texture for pixmap with depth < 24"); /* We want to use the GL_ARB_texture_rectangle extension on some chipsets because GL_ARB_texture_non_power_of_two is not always @@ -332,21 +349,20 @@ create_cogl_texture (ClutterTexture *texture, glGenTextures (1, &tex); glBindTexture (CGL_TEXTURE_RECTANGLE_ARB, tex); glTexImage2D (CGL_TEXTURE_RECTANGLE_ARB, 0, - GL_RGBA, width, height, - 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); + GL_RGB, width, height, + 0, GL_RGB, GL_UNSIGNED_BYTE, NULL); handle = cogl_texture_new_from_foreign (tex, CGL_TEXTURE_RECTANGLE_ARB, width, height, 0, 0, - COGL_PIXEL_FORMAT_RGBA_8888 - | COGL_BGR_BIT); + cogl_format | COGL_BGR_BIT); } else { handle = cogl_texture_new_with_size (width, height, -1, FALSE, - COGL_PIXEL_FORMAT_RGBA_8888|COGL_BGR_BIT); + cogl_format | COGL_BGR_BIT); using_rectangle = FALSE; } From be462b2ea8d2ed908520a498908a83c5ba37a3b7 Mon Sep 17 00:00:00 2001 From: Havoc Pennington Date: Mon, 12 Jan 2009 14:19:48 +0000 Subject: [PATCH 19/43] Bug 1087 - virtualize stage_queue_redraw Add a ClutterStage::queue-redraw signal. The purpose of this signal is to allow combining the Clutter redraw idle with another redraw idle such as gtk's (or any other one really; this is desirable anytime Clutter is not the only thing drawing to a toplevel window). To override the default, you would connect to ::queue-redraw and then stop the signal emission. --- clutter/clutter-stage.c | 118 ++++++++++++++++++++++++++++++---------- clutter/clutter-stage.h | 2 + 2 files changed, 91 insertions(+), 29 deletions(-) diff --git a/clutter/clutter-stage.c b/clutter/clutter-stage.c index 3b312df2f..6a4e850b8 100644 --- a/clutter/clutter-stage.c +++ b/clutter/clutter-stage.c @@ -115,6 +115,8 @@ enum UNFULLSCREEN, ACTIVATE, DEACTIVATE, + QUEUE_REDRAW, + LAST_SIGNAL }; @@ -335,6 +337,42 @@ clutter_stage_real_fullscreen (ClutterStage *stage) clutter_actor_allocate (CLUTTER_ACTOR (stage), &box, FALSE); } +static gboolean +redraw_update_idle (gpointer user_data) +{ + ClutterStage *stage = user_data; + ClutterStagePrivate *priv = stage->priv; + + if (priv->update_idle) + { + g_source_remove (priv->update_idle); + priv->update_idle = 0; + } + + CLUTTER_NOTE (MULTISTAGE, "redrawing via idle for stage:%p", stage); + clutter_redraw (stage); + + return FALSE; +} + +static void +clutter_stage_real_queue_redraw (ClutterStage *stage) +{ + ClutterStagePrivate *priv = stage->priv; + + if (priv->update_idle == 0) + { + CLUTTER_TIMESTAMP (SCHEDULER, "Adding idle source for stage: %p", stage); + + /* FIXME: weak_ref self in case we dissapear before paint? */ + priv->update_idle = + clutter_threads_add_idle_full (CLUTTER_PRIORITY_REDRAW, + redraw_update_idle, + stage, + NULL); + } +} + static void clutter_stage_set_property (GObject *object, guint prop_id, @@ -687,8 +725,58 @@ clutter_stage_class_init (ClutterStageClass *klass) NULL, NULL, clutter_marshal_VOID__VOID, G_TYPE_NONE, 0); + /** + * ClutterStage::queue-redraw: + * @stage: the stage which was queued for redraw + * + * The ::queue-redraw signal is emitted each time a #ClutterStage + * has been queued for a redraw. You can use this signal to know + * when clutter_stage_queue_redraw() has been called. + * + * Toolkits embedding a #ClutterStage which require a redraw and + * relayout cycle can stop the emission of this signal using the + * GSignal API, redraw the UI and then call clutter_redraw() + * themselves, like: + * + * |[ + * static void + * on_redraw_complete (void) + * { + * /* execute the Clutter drawing pipeline */ + * clutter_redraw (); + * } + * + * static void + * on_stage_queue_redraw (ClutterStage *stage) + * { + * /* this prevents the default handler to run */ + * g_signal_stop_emission_by_name (stage, "queue-redraw"); + * + * /* queue a redraw with the host toolkit and call + * * a function when the redraw has been completed + * */ + * queue_a_redraw (G_CALLBACK (on_redraw_complete)); + * } + * ]| + * + * This signal is emitted before the Clutter paint + * pipeline is run. If you want to know when the pipeline has been + * completed you should connect to the ::paint signal on the Stage + * with g_signal_connect_after(). + * + * Since: 1.0 + */ + stage_signals[QUEUE_REDRAW] = + g_signal_new (I_("queue-redraw"), + G_TYPE_FROM_CLASS (gobject_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (ClutterStageClass, queue_redraw), + NULL, NULL, + clutter_marshal_VOID__VOID, + G_TYPE_NONE, 0); klass->fullscreen = clutter_stage_real_fullscreen; + klass->queue_redraw = clutter_stage_real_queue_redraw; g_type_class_add_private (gobject_class, sizeof (ClutterStagePrivate)); } @@ -1826,24 +1914,6 @@ clutter_stage_ensure_viewport (ClutterStage *stage) clutter_stage_queue_redraw (stage); } -static gboolean -redraw_update_idle (gpointer user_data) -{ - ClutterStage *stage = user_data; - ClutterStagePrivate *priv = stage->priv; - - if (priv->update_idle) - { - g_source_remove (priv->update_idle); - priv->update_idle = 0; - } - - CLUTTER_NOTE (MULTISTAGE, "redrawing via idle for stage:%p", stage); - clutter_redraw (stage); - - return FALSE; -} - /** * clutter_stage_queue_redraw: * @stage: the #ClutterStage @@ -1860,17 +1930,7 @@ clutter_stage_queue_redraw (ClutterStage *stage) { g_return_if_fail (CLUTTER_IS_STAGE (stage)); - if (!stage->priv->update_idle) - { - CLUTTER_TIMESTAMP (SCHEDULER, "Adding idle source for stage: %p", stage); - - /* FIXME: weak_ref self in case we dissapear before paint? */ - stage->priv->update_idle = - clutter_threads_add_idle_full (CLUTTER_PRIORITY_REDRAW, - redraw_update_idle, - stage, - NULL); - } + g_signal_emit (stage, stage_signals[QUEUE_REDRAW], 0); } /** diff --git a/clutter/clutter-stage.h b/clutter/clutter-stage.h index 7b174ee30..9cbbdeb92 100644 --- a/clutter/clutter-stage.h +++ b/clutter/clutter-stage.h @@ -106,6 +106,8 @@ struct _ClutterStageClass void (* activate) (ClutterStage *stage); void (* deactivate) (ClutterStage *stage); + void (* queue_redraw) (ClutterStage *stage); + /*< private >*/ /* padding for future expansion */ gpointer _padding_dummy[32]; From 1c114be31a50410c1b2d0621848250102b6dd166 Mon Sep 17 00:00:00 2001 From: Emmanuele Bassi Date: Mon, 12 Jan 2009 16:52:20 +0000 Subject: [PATCH 20/43] Add API for extracting image size from a file For the asynchronous loading we need a function call that parses a file, given its path, and retrieves the image width and height. This commit adds cogl_bitmap_get_size_from_file() to the CoglBitmap API. --- clutter/cogl/cogl-texture.h | 17 +++++++ clutter/cogl/common/cogl-bitmap-pixbuf.c | 65 ++++++++++++++++++++---- clutter/cogl/common/cogl-bitmap.c | 8 +++ clutter/cogl/common/cogl-bitmap.h | 5 ++ 4 files changed, 86 insertions(+), 9 deletions(-) diff --git a/clutter/cogl/cogl-texture.h b/clutter/cogl/cogl-texture.h index 65b29b68c..3a509196a 100644 --- a/clutter/cogl/cogl-texture.h +++ b/clutter/cogl/cogl-texture.h @@ -415,10 +415,27 @@ void cogl_texture_polygon (CoglHandle handle, * * Returns: A #CoglBitmap to the new loaded image data, or %NULL if loading * the image failed. + * + * Since: 1.0 */ CoglBitmap * cogl_bitmap_new_from_file (const gchar *filename, GError **error); +/** + * cogl_bitmap_get_size_from_file: + * @filename: the file to check + * @width: return location for the bitmap width + * @height: return location for the bitmap height + * + * Parses an image file enough to extract the width and height + * of the bitmap. + * + * Since: 1.0 + */ +gboolean cogl_bitmap_get_size_from_file (const gchar *filename, + gint *width, + gint *height); + /** * cogl_bitmap_free: * @bmp: a #CoglBitmap. diff --git a/clutter/cogl/common/cogl-bitmap-pixbuf.c b/clutter/cogl/common/cogl-bitmap-pixbuf.c index 77316dff5..8d86d94e4 100644 --- a/clutter/cogl/common/cogl-bitmap-pixbuf.c +++ b/clutter/cogl/common/cogl-bitmap-pixbuf.c @@ -84,6 +84,20 @@ cogl_bitmap_error_quark (void) return g_quark_from_static_string ("cogl-bitmap-error-quark"); } +gboolean +_cogl_bitmap_get_size_from_file (const gchar *filename, + gint *width, + gint *height) +{ + if (width) + *width = 0; + + if (height) + *height = 0; + + return TRUE; +} + /* the error does not contain the filename as the caller already has it */ gboolean _cogl_bitmap_from_file (CoglBitmap *bmp, @@ -177,9 +191,22 @@ _cogl_bitmap_from_file (CoglBitmap *bmp, #elif defined(USE_GDKPIXBUF) gboolean -_cogl_bitmap_from_file (CoglBitmap *bmp, - const gchar *filename, - GError **error) +_cogl_bitmap_get_size_from_file (const gchar *filename, + gint *width, + gint *height) +{ + g_return_val_if_fail (filename != NULL, FALSE); + + if (gdk_pixbuf_get_file_info (filename, width, height) != NULL) + return TRUE; + + return FALSE; +} + +gboolean +_cogl_bitmap_from_file (CoglBitmap *bmp, + const gchar *filename, + GError **error) { GdkPixbuf *pixbuf; gboolean has_alpha; @@ -198,11 +225,13 @@ _cogl_bitmap_from_file (CoglBitmap *bmp, g_return_val_if_fail (error == NULL || *error == NULL, FALSE); - if (bmp == NULL) return FALSE; - + if (bmp == NULL) + return FALSE; + /* Load from file using GdkPixbuf */ pixbuf = gdk_pixbuf_new_from_file (filename, error); - if (pixbuf == NULL) return FALSE; + if (pixbuf == NULL) + return FALSE; /* Get pixbuf properties */ has_alpha = gdk_pixbuf_get_has_alpha (pixbuf); @@ -278,6 +307,20 @@ _cogl_bitmap_from_file (CoglBitmap *bmp, #include "stb_image.c" +gboolean +_cogl_bitmap_get_size_from_file (const gchar *filename, + gint *width, + gint *height) +{ + if (width) + *width = 0; + + if (height) + *height = 0; + + return TRUE; +} + gboolean _cogl_bitmap_from_file (CoglBitmap *bmp, const gchar *filename, @@ -290,11 +333,15 @@ _cogl_bitmap_from_file (CoglBitmap *bmp, g_return_val_if_fail (error == NULL || *error == NULL, FALSE); - if (bmp == NULL) return FALSE; + if (bmp == NULL) + return FALSE; /* Load from file using stb */ - pixels = stbi_load (filename, &width, &height, &stb_pixel_format, STBI_rgb_alpha); - if (pixels == NULL) return FALSE; + pixels = stbi_load (filename, + &width, &height, &stb_pixel_format, + STBI_rgb_alpha); + if (pixels == NULL) + return FALSE; /* Store bitmap info */ bmp->data = g_memdup (pixels, height * width * 4); diff --git a/clutter/cogl/common/cogl-bitmap.c b/clutter/cogl/common/cogl-bitmap.c index 6f31ebb5c..b0a3b7138 100644 --- a/clutter/cogl/common/cogl-bitmap.c +++ b/clutter/cogl/common/cogl-bitmap.c @@ -149,6 +149,14 @@ _cogl_bitmap_copy_subregion (CoglBitmap *src, } } +gboolean +cogl_bitmap_get_size_from_file (const gchar *filename, + gint *width, + gint *height) +{ + return _cogl_bitmap_get_size_from_file (filename, width, height); +} + CoglBitmap * cogl_bitmap_new_from_file (const gchar *filename, GError **error) diff --git a/clutter/cogl/common/cogl-bitmap.h b/clutter/cogl/common/cogl-bitmap.h index 9baec8170..953ac5a32 100644 --- a/clutter/cogl/common/cogl-bitmap.h +++ b/clutter/cogl/common/cogl-bitmap.h @@ -90,4 +90,9 @@ _cogl_bitmap_copy_subregion (CoglBitmap *src, gint width, gint height); +gboolean +_cogl_bitmap_get_size_from_file (const gchar *filename, + gint *width, + gint *height); + #endif /* __COGL_BITMAP_H */ From 168d558bcf7dcbd707364004fe968093b5bb5546 Mon Sep 17 00:00:00 2001 From: Emmanuele Bassi Date: Mon, 12 Jan 2009 16:54:30 +0000 Subject: [PATCH 21/43] [async-loading] Update asynchronous image loading Provide a main loop-based fallback to the asynchronous loading in case the GLib threading support hasn't been enabled. This also allows us to clean up the asynchronous loading machinery and have it behave consistently across different scenarios. Emit the ::load-finished even if the asynchronous loading from disk was not enabled. Finally, block clutter_texture_set_from_file() until we have an image width and height, so that querying the texture actor size after set_from_file() will still yield the correct result even when asynchronous loading is set. --- clutter/clutter-texture.c | 307 ++++++++++++++++++++++++++++---------- 1 file changed, 230 insertions(+), 77 deletions(-) diff --git a/clutter/clutter-texture.c b/clutter/clutter-texture.c index 10cb2172c..c1a55c3fe 100644 --- a/clutter/clutter-texture.c +++ b/clutter/clutter-texture.c @@ -99,10 +99,10 @@ struct _ClutterTexturePrivate guint load_async : 1; GThread *load_thread; + guint load_idle; gchar *load_filename; CoglBitmap *load_bitmap; GError *load_error; - guint load_source; }; enum @@ -612,8 +612,15 @@ clutter_texture_paint (ClutterActor *self) 0, 0, t_w, t_h); } +/* + * clutter_texture_async_load_cancel: + * @texture: a #ClutterTexture + * + * Cancels an asynchronous loading operation, whether done + * with threads enabled or just using the main loop + */ static void -clutter_texture_thread_cancel (ClutterTexture *texture) +clutter_texture_async_load_cancel (ClutterTexture *texture) { ClutterTexturePrivate *priv = texture->priv; @@ -622,23 +629,26 @@ clutter_texture_thread_cancel (ClutterTexture *texture) g_thread_join (priv->load_thread); priv->load_thread = NULL; } - - if (priv->load_source) + + if (priv->load_idle) { - g_source_remove (priv->load_source); - priv->load_source = 0; - - if (priv->load_error) - { - g_error_free (priv->load_error); - priv->load_error = NULL; - } - else - { - cogl_bitmap_free (priv->load_bitmap); - priv->load_bitmap = NULL; - } + g_source_remove (priv->load_idle); + priv->load_idle = 0; } + + if (priv->load_error) + { + g_error_free (priv->load_error); + priv->load_error = NULL; + } + + if (priv->load_bitmap) + { + cogl_bitmap_free (priv->load_bitmap); + priv->load_bitmap = NULL; + } + + g_free (priv->load_filename); } static void @@ -666,7 +676,7 @@ clutter_texture_dispose (GObject *object) priv->local_data = NULL; } - clutter_texture_thread_cancel (texture); + clutter_texture_async_load_cancel (texture); G_OBJECT_CLASS (clutter_texture_parent_class)->dispose (object); } @@ -730,8 +740,6 @@ clutter_texture_set_property (GObject *object, break; case PROP_LOAD_ASYNC: priv->load_async = g_value_get_boolean (value); - if (priv->load_async && !g_thread_supported()) - priv->load_async = FALSE; break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); @@ -911,6 +919,20 @@ clutter_texture_class_init (ClutterTextureClass *klass) FALSE, CLUTTER_PARAM_READWRITE)); + /** + * ClutterTexture:load-async: + * + * Tries to load a texture from a filename by using a local thread + * to perform the read operations. Threading is only enabled if + * g_thread_init() has been called prior to clutter_init(), otherwise + * #ClutterTexture will use the main loop to load the image. + * + * The upload of the texture data on the GL pipeline is not + * asynchronous, as it must be performed from within the same + * thread that called clutter_main(). + * + * Since: 1.0 + */ g_object_class_install_property (gobject_class, PROP_LOAD_ASYNC, g_param_spec_boolean ("load-async", @@ -960,12 +982,14 @@ clutter_texture_class_init (ClutterTextureClass *klass) * @texture: the texture which received the signal * @error: A set error, or %NULL * - * The ::load-finished signal is emitted when asynchronous texture - * load has completed. If there was an error during loading, @error will - * be set. + * The ::load-finished signal is emitted when a texture load has + * completed. If there was an error during loading, @error will + * be set, otherwise it will be %NULL + * + * Since: 1.0 */ texture_signals[LOAD_FINISHED] = - g_signal_new ("load-finished", + g_signal_new (I_("load-finished"), G_TYPE_FROM_CLASS (gobject_class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (ClutterTextureClass, load_finished), @@ -1340,14 +1364,14 @@ clutter_texture_set_from_rgb_data (ClutterTexture *texture, * Return value: %TRUE if the texture was successfully updated * * Since: 0.4 - **/ + */ gboolean -clutter_texture_set_from_yuv_data (ClutterTexture *texture, - const guchar *data, - gint width, - gint height, - ClutterTextureFlags flags, - GError **error) +clutter_texture_set_from_yuv_data (ClutterTexture *texture, + const guchar *data, + gint width, + gint height, + ClutterTextureFlags flags, + GError **error) { ClutterTexturePrivate *priv; @@ -1379,13 +1403,53 @@ clutter_texture_set_from_yuv_data (ClutterTexture *texture, error); } -static gboolean -clutter_texture_thread_cb (ClutterTexture *self) +/* + * clutter_texture_async_load_complete: + * @self: a #ClutterTexture + * @error: load error + * + * If @error is %NULL, loads the #CoglBitmap into a #CoglTexture. + * + * This function emits the ::load-finished signal on @self. + */ +static void +clutter_texture_async_load_complete (ClutterTexture *self, + const GError *error) { ClutterTexturePrivate *priv = self->priv; - - priv->load_source = 0; - + CoglHandle handle; + gboolean enable_mipmap = FALSE; + gint waste = -1; + + if (error == NULL) + { + if (priv->no_slice) + waste = priv->max_tile_waste; + + if (priv->filter_quality == CLUTTER_TEXTURE_QUALITY_HIGH) + enable_mipmap = TRUE; + + handle = cogl_texture_new_from_bitmap (priv->load_bitmap, + waste, enable_mipmap, + COGL_PIXEL_FORMAT_ANY); + clutter_texture_set_cogl_texture (self, handle); + cogl_texture_unref (handle); + + cogl_bitmap_free (priv->load_bitmap); + priv->load_bitmap = NULL; + } + + g_signal_emit (self, texture_signals[LOAD_FINISHED], 0, error); +} + +static gboolean +clutter_texture_thread_cb (gpointer data) +{ + ClutterTexture *self = data; + ClutterTexturePrivate *priv = self->priv; + + priv->load_idle = 0; + if (priv->load_thread) { g_thread_join (priv->load_thread); @@ -1393,26 +1457,9 @@ clutter_texture_thread_cb (ClutterTexture *self) } else return FALSE; - - if (!priv->load_error) - { - CoglHandle handle; - - handle = cogl_texture_new_from_bitmap (priv->load_bitmap, - priv->no_slice ? - -1 : priv->max_tile_waste, - priv->filter_quality == - CLUTTER_TEXTURE_QUALITY_HIGH, - COGL_PIXEL_FORMAT_ANY); - clutter_texture_set_cogl_texture (self, handle); - cogl_texture_unref (handle); - - cogl_bitmap_free (priv->load_bitmap); - priv->load_bitmap = NULL; - } - - g_signal_emit (self, texture_signals[LOAD_FINISHED], 0, priv->load_error); - + + clutter_texture_async_load_complete (self, priv->load_error); + if (priv->load_error) { g_error_free (priv->load_error); @@ -1423,21 +1470,116 @@ clutter_texture_thread_cb (ClutterTexture *self) } static gpointer -clutter_texture_thread_func (ClutterTexture *self) +clutter_texture_thread_func (gpointer data) { + ClutterTexture *self = data; ClutterTexturePrivate *priv = self->priv; - + /* Try loading with imaging backend */ priv->load_bitmap = cogl_bitmap_new_from_file (priv->load_filename, &priv->load_error); g_free (priv->load_filename); priv->load_filename = NULL; - - clutter_threads_add_idle ((GSourceFunc)clutter_texture_thread_cb, self); - + + /* make sure we load the image in the main thread, where we + * hold the main Clutter lock + */ + priv->load_idle = + clutter_threads_add_idle (clutter_texture_thread_cb, self); + return NULL; } +static gboolean +clutter_texture_idle_func (gpointer data) +{ + ClutterTexture *self = data; + ClutterTexturePrivate *priv = self->priv; + GError *internal_error; + + internal_error = NULL; + priv->load_bitmap = cogl_bitmap_new_from_file (priv->load_filename, + &internal_error); + + clutter_texture_async_load_complete (self, internal_error); + + g_free (priv->load_filename); + priv->load_filename = NULL; + + if (internal_error) + g_error_free (internal_error); + + return FALSE; +} + +/* + * clutter_texture_async_load: + * @self: a #ClutterTexture + * @error: return location for a #GError + * + * Starts an asynchronous load of the file name stored inside + * the load_filename private member. + * + * If threading is enabled we use a GThread to perform the actual + * I/O; if threading is not enabled, we use an idle GSource. + * + * The I/O is the only bit done in a thread -- uploading the + * texture data to the GL pipeline must be done from within the + * same thread that called clutter_main(). Threaded upload should + * be part of the GL implementation. + * + * This function will block until we get a size from the file + * so that we can effectively get the size the texture actor after + * clutter_texture_set_from_file(). + * + * Return value: %TRUE if the asynchronous loading was successfully + * initiated, %FALSE otherwise + */ +static gboolean +clutter_texture_async_load (ClutterTexture *self, + GError **error) +{ + ClutterTexturePrivate *priv = self->priv; + gint width, height; + gboolean res; + + g_assert (priv->load_filename != NULL); + + /* ask the file for a size; if we cannot get the size then + * there's no point in even continuing the asynchronous + * loading, so we just stop there + */ + res = cogl_bitmap_get_size_from_file (priv->load_filename, + &width, + &height); + if (!res) + { + g_set_error (error, CLUTTER_TEXTURE_ERROR, + CLUTTER_TEXTURE_ERROR_BAD_FORMAT, + "Failed to create COGL texture"); + return FALSE; + } + else + clutter_actor_set_size (CLUTTER_ACTOR (self), width, height); + + if (g_thread_supported ()) + { + priv->load_thread = + g_thread_create ((GThreadFunc) clutter_texture_thread_func, + self, TRUE, + error); + + return priv->load_thread != NULL? TRUE : FALSE; + } + else + { + priv->load_idle = + clutter_threads_add_idle (clutter_texture_idle_func, self); + + return TRUE; + } +} + /** * clutter_texture_set_from_file: * @texture: A #ClutterTexture @@ -1456,8 +1598,11 @@ clutter_texture_set_from_file (ClutterTexture *texture, const gchar *filename, GError **error) { - CoglHandle new_texture; - ClutterTexturePrivate *priv; + ClutterTexturePrivate *priv; + CoglHandle new_texture = COGL_INVALID_HANDLE; + GError *internal_error = NULL; + gboolean enable_mipmap = FALSE; + gint max_waste = -1; priv = texture->priv; @@ -1465,30 +1610,36 @@ clutter_texture_set_from_file (ClutterTexture *texture, if (priv->load_async) { - clutter_texture_thread_cancel (texture); - + clutter_texture_async_load_cancel (texture); + priv->load_filename = g_strdup (filename); - priv->load_thread = g_thread_create ((GThreadFunc) - clutter_texture_thread_func, - texture, TRUE, error); - return priv->load_thread ? TRUE : FALSE; + + return clutter_texture_async_load (texture, error); } - if ((new_texture = cogl_texture_new_from_file - (filename, - priv->no_slice ? -1 : priv->max_tile_waste, - priv->filter_quality == CLUTTER_TEXTURE_QUALITY_HIGH, - COGL_PIXEL_FORMAT_ANY, - error)) - == COGL_INVALID_HANDLE) + if (priv->no_slice) + max_waste = priv->max_tile_waste; + + if (priv->filter_quality == CLUTTER_TEXTURE_QUALITY_HIGH) + enable_mipmap = TRUE; + + new_texture = cogl_texture_new_from_file (filename, + max_waste, enable_mipmap, + COGL_PIXEL_FORMAT_ANY, + &internal_error); + if (new_texture == COGL_INVALID_HANDLE) { /* If COGL didn't give an error then make one up */ - if (error && *error == NULL) + if (internal_error == NULL) { g_set_error (error, CLUTTER_TEXTURE_ERROR, CLUTTER_TEXTURE_ERROR_BAD_FORMAT, "Failed to create COGL texture"); } + else + g_propagate_error (error, internal_error); + + g_signal_emit (texture, texture_signals[LOAD_FINISHED], 0, error); return FALSE; } @@ -1501,6 +1652,8 @@ clutter_texture_set_from_file (ClutterTexture *texture, cogl_texture_unref (new_texture); + g_signal_emit (texture, texture_signals[LOAD_FINISHED], 0, error); + return TRUE; } From 5ed62aaf76b49f9539d722f8b78ca99b8304a791 Mon Sep 17 00:00:00 2001 From: Emmanuele Bassi Date: Mon, 12 Jan 2009 17:09:47 +0000 Subject: [PATCH 22/43] [async-loading] Do not force the texture size on async load The size of the texture as retrieved by the filename should be set as the image size, not as the actor size, in order to respect the :sync-size property. When the asynchronous loading process terminates, we queue a relayout so that the scene is updated. --- clutter/clutter-texture.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/clutter/clutter-texture.c b/clutter/clutter-texture.c index c1a55c3fe..71d1f288d 100644 --- a/clutter/clutter-texture.c +++ b/clutter/clutter-texture.c @@ -1440,6 +1440,8 @@ clutter_texture_async_load_complete (ClutterTexture *self, } g_signal_emit (self, texture_signals[LOAD_FINISHED], 0, error); + + clutter_actor_queue_relayout (CLUTTER_ACTOR (self)); } static gboolean @@ -1560,7 +1562,10 @@ clutter_texture_async_load (ClutterTexture *self, return FALSE; } else - clutter_actor_set_size (CLUTTER_ACTOR (self), width, height); + { + priv->width = width; + priv->height = height; + } if (g_thread_supported ()) { @@ -1589,6 +1594,12 @@ clutter_texture_async_load (ClutterTexture *self, * Sets the #ClutterTexture image data from an image file. In case of * failure, %FALSE is returned and @error is set. * + * If #ClutterTexture:load-async is set to %TRUE, this function + * will return as soon as possible, and the actual image loading + * from disk will be performed asynchronously. #ClutterTexture::load-finished + * will be emitted when the image has been loaded or if an error + * occurred. + * * Return value: %TRUE if the image was successfully loaded and set * * Since: 0.8 From e730cd70b1c3cc23b01936878ac913a9fd7d7308 Mon Sep 17 00:00:00 2001 From: Emmanuele Bassi Date: Mon, 12 Jan 2009 17:12:24 +0000 Subject: [PATCH 23/43] Whitespace fixes in ClutterTexture Small whitespace fixes patch; ClutterTexture requires much more love than I can provide at the moment. --- clutter/clutter-texture.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/clutter/clutter-texture.c b/clutter/clutter-texture.c index 71d1f288d..a3b1bd3f8 100644 --- a/clutter/clutter-texture.c +++ b/clutter/clutter-texture.c @@ -263,8 +263,8 @@ clutter_texture_realize (ClutterActor *actor) if (priv->texture != COGL_INVALID_HANDLE) cogl_texture_unref (priv->texture); - priv->texture - = cogl_texture_new_with_size + priv->texture = + cogl_texture_new_with_size (priv->width, priv->height, priv->no_slice ? -1 : priv->max_tile_waste, @@ -2026,7 +2026,7 @@ on_fbo_source_size_change (GObject *object, return; } - clutter_actor_set_size (CLUTTER_ACTOR(texture), w, h); + clutter_actor_set_size (CLUTTER_ACTOR (texture), w, h); } } @@ -2201,9 +2201,9 @@ clutter_texture_new_from_actor (ClutterActor *actor) priv->width = w; priv->height = h; - clutter_actor_set_size (CLUTTER_ACTOR(texture), priv->width, priv->height); + clutter_actor_set_size (CLUTTER_ACTOR (texture), priv->width, priv->height); - return CLUTTER_ACTOR(texture); + return CLUTTER_ACTOR (texture); } static void From a4c8a70c834b5b4fdfd1618ce496425dd5dbcd68 Mon Sep 17 00:00:00 2001 From: Emmanuele Bassi Date: Tue, 13 Jan 2009 12:34:59 +0000 Subject: [PATCH 24/43] Turn ClutterBindingPool a GObject ClutterBindingPool is already "problematic" in terms of memory management for language bindings and gobject-introspection. It also lacks a GType. Turning ClutterBindingPool into a GBoxed would not make much sense, since it does not adhere to the copy/free semantics. It could be referenced/unreferenced, but in that case we can just as well use GObject as a base class instead of reimplemeting a ref-counted object and then boxing it. ClutterBindingPool is obviously a terminal class, so we just hide the instance and class structures. --- clutter/clutter-binding-pool.c | 62 +++++++++++++++++++++++----------- clutter/clutter-binding-pool.h | 12 +++++++ 2 files changed, 55 insertions(+), 19 deletions(-) diff --git a/clutter/clutter-binding-pool.c b/clutter/clutter-binding-pool.c index 78a483f72..037b290c5 100644 --- a/clutter/clutter-binding-pool.c +++ b/clutter/clutter-binding-pool.c @@ -104,6 +104,10 @@ #include "clutter-marshal.h" #include "clutter-private.h" +#define CLUTTER_BINDING_POOL_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), CLUTTER_TYPE_BINDING_POOL, ClutterBindingPoolClass)) +#define CLUTTER_IS_BINDING_POOL_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), CLUTTER_TYPE_BINDING_POOL)) +#define CLUTTER_BINDING_POOL_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), CLUTTER_TYPE_BINDING_POOL, ClutterBindingPoolClass)) + #define BINDING_MOD_MASK ((CLUTTER_SHIFT_MASK | \ CLUTTER_CONTROL_MASK | \ CLUTTER_MOD1_MASK | \ @@ -111,19 +115,27 @@ CLUTTER_HYPER_MASK | \ CLUTTER_META_MASK) | CLUTTER_RELEASE_MASK) -typedef struct _ClutterBindingEntry ClutterBindingEntry; +typedef struct _ClutterBindingPoolClass ClutterBindingPoolClass; +typedef struct _ClutterBindingEntry ClutterBindingEntry; static GSList *binding_pools = NULL; static GQuark key_class_bindings = 0; struct _ClutterBindingPool { + GObject parent_instance; + gchar *name; /* interned string, do not free */ GSList *entries; GHashTable *entries_hash; }; +struct _ClutterBindingPoolClass +{ + GObjectClass parent_class; +}; + struct _ClutterBindingEntry { gchar *name; /* interned string, do not free */ @@ -136,6 +148,8 @@ struct _ClutterBindingEntry guint is_blocked : 1; }; +G_DEFINE_TYPE (ClutterBindingPool, clutter_binding_pool, G_TYPE_OBJECT); + static guint binding_entry_hash (gconstpointer v) { @@ -204,22 +218,37 @@ binding_entry_free (gpointer data) } static void -binding_pool_free (gpointer data) +clutter_binding_pool_finalize (GObject *gobject) { - if (G_LIKELY (data)) - { - ClutterBindingPool *pool = data; + ClutterBindingPool *pool = CLUTTER_BINDING_POOL (gobject); - /* remove from the pools */ - binding_pools = g_slist_remove (binding_pools, pool); + /* remove from the pools */ + binding_pools = g_slist_remove (binding_pools, pool); - g_hash_table_destroy (pool->entries_hash); + g_hash_table_destroy (pool->entries_hash); - g_slist_foreach (pool->entries, (GFunc) binding_entry_free, NULL); - g_slist_free (pool->entries); + g_slist_foreach (pool->entries, (GFunc) binding_entry_free, NULL); + g_slist_free (pool->entries); - g_slice_free (ClutterBindingPool, pool); - } + G_OBJECT_CLASS (clutter_binding_pool_parent_class)->finalize (gobject); +} + +static void +clutter_binding_pool_class_init (ClutterBindingPoolClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + + gobject_class->finalize = clutter_binding_pool_finalize; +} + +static void +clutter_binding_pool_init (ClutterBindingPool *pool) +{ + pool->entries = NULL; + pool->entries_hash = g_hash_table_new (binding_entry_hash, + binding_entry_compare); + + binding_pools = g_slist_prepend (binding_pools, pool); } /** @@ -253,13 +282,8 @@ clutter_binding_pool_new (const gchar *name) return NULL; } - pool = g_slice_new (ClutterBindingPool); + pool = g_object_new (CLUTTER_TYPE_BINDING_POOL, NULL); pool->name = (gchar *) g_intern_string (name); - pool->entries = NULL; - pool->entries_hash = g_hash_table_new (binding_entry_hash, - binding_entry_compare); - - binding_pools = g_slist_prepend (binding_pools, pool); return pool; } @@ -306,7 +330,7 @@ clutter_binding_pool_get_for_class (gpointer klass) pool = clutter_binding_pool_new (G_OBJECT_CLASS_NAME (klass)); g_dataset_id_set_data_full (klass, key_class_bindings, pool, - binding_pool_free); + g_object_unref); return pool; } diff --git a/clutter/clutter-binding-pool.h b/clutter/clutter-binding-pool.h index 55b5273c8..bde939d1d 100644 --- a/clutter/clutter-binding-pool.h +++ b/clutter/clutter-binding-pool.h @@ -33,6 +33,18 @@ G_BEGIN_DECLS +#define CLUTTER_TYPE_BINDING_POOL (clutter_binding_pool_get_type ()) +#define CLUTTER_BINDING_POOL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_BINDING_POOL, ClutterBindingPool)) +#define CLUTTER_IS_BINDING_POOL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_BINDING_POOL)) + +/** + * ClutterBindingPool: + * + * Container of key bindings. The #ClutterBindingPool struct is + * private. + * + * Since: 1.0 + */ typedef struct _ClutterBindingPool ClutterBindingPool; /** From a9ae1c65c3fbe78d197dc202cedf3f77affb72ff Mon Sep 17 00:00:00 2001 From: Emmanuele Bassi Date: Tue, 13 Jan 2009 12:51:03 +0000 Subject: [PATCH 25/43] Add ClutterBindingPool:name The BindingPool constructor should only check for duplicate pools and then set the :name constructor-only property. If a BindingPool is created without a name we also make a fuss about it. It is also possible to simply dispose of a binding pool using g_object_unref(), as long as it has been created by using clutter_binding_pool_new() or directly with g_object_new(). Only BindingPools attached to a class are not owned by the user. --- clutter/clutter-binding-pool.c | 96 ++++++++++++++++++++++++++++++---- 1 file changed, 86 insertions(+), 10 deletions(-) diff --git a/clutter/clutter-binding-pool.c b/clutter/clutter-binding-pool.c index 037b290c5..73398a58d 100644 --- a/clutter/clutter-binding-pool.c +++ b/clutter/clutter-binding-pool.c @@ -118,7 +118,7 @@ typedef struct _ClutterBindingPoolClass ClutterBindingPoolClass; typedef struct _ClutterBindingEntry ClutterBindingEntry; -static GSList *binding_pools = NULL; +static GSList *clutter_binding_pools = NULL; static GQuark key_class_bindings = 0; struct _ClutterBindingPool @@ -148,6 +148,13 @@ struct _ClutterBindingEntry guint is_blocked : 1; }; +enum +{ + PROP_0, + + PROP_NAME +}; + G_DEFINE_TYPE (ClutterBindingPool, clutter_binding_pool, G_TYPE_OBJECT); static guint @@ -223,7 +230,7 @@ clutter_binding_pool_finalize (GObject *gobject) ClutterBindingPool *pool = CLUTTER_BINDING_POOL (gobject); /* remove from the pools */ - binding_pools = g_slist_remove (binding_pools, pool); + clutter_binding_pools = g_slist_remove (clutter_binding_pools, pool); g_hash_table_destroy (pool->entries_hash); @@ -233,22 +240,95 @@ clutter_binding_pool_finalize (GObject *gobject) G_OBJECT_CLASS (clutter_binding_pool_parent_class)->finalize (gobject); } +static void +clutter_binding_pool_set_property (GObject *gobject, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + ClutterBindingPool *pool = CLUTTER_BINDING_POOL (gobject); + + switch (prop_id) + { + case PROP_NAME: + pool->name = (gchar *) g_intern_string (g_value_get_string (value)); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); + break; + } +} + +static void +clutter_binding_pool_get_property (GObject *gobject, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + ClutterBindingPool *pool = CLUTTER_BINDING_POOL (gobject); + + switch (prop_id) + { + case PROP_NAME: + g_value_set_string (value, pool->name); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); + break; + } +} + +static void +clutter_binding_pool_constructed (GObject *gobject) +{ + ClutterBindingPool *pool = CLUTTER_BINDING_POOL (gobject); + + /* bad monkey! bad, bad monkey! */ + if (G_UNLIKELY (pool->name == NULL)) + g_critical ("No name set for ClutterBindingPool %p", pool); + + if (G_OBJECT_CLASS (clutter_binding_pool_parent_class)->constructed) + G_OBJECT_CLASS (clutter_binding_pool_parent_class)->constructed (gobject); +} + static void clutter_binding_pool_class_init (ClutterBindingPoolClass *klass) { GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + GParamSpec *pspec = NULL; + gobject_class->constructed = clutter_binding_pool_constructed; + gobject_class->set_property = clutter_binding_pool_set_property; + gobject_class->get_property = clutter_binding_pool_get_property; gobject_class->finalize = clutter_binding_pool_finalize; + + /** + * ClutterBindingPool:name: + * + * The unique name of the #ClutterBindingPool. + * + * Since: 1.0 + */ + pspec = g_param_spec_string ("name", + "Name", + "The unique name of the binding pool", + NULL, + CLUTTER_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY); + g_object_class_install_property (gobject_class, PROP_NAME, pspec); } static void clutter_binding_pool_init (ClutterBindingPool *pool) { + pool->name = NULL; pool->entries = NULL; pool->entries_hash = g_hash_table_new (binding_entry_hash, binding_entry_compare); - binding_pools = g_slist_prepend (binding_pools, pool); + clutter_binding_pools = g_slist_prepend (clutter_binding_pools, pool); } /** @@ -261,8 +341,7 @@ clutter_binding_pool_init (ClutterBindingPool *pool) * be able to return the correct binding pool. * * Return value: the newly created binding pool with the given - * name. The binding pool is owned by Clutter and should not - * be freed directly + * name. Use g_object_unref() when done. * * Since: 1.0 */ @@ -282,10 +361,7 @@ clutter_binding_pool_new (const gchar *name) return NULL; } - pool = g_object_new (CLUTTER_TYPE_BINDING_POOL, NULL); - pool->name = (gchar *) g_intern_string (name); - - return pool; + return g_object_new (CLUTTER_TYPE_BINDING_POOL, "name", name, NULL); } /** @@ -352,7 +428,7 @@ clutter_binding_pool_find (const gchar *name) g_return_val_if_fail (name != NULL, NULL); - for (l = binding_pools; l != NULL; l = l->next) + for (l = clutter_binding_pools; l != NULL; l = l->next) { ClutterBindingPool *pool = l->data; From ccd9ba2a02cf8f06f002669ffd2ffe2d0af161ea Mon Sep 17 00:00:00 2001 From: Emmanuele Bassi Date: Tue, 13 Jan 2009 14:05:35 +0000 Subject: [PATCH 26/43] [gitignore] Update the ignore file --- .gitignore | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/.gitignore b/.gitignore index c3d05ec40..53c61b6e8 100644 --- a/.gitignore +++ b/.gitignore @@ -153,6 +153,21 @@ stamp-h1 /tests/conform/test-rectangle-opacity /tests/conform/test-backface-culling /tests/conform/test-binding-pool +/tests/conform/test-text-append-some +/tests/conform/test-text-cache +/tests/conform/test-text-cursor +/tests/conform/test-text-delete-chars +/tests/conform/test-text-delete-text +/tests/conform/test-text-empty +/tests/conform/test-text-event +/tests/conform/test-text-get-chars +/tests/conform/test-text-insert +/tests/conform/test-text-password-char +/tests/conform/test-text-prepend-some +/tests/conform/test-text-set-empty +/tests/conform/test-text-set-text +/tests/conform/test-text-utf8-validation +/tests/micro-bench/test-glyph-perf /tests/micro-bench/test-text /tests/tools/disable-npots.sh /clutter/x11/clutter-x11-enum-types.[ch] From 453697fcad0cb8e91c23b3ccebf07ed8ca10591d Mon Sep 17 00:00:00 2001 From: Neil Roberts Date: Mon, 12 Jan 2009 18:32:49 +0000 Subject: [PATCH 27/43] Update gtk-doc 'Since' field for cogl_texture_multiple_rectangles The function has been backported to the 0.8 branch so it will also be available in Clutter 0.8.6 --- clutter/cogl/cogl-texture.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clutter/cogl/cogl-texture.h b/clutter/cogl/cogl-texture.h index 3ca0d8137..5a854d7b0 100644 --- a/clutter/cogl/cogl-texture.h +++ b/clutter/cogl/cogl-texture.h @@ -401,7 +401,7 @@ void cogl_texture_polygon (CoglHandle handle, * parameters x1, y1, x2, y2, tx1, ty1, tx2 and ty2 and have the same * meaning as in cogl_texture_rectangle(). * - * Since: 1.0 + * Since: 0.8.6 */ void cogl_texture_multiple_rectangles (CoglHandle handle, From de114dead76af8e8cccf872dd87aeee838e9e7e8 Mon Sep 17 00:00:00 2001 From: Neil Roberts Date: Thu, 27 Nov 2008 16:44:39 +0000 Subject: [PATCH 28/43] Fix GLES 2 after the multiple-texture-rectangle branch merge The GLES 2 wrapper needs to set up some state before each draw. Previously this was acheived by wrapping glDrawArrays. Since the multiple-texture-rectangle branch merge, glDrawElements is used instead so we also need a wrapper for that. It was also directly calling glBindTexture. GLES 2 uses a wrapper for this function so that it can cope with GL_ALPHA format textures. The format of the current texture needs to be stored as well as the target and object number for this to work. --- clutter/cogl/gles/cogl-context.h | 1 + clutter/cogl/gles/cogl-gles2-wrapper.c | 20 ++++++++++++++++++-- clutter/cogl/gles/cogl-gles2-wrapper.h | 4 +++- clutter/cogl/gles/cogl-texture.c | 7 ++++++- 4 files changed, 28 insertions(+), 4 deletions(-) diff --git a/clutter/cogl/gles/cogl-context.h b/clutter/cogl/gles/cogl-context.h index 5d835712a..92b8b96a2 100644 --- a/clutter/cogl/gles/cogl-context.h +++ b/clutter/cogl/gles/cogl-context.h @@ -72,6 +72,7 @@ typedef struct can be flushed */ GLuint texture_current; GLenum texture_target; + GLenum texture_format; /* Framebuffer objects */ GArray *fbo_handles; diff --git a/clutter/cogl/gles/cogl-gles2-wrapper.c b/clutter/cogl/gles/cogl-gles2-wrapper.c index fea76500e..d43ad21da 100644 --- a/clutter/cogl/gles/cogl-gles2-wrapper.c +++ b/clutter/cogl/gles/cogl-gles2-wrapper.c @@ -891,8 +891,8 @@ cogl_gles2_do_set_uniform (GLint location, CoglBoxedValue *value) } } -void -cogl_wrap_glDrawArrays (GLenum mode, GLint first, GLsizei count) +static void +cogl_wrap_prepare_for_draw (void) { CoglGles2WrapperProgram *program; @@ -999,9 +999,25 @@ cogl_wrap_glDrawArrays (GLenum mode, GLint first, GLsizei count) w->dirty_custom_uniforms = 0; } +} + +void +cogl_wrap_glDrawArrays (GLenum mode, GLint first, GLsizei count) +{ + cogl_wrap_prepare_for_draw (); + glDrawArrays (mode, first, count); } +void +cogl_wrap_glDrawElements (GLenum mode, GLsizei count, GLenum type, + const GLvoid *indices) +{ + cogl_wrap_prepare_for_draw (); + + glDrawElements (mode, count, type, indices); +} + void cogl_gles2_wrapper_bind_texture (GLenum target, GLuint texture, GLenum internal_format) diff --git a/clutter/cogl/gles/cogl-gles2-wrapper.h b/clutter/cogl/gles/cogl-gles2-wrapper.h index ddf181e92..7e7472c58 100644 --- a/clutter/cogl/gles/cogl-gles2-wrapper.h +++ b/clutter/cogl/gles/cogl-gles2-wrapper.h @@ -250,7 +250,8 @@ void cogl_wrap_glFogx (GLenum pname, GLfixed param); void cogl_wrap_glFogxv (GLenum pname, const GLfixed *params); void cogl_wrap_glDrawArrays (GLenum mode, GLint first, GLsizei count); - +void cogl_wrap_glDrawElements (GLenum mode, GLsizei count, GLenum type, + const GLvoid *indices); void cogl_wrap_glTexParameteri (GLenum target, GLenum pname, GLfloat param); void cogl_gles2_wrapper_bind_texture (GLenum target, GLuint texture, @@ -274,6 +275,7 @@ void _cogl_gles2_clear_cache_for_program (CoglHandle program); #define cogl_wrap_glClearColorx glClearColorx #define cogl_wrap_glDrawArrays glDrawArrays +#define cogl_wrap_glDrawElements glDrawElements #define cogl_wrap_glPushMatrix glPushMatrix #define cogl_wrap_glPopMatrix glPopMatrix #define cogl_wrap_glMatrixMode glMatrixMode diff --git a/clutter/cogl/gles/cogl-texture.c b/clutter/cogl/gles/cogl-texture.c index 915e82b23..4949afa1a 100644 --- a/clutter/cogl/gles/cogl-texture.c +++ b/clutter/cogl/gles/cogl-texture.c @@ -44,6 +44,7 @@ #define glTexCoordPointer cogl_wrap_glTexCoordPointer #define glColorPointer cogl_wrap_glColorPointer #define glDrawArrays cogl_wrap_glDrawArrays +#define glDrawElements cogl_wrap_glDrawElements #define glTexParameteri cogl_wrap_glTexParameteri /* @@ -2094,7 +2095,9 @@ _cogl_texture_flush_vertices (void) GE( glTexCoordPointer (2, GL_FLOAT, sizeof (CoglTextureGLVertex), p->t ) ); - GE( glBindTexture (ctx->texture_target, ctx->texture_current) ); + GE( cogl_gles2_wrapper_bind_texture (ctx->texture_target, + ctx->texture_current, + ctx->texture_format) ); GE( glDrawElements (GL_TRIANGLES, needed_indices, GL_UNSIGNED_SHORT, @@ -2284,6 +2287,7 @@ _cogl_texture_quad_sw (CoglTexture *tex, _cogl_texture_flush_vertices (); ctx->texture_target = tex->gl_target; ctx->texture_current = gl_handle; + ctx->texture_format = tex->gl_intformat; _cogl_texture_add_quad_vertices (COGL_FIXED_TO_FLOAT (slice_qx1), COGL_FIXED_TO_FLOAT (slice_qy1), @@ -2328,6 +2332,7 @@ _cogl_texture_quad_hw (CoglTexture *tex, _cogl_texture_flush_vertices (); ctx->texture_target = tex->gl_target; ctx->texture_current = gl_handle; + ctx->texture_format = tex->gl_intformat; /* Don't include the waste in the texture coordinates */ x_span = &g_array_index (tex->slice_x_spans, CoglTexSliceSpan, 0); From e93c266647e0d828459911a0999f342a975158b6 Mon Sep 17 00:00:00 2001 From: Neil Roberts Date: Tue, 13 Jan 2009 17:52:38 +0000 Subject: [PATCH 29/43] [clutter-text] Don't allow control characters to be inserted If an unbound control key is pressed (such as Ctrl+R) it would insert a rectangle into the text. Also zero is considered a valid unicode character by g_unichar_validate so pressing a key such as shift would cause the current selection to be deleted. The character isn't actually inserted because insert_unichar disallows zeroes. --- clutter/clutter-text.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/clutter/clutter-text.c b/clutter/clutter-text.c index 76721a6d2..c5f51773c 100644 --- a/clutter/clutter-text.c +++ b/clutter/clutter-text.c @@ -1017,7 +1017,9 @@ clutter_text_key_press (ClutterActor *actor, if (key_unichar == '\r') key_unichar = '\n'; - if (g_unichar_validate (key_unichar)) + if (key_unichar == '\n' || + (g_unichar_validate (key_unichar) && + !g_unichar_iscntrl (key_unichar))) { /* truncate the eventual selection so that the * Unicode character can replace it From b57c7e12d43e7891ef3125dc03e396c5a24281aa Mon Sep 17 00:00:00 2001 From: Neil Roberts Date: Tue, 13 Jan 2009 18:42:50 +0000 Subject: [PATCH 30/43] [clutter-text] Fix offset_to_bytes to work when pos == 0 The old function ended up returning the length of the string when pos was zero. This caused it to insert characters at the end when the cursor was at the beginning of the string. --- clutter/clutter-text.c | 25 +++++-------------------- 1 file changed, 5 insertions(+), 20 deletions(-) diff --git a/clutter/clutter-text.c b/clutter/clutter-text.c index c5f51773c..515252f57 100644 --- a/clutter/clutter-text.c +++ b/clutter/clutter-text.c @@ -202,31 +202,16 @@ static gint offset_to_bytes (const gchar *text, gint pos) { - gchar *c = NULL; - gint i, j, len; + const gchar *ptr; if (pos < 0) return strlen (text); - c = g_utf8_next_char (text); - j = 1; - len = strlen (text); + /* Loop over each character in the string until we either reach the + end or the requested position */ + for (ptr = text; *ptr && pos-- > 0; ptr = g_utf8_next_char (ptr)); - for (i = 0; i < len; i++) - { - if (&text[i] == c) - { - if (j == pos) - break; - else - { - c = g_utf8_next_char (c); - j++; - } - } - } - - return i; + return ptr - text; } #define bytes_to_offset(t,p) (g_utf8_pointer_to_offset ((t), (t) + (p))) From ffc15e0962a0b24afce1ff08eab13537fe23eadc Mon Sep 17 00:00:00 2001 From: Neil Roberts Date: Wed, 14 Jan 2009 11:12:02 +0000 Subject: [PATCH 31/43] [clutter-text] Fix x-position of cursor when moving up or down ClutterText already has code to try to preserve the x position when moving up or down. A target x-position is stored and the cursor is positioned at the nearest point to that in the appropriate line when up or down is pressed. However the target position was never cleared so it would always target the x-position of the cursor from the first time you pressed up or down. To fix this the patch clears the target position in set_position and then sets it after the call in real_move_up/down. That way pressing up or down sets the target position and any other movement will clear it. To get an index for the pixel position in the line pango_layout_line_x_to_index is used. However when x is greater than the length of the line then the index before the last grapheme is returned which was causing it to jump to the penultimate character. The patch makes it add on the trailing value so that it will jump to the last character. --- clutter/clutter-text.c | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/clutter/clutter-text.c b/clutter/clutter-text.c index 515252f57..94229694d 100644 --- a/clutter/clutter-text.c +++ b/clutter/clutter-text.c @@ -1278,7 +1278,7 @@ clutter_text_real_move_up (ClutterText *self, PangoLayoutLine *layout_line; PangoLayout *layout; gint line_no; - gint index_; + gint index_, trailing; gint x; layout = clutter_text_get_layout (self); @@ -1298,21 +1298,23 @@ clutter_text_real_move_up (ClutterText *self, if (priv->x_pos != -1) x = priv->x_pos; - else - priv->x_pos = x; layout_line = pango_layout_get_line_readonly (layout, line_no); if (!layout_line) return FALSE; - pango_layout_line_x_to_index (layout_line, x, &index_, NULL); + pango_layout_line_x_to_index (layout_line, x, &index_, &trailing); { gint pos = bytes_to_offset (priv->text, index_); - clutter_text_set_cursor_position (self, pos); + clutter_text_set_cursor_position (self, pos + trailing); } + /* Store the target x position to avoid drifting left and right when + moving the cursor up and down */ + priv->x_pos = x; + if (!(priv->selectable && (modifiers & CLUTTER_SHIFT_MASK))) clutter_text_clear_selection (self); @@ -1329,7 +1331,7 @@ clutter_text_real_move_down (ClutterText *self, PangoLayoutLine *layout_line; PangoLayout *layout; gint line_no; - gint index_; + gint index_, trailing; gint x; layout = clutter_text_get_layout (self); @@ -1345,21 +1347,23 @@ clutter_text_real_move_down (ClutterText *self, if (priv->x_pos != -1) x = priv->x_pos; - else - priv->x_pos = x; layout_line = pango_layout_get_line_readonly (layout, line_no + 1); if (!layout_line) return FALSE; - pango_layout_line_x_to_index (layout_line, x, &index_, NULL); + pango_layout_line_x_to_index (layout_line, x, &index_, &trailing); { gint pos = bytes_to_offset (priv->text, index_); - clutter_text_set_cursor_position (self, pos); + clutter_text_set_cursor_position (self, pos + trailing); } + /* Store the target x position to avoid drifting left and right when + moving the cursor up and down */ + priv->x_pos = x; + if (!(priv->selectable && (modifiers & CLUTTER_SHIFT_MASK))) clutter_text_clear_selection (self); @@ -3301,6 +3305,10 @@ clutter_text_set_cursor_position (ClutterText *self, else priv->position = position; + /* Forget the target x position so that it will be recalculated next + time the cursor is moved up or down */ + priv->x_pos = -1; + if (CLUTTER_ACTOR_IS_VISIBLE (self)) clutter_actor_queue_redraw (CLUTTER_ACTOR (self)); } From c83d955af3848d75555a917ece0b7da6cd71d945 Mon Sep 17 00:00:00 2001 From: Emmanuele Bassi Date: Wed, 14 Jan 2009 14:34:35 +0000 Subject: [PATCH 32/43] Fix compilation warning Declare the width and height variables as unsigned ints, in order to match the required arguments for clutter_actor_get_size(). --- tests/interactive/test-depth.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/interactive/test-depth.c b/tests/interactive/test-depth.c index 34c024ede..02e5e8bce 100644 --- a/tests/interactive/test-depth.c +++ b/tests/interactive/test-depth.c @@ -26,7 +26,7 @@ raise_top (gpointer ignored) static ClutterActor * clone_box (ClutterTexture *original) { - gint width, height; + guint width, height; ClutterActor *group; ClutterActor *clone; From 0e1bbcdc02a751f6024d4da9db3b4afba51dfa4d Mon Sep 17 00:00:00 2001 From: Emmanuele Bassi Date: Wed, 14 Jan 2009 15:03:30 +0000 Subject: [PATCH 33/43] Add declaration of clutter_binding_pool_get_type() The function is automagically created by G_DEFINE_TYPE(), but it should also be declared in the header. --- clutter/clutter-binding-pool.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/clutter/clutter-binding-pool.h b/clutter/clutter-binding-pool.h index bde939d1d..fd85f2664 100644 --- a/clutter/clutter-binding-pool.h +++ b/clutter/clutter-binding-pool.h @@ -68,6 +68,8 @@ typedef gboolean (* ClutterBindingActionFunc) (GObject *gobject, guint key_val, ClutterModifierType modifiers); +GType clutter_binding_pool_get_type (void) G_GNUC_CONST; + ClutterBindingPool * clutter_binding_pool_new (const gchar *name); ClutterBindingPool * clutter_binding_pool_get_for_class (gpointer klass); ClutterBindingPool * clutter_binding_pool_find (const gchar *name); From df62a037b00ca24deceb74d3ea0d26bdc94c4194 Mon Sep 17 00:00:00 2001 From: Emmanuele Bassi Date: Wed, 14 Jan 2009 15:04:28 +0000 Subject: [PATCH 34/43] Fix compile warning for a possible uninitialized variable --- clutter/glx/clutter-glx-texture-pixmap.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clutter/glx/clutter-glx-texture-pixmap.c b/clutter/glx/clutter-glx-texture-pixmap.c index 0dfe23941..ecc6e8dd9 100644 --- a/clutter/glx/clutter-glx-texture-pixmap.c +++ b/clutter/glx/clutter-glx-texture-pixmap.c @@ -320,7 +320,7 @@ create_cogl_texture (ClutterTexture *texture, CoglHandle handle; gboolean using_rectangle; GLint gl_format; - CoglPixelFormat cogl_format; + CoglPixelFormat cogl_format = COGL_PIXEL_FORMAT_RGBA_8888; guint depth; g_object_get (G_OBJECT (texture_glx), "pixmap-depth", &depth, NULL); From 1cac3d91f9fc84bd11636f19ac220158490c531f Mon Sep 17 00:00:00 2001 From: Emmanuele Bassi Date: Wed, 14 Jan 2009 15:05:03 +0000 Subject: [PATCH 35/43] Add unused symbols Append the newly added ClutterBindingPool symbols and clutter_stage_ensure_viewport() to the API reference. --- doc/reference/clutter/clutter-sections.txt | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/doc/reference/clutter/clutter-sections.txt b/doc/reference/clutter/clutter-sections.txt index 6f3864908..34b9d8928 100644 --- a/doc/reference/clutter/clutter-sections.txt +++ b/doc/reference/clutter/clutter-sections.txt @@ -547,6 +547,7 @@ clutter_stage_show_cursor clutter_stage_hide_cursor clutter_stage_get_actor_at_pos clutter_stage_ensure_current +clutter_stage_ensure_viewport clutter_stage_queue_redraw clutter_stage_event clutter_stage_set_key_focus @@ -1761,4 +1762,12 @@ clutter_binding_pool_unblock_action clutter_binding_pool_activate + + +CLUTTER_BINDING_POOL +CLUTTER_IS_BINDING_POOL +CLUTTER_TYPE_BINDING_POOL + + +clutter_binding_pool_get_type From d454bfcc87e594eeee601755f53b1315fc2da093 Mon Sep 17 00:00:00 2001 From: Neil Roberts Date: Wed, 14 Jan 2009 13:37:31 +0000 Subject: [PATCH 36/43] [ClutterStageX11] Remove the handling_configure flag Since Clutter changed to using a layout scheme the handling_configure flag no longer works because the allocate method is not invoked immediately during the call to set_size from the ConfigureNotify handler. However it is also no longer neccessary because the resizes are effectively batched up until a relayout is run so it won't cause an infinite loop of resize and notify events anyway. --- clutter/x11/clutter-event-x11.c | 8 -------- clutter/x11/clutter-stage-x11.c | 16 +--------------- clutter/x11/clutter-stage-x11.h | 1 - 3 files changed, 1 insertion(+), 24 deletions(-) diff --git a/clutter/x11/clutter-event-x11.c b/clutter/x11/clutter-event-x11.c index b83a0b2f3..0f75daf2c 100644 --- a/clutter/x11/clutter-event-x11.c +++ b/clutter/x11/clutter-event-x11.c @@ -427,12 +427,6 @@ event_translate (ClutterBackend *backend, case ConfigureNotify: if (!stage_x11->is_foreign_xwin) { - /* Set a flag so that the stage will know the actor is being - resized in response to the window size changing as - opposed to a request from the application. This prevents - it from trying to resize the window again */ - stage_x11->handling_configure = TRUE; - CLUTTER_NOTE (BACKEND, "%s: ConfigureNotify[%x] (%d, %d)", G_STRLOC, (unsigned int) stage_x11->xwin, @@ -443,8 +437,6 @@ event_translate (ClutterBackend *backend, xevent->xconfigure.width, xevent->xconfigure.height); - stage_x11->handling_configure = FALSE; - /* the resize process is complete, so we can ask the stage * to set up the GL viewport with the new size */ diff --git a/clutter/x11/clutter-stage-x11.c b/clutter/x11/clutter-stage-x11.c index d01d8e2b1..725a75650 100644 --- a/clutter/x11/clutter-stage-x11.c +++ b/clutter/x11/clutter-stage-x11.c @@ -270,21 +270,8 @@ clutter_stage_x11_allocate (ClutterActor *self, stage_x11->xwin_width = new_width; stage_x11->xwin_height = new_height; - /* The 'handling_configure' flag below is used to prevent the - window from being resized again in response to a - ConfigureNotify event. Normally this will not be a problem - because the window will be resized to xwin_width and - xwin_height so the above test will prevent it from resizing - the window a second time. However if the stage is resized - multiple times without the events being processed in between - (eg, when calling g_object_set to set both width and height) - then there will be multiple ConfigureNotify events in the - queue. Handling the first event will undo the work of setting - the second property which will cause it to keep generating - events in an infinite loop. See bug #810 */ if (stage_x11->xwin != None && - !stage_x11->is_foreign_xwin && - !stage_x11->handling_configure) + !stage_x11->is_foreign_xwin) { CLUTTER_NOTE (BACKEND, "%s: XResizeWindow[%x] (%d, %d)", G_STRLOC, @@ -577,7 +564,6 @@ clutter_stage_x11_init (ClutterStageX11 *stage) stage->is_foreign_xwin = FALSE; stage->fullscreen_on_map = FALSE; - stage->handling_configure = FALSE; stage->is_cursor_visible = TRUE; stage->title = NULL; diff --git a/clutter/x11/clutter-stage-x11.h b/clutter/x11/clutter-stage-x11.h index 229f058e1..c1a913950 100644 --- a/clutter/x11/clutter-stage-x11.h +++ b/clutter/x11/clutter-stage-x11.h @@ -47,7 +47,6 @@ struct _ClutterStageX11 guint is_foreign_xwin : 1; guint fullscreen_on_map : 1; - guint handling_configure : 1; guint is_cursor_visible : 1; Display *xdpy; From f1b15efcdc6ac2efd15d2946c93a1cb2a3a5b063 Mon Sep 17 00:00:00 2001 From: Robert Bragg Date: Thu, 8 Jan 2009 18:54:48 +0000 Subject: [PATCH 37/43] [tests] Adds a flowery clutter_cairo_texture unit test This is simply a copy of flowers.c from the old clutter-cairo repo --- tests/interactive/Makefile.am | 3 +- .../interactive/test-clutter-cairo-flowers.c | 212 ++++++++++++++++++ 2 files changed, 214 insertions(+), 1 deletion(-) create mode 100644 tests/interactive/test-clutter-cairo-flowers.c diff --git a/tests/interactive/Makefile.am b/tests/interactive/Makefile.am index 33b371437..08a2be02d 100644 --- a/tests/interactive/Makefile.am +++ b/tests/interactive/Makefile.am @@ -39,7 +39,8 @@ UNIT_TESTS = \ test-easing.c \ test-binding-pool.c \ test-text.c \ - test-text-field.c + test-text-field.c \ + test-clutter-cairo-flowers.c if X11_TESTS UNIT_TESTS += test-pixmap.c diff --git a/tests/interactive/test-clutter-cairo-flowers.c b/tests/interactive/test-clutter-cairo-flowers.c new file mode 100644 index 000000000..c66531672 --- /dev/null +++ b/tests/interactive/test-clutter-cairo-flowers.c @@ -0,0 +1,212 @@ +/* + * Pretty cairo flower hack. + */ + +#include + +#include /* for sleep(), used for screenshots */ +#include +#include "math.h" + +#define PETAL_MIN 20 +#define PETAL_VAR 40 +#define N_FLOWERS 40 /* reduce if you have a small card */ + +typedef struct Flower +{ + ClutterActor *ctex; + gint x,y,rot,v,rv; +} +Flower; + +ClutterActor* +make_flower_actor (void) +{ + /* No science here, just a hack from toying */ + gint i, j; + + double colors[] = { + 0.71, 0.81, 0.83, + 1.0, 0.78, 0.57, + 0.64, 0.30, 0.35, + 0.73, 0.40, 0.39, + 0.91, 0.56, 0.64, + 0.70, 0.47, 0.45, + 0.92, 0.75, 0.60, + 0.82, 0.86, 0.85, + 0.51, 0.56, 0.67, + 1.0, 0.79, 0.58, + + }; + + gint size; + gint petal_size; + gint n_groups; /* Num groups of petals 1-3 */ + gint n_petals; /* num of petals 4 - 8 */ + gint pm1, pm2; + + gint idx, last_idx = -1; + + ClutterActor *ctex; + cairo_t *cr; + + petal_size = PETAL_MIN + rand() % PETAL_VAR; + size = petal_size * 8; + + n_groups = rand() % 3 + 1; + + ctex = clutter_cairo_texture_new (size, size); + + cr = clutter_cairo_texture_create (CLUTTER_CAIRO_TEXTURE (ctex)); + + cairo_set_tolerance (cr, 0.1); + + /* Clear */ + cairo_set_operator (cr, CAIRO_OPERATOR_CLEAR); + cairo_paint(cr); + cairo_set_operator (cr, CAIRO_OPERATOR_OVER); + + cairo_translate(cr, size/2, size/2); + + for (i=0; iy += flowers[i]->v; + flowers[i]->rot += flowers[i]->rv; + + if (flowers[i]->y > (gint)clutter_actor_get_height + (clutter_stage_get_default ())) + flowers[i]->y = -clutter_actor_get_height (flowers[i]->ctex); + + clutter_actor_set_position (flowers[i]->ctex, + flowers[i]->x, flowers[i]->y); + + clutter_actor_set_rotation (flowers[i]->ctex, + CLUTTER_Z_AXIS, + flowers[i]->rot, + clutter_actor_get_width (flowers[i]->ctex)/2, + clutter_actor_get_height (flowers[i]->ctex)/2, + 0); + } + + return TRUE; +} + +void foo(void) { g_usleep(10000000); } + +int +test_clutter_cairo_flowers_main (int argc, char **argv) +{ + int i; + ClutterActor *stage; + ClutterColor stage_color = { 0x0, 0x0, 0x0, 0xff }; + Flower *flowers[N_FLOWERS]; + + srand(time(NULL)); + + clutter_init (&argc, &argv); + + stage = clutter_stage_get_default (); + + clutter_stage_set_color (CLUTTER_STAGE (stage), + &stage_color); + + g_object_set(stage, "fullscreen", TRUE, NULL); + + for (i=0; i< N_FLOWERS; i++) + { + flowers[i] = g_new0(Flower, 1); + flowers[i]->ctex = make_flower_actor(); + flowers[i]->x = rand() % clutter_actor_get_width(stage) + - (PETAL_MIN+PETAL_VAR)*2; + flowers[i]->y = rand() % clutter_actor_get_height(stage); + flowers[i]->rv = rand() % 5 + 1; + flowers[i]->v = rand() % 10 + 2; + + clutter_group_add (CLUTTER_GROUP(stage), flowers[i]->ctex); + clutter_actor_set_position (flowers[i]->ctex, + flowers[i]->x, flowers[i]->y); + } + + g_timeout_add (50, tick, flowers); + + clutter_actor_show_all (CLUTTER_ACTOR (stage)); + + g_signal_connect (stage, "key-press-event", + G_CALLBACK (clutter_main_quit), + NULL); + + clutter_main(); + + return 1; +} + From 3e9e5a11da12e9b8e8cfbace8146e3b86231c5c9 Mon Sep 17 00:00:00 2001 From: Robert Bragg Date: Wed, 14 Jan 2009 15:18:05 +0000 Subject: [PATCH 38/43] [test-depth] cast width to gint when calculating -width/2 It was a fluke that this worked out due to how clutter_actor_set_depth internally converts the incorrect integer result to fixed point. --- tests/interactive/test-depth.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/interactive/test-depth.c b/tests/interactive/test-depth.c index 02e5e8bce..394398147 100644 --- a/tests/interactive/test-depth.c +++ b/tests/interactive/test-depth.c @@ -40,7 +40,7 @@ clone_box (ClutterTexture *original) clone = clutter_clone_texture_new (original); clutter_container_add_actor (CLUTTER_CONTAINER (group), clone); clutter_actor_set_rotation (clone, CLUTTER_Y_AXIS, 180, width/2, 0, 0); - clutter_actor_set_depth (clone, -width/2); + clutter_actor_set_depth (clone, -(gint)width/2); clone = clutter_clone_texture_new (original); clutter_container_add_actor (CLUTTER_CONTAINER (group), clone); @@ -57,13 +57,13 @@ clone_box (ClutterTexture *original) clone = clutter_clone_texture_new (original); clutter_container_add_actor (CLUTTER_CONTAINER (group), clone); clutter_actor_set_rotation (clone, CLUTTER_X_AXIS, 90, 0, 0, 0); - clutter_actor_set_depth (clone, -width/2); + clutter_actor_set_depth (clone, -(gint)width/2); clutter_actor_set_position (clone, 0, height); clone = clutter_clone_texture_new (original); clutter_container_add_actor (CLUTTER_CONTAINER (group), clone); clutter_actor_set_rotation (clone, CLUTTER_X_AXIS, 90, 0, 0, 0); - clutter_actor_set_depth (clone, -width/2); + clutter_actor_set_depth (clone, -(gint)width/2); clutter_actor_set_position (clone, 0, 0); clutter_actor_show_all (group); From 5d346cca5705c5c3fc21444b8c9c758f55b0bc67 Mon Sep 17 00:00:00 2001 From: Emmanuele Bassi Date: Wed, 14 Jan 2009 15:30:10 +0000 Subject: [PATCH 39/43] Emit ::load-finished for every texture load The ::load-finished signal is emitted only when loading a texture using clutter_texture_set_from_file(). Since this breaks user expectations and consistency, we should also emit ::load-finished when loading a texture from image data. --- clutter/clutter-texture.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/clutter/clutter-texture.c b/clutter/clutter-texture.c index a3b1bd3f8..d081b3889 100644 --- a/clutter/clutter-texture.c +++ b/clutter/clutter-texture.c @@ -1270,6 +1270,8 @@ clutter_texture_set_from_data (ClutterTexture *texture, cogl_texture_unref (new_texture); + g_signal_emit (texture, texture_signals[LOAD_FINISHED], 0, error); + return TRUE; } From 41386a5f72b389956c363fa06669f6d554d73b53 Mon Sep 17 00:00:00 2001 From: Emmanuele Bassi Date: Wed, 7 Jan 2009 18:30:46 +0000 Subject: [PATCH 40/43] Remove the Effects API The Effects API and all related symbols have been superceded by the newly added Animation API and clutter_actor_animate(). This commit removes the Effects implementation, the documentation and the interactive test/example code. --- clutter/Makefile.am | 2 - clutter/clutter-effect.c | 848 --------------------- clutter/clutter-effect.h | 162 ---- clutter/clutter.h | 1 - doc/reference/clutter/clutter-sections.txt | 33 - tests/interactive/Makefile.am | 1 - tests/interactive/test-effects.c | 95 --- 7 files changed, 1142 deletions(-) delete mode 100644 clutter/clutter-effect.c delete mode 100644 clutter/clutter-effect.h delete mode 100644 tests/interactive/test-effects.c diff --git a/clutter/Makefile.am b/clutter/Makefile.am index 2f325161b..ecb3e777f 100644 --- a/clutter/Makefile.am +++ b/clutter/Makefile.am @@ -64,7 +64,6 @@ source_h = \ $(srcdir)/clutter-color.h \ $(srcdir)/clutter-container.h \ $(srcdir)/clutter-deprecated.h \ - $(srcdir)/clutter-effect.h \ $(srcdir)/clutter-event.h \ $(srcdir)/clutter-feature.h \ $(srcdir)/clutter-fixed.h \ @@ -155,7 +154,6 @@ source_c = \ clutter-clone-texture.c \ clutter-color.c \ clutter-container.c \ - clutter-effect.c \ clutter-enum-types.c \ clutter-event.c \ clutter-feature.c \ diff --git a/clutter/clutter-effect.c b/clutter/clutter-effect.c deleted file mode 100644 index 64fd25b4a..000000000 --- a/clutter/clutter-effect.c +++ /dev/null @@ -1,848 +0,0 @@ -/* - * Clutter. - * - * An OpenGL based 'interactive canvas' library. - * - * Authored By Matthew Allum - * Jorn Baayen - * Emmanuele Bassi - * - * Copyright (C) 2006 OpenedHand - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -/** - * SECTION:clutter-effect - * @short_description: Utility Class for basic visual effects - * - * The #ClutterEffectTemplate class provides a simple API for applying - * pre-defined effects to a single actor. It works as a wrapper around - * the #ClutterBehaviour objects - * - * Since: 0.4 - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include - -#include "clutter-alpha.h" -#include "clutter-main.h" -#include "clutter-marshal.h" -#include "clutter-private.h" -#include "clutter-debug.h" -#include "clutter-behaviour-depth.h" -#include "clutter-behaviour-ellipse.h" -#include "clutter-behaviour-opacity.h" -#include "clutter-behaviour-path.h" -#include "clutter-behaviour-rotate.h" -#include "clutter-behaviour-scale.h" - -#include "clutter-effect.h" - -typedef struct ClutterEffectClosure -{ - ClutterActor *actor; - ClutterTimeline *timeline; - ClutterAlpha *alpha; - ClutterBehaviour *behave; - - gulong signal_id; - - ClutterEffectCompleteFunc completed_func; - gpointer completed_data; - ClutterEffectTemplate *template; -} -ClutterEffectClosure; - -G_DEFINE_TYPE (ClutterEffectTemplate, clutter_effect_template, G_TYPE_OBJECT); - -#define EFFECT_TEMPLATE_PRIVATE(o) \ - (G_TYPE_INSTANCE_GET_PRIVATE ((o), \ - CLUTTER_TYPE_EFFECT_TEMPLATE, \ - ClutterEffectTemplatePrivate)) - -struct _ClutterEffectTemplatePrivate -{ - ClutterTimeline *timeline; - - guint do_clone : 1; - guint dirty : 1; - - ClutterAlphaFunc alpha_func; - gpointer alpha_data; - GDestroyNotify alpha_notify; -}; - -enum -{ - PROP_0, - - PROP_TIMELINE, - PROP_DO_CLONE -}; - -static void -clutter_effect_template_finalize (GObject *gobject) -{ - ClutterEffectTemplate *template = CLUTTER_EFFECT_TEMPLATE (gobject); - ClutterEffectTemplatePrivate *priv = template->priv; - - if (priv->alpha_notify) - { - priv->alpha_notify (priv->alpha_data); - priv->alpha_notify = NULL; - } - - priv->alpha_data = NULL; - priv->alpha_func = NULL; - - G_OBJECT_CLASS (clutter_effect_template_parent_class)->finalize (gobject); -} - -static void -clutter_effect_template_dispose (GObject *object) -{ - ClutterEffectTemplate *template; - ClutterEffectTemplatePrivate *priv; - - template = CLUTTER_EFFECT_TEMPLATE (object); - priv = template->priv; - - if (priv->timeline) - { - g_object_unref (priv->timeline); - priv->timeline = NULL; - } - - G_OBJECT_CLASS (clutter_effect_template_parent_class)->dispose (object); -} - -static void -clutter_effect_template_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - ClutterEffectTemplate *template; - ClutterEffectTemplatePrivate *priv; - - template = CLUTTER_EFFECT_TEMPLATE (object); - priv = template->priv; - - switch (prop_id) - { - case PROP_TIMELINE: - priv->timeline = g_value_dup_object (value); - break; - case PROP_DO_CLONE: - clutter_effect_template_set_timeline_clone (template, - g_value_get_boolean (value)); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -clutter_effect_template_get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec) -{ - ClutterEffectTemplate *template; - ClutterEffectTemplatePrivate *priv; - - template = CLUTTER_EFFECT_TEMPLATE (object); - priv = template->priv; - - switch (prop_id) - { - case PROP_TIMELINE: - g_value_set_object (value, priv->timeline); - break; - case PROP_DO_CLONE: - g_value_set_boolean (value, priv->do_clone); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -clutter_effect_template_class_init (ClutterEffectTemplateClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - g_type_class_add_private (klass, sizeof (ClutterEffectTemplatePrivate)); - - object_class->finalize = clutter_effect_template_finalize; - object_class->dispose = clutter_effect_template_dispose; - object_class->set_property = clutter_effect_template_set_property; - object_class->get_property = clutter_effect_template_get_property; - - /** - * ClutterEffectTemplate:timeline: - * - * #ClutterTimeline to be used by the template - * - * Since: 0.4 - */ - g_object_class_install_property - (object_class, - PROP_TIMELINE, - g_param_spec_object ("timeline", - "Timeline", - "Timeline to use as a reference for the Template", - CLUTTER_TYPE_TIMELINE, - G_PARAM_CONSTRUCT_ONLY | - CLUTTER_PARAM_READWRITE)); - - /** - * ClutterEffectTemplate:clone: - * - * Controls if effects should clone or reference the templated timeline - * - * Since: 0.6 - */ - g_object_class_install_property - (object_class, - PROP_DO_CLONE, - g_param_spec_boolean ("clone", - "Clone", - "controls if effects should clone or reference the templated timeline", - TRUE, - CLUTTER_PARAM_READWRITE)); - -} - -static void -clutter_effect_template_init (ClutterEffectTemplate *self) -{ - self->priv = EFFECT_TEMPLATE_PRIVATE (self); - - self->priv->do_clone = TRUE; - self->priv->dirty = TRUE; -} - -static void -clutter_effect_template_set_alpha_func (ClutterEffectTemplate *self, - ClutterAlphaFunc alpha_func, - gpointer alpha_data, - GDestroyNotify alpha_notify) -{ - ClutterEffectTemplatePrivate *priv; - - priv = self->priv; - - if (priv->alpha_notify) - { - priv->alpha_notify (priv->alpha_data); - priv->alpha_notify = NULL; - } - - priv->alpha_data = alpha_data; - priv->alpha_notify = alpha_notify; - priv->alpha_func = alpha_func; - - priv->dirty = FALSE; -} - -/** - * clutter_effect_template_set_timeline_clone: - * @template_: A #ClutterEffectTemplate - * @setting: A boolean indicating if effects should clone the timeline. - * - * Sets if effects using this template should make a copy of the - * templates timeline (default) or reference the effects timeline. - * - * Since: 0.6 - */ -void -clutter_effect_template_set_timeline_clone (ClutterEffectTemplate *template_, - gboolean setting) -{ - g_return_if_fail (CLUTTER_IS_EFFECT_TEMPLATE (template_)); - - if (template_->priv->do_clone != setting) - { - template_->priv->do_clone = setting; - - g_object_notify (G_OBJECT (template_), "clone"); - } -} - -/** - * clutter_effect_template_get_timeline_clone: - * @template_: A #ClutterEffectTemplate - * - * Gets whether timelines should be cloned when creating a new - * effect or just referenced. - * - * Return value: %TRUE if the templates timeline is to be cloned. - * - * Since: 0.6 - */ -gboolean -clutter_effect_template_get_timeline_clone (ClutterEffectTemplate *template_) -{ - g_return_val_if_fail (CLUTTER_IS_EFFECT_TEMPLATE (template_), FALSE); - - return template_->priv->do_clone; -} - - -/** - * clutter_effect_template_new: - * @timeline: A #ClutterTimeline for the template (will be cloned) - * @alpha_func: An alpha func to use for the template. - * - * Creates a new #ClutterEffectTemplate, to be used with the effects API. - * - * A #ClutterEffectTemplate binds a timeline and an alpha function and can - * be used as a template for multiple calls of clutter_effect_fade(), - * clutter_effect_move() and clutter_effect_scale(). - * - * This API is intended for simple animations involving a single actor; - * for more complex animations, you should see #ClutterBehaviour and the - * derived classes. - * - * Return value: a #ClutterEffectTemplate - * - * Since: 0.4 - */ -ClutterEffectTemplate* -clutter_effect_template_new (ClutterTimeline *timeline, - ClutterAlphaFunc alpha_func) -{ - ClutterEffectTemplate *retval; - - g_return_val_if_fail (CLUTTER_IS_TIMELINE (timeline), NULL); - g_return_val_if_fail (alpha_func != NULL, NULL); - - retval = g_object_new (CLUTTER_TYPE_EFFECT_TEMPLATE, - "timeline", timeline, - NULL); - - clutter_effect_template_set_alpha_func (retval, alpha_func, NULL, NULL); - - return retval; -} - -/** - * clutter_effect_template_new_full: - * @timeline: a #ClutterTimeline - * @alpha_func: an alpha function to use for the template - * @user_data: data to be passed to the alpha function, or %NULL - * @notify: function to be called when disposing the alpha function's use - * data, or %NULL - * - * Creates a new #ClutterEffectTemplate, to be used with the effects API. - * - * A #ClutterEffectTemplate binds a timeline and an alpha function and can - * be used as a template for multiple calls of clutter_effect_fade(), - * clutter_effect_move() and clutter_effect_scale(). - * - * This API is intended for simple animations involving a single actor; - * for more complex animations, you should see #ClutterBehaviour and the - * derived classes. - * - * This function is intended for language bindings only: if @notify is - * not %NULL it will be called to dispose of @user_data. - * - * Return value: the newly created #ClutterEffectTemplate object - * - * Since: 0.4 - */ -ClutterEffectTemplate * -clutter_effect_template_new_full (ClutterTimeline *timeline, - ClutterAlphaFunc alpha_func, - gpointer user_data, - GDestroyNotify notify) -{ - ClutterEffectTemplate *retval; - - g_return_val_if_fail (CLUTTER_IS_TIMELINE (timeline), NULL); - g_return_val_if_fail (alpha_func != NULL, NULL); - - retval = g_object_new (CLUTTER_TYPE_EFFECT_TEMPLATE, - "timeline", timeline, - NULL); - - clutter_effect_template_set_alpha_func (retval, - alpha_func, - user_data, notify); - - return retval; -} - -/** - * clutter_effect_template_new_for_duration: - * @msecs: the duration of the effects, in milliseconds - * @alpha_func: an alpha function to use for the template - * - * Creates a new #ClutterEffectTemplate, to be used with the effects API. - * - * A #ClutterEffectTemplate binds a timeline and an alpha function and can - * be used as a template for multiple calls of clutter_effect_fade(), - * clutter_effect_move() and clutter_effect_scale(). - * - * This API is intended for simple animations involving a single actor; - * for more complex animations, you should see #ClutterBehaviour and the - * derived classes. - * - * This function creates a #ClutterTimeline with a duration of @msecs - * milliseconds and transfers ownership of the timeline object to the - * returned #ClutterEffectTemplate. - * - * Return value: the newly created #ClutterEffectTemplate object - * - * Since: 0.6 - */ -ClutterEffectTemplate * -clutter_effect_template_new_for_duration (guint msecs, - ClutterAlphaFunc alpha_func) -{ - ClutterTimeline *timeline; - ClutterEffectTemplate *retval; - - g_return_val_if_fail (msecs > 0, NULL); - g_return_val_if_fail (alpha_func != NULL, NULL); - - timeline = clutter_timeline_new_for_duration (msecs); - retval = clutter_effect_template_new (timeline, alpha_func); - - /* the effect template takes ownership of the timeline */ - g_object_unref (timeline); - - return retval; -} - -/** - * clutter_effect_template_construct: - * @template_: a #ClutterEffectTemplate - * @timeline: a #ClutterTimeline - * @alpha_func: an alpha function to use for the template - * @user_data: data to be passed to the alpha function, or %NULL - * @notify: function to be called when disposing the alpha function's use - * data, or %NULL - * - * Constructs a #ClutterEffectTemplate, to be used with the effects API. - * - * This function can only be called once after the creation of @template_ - * and is only useful for language bindings. - * - * Since: 0.6 - */ -void -clutter_effect_template_construct (ClutterEffectTemplate *template_, - ClutterTimeline *timeline, - ClutterAlphaFunc alpha_func, - gpointer user_data, - GDestroyNotify notify) -{ - ClutterEffectTemplatePrivate *priv; - - g_return_if_fail (CLUTTER_IS_EFFECT_TEMPLATE (template_)); - g_return_if_fail (CLUTTER_IS_TIMELINE (timeline)); - g_return_if_fail (alpha_func != NULL); - - if (!template_->priv->dirty) - return; - - priv = template_->priv; - - if (priv->timeline) - g_object_unref (priv->timeline); - - priv->timeline = g_object_ref (timeline); - clutter_effect_template_set_alpha_func (template_, - alpha_func, - user_data, notify); -} - -static void -clutter_effect_closure_destroy (ClutterEffectClosure *c) -{ - g_signal_handler_disconnect (c->timeline, c->signal_id); - - g_object_unref (c->actor); - g_object_unref (c->template); - g_object_unref (c->behave); - g_object_unref (c->timeline); - - g_slice_free (ClutterEffectClosure, c); -} - -static ClutterEffectClosure * -clutter_effect_closure_new (ClutterEffectTemplate *template, - ClutterActor *actor, - GCallback complete) -{ - ClutterEffectClosure *c; - ClutterEffectTemplatePrivate *priv = EFFECT_TEMPLATE_PRIVATE(template); - - c = g_slice_new0(ClutterEffectClosure); - - g_object_ref (actor); - g_object_ref (template); - - c->template = template; - c->actor = actor; - - if (clutter_effect_template_get_timeline_clone (template)) - c->timeline = clutter_timeline_clone (priv->timeline); - else - { - c->timeline = priv->timeline; - g_object_ref (priv->timeline); - } - - c->alpha = clutter_alpha_new_full (c->timeline, - priv->alpha_func, - priv->alpha_data, - NULL); - - c->signal_id = - g_signal_connect (c->timeline, "completed", G_CALLBACK (complete), c); - - return c; -} - -static void -on_effect_complete (ClutterTimeline *timeline, - gpointer user_data) -{ - ClutterEffectClosure *c = (ClutterEffectClosure*)user_data; - - if (c->completed_func) - c->completed_func (c->actor, c->completed_data); - - clutter_effect_closure_destroy (c); -} - -/** - * clutter_effect_fade: - * @template_: A #ClutterEffectTemplate - * @actor: A #ClutterActor to apply the effect to. - * @opacity_end: Final opacity value to apply to actor - * @func: A #ClutterEffectCompleteFunc to call on effect - * completion or %NULL - * @data: Data to pass to supplied #ClutterEffectCompleteFunc - * or %NULL - * - * Simple effect for fading a single #ClutterActor. - * - * Return value: a #ClutterTimeline for the effect. Will be unrefed by - * the effect when completed. - * - * Since: 0.6 - */ -ClutterTimeline * -clutter_effect_fade (ClutterEffectTemplate *template_, - ClutterActor *actor, - guint8 opacity_end, - ClutterEffectCompleteFunc func, - gpointer data) -{ - ClutterEffectClosure *c; - guint8 opacity_start; - - c = clutter_effect_closure_new (template_, - actor, - G_CALLBACK (on_effect_complete)); - - c->completed_func = func; - c->completed_data = data; - - opacity_start = clutter_actor_get_opacity (actor); - - c->behave = clutter_behaviour_opacity_new (c->alpha, - opacity_start, - opacity_end); - - clutter_behaviour_apply (c->behave, actor); - clutter_timeline_start (c->timeline); - - return c->timeline; -} - -/** - * clutter_effect_depth: - * @template_: A #ClutterEffectTemplate - * @actor: A #ClutterActor to apply the effect to. - * @depth_end: Final depth value to apply to actor - * @func: A #ClutterEffectCompleteFunc to call on effect - * completion or %NULL - * @data: Data to pass to supplied #ClutterEffectCompleteFunc - * or %NULL - * - * Simple effect for changing the depth of a single #ClutterActor. - * - * Return value: a #ClutterTimeline for the effect. Will be unrefed by - * the effect when completed. - * - * Since: 0.6 - */ -ClutterTimeline * -clutter_effect_depth (ClutterEffectTemplate *template_, - ClutterActor *actor, - gint depth_end, - ClutterEffectCompleteFunc func, - gpointer data) -{ - ClutterEffectClosure *c; - gint depth_start; - - c = clutter_effect_closure_new (template_, - actor, - G_CALLBACK (on_effect_complete)); - - c->completed_func = func; - c->completed_data = data; - - depth_start = clutter_actor_get_depth (actor); - - c->behave = clutter_behaviour_depth_new (c->alpha, depth_start, depth_end); - - clutter_behaviour_apply (c->behave, actor); - clutter_timeline_start (c->timeline); - - return c->timeline; -} - -/** - * clutter_effect_move: - * @template_: A #ClutterEffectTemplate - * @actor: A #ClutterActor to apply the effect to. - * @x: X coordinate of the destination - * @y: Y coordinate of the destination - * @func: A #ClutterEffectCompleteFunc to call on effect - * completion or %NULL - * @data: Data to pass to supplied #ClutterEffectCompleteFunc - * or %NULL - * - * Simple effect for moving a single #ClutterActor along to a - * destination point. - * - * Return value: a #ClutterTimeline for the effect. Will be unreferenced by - * the effect when completed. - * - * Since: 0.6 - */ -ClutterTimeline * -clutter_effect_move (ClutterEffectTemplate *template_, - ClutterActor *actor, - gint x, - gint y, - ClutterEffectCompleteFunc func, - gpointer data) -{ - ClutterEffectClosure *c; - ClutterPath *path; - - c = clutter_effect_closure_new (template_, - actor, - G_CALLBACK (on_effect_complete)); - - c->completed_func = func; - c->completed_data = data; - - path = clutter_path_new (); - - clutter_path_add_move_to (path, - clutter_actor_get_x (actor), - clutter_actor_get_y (actor)); - clutter_path_add_line_to (path, x, y); - - c->behave = clutter_behaviour_path_new (c->alpha, path); - - clutter_behaviour_apply (c->behave, actor); - clutter_timeline_start (c->timeline); - - return c->timeline; -} -/** - * clutter_effect_path: - * @template_: A #ClutterEffectTemplate - * @actor: A #ClutterActor to apply the effect to. - * @knots: An array of #ClutterKnots representing path for the actor - * @n_knots: Number of #ClutterKnots in passed array. - * @func: A #ClutterEffectCompleteFunc to call on effect - * completion or %NULL - * @data: Data to pass to supplied #ClutterEffectCompleteFunc - * or %NULL - * - * Simple effect for moving a single #ClutterActor along a path. - * - * Return value: a #ClutterTimeline for the effect. Will be unreferenced by - * the effect when completed. - * - * Since: 0.6 - */ -ClutterTimeline * -clutter_effect_path (ClutterEffectTemplate *template_, - ClutterActor *actor, - const ClutterKnot *knots, - guint n_knots, - ClutterEffectCompleteFunc func, - gpointer data) -{ - ClutterEffectClosure *c; - ClutterPath *path; - guint i; - - c = clutter_effect_closure_new (template_, - actor, - G_CALLBACK (on_effect_complete)); - - path = clutter_path_new (); - - c->completed_func = func; - c->completed_data = data; - - path = clutter_path_new (); - - if (n_knots) - { - clutter_actor_set_position (actor, knots[0].x, knots[0].y); - clutter_path_add_move_to (path, knots[0].x, knots[0].y); - - for (i = 1; i < n_knots; i++) - clutter_path_add_line_to (path, knots[i].x, knots[i].y); - } - - c->behave = clutter_behaviour_path_new (c->alpha, path); - - clutter_behaviour_apply (c->behave, actor); - clutter_timeline_start (c->timeline); - - return c->timeline; -} - -/** - * clutter_effect_scale: - * @template_: A #ClutterEffectTemplate - * @actor: A #ClutterActor to apply the effect to. - * @x_scale_end: Final X axis scale factor to apply to actor - * @y_scale_end: Final Y axis scale factor to apply to actor - * @func: A #ClutterEffectCompleteFunc to call on effect - * completion or NULL - * @data: Data to pass to supplied #ClutterEffectCompleteFunc - * or NULL - * - * Simple effect for scaling a single #ClutterActor. - * - * Return value: a #ClutterTimeline for the effect. Will be unreferenced by - * the effect when completed. - * - * Since: 0.6 - */ -ClutterTimeline * -clutter_effect_scale (ClutterEffectTemplate *template_, - ClutterActor *actor, - gdouble x_scale_end, - gdouble y_scale_end, - ClutterEffectCompleteFunc func, - gpointer data) -{ - ClutterEffectClosure *c; - gdouble x_scale_start, y_scale_start; - - c = clutter_effect_closure_new (template_, - actor, - G_CALLBACK (on_effect_complete)); - - c->completed_func = func; - c->completed_data = data; - - clutter_actor_get_scale (actor, &x_scale_start, &y_scale_start); - c->behave = clutter_behaviour_scale_new (c->alpha, - x_scale_start, y_scale_start, - x_scale_end, y_scale_end); - - clutter_behaviour_apply (c->behave, actor); - clutter_timeline_start (c->timeline); - - return c->timeline; -} - -/** - * clutter_effect_rotate: - * @template_: a #ClutterEffectTemplate - * @actor: a #ClutterActor to apply the effect to. - * @axis: axis of rotation - * @angle: final angle to apply to actor - * @center_x: position on X axis to rotate about. - * @center_y: position on Y axis to rotate about. - * @center_z: position on Z axis to rotate about. - * @direction: a #ClutterRotateDirection for the rotation. - * @func: a #ClutterEffectCompleteFunc to call on effect - * completion or %NULL - * @data: user data to pass to supplied @func or %NULL - * - * Simple effect for rotating a single #ClutterActor. - * - * Return value: a #ClutterTimeline for the effect. Will be unreferenced by - * the effect when completed. - * - * Since: 0.6 - */ -ClutterTimeline * -clutter_effect_rotate (ClutterEffectTemplate *template_, - ClutterActor *actor, - ClutterRotateAxis axis, - gdouble angle_end, - gint center_x, - gint center_y, - gint center_z, - ClutterRotateDirection direction, - ClutterEffectCompleteFunc func, - gpointer data) -{ - ClutterEffectClosure *c; - gdouble angle_start; - - c = clutter_effect_closure_new (template_, - actor, - G_CALLBACK (on_effect_complete)); - - c->completed_func = func; - c->completed_data = data; - - angle_start = clutter_actor_get_rotation (actor, axis, NULL, NULL, NULL); - - c->behave = clutter_behaviour_rotate_new (c->alpha, - axis, - direction, - angle_start, - angle_end); - g_object_set (c->behave, - "center-x", center_x, - "center-y", center_y, - "center-z", center_z, - NULL); - - clutter_behaviour_apply (c->behave, actor); - clutter_timeline_start (c->timeline); - - return c->timeline; -} diff --git a/clutter/clutter-effect.h b/clutter/clutter-effect.h deleted file mode 100644 index 0d1fb176d..000000000 --- a/clutter/clutter-effect.h +++ /dev/null @@ -1,162 +0,0 @@ -/* - * Clutter. - * - * An OpenGL based 'interactive canvas' library. - * - * Authored By Matthew Allum - * - * Copyright (C) 2006, 2007 OpenedHand - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library. If not, see . - */ - -#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION) -#error "Only can be included directly." -#endif - -#ifndef __CLUTTER_EFFECT_H__ -#define __CLUTTER_EFFECT_H__ - -#include -#include -#include -#include -#include - -G_BEGIN_DECLS - -/** - * ClutterEffectCompleteFunc: - * @actor: a #ClutterActor - * @user_data: user data - * - * Callback function invoked when an effect is complete. - * - * Since: 0.4 - */ -typedef void (*ClutterEffectCompleteFunc) (ClutterActor *actor, - gpointer user_data); - -#define CLUTTER_TYPE_EFFECT_TEMPLATE clutter_effect_template_get_type() - -#define CLUTTER_EFFECT_TEMPLATE(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST ((obj), \ - CLUTTER_TYPE_EFFECT_TEMPLATE, ClutterEffectTemplate)) - -#define CLUTTER_EFFECT_TEMPLATE_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST ((klass), \ - CLUTTER_TYPE_EFFECT_TEMPLATE, ClutterEffectTemplateClass)) - -#define CLUTTER_IS_EFFECT_TEMPLATE(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \ - CLUTTER_TYPE_EFFECT_TEMPLATE)) - -#define CLUTTER_IS_EFFECT_TEMPLATE_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_TYPE ((klass), \ - CLUTTER_TYPE_EFFECT_TEMPLATE)) - -#define CLUTTER_EFFECT_TEMPLATE_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS ((obj), \ - CLUTTER_TYPE_EFFECT_TEMPLATE, ClutterEffectTemplateClass)) - -typedef struct _ClutterEffectTemplate ClutterEffectTemplate; -typedef struct _ClutterEffectTemplatePrivate ClutterEffectTemplatePrivate; -typedef struct _ClutterEffectTemplateClass ClutterEffectTemplateClass; - - -struct _ClutterEffectTemplate -{ - /*< private >*/ - GObject parent_instance; - - ClutterEffectTemplatePrivate *priv; -}; - -struct _ClutterEffectTemplateClass -{ - /*< private >*/ - GObjectClass parent_class; - - /* padding, for future expansion */ - void (*_clutter_reserved1) (void); - void (*_clutter_reserved2) (void); - void (*_clutter_reserved3) (void); - void (*_clutter_reserved4) (void); -}; - -GType clutter_effect_template_get_type (void) G_GNUC_CONST; -ClutterEffectTemplate *clutter_effect_template_new (ClutterTimeline *timeline, - ClutterAlphaFunc alpha_func); -ClutterEffectTemplate *clutter_effect_template_new_full (ClutterTimeline *timeline, - ClutterAlphaFunc alpha_func, - gpointer user_data, - GDestroyNotify notify); -ClutterEffectTemplate *clutter_effect_template_new_for_duration (guint msecs, - ClutterAlphaFunc alpha_func); -void clutter_effect_template_construct (ClutterEffectTemplate *template_, - ClutterTimeline *timeline, - ClutterAlphaFunc alpha_func, - gpointer user_data, - GDestroyNotify notify); -void clutter_effect_template_set_timeline_clone (ClutterEffectTemplate *template_, - gboolean setting); -gboolean clutter_effect_template_get_timeline_clone (ClutterEffectTemplate *template_); - - -/* - * Clutter effects - */ - -ClutterTimeline *clutter_effect_fade (ClutterEffectTemplate *template_, - ClutterActor *actor, - guint8 opacity_end, - ClutterEffectCompleteFunc func, - gpointer data); -ClutterTimeline *clutter_effect_depth (ClutterEffectTemplate *template_, - ClutterActor *actor, - gint depth_end, - ClutterEffectCompleteFunc func, - gpointer data); -ClutterTimeline *clutter_effect_move (ClutterEffectTemplate *template_, - ClutterActor *actor, - gint x, - gint y, - ClutterEffectCompleteFunc func, - gpointer data); -ClutterTimeline *clutter_effect_path (ClutterEffectTemplate *template_, - ClutterActor *actor, - const ClutterKnot *knots, - guint n_knots, - ClutterEffectCompleteFunc func, - gpointer data); -ClutterTimeline *clutter_effect_scale (ClutterEffectTemplate *template_, - ClutterActor *actor, - gdouble x_scale_end, - gdouble y_scale_end, - ClutterEffectCompleteFunc func, - gpointer data); -ClutterTimeline *clutter_effect_rotate (ClutterEffectTemplate *template_, - ClutterActor *actor, - ClutterRotateAxis axis, - gdouble angle, - gint center_x, - gint center_y, - gint center_z, - ClutterRotateDirection direction, - ClutterEffectCompleteFunc func, - gpointer data); - -G_END_DECLS - -#endif /* __CLUTTER_EFFECT_H__ */ diff --git a/clutter/clutter.h b/clutter/clutter.h index 8306ee50a..478d7b19f 100644 --- a/clutter/clutter.h +++ b/clutter/clutter.h @@ -47,7 +47,6 @@ #include "clutter-color.h" #include "clutter-container.h" #include "clutter-deprecated.h" -#include "clutter-effect.h" #include "clutter-event.h" #include "clutter-feature.h" #include "clutter-frame-source.h" diff --git a/doc/reference/clutter/clutter-sections.txt b/doc/reference/clutter/clutter-sections.txt index 34b9d8928..2f66645de 100644 --- a/doc/reference/clutter/clutter-sections.txt +++ b/doc/reference/clutter/clutter-sections.txt @@ -1217,39 +1217,6 @@ CLUTTER_COGL CLUTTER_NO_FPU -
-clutter-effect -Clutter Effects -ClutterEffectTemplate -ClutterEffectTemplateClass -clutter_effect_template_new -clutter_effect_template_new_full -clutter_effect_template_new_for_duration -clutter_effect_template_construct -clutter_effect_template_get_timeline_clone -clutter_effect_template_set_timeline_clone - - -ClutterEffectCompleteFunc -clutter_effect_fade -clutter_effect_move -clutter_effect_path -clutter_effect_scale -clutter_effect_depth -clutter_effect_rotate - - -CLUTTER_TYPE_EFFECT_TEMPLATE -CLUTTER_EFFECT_TEMPLATE -CLUTTER_IS_EFFECT_TEMPLATE -CLUTTER_EFFECT_TEMPLATE_CLASS -CLUTTER_IS_EFFECT_TEMPLATE_CLASS -CLUTTER_EFFECT_TEMPLATE_GET_CLASS - -ClutterEffectTemplatePrivate -clutter_effect_template_get_type -
-
clutter-behaviour-depth ClutterBehaviourDepth diff --git a/tests/interactive/Makefile.am b/tests/interactive/Makefile.am index 08a2be02d..8c20d7c9e 100644 --- a/tests/interactive/Makefile.am +++ b/tests/interactive/Makefile.am @@ -15,7 +15,6 @@ UNIT_TESTS = \ test-script.c \ test-model.c \ test-grab.c \ - test-effects.c \ test-fullscreen.c \ test-shader.c \ test-unproject.c \ diff --git a/tests/interactive/test-effects.c b/tests/interactive/test-effects.c deleted file mode 100644 index 10dcbec7b..000000000 --- a/tests/interactive/test-effects.c +++ /dev/null @@ -1,95 +0,0 @@ -#include -#include -#include - -static ClutterEffectTemplate *tmpl = NULL; -static ClutterTimeline *timeline = NULL; - -G_MODULE_EXPORT int -test_effects_main (int argc, char *argv[]) -{ - ClutterActor *stage, *actor; - ClutterContainer *container; - ClutterColor stage_color = { 0xcc, 0xcc, 0xcc, 0xff }; - ClutterColor rect_color = { 0, 0, 0, 0xdd }; - - clutter_init (&argc, &argv); - - timeline = clutter_timeline_new_for_duration (5000); - clutter_timeline_set_loop (timeline, TRUE); - tmpl = - clutter_effect_template_new (timeline, clutter_ramp_inc_func); - - stage = clutter_stage_get_default (); - container = CLUTTER_CONTAINER (stage); - g_signal_connect (stage, - "button-press-event", G_CALLBACK (clutter_main_quit), - NULL); - - clutter_stage_set_color (CLUTTER_STAGE (stage), &stage_color); - clutter_stage_set_use_fog (CLUTTER_STAGE (stage), TRUE); - clutter_actor_set_size (stage, 800, 600); - clutter_actor_show_all (stage); - - actor = clutter_rectangle_new_with_color (&rect_color); - clutter_container_add_actor (container, actor); - clutter_actor_set_size (actor, 50, 50); - clutter_actor_set_position (actor, 50, 10); - clutter_effect_fade (tmpl, actor, 0x22, NULL, NULL); - clutter_actor_show (actor); - - actor = clutter_rectangle_new_with_color (&rect_color); - clutter_container_add_actor (container, actor); - clutter_actor_set_size (actor, 50, 50); - clutter_actor_set_position (actor, 750, 70); - clutter_effect_depth (tmpl, actor, -500, NULL, NULL); - clutter_actor_show (actor); - - actor = clutter_rectangle_new_with_color (&rect_color); - clutter_container_add_actor (container, actor); - clutter_actor_set_size (actor, 50, 50); - clutter_actor_set_position (actor, 50, 140); - clutter_effect_move (tmpl, actor, 750, 140, NULL, NULL); - clutter_actor_show (actor); - - actor = clutter_rectangle_new_with_color (&rect_color); - clutter_container_add_actor (container, actor); - clutter_actor_set_size (actor, 50, 50); - clutter_actor_set_position (actor, 750, 210); - { - ClutterKnot knots[2]; - - knots[0].x = 750; knots[0].y = 210; - knots[1].x = 350; knots[1].y = 210; - - clutter_effect_path (tmpl, actor, knots, 2, NULL, NULL); - } - clutter_actor_show (actor); - - actor = clutter_rectangle_new_with_color (&rect_color); - clutter_container_add_actor (container, actor); - clutter_actor_set_size (actor, 50, 50); - clutter_actor_set_position (actor, 50, 280); - clutter_actor_set_anchor_point_from_gravity (actor, CLUTTER_GRAVITY_CENTER); - - clutter_effect_scale (tmpl, actor, 2.0, 2.0, NULL, NULL); - clutter_actor_show (actor); - - actor = clutter_rectangle_new_with_color (&rect_color); - clutter_container_add_actor (container, actor); - clutter_actor_set_size (actor, 50, 50); - clutter_actor_set_position (actor, 750, 350); - clutter_effect_rotate (tmpl, actor, - CLUTTER_Z_AXIS, 180.0, - 25, 25, 0, - CLUTTER_ROTATE_CW, - NULL, NULL); - clutter_actor_show (actor); - - clutter_main (); - - g_object_unref (tmpl); - g_object_unref (timeline); - - return EXIT_SUCCESS; -} From 22183c7a8f092f0792c6f805d4b313651c999730 Mon Sep 17 00:00:00 2001 From: Emmanuele Bassi Date: Wed, 14 Jan 2009 18:14:46 +0000 Subject: [PATCH 41/43] Bug 1380 - Return booleans from CLUTTER_ACTOR_IS_* macros If you try to use the CLUTTER_ACTOR_IS_* macros defined in ClutterActor like this: typedef struct { unsigned int reactive : 1; } foo_t; foo_t f; f.reactive = CLUTTER_ACTOR_IS_REACTIVE (actor); It will blow up because while the macros evaluate to 0 they can also evaluate to non-zero values. Since most of the boolean flags in Clutter and Clutter-based code are going to be stored like in the example above, we should change the macros and let them evaluate stricly either to 0 or to 1. --- clutter/clutter-actor.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/clutter/clutter-actor.h b/clutter/clutter-actor.h index af962caf1..f6d889982 100644 --- a/clutter/clutter-actor.h +++ b/clutter/clutter-actor.h @@ -74,10 +74,10 @@ G_BEGIN_DECLS */ #define CLUTTER_ACTOR_UNSET_FLAGS(a,f) (((ClutterActor*)(a))->flags &= ~(f)) -#define CLUTTER_ACTOR_IS_MAPPED(e) (((ClutterActor*)(e))->flags & CLUTTER_ACTOR_MAPPED) -#define CLUTTER_ACTOR_IS_REALIZED(e) (((ClutterActor*)(e))->flags & CLUTTER_ACTOR_REALIZED) +#define CLUTTER_ACTOR_IS_MAPPED(e) ((((ClutterActor*)(e))->flags & CLUTTER_ACTOR_MAPPED) != FALSE) +#define CLUTTER_ACTOR_IS_REALIZED(e) ((((ClutterActor*)(e))->flags & CLUTTER_ACTOR_REALIZED) != FALSE) #define CLUTTER_ACTOR_IS_VISIBLE(e) (CLUTTER_ACTOR_IS_MAPPED (e) && CLUTTER_ACTOR_IS_REALIZED (e)) -#define CLUTTER_ACTOR_IS_REACTIVE(e) (((ClutterActor*)(e))->flags & CLUTTER_ACTOR_REACTIVE) +#define CLUTTER_ACTOR_IS_REACTIVE(e) ((((ClutterActor*)(e))->flags & CLUTTER_ACTOR_REACTIVE) != FALSE) typedef struct _ClutterActorClass ClutterActorClass; typedef struct _ClutterActorBox ClutterActorBox; From 642617b7a0d74c346206b673729288d7c5454a8e Mon Sep 17 00:00:00 2001 From: Robert Bragg Date: Thu, 15 Jan 2009 13:58:31 +0000 Subject: [PATCH 42/43] [test-text] queue redraws instead of calling clutter_actor_paint directly Directly calling clutter_actor_paint skips out quite a bit code such as the backend swap buffer call. Since we are interested in the highest fps possible, and it now goes through to the backend swap buffer call we now do a setenv (CLUTTER_VBLANK, none, 0) before calling clutter_init. --- tests/micro-bench/test-text.c | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/tests/micro-bench/test-text.c b/tests/micro-bench/test-text.c index afbb8b47b..a322e3c4f 100644 --- a/tests/micro-bench/test-text.c +++ b/tests/micro-bench/test-text.c @@ -9,10 +9,9 @@ #define COLS 18 #define ROWS 20 -gboolean idle (gpointer data) +static void +on_paint (ClutterActor *actor, gconstpointer *data) { - ClutterActor *stage = CLUTTER_ACTOR (data); - static GTimer *timer = NULL; static int fps = 0; @@ -29,8 +28,13 @@ gboolean idle (gpointer data) fps = 0; } - clutter_actor_paint (stage); ++fps; +} + +static gboolean +queue_redraw (gpointer stage) +{ + clutter_actor_queue_redraw (CLUTTER_ACTOR (stage)); return TRUE; } @@ -41,6 +45,9 @@ main (int argc, char *argv[]) ClutterActor *stage; ClutterColor stage_color = { 0x00, 0x00, 0x00, 0xff }; ClutterColor label_color = { 0xff, 0xff, 0xff, 0xff }; + ClutterActor *group; + + setenv ("CLUTTER_VBLANK", "none", 0); clutter_init (&argc, &argv); @@ -48,6 +55,14 @@ main (int argc, char *argv[]) clutter_actor_set_size (stage, STAGE_WIDTH, STAGE_HEIGHT); clutter_stage_set_color (CLUTTER_STAGE (stage), &stage_color); + group = clutter_group_new (); + clutter_actor_set_size (group, STAGE_WIDTH, STAGE_WIDTH); + clutter_container_add_actor (CLUTTER_CONTAINER (stage), group); + + g_idle_add (queue_redraw, stage); + + g_signal_connect (group, "paint", G_CALLBACK (on_paint), NULL); + { gint row, col; @@ -88,15 +103,13 @@ main (int argc, char *argv[]) (1.0*STAGE_HEIGHT/ROWS));*/ clutter_actor_set_scale (label, scale, scale); clutter_text_set_line_wrap (CLUTTER_TEXT (label), FALSE); - clutter_container_add_actor (CLUTTER_CONTAINER (stage), label); + clutter_container_add_actor (CLUTTER_CONTAINER (group), label); } } clutter_actor_show_all (stage); g_signal_connect (stage, "key-press-event", G_CALLBACK (clutter_main_quit), NULL); - - g_idle_add (idle, (gpointer) stage); clutter_main(); From 9339334a4370bb8d57ce0aff0bf46ef205f93f21 Mon Sep 17 00:00:00 2001 From: Neil Roberts Date: Thu, 15 Jan 2009 18:09:54 +0000 Subject: [PATCH 43/43] Fix GLES backends after merging the async-textures branch The changes from the GL version of cogl-texture.c have been mirrored in the GLES version. This adds the cogl_texture_new_from_bitmap function and fixes the build errors. --- clutter/cogl/gles/cogl-texture.c | 52 ++++++++++++++++++-------------- 1 file changed, 30 insertions(+), 22 deletions(-) diff --git a/clutter/cogl/gles/cogl-texture.c b/clutter/cogl/gles/cogl-texture.c index 4949afa1a..7de709507 100644 --- a/clutter/cogl/gles/cogl-texture.c +++ b/clutter/cogl/gles/cogl-texture.c @@ -1447,30 +1447,13 @@ cogl_texture_new_from_data (guint width, } CoglHandle -cogl_texture_new_from_file (const gchar *filename, - gint max_waste, - gboolean auto_mipmap, - CoglPixelFormat internal_format, - GError **error) +cogl_texture_new_from_bitmap (CoglBitmap *bmp, + gint max_waste, + gboolean auto_mipmap, + CoglPixelFormat internal_format) { - CoglBitmap bmp; CoglTexture *tex; - - g_return_val_if_fail (error == NULL || *error == NULL, COGL_INVALID_HANDLE); - /* Try loading with imaging backend */ - if (!_cogl_bitmap_from_file (&bmp, filename, error)) - { - /* Try fallback */ - if (!_cogl_bitmap_fallback_from_file (&bmp, filename)) - return COGL_INVALID_HANDLE; - else if (error && *error) - { - g_error_free (*error); - *error = NULL; - } - } - /* Create new texture and fill with loaded data */ tex = (CoglTexture*) g_malloc ( sizeof (CoglTexture)); @@ -1480,8 +1463,9 @@ cogl_texture_new_from_file (const gchar *filename, tex->is_foreign = FALSE; tex->auto_mipmap = auto_mipmap; - tex->bitmap = bmp; + tex->bitmap = *bmp; tex->bitmap_owner = TRUE; + bmp->data = NULL; tex->slice_x_spans = NULL; tex->slice_y_spans = NULL; @@ -1522,6 +1506,30 @@ cogl_texture_new_from_file (const gchar *filename, return _cogl_texture_handle_new (tex); } +CoglHandle +cogl_texture_new_from_file (const gchar *filename, + gint max_waste, + gboolean auto_mipmap, + CoglPixelFormat internal_format, + GError **error) +{ + CoglBitmap *bmp; + CoglHandle handle; + + g_return_val_if_fail (error == NULL || *error == NULL, COGL_INVALID_HANDLE); + + if (!(bmp = cogl_bitmap_new_from_file (filename, error))) + return COGL_INVALID_HANDLE; + + handle = cogl_texture_new_from_bitmap (bmp, + max_waste, + auto_mipmap, + internal_format); + cogl_bitmap_free (bmp); + + return handle; +} + CoglHandle cogl_texture_new_from_foreign (GLuint gl_handle, GLenum gl_target,