summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobert Bragg <robert@linux.intel.com>2011-03-15 13:17:04 +0000
committerRobert Bragg <robert@linux.intel.com>2011-04-01 17:26:29 +0100
commit8c48074a5892b77421bfc4b49ac3c29780232a95 (patch)
tree62d964a4946beb6ee103bc256423fbdd2fa8095e
parent4594d1bafe835d1fa68e04564528a497d259d7dc (diff)
downloadclutter-8c48074a5892b77421bfc4b49ac3c29780232a95.tar.gz
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.
-rw-r--r--clutter/clutter-input-device.c3
-rw-r--r--clutter/clutter-main.c270
-rw-r--r--clutter/clutter-private.h7
-rw-r--r--clutter/clutter-stage-private.h13
-rw-r--r--clutter/clutter-stage.c343
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 <glib/gi18n-lib.h>
#include <locale.h>
-#ifdef USE_GDKPIXBUF
-#include <gdk-pixbuf/gdk-pixbuf.h>
-#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 <math.h>
+#ifdef USE_GDKPIXBUF
+#include <gdk-pixbuf/gdk-pixbuf.h>
+#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