diff --git a/clutter/clutter-texture.c b/clutter/clutter-texture.c index 88329c2b5..e87bfb7ec 100644 --- a/clutter/clutter-texture.c +++ b/clutter/clutter-texture.c @@ -100,6 +100,8 @@ struct _ClutterTexturePrivate guint in_dispose : 1; guint keep_aspect_ratio : 1; guint load_async : 1; + guint load_size_async : 1; + guint load_data_async : 1; ClutterTextureAsyncData *async_data; }; @@ -143,7 +145,9 @@ enum PROP_COGL_MATERIAL, PROP_FILENAME, PROP_KEEP_ASPECT_RATIO, - PROP_LOAD_ASYNC + PROP_LOAD_ASYNC, + PROP_LOAD_DATA_ASYNC, + PROP_LOAD_SIZE_ASYNC }; enum @@ -152,7 +156,6 @@ enum PIXBUF_CHANGE, LOAD_SUCCESS, LOAD_FINISHED, - LAST_SIGNAL }; @@ -839,6 +842,12 @@ clutter_texture_set_property (GObject *object, case PROP_LOAD_ASYNC: priv->load_async = g_value_get_boolean (value); break; + case PROP_LOAD_DATA_ASYNC: + priv->load_data_async = g_value_get_boolean (value); + break; + case PROP_LOAD_SIZE_ASYNC: + priv->load_size_async = g_value_get_boolean (value); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -897,6 +906,12 @@ clutter_texture_get_property (GObject *object, case PROP_LOAD_ASYNC: g_value_set_boolean (value, priv->load_async); break; + case PROP_LOAD_DATA_ASYNC: + g_value_set_boolean (value, priv->load_data_async); + break; + case PROP_LOAD_SIZE_ASYNC: + g_value_set_boolean (value, priv->load_size_async); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -1032,6 +1047,24 @@ clutter_texture_class_init (ClutterTextureClass *klass) FALSE, CLUTTER_PARAM_READWRITE)); + /** + * ClutterTexture:load-size-sync: + * + * When set to TRUE clutter will not block loading the size initially, + * when used in this manner the size of the actor will change (and the + * load-size-complete signal will be fired when the size is available). + * + * Since: 1.0 + */ + g_object_class_install_property + (gobject_class, PROP_LOAD_SIZE_ASYNC, + g_param_spec_boolean ("load-size-async", + "Load size asynchronously", + "If set to TRUE clutter will not block until it has " + "loaded the size of the file.", + FALSE, + CLUTTER_PARAM_READWRITE)); + /** * ClutterTexture:load-async: * @@ -1046,6 +1079,24 @@ clutter_texture_class_init (ClutterTextureClass *klass) * * Since: 1.0 */ + g_object_class_install_property + (gobject_class, PROP_LOAD_ASYNC, + g_param_spec_boolean ("load-data-async", + "Load data asynchronously", + "Load files inside a thread to avoid blocking when " + "loading images.", + FALSE, + CLUTTER_PARAM_READWRITE)); + + + /** + * ClutterTexture:load-async: + * + * Load texture fully asynchronosuly, loading both the size and data + * in a separate thread. + * + * Since: 1.0 + */ g_object_class_install_property (gobject_class, PROP_LOAD_ASYNC, g_param_spec_boolean ("load-async", @@ -1053,7 +1104,7 @@ clutter_texture_class_init (ClutterTextureClass *klass) "Load files inside a thread to avoid blocking when " "loading images.", FALSE, - CLUTTER_PARAM_READWRITE)); + CLUTTER_PARAM_WRITABLE)); /** * ClutterTexture::size-change: @@ -1639,6 +1690,8 @@ clutter_texture_async_load_complete (ClutterTexture *self, waste, flags, COGL_PIXEL_FORMAT_ANY); clutter_texture_set_cogl_texture (self, handle); + /*clutter_actor_set_size (self, cogl_texture_get_width (handle), + cogl_texture_get_height (handle));*/ cogl_texture_unref (handle); } @@ -1687,6 +1740,7 @@ clutter_texture_thread_func (gpointer user_data, gpointer pool_data) data->load_bitmap = cogl_bitmap_new_from_file (data->load_filename, &data->load_error); + g_print ("."); /* Check again if we've been told to abort */ g_mutex_lock (data->mutex); @@ -1772,15 +1826,21 @@ clutter_texture_async_load (ClutterTexture *self, * there's no point in even continuing the asynchronous * loading, so we just stop there */ - res = cogl_bitmap_get_size_from_file (filename, - &width, - &height); + + if (priv->load_size_async) + { + res = TRUE; + } + else + { + res = cogl_bitmap_get_size_from_file (filename, &width, &height); + } + if (!res) { g_set_error (error, CLUTTER_TEXTURE_ERROR, CLUTTER_TEXTURE_ERROR_BAD_FORMAT, "Failed to create COGL texture"); - clutter_texture_async_data_free (data); return FALSE; } else diff --git a/tests/interactive/Makefile.am b/tests/interactive/Makefile.am index f9043dff1..4f0bf3b70 100644 --- a/tests/interactive/Makefile.am +++ b/tests/interactive/Makefile.am @@ -1,6 +1,7 @@ UNIT_TESTS = \ test-textures.c \ + test-texture-async.c \ test-events.c \ test-offscreen.c \ test-scale.c \ diff --git a/tests/interactive/test-texture-async.c b/tests/interactive/test-texture-async.c new file mode 100644 index 000000000..9983bac57 --- /dev/null +++ b/tests/interactive/test-texture-async.c @@ -0,0 +1,76 @@ +#include +#include +#include + +G_MODULE_EXPORT gint +test_texture_async_main (int argc, char *argv[]) +{ + ClutterTimeline *timeline; + ClutterAlpha *alpha; + ClutterBehaviour *depth_behavior; + ClutterActor *stage; + ClutterActor *image[4]; + ClutterColor stage_color = { 0x12, 0x34, 0x56, 0xff }; + GError *error; + const gchar *path = "redhand.png"; + gint i; + + clutter_init (&argc, &argv); + + stage = clutter_stage_get_default (); + clutter_stage_set_color (CLUTTER_STAGE (stage), &stage_color); + clutter_stage_set_use_fog (CLUTTER_STAGE (stage), TRUE); + clutter_stage_set_fog (CLUTTER_STAGE (stage), 1.0, 10, -50); + + g_signal_connect (stage, + "button-press-event", G_CALLBACK (clutter_main_quit), + NULL); + + error = NULL; + path = argv[1]?argv[1]:"redhand.png"; + + if (!argv[1]) + g_print ("Hint: the redhand.png isn't a good test image for this test.\n" + "This test can take any clutter loadable image as an argument\n"); + + for (i=0;i<4;i++) + image[i] = g_object_new (CLUTTER_TYPE_TEXTURE, + "filename", path, + NULL); + /* + image[1] = g_object_new (CLUTTER_TYPE_TEXTURE, + "filename", path, + "load-async", TRUE, + NULL); + image[2] = g_object_new (CLUTTER_TYPE_TEXTURE, + "filename", path, + "load-data-async", TRUE, + NULL); + image[3] = g_object_new (CLUTTER_TYPE_TEXTURE, + "filename", path, + "load-data-async", TRUE, + "load-size-async", TRUE, + NULL);*/ + + /* center the image */ + + for (i=0;i<4;i++) + { + clutter_actor_set_position (image[i], 50+i*100, 50+i*50); + clutter_container_add (CLUTTER_CONTAINER (stage), image[i], NULL); + timeline = clutter_timeline_new (60*5, 60); + alpha = clutter_alpha_new_full (timeline, CLUTTER_LINEAR); + depth_behavior = clutter_behaviour_depth_new (alpha, -2500, 0); + clutter_behaviour_apply (depth_behavior, image[i]); + clutter_timeline_start (timeline); + } + + clutter_actor_show (stage); + + clutter_main (); + + /*g_object_unref (depth_behavior); + g_object_unref (timeline);*/ + + return EXIT_SUCCESS; +}