[clutter/wip/clip-with-swap-buffers: 3/4] stage: add dedicated pixel pick buffer
- From: Robert Bragg <rbragg src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [clutter/wip/clip-with-swap-buffers: 3/4] stage: add dedicated pixel pick buffer
- Date: Fri, 1 Apr 2011 16:58:13 +0000 (UTC)
commit 5c548ad9bd95bcec0c43bfe6c313b8f391ab2abd
Author: Robert Bragg <robert linux intel com>
Date: Fri Apr 1 13:33:41 2011 +0100
stage: add dedicated pixel pick buffer
This gives each stage a dedicated 1 pixel framebuffer for handling
picking when we are only reading back a single point under the cursor.
Having a dedicated pick buffer means we can avoid damaging the contents
of the back buffer used for painting so we can re-use the contents of
old back buffers to reduce how much is drawn each frame.
Note that we don't create a full stage size pick buffer because we want
to avoid the large allocations of memory that would imply.
Note when a clutter scene is static then we will still use the back
buffer for picking so that we can do a full stage size pick render
without requiring the allocation of a dedicated buffer.
clutter/clutter-stage.c | 66 ++++++++++++++++++++++++++++++++--------------
1 files changed, 46 insertions(+), 20 deletions(-)
---
diff --git a/clutter/clutter-stage.c b/clutter/clutter-stage.c
index bf55647..dd416e6 100644
--- a/clutter/clutter-stage.c
+++ b/clutter/clutter-stage.c
@@ -144,6 +144,7 @@ struct _ClutterStagePrivate
GList *pending_queue_redraws;
ClutterPickMode pick_buffer_mode;
+ CoglHandle pixel_pick_buffer;
GHashTable *devices;
@@ -1239,6 +1240,8 @@ _clutter_stage_do_pick (ClutterStage *stage,
GLboolean dither_was_on;
ClutterActor *actor;
gboolean is_clipped;
+ gint read_x;
+ gint read_y;
CLUTTER_STATIC_COUNTER (do_pick_counter,
"_clutter_stage_do_pick counter",
"Increments for each full pick run",
@@ -1323,13 +1326,21 @@ _clutter_stage_do_pick (ClutterStage *stage,
* 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);
+ cogl_push_framebuffer (priv->pixel_pick_buffer);
+ cogl_set_viewport (priv->viewport[0] - x,
+ priv->viewport[1] - y,
+ priv->viewport[2],
+ priv->viewport[3]);
+ read_x = 0;
+ read_y = 0;
is_clipped = TRUE;
}
else
- is_clipped = FALSE;
+ {
+ read_x = x;
+ read_y = y;
+ is_clipped = FALSE;
+ }
CLUTTER_NOTE (PICK, "Performing %s pick at %i,%i",
is_clipped ? "clippped" : "full", x, y);
@@ -1356,21 +1367,6 @@ _clutter_stage_do_pick (ClutterStage *stage,
context->pick_mode = CLUTTER_PICK_NONE;
CLUTTER_TIMER_STOP (_clutter_uprof_context, pick_paint);
- /* Notify the backend that we have trashed the contents of
- * the back buffer... */
- _clutter_stage_window_dirty_back_buffer (priv->impl);
-
- 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
@@ -1379,7 +1375,7 @@ _clutter_stage_do_pick (ClutterStage *stage,
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 (read_x, read_y, 1, 1,
COGL_READ_PIXELS_COLOR_BUFFER,
COGL_PIXEL_FORMAT_RGBA_8888_PRE,
pixel);
@@ -1396,6 +1392,21 @@ _clutter_stage_do_pick (ClutterStage *stage,
if (dither_was_on)
glEnable (GL_DITHER);
+ if (is_clipped)
+ {
+ cogl_pop_framebuffer ();
+
+ _clutter_stage_set_pick_buffer_valid (stage, FALSE, -1);
+ }
+ else
+ {
+ /* Notify the backend that we have trashed the contents of
+ * the back buffer... */
+ _clutter_stage_window_dirty_back_buffer (priv->impl);
+
+ _clutter_stage_set_pick_buffer_valid (stage, TRUE, mode);
+ }
+
if (pixel[0] == 0xff && pixel[1] == 0xff && pixel[2] == 0xff)
{
actor = CLUTTER_ACTOR (stage);
@@ -1981,6 +1992,7 @@ clutter_stage_init (ClutterStage *self)
ClutterStagePrivate *priv;
ClutterBackend *backend;
ClutterGeometry geom;
+ CoglHandle color_buffer;
/* a stage is a top-level object */
CLUTTER_SET_PRIVATE_FLAGS (self, CLUTTER_IS_TOPLEVEL);
@@ -2061,6 +2073,16 @@ clutter_stage_init (ClutterStage *self)
g_array_new (FALSE, FALSE, sizeof (ClutterPaintVolume));
priv->devices = g_hash_table_new (NULL, NULL);
+
+ color_buffer = cogl_texture_new_with_size (1, 1,
+ COGL_TEXTURE_NONE,
+ COGL_PIXEL_FORMAT_RGB_888);
+
+ /* XXX: We are only using cogl_offscreen_new_to_texture for convenience
+ * and wont need to reference the underlying texture handle once we
+ * have the buffer. */
+ priv->pixel_pick_buffer = cogl_offscreen_new_to_texture (color_buffer);
+ cogl_handle_unref (color_buffer);
}
/**
@@ -3162,6 +3184,10 @@ _clutter_stage_maybe_setup_viewport (ClutterStage *stage)
{
cogl_set_projection_matrix (&priv->projection);
+ cogl_push_framebuffer (priv->pixel_pick_buffer);
+ cogl_set_projection_matrix (&priv->projection);
+ cogl_pop_framebuffer ();
+
priv->dirty_projection = FALSE;
}
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]