From ec0b7814667fbbeee3dd25c79d565c645d8f01ba Mon Sep 17 00:00:00 2001 From: Robert Bragg Date: Tue, 15 Mar 2011 13:17:04 +0000 Subject: [PATCH] stage: Move _clutter_do_pick to clutter-stage.c This moves the implementation of _clutter_do_pick to clutter-stage.c and renames it _clutter_stage_do_pick. This function can be compared to _clutter_stage_do_update/redraw in that it prepares for and starts a traversal of a scenegraph descending from a given stage. Since it is desirable that this function should have access to the private state of the stage it is awkward to maintain outside of clutter-stage.c. Besides moving _clutter_do_pick this patch is also able to remove the following private state accessors from clutter-stage-private.h: _clutter_stage_set_pick_buffer_valid, _clutter_stage_get_pick_buffer_valid, _clutter_stage_increment_picks_per_frame_counter, _clutter_stage_reset_picks_per_frame_counter and _clutter_stage_get_picks_per_frame_counter. --- clutter/clutter-input-device.c | 3 +- clutter/clutter-main.c | 270 +------------------------ clutter/clutter-private.h | 7 +- clutter/clutter-stage-private.h | 13 +- clutter/clutter-stage.c | 343 +++++++++++++++++++++++++++----- 5 files changed, 307 insertions(+), 329 deletions(-) diff --git a/clutter/clutter-input-device.c b/clutter/clutter-input-device.c index dd277d13d..24f0b9486 100644 --- a/clutter/clutter-input-device.c +++ b/clutter/clutter-input-device.c @@ -708,7 +708,8 @@ _clutter_input_device_update (ClutterInputDevice *device, clutter_input_device_get_device_coords (device, &x, &y); old_cursor_actor = device->cursor_actor; - new_cursor_actor = _clutter_do_pick (stage, x, y, CLUTTER_PICK_REACTIVE); + new_cursor_actor = + _clutter_stage_do_pick (stage, x, y, CLUTTER_PICK_REACTIVE); /* if the pick could not find an actor then we do not update the * input device, to avoid ghost enter/leave events; the pick should diff --git a/clutter/clutter-main.c b/clutter/clutter-main.c index 533839ead..c1e6884a6 100644 --- a/clutter/clutter-main.c +++ b/clutter/clutter-main.c @@ -94,10 +94,6 @@ #include #include -#ifdef USE_GDKPIXBUF -#include -#endif - #include "clutter-actor.h" #include "clutter-backend-private.h" #include "clutter-debug.h" @@ -307,8 +303,8 @@ clutter_get_motion_events_enabled (void) return context->motion_events_per_actor; } -static inline ClutterActor * -_clutter_actor_get_by_id (guint32 actor_id) +ClutterActor * +_clutter_get_actor_by_id (guint32 actor_id) { ClutterMainContext *context = _clutter_context_get_default (); @@ -388,7 +384,7 @@ _clutter_id_to_color (guint id_, } } -static inline guint +guint _clutter_pixel_to_id (guchar pixel[4]) { ClutterMainContext *ctx; @@ -436,258 +432,6 @@ _clutter_pixel_to_id (guchar pixel[4]) return retval; } -#ifdef USE_GDKPIXBUF -static void -pixbuf_free (guchar *pixels, - gpointer data) -{ - g_free (pixels); -} -#endif - -static void -read_pixels_to_file (char *filename_stem, - int x, - int y, - int width, - int height) -{ -#ifdef USE_GDKPIXBUF - GLubyte *data; - GdkPixbuf *pixbuf; - static int read_count = 0; - - data = g_malloc (4 * width * height); - cogl_read_pixels (x, y, width, height, - COGL_READ_PIXELS_COLOR_BUFFER, - COGL_PIXEL_FORMAT_RGB_888, - data); - pixbuf = gdk_pixbuf_new_from_data (data, - GDK_COLORSPACE_RGB, - FALSE, /* has alpha */ - 8, /* bits per sample */ - width, /* width */ - height, /* height */ - width * 3, /* rowstride */ - pixbuf_free, /* callback to free data */ - NULL); /* callback data */ - if (pixbuf) - { - char *filename = g_strdup_printf ("%s-%05d.png", - filename_stem, - read_count); - GError *error = NULL; - - if (!gdk_pixbuf_save (pixbuf, filename, "png", &error, NULL)) - { - g_warning ("Failed to save pick buffer to file %s: %s", - filename, error->message); - g_error_free (error); - } - - g_free (filename); - g_object_unref (pixbuf); - read_count++; - } -#else /* !USE_GDKPIXBUF */ - { - static gboolean seen = FALSE; - - if (!seen) - { - g_warning ("dumping buffers to an image isn't supported on platforms " - "without gdk pixbuf support\n"); - seen = TRUE; - } - } -#endif /* USE_GDKPIXBUF */ -} - -ClutterActor * -_clutter_do_pick (ClutterStage *stage, - gint x, - gint y, - ClutterPickMode mode) -{ - ClutterMainContext *context; - guchar pixel[4] = { 0xff, 0xff, 0xff, 0xff }; - CoglColor stage_pick_id; - guint32 id_; - GLboolean dither_was_on; - ClutterActor *actor; - gboolean is_clipped; - CLUTTER_STATIC_COUNTER (do_pick_counter, - "_clutter_do_pick counter", - "Increments for each full pick run", - 0 /* no application private data */); - CLUTTER_STATIC_TIMER (pick_timer, - "Mainloop", /* parent */ - "Picking", - "The time spent picking", - 0 /* no application private data */); - CLUTTER_STATIC_TIMER (pick_clear, - "Picking", /* parent */ - "Stage clear (pick)", - "The time spent clearing stage for picking", - 0 /* no application private data */); - CLUTTER_STATIC_TIMER (pick_paint, - "Picking", /* parent */ - "Painting actors (pick mode)", - "The time spent painting actors in pick mode", - 0 /* no application private data */); - CLUTTER_STATIC_TIMER (pick_read, - "Picking", /* parent */ - "Read Pixels", - "The time spent issuing a read pixels", - 0 /* no application private data */); - - g_return_val_if_fail (CLUTTER_IS_STAGE (stage), NULL); - - if (G_UNLIKELY (clutter_pick_debug_flags & CLUTTER_DEBUG_NOP_PICKING)) - return CLUTTER_ACTOR (stage); - -#ifdef CLUTTER_ENABLE_PROFILE - if (clutter_profile_flags & CLUTTER_PROFILE_PICKING_ONLY) - _clutter_profile_resume (); -#endif /* CLUTTER_ENABLE_PROFILE */ - - CLUTTER_COUNTER_INC (_clutter_uprof_context, do_pick_counter); - CLUTTER_TIMER_START (_clutter_uprof_context, pick_timer); - - context = _clutter_context_get_default (); - - /* It's possible that we currently have a static scene and have renderered a - * full, unclipped pick buffer. If so we can simply continue to read from - * this cached buffer until the scene next changes. */ - if (_clutter_stage_get_pick_buffer_valid (stage, mode)) - { - CLUTTER_TIMER_START (_clutter_uprof_context, pick_read); - cogl_read_pixels (x, y, 1, 1, - COGL_READ_PIXELS_COLOR_BUFFER, - COGL_PIXEL_FORMAT_RGBA_8888_PRE, - pixel); - CLUTTER_TIMER_STOP (_clutter_uprof_context, pick_read); - - CLUTTER_NOTE (PICK, "Reusing pick buffer from previous render to fetch " - "actor at %i,%i", x, y); - - /* FIXME: This is a lazy copy and paste of the logic at the end of this - * function used when we actually do a pick render. It should be - * consolidated somehow. - */ - if (pixel[0] == 0xff && pixel[1] == 0xff && pixel[2] == 0xff) - { - actor = CLUTTER_ACTOR (stage); - goto result; - } - - id_ = _clutter_pixel_to_id (pixel); - actor = _clutter_actor_get_by_id (id_); - goto result; - } - - _clutter_stage_increment_picks_per_frame_counter (stage); - - _clutter_backend_ensure_context (context->backend, stage); - - /* needed for when a context switch happens */ - _clutter_stage_maybe_setup_viewport (stage); - - /* If we are seeing multiple picks per frame that means the scene is static - * so we promote to doing a non-scissored pick render so that all subsequent - * picks for the same static scene won't require additional renders */ - if (_clutter_stage_get_picks_per_frame_counter (stage) < 2) - { - if (G_LIKELY (!(clutter_pick_debug_flags & - CLUTTER_DEBUG_DUMP_PICK_BUFFERS))) - cogl_clip_push_window_rectangle (x, y, 1, 1); - is_clipped = TRUE; - } - else - is_clipped = FALSE; - - CLUTTER_NOTE (PICK, "Performing %s pick at %i,%i", - is_clipped ? "clippped" : "full", x, y); - - cogl_disable_fog (); - cogl_color_init_from_4ub (&stage_pick_id, 255, 255, 255, 255); - CLUTTER_TIMER_START (_clutter_uprof_context, pick_clear); - cogl_clear (&stage_pick_id, - COGL_BUFFER_BIT_COLOR | - COGL_BUFFER_BIT_DEPTH); - CLUTTER_TIMER_STOP (_clutter_uprof_context, pick_clear); - - /* Disable dithering (if any) when doing the painting in pick mode */ - dither_was_on = glIsEnabled (GL_DITHER); - if (dither_was_on) - glDisable (GL_DITHER); - - /* Render the entire scence in pick mode - just single colored silhouette's - * are drawn offscreen (as we never swap buffers) - */ - CLUTTER_TIMER_START (_clutter_uprof_context, pick_paint); - context->pick_mode = mode; - _clutter_stage_do_paint (stage, NULL); - context->pick_mode = CLUTTER_PICK_NONE; - CLUTTER_TIMER_STOP (_clutter_uprof_context, pick_paint); - - if (is_clipped) - { - if (G_LIKELY (!(clutter_pick_debug_flags & - CLUTTER_DEBUG_DUMP_PICK_BUFFERS))) - cogl_clip_pop (); - - _clutter_stage_set_pick_buffer_valid (stage, FALSE, -1); - } - else - _clutter_stage_set_pick_buffer_valid (stage, TRUE, mode); - - /* Read the color of the screen co-ords pixel. RGBA_8888_PRE is used - even though we don't care about the alpha component because under - GLES this is the only format that is guaranteed to work so Cogl - will end up having to do a conversion if any other format is - used. The format is requested as pre-multiplied because Cogl - assumes that all pixels in the framebuffer are premultiplied so - it avoids a conversion. */ - CLUTTER_TIMER_START (_clutter_uprof_context, pick_read); - cogl_read_pixels (x, y, 1, 1, - COGL_READ_PIXELS_COLOR_BUFFER, - COGL_PIXEL_FORMAT_RGBA_8888_PRE, - pixel); - CLUTTER_TIMER_STOP (_clutter_uprof_context, pick_read); - - if (G_UNLIKELY (clutter_pick_debug_flags & CLUTTER_DEBUG_DUMP_PICK_BUFFERS)) - { - read_pixels_to_file ("pick-buffer", 0, 0, - clutter_actor_get_width (CLUTTER_ACTOR (stage)), - clutter_actor_get_height (CLUTTER_ACTOR (stage))); - } - - /* Restore whether GL_DITHER was enabled */ - if (dither_was_on) - glEnable (GL_DITHER); - - if (pixel[0] == 0xff && pixel[1] == 0xff && pixel[2] == 0xff) - { - actor = CLUTTER_ACTOR (stage); - goto result; - } - - id_ = _clutter_pixel_to_id (pixel); - actor = _clutter_actor_get_by_id (id_); - -result: - - CLUTTER_TIMER_STOP (_clutter_uprof_context, pick_timer); - -#ifdef CLUTTER_ENABLE_PROFILE - if (clutter_profile_flags & CLUTTER_PROFILE_PICKING_ONLY) - _clutter_profile_suspend (); -#endif - - return actor; -} - static CoglPangoFontMap * clutter_context_get_pango_fontmap (void) { @@ -2482,9 +2226,9 @@ _clutter_process_event_details (ClutterActor *stage, { CLUTTER_NOTE (EVENT, "No device found: picking"); - actor = _clutter_do_pick (CLUTTER_STAGE (stage), - x, y, - CLUTTER_PICK_REACTIVE); + actor = _clutter_stage_do_pick (CLUTTER_STAGE (stage), + x, y, + CLUTTER_PICK_REACTIVE); } if (actor == NULL) @@ -2568,7 +2312,7 @@ _clutter_process_event (ClutterEvent *event) ClutterActor * clutter_get_actor_by_gid (guint32 id_) { - return _clutter_actor_get_by_id (id_); + return _clutter_get_actor_by_id (id_); } void diff --git a/clutter/clutter-private.h b/clutter/clutter-private.h index c88f718ac..4a27343a8 100644 --- a/clutter/clutter-private.h +++ b/clutter/clutter-private.h @@ -194,13 +194,10 @@ G_CONST_RETURN gchar *_clutter_gettext (const gchar *str); gboolean _clutter_feature_init (GError **error); /* Picking code */ -ClutterActor *_clutter_do_pick (ClutterStage *stage, - gint x, - gint y, - ClutterPickMode mode); - +guint _clutter_pixel_to_id (guchar pixel[4]); void _clutter_id_to_color (guint id, ClutterColor *col); +ClutterActor *_clutter_get_actor_by_id (guint32 actor_id); /* use this function as the accumulator if you have a signal with * a G_TYPE_BOOLEAN return value; this will stop the emission as diff --git a/clutter/clutter-stage-private.h b/clutter/clutter-stage-private.h index 7dad14fc7..79a22f3d3 100644 --- a/clutter/clutter-stage-private.h +++ b/clutter/clutter-stage-private.h @@ -64,14 +64,11 @@ void _clutter_stage_process_queued_events (ClutterStage *stage); void _clutter_stage_update_input_devices (ClutterStage *stage); int _clutter_stage_get_pending_swaps (ClutterStage *stage); gboolean _clutter_stage_has_full_redraw_queued (ClutterStage *stage); -void _clutter_stage_set_pick_buffer_valid (ClutterStage *stage, - gboolean valid, - ClutterPickMode mode); -gboolean _clutter_stage_get_pick_buffer_valid (ClutterStage *stage, - ClutterPickMode mode); -void _clutter_stage_increment_picks_per_frame_counter (ClutterStage *stage); -void _clutter_stage_reset_picks_per_frame_counter (ClutterStage *stage); -guint _clutter_stage_get_picks_per_frame_counter (ClutterStage *stage); + +ClutterActor *_clutter_stage_do_pick (ClutterStage *stage, + gint x, + gint y, + ClutterPickMode mode); ClutterPaintVolume *_clutter_stage_paint_volume_stack_allocate (ClutterStage *stage); void _clutter_stage_paint_volume_stack_free_all (ClutterStage *stage); diff --git a/clutter/clutter-stage.c b/clutter/clutter-stage.c index 689b782f7..bb2b3456a 100644 --- a/clutter/clutter-stage.c +++ b/clutter/clutter-stage.c @@ -73,11 +73,17 @@ #include "clutter-stage-private.h" #include "clutter-util.h" #include "clutter-version.h" /* For flavour */ +#include "clutter-private.h" #include "cogl/cogl.h" #include +#ifdef USE_GDKPIXBUF +#include +#endif + + G_DEFINE_TYPE (ClutterStage, clutter_stage, CLUTTER_TYPE_GROUP); #define CLUTTER_STAGE_GET_PRIVATE(obj) \ @@ -954,6 +960,28 @@ _clutter_stage_maybe_relayout (ClutterActor *actor) } } +static gboolean +_clutter_stage_get_pick_buffer_valid (ClutterStage *stage, ClutterPickMode mode) +{ + g_return_val_if_fail (CLUTTER_IS_STAGE (stage), FALSE); + + if (stage->priv->pick_buffer_mode != mode) + return FALSE; + + return stage->priv->have_valid_pick_buffer; +} + +static void +_clutter_stage_set_pick_buffer_valid (ClutterStage *stage, + gboolean valid, + ClutterPickMode mode) +{ + g_return_if_fail (CLUTTER_IS_STAGE (stage)); + + stage->priv->have_valid_pick_buffer = !!valid; + stage->priv->pick_buffer_mode = mode; +} + static void clutter_stage_do_redraw (ClutterStage *stage) { @@ -966,7 +994,7 @@ clutter_stage_do_redraw (ClutterStage *stage) stage); _clutter_stage_set_pick_buffer_valid (stage, FALSE, -1); - _clutter_stage_reset_picks_per_frame_counter (stage); + priv->picks_per_frame = 0; _clutter_backend_ensure_context (backend, stage); @@ -1130,6 +1158,263 @@ _clutter_stage_has_full_redraw_queued (ClutterStage *stage) return FALSE; } +#ifdef USE_GDKPIXBUF +static void +pixbuf_free (guchar *pixels, + gpointer data) +{ + g_free (pixels); +} +#endif + +static void +read_pixels_to_file (char *filename_stem, + int x, + int y, + int width, + int height) +{ +#ifdef USE_GDKPIXBUF + GLubyte *data; + GdkPixbuf *pixbuf; + static int read_count = 0; + + data = g_malloc (4 * width * height); + cogl_read_pixels (x, y, width, height, + COGL_READ_PIXELS_COLOR_BUFFER, + COGL_PIXEL_FORMAT_RGB_888, + data); + pixbuf = gdk_pixbuf_new_from_data (data, + GDK_COLORSPACE_RGB, + FALSE, /* has alpha */ + 8, /* bits per sample */ + width, /* width */ + height, /* height */ + width * 3, /* rowstride */ + pixbuf_free, /* callback to free data */ + NULL); /* callback data */ + if (pixbuf) + { + char *filename = g_strdup_printf ("%s-%05d.png", + filename_stem, + read_count); + GError *error = NULL; + + if (!gdk_pixbuf_save (pixbuf, filename, "png", &error, NULL)) + { + g_warning ("Failed to save pick buffer to file %s: %s", + filename, error->message); + g_error_free (error); + } + + g_free (filename); + g_object_unref (pixbuf); + read_count++; + } +#else /* !USE_GDKPIXBUF */ + { + static gboolean seen = FALSE; + + if (!seen) + { + g_warning ("dumping buffers to an image isn't supported on platforms " + "without gdk pixbuf support\n"); + seen = TRUE; + } + } +#endif /* USE_GDKPIXBUF */ +} + +ClutterActor * +_clutter_stage_do_pick (ClutterStage *stage, + gint x, + gint y, + ClutterPickMode mode) +{ + ClutterStagePrivate *priv; + ClutterMainContext *context; + guchar pixel[4] = { 0xff, 0xff, 0xff, 0xff }; + CoglColor stage_pick_id; + guint32 id_; + GLboolean dither_was_on; + ClutterActor *actor; + gboolean is_clipped; + CLUTTER_STATIC_COUNTER (do_pick_counter, + "_clutter_stage_do_pick counter", + "Increments for each full pick run", + 0 /* no application private data */); + CLUTTER_STATIC_TIMER (pick_timer, + "Mainloop", /* parent */ + "Picking", + "The time spent picking", + 0 /* no application private data */); + CLUTTER_STATIC_TIMER (pick_clear, + "Picking", /* parent */ + "Stage clear (pick)", + "The time spent clearing stage for picking", + 0 /* no application private data */); + CLUTTER_STATIC_TIMER (pick_paint, + "Picking", /* parent */ + "Painting actors (pick mode)", + "The time spent painting actors in pick mode", + 0 /* no application private data */); + CLUTTER_STATIC_TIMER (pick_read, + "Picking", /* parent */ + "Read Pixels", + "The time spent issuing a read pixels", + 0 /* no application private data */); + + g_return_val_if_fail (CLUTTER_IS_STAGE (stage), NULL); + + priv = stage->priv; + + if (G_UNLIKELY (clutter_pick_debug_flags & CLUTTER_DEBUG_NOP_PICKING)) + return CLUTTER_ACTOR (stage); + +#ifdef CLUTTER_ENABLE_PROFILE + if (clutter_profile_flags & CLUTTER_PROFILE_PICKING_ONLY) + _clutter_profile_resume (); +#endif /* CLUTTER_ENABLE_PROFILE */ + + CLUTTER_COUNTER_INC (_clutter_uprof_context, do_pick_counter); + CLUTTER_TIMER_START (_clutter_uprof_context, pick_timer); + + context = _clutter_context_get_default (); + + /* It's possible that we currently have a static scene and have renderered a + * full, unclipped pick buffer. If so we can simply continue to read from + * this cached buffer until the scene next changes. */ + if (_clutter_stage_get_pick_buffer_valid (stage, mode)) + { + CLUTTER_TIMER_START (_clutter_uprof_context, pick_read); + cogl_read_pixels (x, y, 1, 1, + COGL_READ_PIXELS_COLOR_BUFFER, + COGL_PIXEL_FORMAT_RGBA_8888_PRE, + pixel); + CLUTTER_TIMER_STOP (_clutter_uprof_context, pick_read); + + CLUTTER_NOTE (PICK, "Reusing pick buffer from previous render to fetch " + "actor at %i,%i", x, y); + + /* FIXME: This is a lazy copy and paste of the logic at the end of this + * function used when we actually do a pick render. It should be + * consolidated somehow. + */ + if (pixel[0] == 0xff && pixel[1] == 0xff && pixel[2] == 0xff) + { + actor = CLUTTER_ACTOR (stage); + goto result; + } + + id_ = _clutter_pixel_to_id (pixel); + actor = _clutter_get_actor_by_id (id_); + goto result; + } + + priv->picks_per_frame++; + + _clutter_backend_ensure_context (context->backend, stage); + + /* needed for when a context switch happens */ + _clutter_stage_maybe_setup_viewport (stage); + + /* If we are seeing multiple picks per frame that means the scene is static + * so we promote to doing a non-scissored pick render so that all subsequent + * picks for the same static scene won't require additional renders */ + if (priv->picks_per_frame < 2) + { + if (G_LIKELY (!(clutter_pick_debug_flags & + CLUTTER_DEBUG_DUMP_PICK_BUFFERS))) + cogl_clip_push_window_rectangle (x, y, 1, 1); + is_clipped = TRUE; + } + else + is_clipped = FALSE; + + CLUTTER_NOTE (PICK, "Performing %s pick at %i,%i", + is_clipped ? "clippped" : "full", x, y); + + cogl_disable_fog (); + cogl_color_init_from_4ub (&stage_pick_id, 255, 255, 255, 255); + CLUTTER_TIMER_START (_clutter_uprof_context, pick_clear); + cogl_clear (&stage_pick_id, + COGL_BUFFER_BIT_COLOR | + COGL_BUFFER_BIT_DEPTH); + CLUTTER_TIMER_STOP (_clutter_uprof_context, pick_clear); + + /* Disable dithering (if any) when doing the painting in pick mode */ + dither_was_on = glIsEnabled (GL_DITHER); + if (dither_was_on) + glDisable (GL_DITHER); + + /* Render the entire scence in pick mode - just single colored silhouette's + * are drawn offscreen (as we never swap buffers) + */ + CLUTTER_TIMER_START (_clutter_uprof_context, pick_paint); + context->pick_mode = mode; + _clutter_stage_do_paint (stage, NULL); + context->pick_mode = CLUTTER_PICK_NONE; + CLUTTER_TIMER_STOP (_clutter_uprof_context, pick_paint); + + if (is_clipped) + { + if (G_LIKELY (!(clutter_pick_debug_flags & + CLUTTER_DEBUG_DUMP_PICK_BUFFERS))) + cogl_clip_pop (); + + _clutter_stage_set_pick_buffer_valid (stage, FALSE, -1); + } + else + _clutter_stage_set_pick_buffer_valid (stage, TRUE, mode); + + /* Read the color of the screen co-ords pixel. RGBA_8888_PRE is used + even though we don't care about the alpha component because under + GLES this is the only format that is guaranteed to work so Cogl + will end up having to do a conversion if any other format is + used. The format is requested as pre-multiplied because Cogl + assumes that all pixels in the framebuffer are premultiplied so + it avoids a conversion. */ + CLUTTER_TIMER_START (_clutter_uprof_context, pick_read); + cogl_read_pixels (x, y, 1, 1, + COGL_READ_PIXELS_COLOR_BUFFER, + COGL_PIXEL_FORMAT_RGBA_8888_PRE, + pixel); + CLUTTER_TIMER_STOP (_clutter_uprof_context, pick_read); + + if (G_UNLIKELY (clutter_pick_debug_flags & CLUTTER_DEBUG_DUMP_PICK_BUFFERS)) + { + read_pixels_to_file ("pick-buffer", 0, 0, + clutter_actor_get_width (CLUTTER_ACTOR (stage)), + clutter_actor_get_height (CLUTTER_ACTOR (stage))); + } + + /* Restore whether GL_DITHER was enabled */ + if (dither_was_on) + glEnable (GL_DITHER); + + if (pixel[0] == 0xff && pixel[1] == 0xff && pixel[2] == 0xff) + { + actor = CLUTTER_ACTOR (stage); + goto result; + } + + id_ = _clutter_pixel_to_id (pixel); + actor = _clutter_get_actor_by_id (id_); + +result: + + CLUTTER_TIMER_STOP (_clutter_uprof_context, pick_timer); + +#ifdef CLUTTER_ENABLE_PROFILE + if (clutter_profile_flags & CLUTTER_PROFILE_PICKING_ONLY) + _clutter_profile_suspend (); +#endif + + return actor; +} + + + static gboolean clutter_stage_real_delete_event (ClutterStage *stage, ClutterEvent *event) @@ -1766,7 +2051,7 @@ clutter_stage_init (ClutterStage *self) _clutter_stage_set_viewport (self, 0, 0, geom.width, geom.height); _clutter_stage_set_pick_buffer_valid (self, FALSE, CLUTTER_PICK_ALL); - _clutter_stage_reset_picks_per_frame_counter (self); + priv->picks_per_frame = 0; priv->paint_volume_stack = g_array_new (FALSE, FALSE, sizeof (ClutterPaintVolume)); @@ -2331,7 +2616,7 @@ clutter_stage_get_actor_at_pos (ClutterStage *stage, gint x, gint y) { - return _clutter_do_pick (stage, x, y, pick_mode); + return _clutter_stage_do_pick (stage, x, y, pick_mode); } /** @@ -3250,52 +3535,6 @@ clutter_stage_get_no_clear_hint (ClutterStage *stage) return (stage->priv->stage_hints & CLUTTER_STAGE_NO_CLEAR_ON_PAINT) != 0; } -gboolean -_clutter_stage_get_pick_buffer_valid (ClutterStage *stage, ClutterPickMode mode) -{ - g_return_val_if_fail (CLUTTER_IS_STAGE (stage), FALSE); - - if (stage->priv->pick_buffer_mode != mode) - return FALSE; - - return stage->priv->have_valid_pick_buffer; -} - -void -_clutter_stage_set_pick_buffer_valid (ClutterStage *stage, - gboolean valid, - ClutterPickMode mode) -{ - g_return_if_fail (CLUTTER_IS_STAGE (stage)); - - stage->priv->have_valid_pick_buffer = !!valid; - stage->priv->pick_buffer_mode = mode; -} - -void -_clutter_stage_increment_picks_per_frame_counter (ClutterStage *stage) -{ - g_return_if_fail (CLUTTER_IS_STAGE (stage)); - - stage->priv->picks_per_frame++; -} - -void -_clutter_stage_reset_picks_per_frame_counter (ClutterStage *stage) -{ - g_return_if_fail (CLUTTER_IS_STAGE (stage)); - - stage->priv->picks_per_frame = 0; -} - -guint -_clutter_stage_get_picks_per_frame_counter (ClutterStage *stage) -{ - g_return_val_if_fail (CLUTTER_IS_STAGE (stage), 0); - - return stage->priv->picks_per_frame; -} - ClutterPaintVolume * _clutter_stage_paint_volume_stack_allocate (ClutterStage *stage) { @@ -3376,9 +3615,9 @@ _clutter_stage_queue_actor_redraw (ClutterStage *stage, } #endif /* CLUTTER_ENABLE_DEBUG */ - /* We have an optimization in _clutter_do_pick to detect when the - * scene is static so we can cache a full, un-clipped pick buffer to - * avoid continuous pick renders. + /* We have an optimization in _clutter_stage_do_pick to detect when + * the scene is static so we can cache a full, un-clipped pick + * buffer to avoid continuous pick renders. * * Currently the assumption is that actors queue a redraw when some * state changes that affects painting *or* picking so we can use