diff --git a/clutter/clutter-debug.h b/clutter/clutter-debug.h index f4a9bf872..be551e155 100644 --- a/clutter/clutter-debug.h +++ b/clutter/clutter-debug.h @@ -27,7 +27,8 @@ typedef enum { CLUTTER_DEBUG_PICK = 1 << 16, CLUTTER_DEBUG_EVENTLOOP = 1 << 17, CLUTTER_DEBUG_CLIPPING = 1 << 18, - CLUTTER_DEBUG_OOB_TRANSFORMS = 1 << 19 + CLUTTER_DEBUG_OOB_TRANSFORMS = 1 << 19, + CLUTTER_DEBUG_PAINT_DEFORM_TILES = 1 << 20, } ClutterDebugFlag; typedef enum { diff --git a/clutter/clutter-deform-effect.c b/clutter/clutter-deform-effect.c index 2454f233e..8037a1d99 100644 --- a/clutter/clutter-deform-effect.c +++ b/clutter/clutter-deform-effect.c @@ -290,6 +290,26 @@ clutter_deform_effect_paint_target (ClutterOffscreenEffect *effect) cogl_set_backface_culling_enabled (FALSE); else if (priv->back_material == COGL_INVALID_HANDLE && is_cull_enabled) cogl_set_backface_culling_enabled (TRUE); + + if (G_UNLIKELY (clutter_debug_flags & CLUTTER_DEBUG_PAINT_DEFORM_TILES)) + { + cogl_set_source_color4f (1.0, 0, 0, 1.0); + cogl_vertex_buffer_draw_elements (priv->vbo, + COGL_VERTICES_MODE_LINE_STRIP, + priv->indices, + 0, + n_tiles, + 0, + priv->n_indices); + + cogl_vertex_buffer_draw_elements (priv->vbo, + COGL_VERTICES_MODE_LINE_STRIP, + priv->back_indices, + 0, + n_tiles, + 0, + priv->n_indices); + } } static inline void diff --git a/clutter/clutter-main.c b/clutter/clutter-main.c index 70fd22ab9..a589b12e0 100644 --- a/clutter/clutter-main.c +++ b/clutter/clutter-main.c @@ -168,7 +168,8 @@ static const GDebugKey clutter_debug_keys[] = { { "animation", CLUTTER_DEBUG_ANIMATION }, { "layout", CLUTTER_DEBUG_LAYOUT }, { "clipping", CLUTTER_DEBUG_CLIPPING }, - { "oob-transforms", CLUTTER_DEBUG_OOB_TRANSFORMS } + { "oob-transforms", CLUTTER_DEBUG_OOB_TRANSFORMS }, + { "paint-deform-tiles", CLUTTER_DEBUG_PAINT_DEFORM_TILES }, }; #endif /* CLUTTER_ENABLE_DEBUG */ diff --git a/clutter/clutter-texture.c b/clutter/clutter-texture.c index ff602f711..2c3c4e769 100644 --- a/clutter/clutter-texture.c +++ b/clutter/clutter-texture.c @@ -99,36 +99,37 @@ struct _ClutterTexturePrivate guint seen_create_pick_material_warning : 1; }; +#define ASYNC_STATE_LOCKED 1 +#define ASYNC_STATE_CANCELLED 2 +#define ASYNC_STATE_QUEUED 3 + struct _ClutterTextureAsyncData { - /* Mutex used to synchronize setting the abort flag */ - GMutex *mutex; - - /* If set to true, the loaded data will be discarded */ - gboolean abort; - /* The texture for which the data is being loaded */ ClutterTexture *texture; - /* Source ID of the idle handler for loading. If this is zero then - the data is being loaded in a thread from the thread pool. Once - the thread is finished it will be converted to idle load handler - and load_idle will be nonzero. If load_idle is nonzero, and - upload_queued is FALSE then the rest of the load can safely be - aborted by just removing the source, otherwise the abort flag - needs to be set and the data should be disowned */ - guint load_idle; + gchar *load_filename; + CoglHandle load_bitmap; - /* Set when the texture is queued for GPU upload, used to determine - * what to do with the texture data when load_idle is zero. - */ - gboolean upload_queued; + guint load_idle; - gchar *load_filename; - CoglHandle load_bitmap; - GError *load_error; + GError *load_error; + + gint state; }; +static inline void +clutter_texture_async_data_lock (ClutterTextureAsyncData *data) +{ + g_bit_lock (&data->state, 0); +} + +static inline void +clutter_texture_async_data_unlock (ClutterTextureAsyncData *data) +{ + g_bit_unlock (&data->state, 0); +} + enum { PROP_0, @@ -166,7 +167,7 @@ static int texture_signals[LAST_SIGNAL] = { 0 }; static GThreadPool *async_thread_pool = NULL; static guint repaint_upload_func = 0; static GList *upload_list = NULL; -static GStaticMutex upload_list_mutex = G_STATIC_MUTEX_INIT; +static GMutex upload_list_mutex = G_MUTEX_INIT; static CoglMaterial *texture_template_material = NULL; @@ -711,19 +712,14 @@ clutter_texture_async_data_free (ClutterTextureAsyncData *data) once it is known that the load thread has completed or from the load thread/upload function itself if the abort flag is true (in which case the main thread has disowned the data) */ + g_free (data->load_filename); - if (data->load_filename) - g_free (data->load_filename); - - if (data->load_bitmap) + if (data->load_bitmap != NULL) cogl_handle_unref (data->load_bitmap); - if (data->load_error) + if (data->load_error != NULL) g_error_free (data->load_error); - if (data->mutex) - g_mutex_free (data->mutex); - g_slice_free (ClutterTextureAsyncData, data); } @@ -739,40 +735,30 @@ clutter_texture_async_load_cancel (ClutterTexture *texture) { ClutterTexturePrivate *priv = texture->priv; - if (priv->async_data) + if (priv->async_data != NULL) { - GMutex *mutex = priv->async_data->mutex; + ClutterTextureAsyncData *async_data = priv->async_data; - /* The mutex will only be NULL if the no thread was used for - this load, in which case there's no need for any - synchronization */ - if (mutex) - g_mutex_lock (mutex); + priv->async_data = NULL; - /* If there is no thread behind this load then we can just abort - the idle handler and destroy the load data immediately */ - if (priv->async_data->load_idle) + if (async_data->load_idle != 0) { - g_source_remove (priv->async_data->load_idle); - priv->async_data->load_idle = 0; + g_source_remove (async_data->load_idle); + async_data->load_idle = 0; - if (mutex) - g_mutex_unlock (mutex); - - clutter_texture_async_data_free (priv->async_data); + clutter_texture_async_data_free (async_data); } else { - /* Otherwise we need to tell the thread to abort and disown - the data, if the data has been loaded and decoded the data - is now waiting for a master clock iteration to be repainted */ - priv->async_data->abort = TRUE; + clutter_texture_async_data_lock (async_data); - if (mutex) - g_mutex_unlock (mutex); + CLUTTER_NOTE (TEXTURE, "[async] cancelling operation for '%s'", + async_data->load_filename); + + async_data->state |= ASYNC_STATE_CANCELLED; + + clutter_texture_async_data_unlock (async_data); } - - priv->async_data = NULL; } } @@ -1736,8 +1722,8 @@ clutter_texture_async_load_complete (ClutterTexture *self, const GError *error) { ClutterTexturePrivate *priv = self->priv; - CoglHandle handle; CoglTextureFlags flags = COGL_TEXTURE_NONE; + CoglHandle handle; priv->async_data = NULL; @@ -1766,38 +1752,14 @@ clutter_texture_async_load_complete (ClutterTexture *self, clutter_actor_queue_relayout (CLUTTER_ACTOR (self)); } -static gboolean -clutter_texture_thread_idle_func (gpointer user_data) -{ - ClutterTextureAsyncData *data = user_data; - - /* Grab the mutex so we can be sure the thread has unlocked it - before we destroy it */ - g_mutex_lock (data->mutex); - if (data->abort) - { - g_mutex_unlock (data->mutex); - clutter_texture_async_data_free (data); - return FALSE; - } - g_mutex_unlock (data->mutex); - - clutter_texture_async_load_complete (data->texture, data->load_bitmap, - data->load_error); - - clutter_texture_async_data_free (data); - - return FALSE; -} - static gboolean texture_repaint_upload_func (gpointer user_data) { gulong start_time; - g_static_mutex_lock (&upload_list_mutex); + g_mutex_lock (&upload_list_mutex); - if (upload_list) + if (upload_list != NULL) { start_time = clutter_get_timestamp (); @@ -1806,16 +1768,32 @@ texture_repaint_upload_func (gpointer user_data) */ do { - ClutterTextureAsyncData *data = upload_list->data; + ClutterTextureAsyncData *async_data = upload_list->data; - clutter_texture_thread_idle_func (data); + clutter_texture_async_data_lock (async_data); - upload_list = g_list_remove (upload_list, data); + if (async_data->state & ASYNC_STATE_QUEUED) + { + CLUTTER_NOTE (TEXTURE, "[async] operation complete for '%s'", + async_data->load_filename); + + clutter_texture_async_load_complete (async_data->texture, + async_data->load_bitmap, + async_data->load_error); + } + else + CLUTTER_NOTE (TEXTURE, "[async] operation cancelled for '%s'", + async_data->load_filename); + + clutter_texture_async_data_unlock (async_data); + + upload_list = g_list_remove (upload_list, async_data); + clutter_texture_async_data_free (async_data); } while (upload_list && clutter_get_timestamp () < start_time + 5 * 1000); } - if (upload_list) + if (upload_list != NULL) { ClutterMasterClock *master_clock; @@ -1823,54 +1801,30 @@ texture_repaint_upload_func (gpointer user_data) _clutter_master_clock_ensure_next_iteration (master_clock); } - g_static_mutex_unlock (&upload_list_mutex); + g_mutex_unlock (&upload_list_mutex); return TRUE; } static void -clutter_texture_thread_func (gpointer user_data, gpointer pool_data) +clutter_texture_thread_load (gpointer user_data, + gpointer pool_data) { - ClutterTextureAsyncData *data = user_data; - gboolean should_abort; + ClutterTextureAsyncData *async_data = user_data; + ClutterMasterClock *master_clock = _clutter_master_clock_get_default (); - /* Make sure we haven't been told to abort before the thread had a - chance to run */ - g_mutex_lock (data->mutex); - should_abort = data->abort; - g_mutex_unlock (data->mutex); + clutter_texture_async_data_lock (async_data); - if (should_abort) + if (~async_data->state & ASYNC_STATE_CANCELLED) { - /* If we've been told to abort then main thread has disowned the - async data and we need to free it */ - clutter_texture_async_data_free (data); - return; - } + CLUTTER_NOTE (TEXTURE, "[async] loading bitmap from file '%s'", + async_data->load_filename); - data->load_bitmap = cogl_bitmap_new_from_file (data->load_filename, - &data->load_error); + async_data->load_bitmap = + cogl_bitmap_new_from_file (async_data->load_filename, + &async_data->load_error); - /* Check again if we've been told to abort */ - g_mutex_lock (data->mutex); - - if (data->abort) - { - g_mutex_unlock (data->mutex); - - clutter_texture_async_data_free (data); - } - else - { - ClutterMasterClock *master_clock = _clutter_master_clock_get_default (); - - /* Make sure we give the image to GL in the main thread, where we - * hold the main Clutter lock. Once load_idle is non-NULL then the - * main thread is guaranteed not to set the abort flag. It can't - * set it while we're holding the mutex so we can safely start the - * idle handler now without the possibility of calling the - * callback after it is aborted */ - g_static_mutex_lock (&upload_list_mutex); + g_mutex_lock (&upload_list_mutex); if (repaint_upload_func == 0) { @@ -1879,33 +1833,40 @@ clutter_texture_thread_func (gpointer user_data, gpointer pool_data) NULL, NULL); } - upload_list = g_list_append (upload_list, data); - data->upload_queued = TRUE; + upload_list = g_list_append (upload_list, async_data); + async_data->state |= ASYNC_STATE_QUEUED; - g_static_mutex_unlock (&upload_list_mutex); + CLUTTER_NOTE (TEXTURE, "[async] operation queued"); - g_mutex_unlock (data->mutex); - - _clutter_master_clock_ensure_next_iteration (master_clock); + g_mutex_unlock (&upload_list_mutex); } + else + { + clutter_texture_async_data_unlock (async_data); + clutter_texture_async_data_free (async_data); + + return; + } + + clutter_texture_async_data_unlock (async_data); + + _clutter_master_clock_ensure_next_iteration (master_clock); } static gboolean -clutter_texture_idle_func (gpointer user_data) +clutter_texture_idle_load (gpointer data) { - ClutterTextureAsyncData *data = user_data; - GError *internal_error = NULL; + ClutterTextureAsyncData *async_data = data; - data->load_bitmap = cogl_bitmap_new_from_file (data->load_filename, - &internal_error); + async_data->load_bitmap = + cogl_bitmap_new_from_file (async_data->load_filename, + &async_data->load_error); - clutter_texture_async_load_complete (data->texture, data->load_bitmap, - internal_error); + clutter_texture_async_load_complete (async_data->texture, + async_data->load_bitmap, + async_data->load_error); - if (internal_error) - g_error_free (internal_error); - - clutter_texture_async_data_free (data); + clutter_texture_async_data_free (async_data); return FALSE; } @@ -1956,9 +1917,7 @@ clutter_texture_async_load (ClutterTexture *self, height = 0; } else - { - res = cogl_bitmap_get_size_from_file (filename, &width, &height); - } + res = cogl_bitmap_get_size_from_file (filename, &width, &height); if (!res) { @@ -1975,35 +1934,34 @@ clutter_texture_async_load (ClutterTexture *self, clutter_texture_async_load_cancel (self); - data = g_slice_new (ClutterTextureAsyncData); + data = g_slice_new0 (ClutterTextureAsyncData); - data->abort = FALSE; data->texture = self; - data->load_idle = 0; data->load_filename = g_strdup (filename); - data->load_bitmap = NULL; - data->load_error = NULL; priv->async_data = data; if (g_thread_supported ()) { - data->mutex = g_mutex_new (); - - if (async_thread_pool == NULL) - /* This apparently can't fail if exclusive == FALSE */ - async_thread_pool - = g_thread_pool_new (clutter_texture_thread_func, - NULL, 1, FALSE, NULL); + if (G_UNLIKELY (async_thread_pool == NULL)) + { + /* This apparently can't fail if exclusive == FALSE */ + async_thread_pool = + g_thread_pool_new (clutter_texture_thread_load, NULL, + 1, + FALSE, + NULL); + } g_thread_pool_push (async_thread_pool, data, NULL); } else { - data->mutex = NULL; - - data->load_idle - = clutter_threads_add_idle (clutter_texture_idle_func, data); + data->load_idle = + clutter_threads_add_idle_full (G_PRIORITY_DEFAULT_IDLE, + clutter_texture_idle_load, + data, + NULL); } return TRUE; @@ -2921,6 +2879,8 @@ clutter_texture_set_load_async (ClutterTexture *texture, priv = texture->priv; + load_async = !!load_async; + if (priv->load_async_set != load_async) { priv->load_data_async = load_async; diff --git a/configure.ac b/configure.ac index b371bf3b5..091f1f690 100644 --- a/configure.ac +++ b/configure.ac @@ -113,7 +113,7 @@ LT_INIT([disable-static]) AC_HEADER_STDC # required versions for dependencies -m4_define([glib_req_version], [2.28.0]) +m4_define([glib_req_version], [2.31.0]) m4_define([cogl_req_version], [1.8.0]) m4_define([json_glib_req_version], [0.12.0]) m4_define([atk_req_version], [2.1.5]) diff --git a/po/te.po b/po/te.po index 15353c3e8..460360987 100644 --- a/po/te.po +++ b/po/te.po @@ -8,7 +8,7 @@ msgstr "" "Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug." "cgi?product=clutter&keywords=I18N+L10N&component=general\n" "POT-Creation-Date: 2011-09-23 07:16+0000\n" -"PO-Revision-Date: 2011-09-23 14:38+0530\n" +"PO-Revision-Date: 2011-09-26 21:28+0530\n" "Last-Translator: Krishnababu Krothapalli \n" "Language-Team: Telugu \n" "MIME-Version: 1.0\n" @@ -24,15 +24,15 @@ msgstr "X అక్షము" #: ../clutter/clutter-actor.c:3876 msgid "X coordinate of the actor" -msgstr "" +msgstr "ఏక్టర్ యొక్క X అక్షము" #: ../clutter/clutter-actor.c:3891 msgid "Y coordinate" -msgstr "" +msgstr "Y అక్షము" #: ../clutter/clutter-actor.c:3892 msgid "Y coordinate of the actor" -msgstr "" +msgstr "ఏక్టర్ యొక్క Y అక్షము" #: ../clutter/clutter-actor.c:3907 ../clutter/clutter-behaviour-ellipse.c:477 msgid "Width" @@ -40,7 +40,7 @@ msgstr "వెడల్పు" #: ../clutter/clutter-actor.c:3908 msgid "Width of the actor" -msgstr "" +msgstr "ఏక్టర్ యొక్క వెడల్పు" #: ../clutter/clutter-actor.c:3922 ../clutter/clutter-behaviour-ellipse.c:493 msgid "Height" @@ -48,31 +48,31 @@ msgstr "ఎత్తు" #: ../clutter/clutter-actor.c:3923 msgid "Height of the actor" -msgstr "" +msgstr "ఏక్టర్ యొక్క యెత్తు" #: ../clutter/clutter-actor.c:3941 msgid "Fixed X" -msgstr "" +msgstr "నిర్దిష్ట X" #: ../clutter/clutter-actor.c:3942 msgid "Forced X position of the actor" -msgstr "" +msgstr "ఏక్టర్ యొక్క నిర్దిష్ట X స్థానం" #: ../clutter/clutter-actor.c:3960 msgid "Fixed Y" -msgstr "" +msgstr "నిర్దిష్ట Y" #: ../clutter/clutter-actor.c:3961 msgid "Forced Y position of the actor" -msgstr "" +msgstr "ఏక్టర్ యొక్క బలవంతపు Y స్థానం" #: ../clutter/clutter-actor.c:3977 msgid "Fixed position set" -msgstr "" +msgstr "నిర్దిష్ట స్థాన అమర్పు" #: ../clutter/clutter-actor.c:3978 msgid "Whether to use fixed positioning for the actor" -msgstr "" +msgstr "ఏక్టర్ కొరకు నిర్దిష్టంగా స్థానపరచుటను వుపయోగించాలా" #: ../clutter/clutter-actor.c:4000 msgid "Min Width" @@ -80,7 +80,7 @@ msgstr "కనిష్ఠ వెడల్పు" #: ../clutter/clutter-actor.c:4001 msgid "Forced minimum width request for the actor" -msgstr "" +msgstr "ఏక్టర్ కొరకు అభ్యర్దించిన బలవంతపు కనిష్ట వెడల్పు" #: ../clutter/clutter-actor.c:4020 msgid "Min Height" @@ -88,119 +88,120 @@ msgstr "కనిష్ఠ ఎత్తు" #: ../clutter/clutter-actor.c:4021 msgid "Forced minimum height request for the actor" -msgstr "" +msgstr "ఏక్టర్ కొరకు అభ్యర్దించిన బలవంతపు కనిష్ట యెత్తు" #: ../clutter/clutter-actor.c:4040 msgid "Natural Width" -msgstr "" +msgstr "సహజ వెడల్పు" #: ../clutter/clutter-actor.c:4041 msgid "Forced natural width request for the actor" -msgstr "" +msgstr "ఏక్టర్ కొరకు అభ్యర్దించిన బలవంతపు సహజ వెడల్పు" #: ../clutter/clutter-actor.c:4060 msgid "Natural Height" -msgstr "" +msgstr "సహజ యెత్తు" #: ../clutter/clutter-actor.c:4061 msgid "Forced natural height request for the actor" -msgstr "" +msgstr "ఏక్టర్ కొరకు అభ్యర్దించిన బలవంతపు సహజ యెత్తు" #: ../clutter/clutter-actor.c:4077 msgid "Minimum width set" -msgstr "" +msgstr "కనిష్ట వెడల్పు అమర్పు" #: ../clutter/clutter-actor.c:4078 msgid "Whether to use the min-width property" -msgstr "" +msgstr "కనిష్ట-వెడల్పు లక్షణం వుపయోగించాలా" #: ../clutter/clutter-actor.c:4093 msgid "Minimum height set" -msgstr "" +msgstr "కనిష్ట యెత్తు అమర్పు" #: ../clutter/clutter-actor.c:4094 msgid "Whether to use the min-height property" -msgstr "" +msgstr "కనిష్ట-యెత్తు లక్షణం వుపయోగించాలా" #: ../clutter/clutter-actor.c:4109 msgid "Natural width set" -msgstr "" +msgstr "సహజ వెడల్పు అమర్పు" #: ../clutter/clutter-actor.c:4110 msgid "Whether to use the natural-width property" -msgstr "" +msgstr "సహజ-వెడల్పు లక్షణం వుపయోగించాలా" #: ../clutter/clutter-actor.c:4127 msgid "Natural height set" -msgstr "" +msgstr "సహజ యెత్తు అమర్పు" #: ../clutter/clutter-actor.c:4128 msgid "Whether to use the natural-height property" -msgstr "" +msgstr "సహజ-యెత్తు లక్షణం వుపయోగించాలా" #: ../clutter/clutter-actor.c:4147 msgid "Allocation" -msgstr "" +msgstr "కేటాయింపు" #: ../clutter/clutter-actor.c:4148 msgid "The actor's allocation" -msgstr "" +msgstr "ఏక్టర్ యొక్క కేటాయింపు" #: ../clutter/clutter-actor.c:4204 msgid "Request Mode" -msgstr "" +msgstr "అభ్యర్దన రీతి" #: ../clutter/clutter-actor.c:4205 msgid "The actor's request mode" -msgstr "" +msgstr "ఏక్టర్ యొక్క అభ్యర్దన రీతి" #: ../clutter/clutter-actor.c:4220 msgid "Depth" -msgstr "" +msgstr "లోతు" #: ../clutter/clutter-actor.c:4221 msgid "Position on the Z axis" -msgstr "" +msgstr "Z అక్షంపై స్థానం" #: ../clutter/clutter-actor.c:4235 msgid "Opacity" -msgstr "" +msgstr "మసక" #: ../clutter/clutter-actor.c:4236 msgid "Opacity of an actor" -msgstr "" +msgstr "ఏక్టర్ యొక్క మసక" #: ../clutter/clutter-actor.c:4255 msgid "Offscreen redirect" -msgstr "" +msgstr "ఆఫ్‌స్క్రీన్ రీడైరెక్ట్" #: ../clutter/clutter-actor.c:4256 msgid "Flags controlling when to flatten the actor into a single image" msgstr "" +"ఏక్టర్‌ను వొంటరి ప్రతిరూపమునకు యెప్పుడు ఫ్లాటెన్ చేయాలో నియంత్రించే ఫ్లాగులు" #: ../clutter/clutter-actor.c:4274 msgid "Visible" -msgstr "" +msgstr "దృశ్యనీయం" #: ../clutter/clutter-actor.c:4275 msgid "Whether the actor is visible or not" -msgstr "" +msgstr "ఏక్టర్ దృశ్యనీయం కావలెనా లేదా" #: ../clutter/clutter-actor.c:4290 msgid "Mapped" -msgstr "" +msgstr "మాప్‌డ్" #: ../clutter/clutter-actor.c:4291 msgid "Whether the actor will be painted" -msgstr "" +msgstr "ఏక్టర్ రంగు వేయబడుదురా" #: ../clutter/clutter-actor.c:4305 msgid "Realized" -msgstr "" +msgstr "తెలుసుకొనెను" #: ../clutter/clutter-actor.c:4306 msgid "Whether the actor has been realized" -msgstr "" +msgstr "ఏక్టర్‌కు తెలియవలెనా" #: ../clutter/clutter-actor.c:4322 msgid "Reactive" diff --git a/tests/interactive/Makefile.am b/tests/interactive/Makefile.am index 65ab1e838..175fcb7ae 100644 --- a/tests/interactive/Makefile.am +++ b/tests/interactive/Makefile.am @@ -1,7 +1,7 @@ include $(top_srcdir)/build/autotools/Makefile.am.silent UNIT_TESTS = \ - test-textures.c \ + test-texture-slicing.c \ test-texture-async.c \ test-texture-material.c \ test-events.c \ @@ -74,11 +74,13 @@ endif # For convenience, this provides a way to easily run individual unit tests: wrappers: stamp-test-interactive ../../build/win32/test-interactive.bat @true -stamp-test-interactive: Makefile test-interactive$(EXEEXT) +stamp-test-interactive: Makefile @wrapper=$(abs_builddir)/wrapper.sh ; \ chmod +x $$wrapper && \ ( echo "/stamp-test-interactive" ; \ + echo "/stamp-test-unit-names" ; \ echo "/test-interactive" ; \ + echo "/test-unit-names.h" ; \ echo "*.o" ; \ echo ".gitignore" ) > .gitignore ; \ for i in $(UNIT_TESTS); \ @@ -107,6 +109,21 @@ stamp-test-interactive: Makefile test-interactive$(EXEEXT) done \ && cp *.bat $(top_srcdir)/build/win32/ +test-unit-names.h: stamp-test-unit-names + @true + +stamp-test-unit-names: Makefile + @( echo "/* ** This file is autogenerated. Do not edit. ** */" ; \ + echo "" ; \ + echo "const char *test_unit_names[] = {" ) > test-unit-names.h ; \ + for i in $(UNIT_TESTS); \ + do \ + test_bin=$${i%*.c} ; \ + echo " \"$$test_bin\"," >> test-unit-names.h ; \ + done \ + && echo "};" >> test-unit-names.h \ + && echo timestamp > $(@F) + clean-wrappers: @for i in $(UNIT_TESTS); \ do \ @@ -131,7 +148,7 @@ common_ldadd = $(top_builddir)/clutter/libclutter-@CLUTTER_SONAME_INFIX@-@CLUTTE noinst_PROGRAMS = test-interactive -test_interactive_SOURCES = test-main.c $(UNIT_TESTS) +test_interactive_SOURCES = test-main.c test-unit-names.h $(UNIT_TESTS) test_interactive_CFLAGS = $(CLUTTER_CFLAGS) $(MAINTAINER_CFLAGS) test_interactive_CPPFLAGS = \ -DTESTS_DATADIR=\""$(abs_top_srcdir)/tests/data"\" \ @@ -142,9 +159,9 @@ test_interactive_LDFLAGS = -export-dynamic test_interactive_LDADD = $(CLUTTER_LIBS) $(common_ldadd) -lm EXTRA_DIST = wrapper.sh.in -DISTCLEANFILES = wrapper.sh .gitignore +DISTCLEANFILES = wrapper.sh .gitignore test-unit-names.h -BUILT_SOURCES = wrappers +BUILT_SOURCES = wrappers test-unit-names.h dist-hook: ../../build/win32/vs9/test-interactive.vcproj ../../build/win32/vs10/test-interactive.vcxproj ../../build/win32/vs10/test-interactive.vcxproj.filters diff --git a/tests/interactive/test-animation.c b/tests/interactive/test-animation.c index 85b7213bc..aba1a9d50 100644 --- a/tests/interactive/test-animation.c +++ b/tests/interactive/test-animation.c @@ -114,3 +114,9 @@ test_animation_main (int argc, char *argv[]) return EXIT_SUCCESS; } + +G_MODULE_EXPORT const char * +test_animation_describe (void) +{ + return "Simple clutter_actor_animate() demo"; +} diff --git a/tests/interactive/test-cairo-clock.c b/tests/interactive/test-cairo-clock.c index 6c292d0df..6edd83ba2 100644 --- a/tests/interactive/test-cairo-clock.c +++ b/tests/interactive/test-cairo-clock.c @@ -111,3 +111,9 @@ test_cairo_clock_main (int argc, char *argv[]) return EXIT_SUCCESS; } + +G_MODULE_EXPORT const char * +test_cairo_clock_describe (void) +{ + return "Simple 2D canvas using a Cairo texture actor"; +} diff --git a/tests/interactive/test-constraints.c b/tests/interactive/test-constraints.c index 9f9a5f2c2..3e45ce990 100644 --- a/tests/interactive/test-constraints.c +++ b/tests/interactive/test-constraints.c @@ -247,3 +247,9 @@ test_constraints_main (int argc, char *argv[]) return EXIT_SUCCESS; } + +G_MODULE_EXPORT const char * +test_constraints_describe (void) +{ + return "Visualize usage of Bind and Align constraints"; +} diff --git a/tests/interactive/test-drop.c b/tests/interactive/test-drop.c index 2b511d4e8..0427b02e0 100644 --- a/tests/interactive/test-drop.c +++ b/tests/interactive/test-drop.c @@ -243,3 +243,9 @@ test_drop_main (int argc, char *argv[]) return EXIT_SUCCESS; } + +G_MODULE_EXPORT const char * +test_drop_describe (void) +{ + return "Drop action support"; +} diff --git a/tests/interactive/test-easing.c b/tests/interactive/test-easing.c index 2bd8a9c18..876ad957f 100644 --- a/tests/interactive/test-easing.c +++ b/tests/interactive/test-easing.c @@ -262,3 +262,9 @@ test_easing_main (int argc, char *argv[]) return EXIT_SUCCESS; } + +G_MODULE_EXPORT const char * +test_easing_describe (void) +{ + return "Visualize all easing modes provided by Clutter"; +} diff --git a/tests/interactive/test-main.c b/tests/interactive/test-main.c index 2a0cd74a5..10d032233 100644 --- a/tests/interactive/test-main.c +++ b/tests/interactive/test-main.c @@ -1,37 +1,207 @@ +#include +#include #include #include +#include "test-unit-names.h" + +#define MAX_DESC_SIZE 72 + +static GModule *module = NULL; + +static gpointer +get_symbol_with_suffix (const char *unit_name, + const char *suffix) +{ + char *main_symbol_name; + gpointer func; + + main_symbol_name = g_strconcat (unit_name, "_", suffix, NULL); + main_symbol_name = g_strdelimit (main_symbol_name, "-", '_'); + + g_module_symbol (module, main_symbol_name, &func); + + g_free (main_symbol_name); + + return func; +} + +static gpointer +get_unit_name_main (const char *unit_name) +{ + return get_symbol_with_suffix (unit_name, "main"); +} +static char * +get_unit_name_description (const char *unit_name, + gssize max_len) +{ + const char *description; + gpointer func; + char *retval; + + func = get_symbol_with_suffix (unit_name, "describe"); + if (func == NULL) + description = "No description found"; + else + { + const char *(* unit_test_describe) (void); + + unit_test_describe = func; + + description = unit_test_describe (); + } + + if (max_len > 0 && strlen (description) >= max_len) + { + GString *buf = g_string_sized_new (max_len); + char *newline; + + newline = strchr (description, '\n'); + if (newline != NULL) + { + g_string_append_len (buf, description, + MIN (newline - description - 1, max_len - 3)); + } + else + g_string_append_len (buf, description, max_len - 3); + + g_string_append (buf, "..."); + + retval = g_string_free (buf, FALSE); + } + else + retval = g_strdup (description); + + return retval; +} + +static gboolean list_all = FALSE; +static gboolean describe = FALSE; +static char **unit_names = NULL; + +static GOptionEntry entries[] = { + { + "describe", 'd', + 0, + G_OPTION_ARG_NONE, &describe, + "Describe the interactive unit test", NULL, + }, + { + "list-all", 'l', + 0, + G_OPTION_ARG_NONE, &list_all, + "List all available units", NULL, + }, + { + G_OPTION_REMAINING, 0, + 0, + G_OPTION_ARG_STRING_ARRAY, &unit_names, + "The interactive unit test", "UNIT_NAME" + }, + { NULL } +}; int main (int argc, char **argv) { - GModule *module; - char *unit_test; - char *main_symbol_name; - gpointer func; - int (*unit_test_main) (int argc, char **argv); - int ret; + int ret, i, n_unit_names; + GOptionContext *context; + + context = g_option_context_new (" - Interactive test suite"); + g_option_context_add_main_entries (context, entries, NULL); + g_option_context_set_help_enabled (context, TRUE); + g_option_context_set_ignore_unknown_options (context, TRUE); + if (!g_option_context_parse (context, &argc, &argv, NULL)) + { + g_print ("Usage: test-interactive \n"); + return EXIT_FAILURE; + } + + g_option_context_free (context); - if (argc < 2) - g_error ("Usage: %s unit_test", argv[0]); - module = g_module_open (NULL, 0); if (!module) - g_error ("Failed to open self for symbol lookup"); + g_error ("*** Failed to open self for symbol lookup"); - unit_test = g_path_get_basename (argv[1]); + ret = EXIT_SUCCESS; - main_symbol_name = g_strdup_printf ("%s_main", unit_test); - main_symbol_name = g_strdelimit (main_symbol_name, "-", '_'); + if (list_all) + { + g_print ("* Available unit tests:\n"); - if (!g_module_symbol (module, main_symbol_name, &func)) - g_error ("Failed to look up main symbol for the test: %s", unit_test); + for (i = 0; i < G_N_ELEMENTS (test_unit_names); i++) + { + char *str; + gsize len; - unit_test_main = func; - ret = unit_test_main (argc - 1, argv + 1); - - g_free (unit_test); - g_free (main_symbol_name); + len = MAX_DESC_SIZE - strlen (test_unit_names[i]); + str = get_unit_name_description (test_unit_names[i], len - 2); + + g_print (" - %s:%*s%s\n", + test_unit_names[i], + (int) len - strlen (str), " ", + str); + + g_free (str); + } + + ret = EXIT_SUCCESS; + goto out; + } + + n_unit_names = g_strv_length (unit_names); + for (i = 0; i < n_unit_names; i++) + { + const char *unit_name = unit_names[i]; + char *unit_test = NULL; + gboolean found; + int j; + + unit_test = g_path_get_basename (unit_name); + + found = FALSE; + for (j = 0; j < G_N_ELEMENTS (test_unit_names); j++) + { + if (strcmp (test_unit_names[j], unit_test) == 0) + { + found = TRUE; + break; + } + } + + if (!found) + g_error ("*** Unit '%s' does not exist", unit_test); + + if (describe) + { + char *str; + + str = get_unit_name_description (unit_test, -1); + + g_print ("* %s:\n%s\n\n", unit_test, str); + + g_free (str); + + ret = EXIT_SUCCESS; + } + else + { + int (* unit_test_main) (int argc, char **argv); + gpointer func; + + func = get_unit_name_main (unit_test); + if (func == NULL) + g_error ("*** Unable to find the main entry point for '%s'", unit_test); + + unit_test_main = func; + + ret = unit_test_main (argc, argv); + } + + g_free (unit_test); + } + +out: g_module_close (module); return ret; diff --git a/tests/interactive/test-table-layout.c b/tests/interactive/test-table-layout.c index 209659b48..62f3b17a1 100644 --- a/tests/interactive/test-table-layout.c +++ b/tests/interactive/test-table-layout.c @@ -274,3 +274,9 @@ test_table_layout_main (int argc, char *argv[]) return EXIT_SUCCESS; } + +G_MODULE_EXPORT const char * +test_table_layout_describe (void) +{ + return "Table layout manager"; +} diff --git a/tests/interactive/test-text-field.c b/tests/interactive/test-text-field.c index e837a021a..2897befa8 100644 --- a/tests/interactive/test-text-field.c +++ b/tests/interactive/test-text-field.c @@ -334,3 +334,14 @@ test_text_field_main (gint argc, return EXIT_SUCCESS; } + +G_MODULE_EXPORT const char * +test_text_field_describe (void) +{ + return +"Text actor single-line and password mode support\n" +"\n" +"This test checks the :single-line-mode and :password-char properties of\n" +"the ClutterText actor, plus the password hint feature and the :max-length\n" +"property."; +} diff --git a/tests/interactive/test-texture-async.c b/tests/interactive/test-texture-async.c index f88f382a5..a69690b27 100644 --- a/tests/interactive/test-texture-async.c +++ b/tests/interactive/test-texture-async.c @@ -1,7 +1,5 @@ #include #include - -#undef CLUTTER_DISABLE_DEPRECATED #include enum @@ -11,6 +9,8 @@ enum LOAD_ASYNC }; +static ClutterActor *stage = NULL; + static void on_load_finished (ClutterTexture *texture, const GError *error, @@ -52,17 +52,11 @@ size_change_cb (ClutterTexture *texture, static gboolean task (gpointer user_data) { - ClutterTimeline *timeline; - ClutterAlpha *alpha; - ClutterBehaviour *depth_behavior; - ClutterActor *image[4]; - ClutterActor *clone[4]; - ClutterActor *stage; - gchar *path = user_data; + const gchar *path = user_data; + ClutterActor *image[3]; + ClutterActor *clone[3]; gint i; - stage = clutter_stage_get_default (); - image[0] = g_object_new (CLUTTER_TYPE_TEXTURE, NULL); g_signal_connect (image[0], "load-finished", G_CALLBACK (on_load_finished), @@ -93,62 +87,69 @@ gboolean task (gpointer user_data) } for (i = 0; i < 3; i++) - clutter_container_add (CLUTTER_CONTAINER (stage), image[i], NULL); + clutter_container_add_actor (CLUTTER_CONTAINER (stage), image[i]); for (i = 0; i < 3; i++) { - clutter_actor_set_position (image[i], 50+i*100, 0+i*50); - clone[i]=clutter_clone_new (image[i]); + clutter_actor_set_position (image[i], 50 + i * 100, 0 + i * 50); + clone[i] = clutter_clone_new (image[i]); g_signal_connect (image[i], "size-change", G_CALLBACK (size_change_cb), clone[i]); - clutter_container_add (CLUTTER_CONTAINER (stage), clone[i], NULL); - clutter_actor_set_position (clone[i], 50+i*100, 150+i*50+100); + clutter_container_add_actor (CLUTTER_CONTAINER (stage), clone[i]); + clutter_actor_set_position (clone[i], 50 + i * 100, 150 + i * 50 + 100); } for (i = 0; i < 3; i++) { - timeline = clutter_timeline_new (5000); - 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_set_depth (image[i], -2500); + clutter_actor_animate (image[i], CLUTTER_LINEAR, 5000, + "depth", 0.0, + NULL); } return FALSE; } +static void +cleanup_task (gpointer data) +{ +} G_MODULE_EXPORT gint test_texture_async_main (int argc, char *argv[]) { - ClutterActor *stage; - ClutterColor stage_color = { 0x12, 0x34, 0x56, 0xff }; - gchar *path; + gchar *path; + + g_thread_init (NULL); + clutter_threads_init (); if (clutter_init (&argc, &argv) != CLUTTER_INIT_SUCCESS) return 1; - g_thread_init (NULL); - stage = clutter_stage_get_default (); - clutter_stage_set_color (CLUTTER_STAGE (stage), &stage_color); + stage = clutter_stage_new (); + clutter_stage_set_title (CLUTTER_STAGE (stage), "Asynchronous Texture Loading"); + clutter_stage_set_color (CLUTTER_STAGE (stage), CLUTTER_COLOR_LightSkyBlue); + g_signal_connect (stage, "destroy", G_CALLBACK (clutter_main_quit), NULL); clutter_actor_show (stage); - g_signal_connect (stage, - "button-press-event", G_CALLBACK (clutter_main_quit), - NULL); path = (argc > 1) ? g_strdup (argv[1]) : g_build_filename (TESTS_DATADIR, "redhand.png", NULL); - clutter_threads_add_timeout (500, task, path); + clutter_threads_add_timeout_full (G_PRIORITY_DEFAULT, 500, + task, path, + cleanup_task); clutter_main (); g_free (path); - /*g_object_unref (depth_behavior); - g_object_unref (timeline);*/ - return EXIT_SUCCESS; } + +G_MODULE_EXPORT const char * +test_texture_async_describe (void) +{ + return "Texture asynchronous loading using threads"; +} diff --git a/tests/interactive/test-textures.c b/tests/interactive/test-texture-slicing.c similarity index 95% rename from tests/interactive/test-textures.c rename to tests/interactive/test-texture-slicing.c index d8094e947..f86a76e0c 100644 --- a/tests/interactive/test-textures.c +++ b/tests/interactive/test-texture-slicing.c @@ -110,3 +110,9 @@ test_textures_main (int argc, char *argv[]) return EXIT_SUCCESS; } + +G_MODULE_EXPORT const char * +test_texture_slicing_describe (void) +{ + return "Check texture slicing support in CoglTexture"; +}