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.
This commit is contained in:
Robert Bragg 2011-03-15 13:17:04 +00:00
parent 114133c98c
commit ec0b781466
5 changed files with 307 additions and 329 deletions

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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);

View File

@ -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