[clutter/wip/wayland: 43/45] stage: add dedicated pixel pick buffer
- From: Robert Bragg <rbragg src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [clutter/wip/wayland: 43/45] stage: add dedicated pixel pick buffer
- Date: Wed, 22 Feb 2012 18:03:20 +0000 (UTC)
commit 4861716dfbf0c5900aa2f5fd8711d1049345493e
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 | 71 +++++++++++++++++++++++++++++++++-------------
1 files changed, 51 insertions(+), 20 deletions(-)
---
diff --git a/clutter/clutter-stage.c b/clutter/clutter-stage.c
index 80bd1c0..e026b6c 100644
--- a/clutter/clutter-stage.c
+++ b/clutter/clutter-stage.c
@@ -52,6 +52,7 @@
#include <cairo.h>
#define CLUTTER_DISABLE_DEPRECATION_WARNINGS
+#define CLUTTER_ENABLE_EXPERIMENTAL_API
#include "clutter-stage.h"
#include "deprecated/clutter-stage.h"
@@ -145,6 +146,7 @@ struct _ClutterStagePrivate
GList *pending_queue_redraws;
ClutterPickMode pick_buffer_mode;
+ CoglOffscreen *pixel_pick_buffer;
CoglFramebuffer *active_framebuffer;
@@ -1388,6 +1390,8 @@ _clutter_stage_do_pick (ClutterStage *stage,
CoglFramebuffer *fb;
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",
@@ -1461,13 +1465,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 (COGL_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);
@@ -1494,21 +1506,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
@@ -1517,7 +1514,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);
@@ -1540,6 +1537,21 @@ _clutter_stage_do_pick (ClutterStage *stage,
/* Restore whether GL_DITHER was enabled */
cogl_framebuffer_set_dither_enabled (fb, dither_enabled_save);
+ 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);
+ }
+
check_pixel:
if (pixel[0] == 0xff && pixel[1] == 0xff && pixel[2] == 0xff)
{
@@ -2185,6 +2197,9 @@ clutter_stage_init (ClutterStage *self)
ClutterStageWindow *impl;
ClutterBackend *backend;
GError *error;
+ CoglTexture2D *color_buffer;
+ CoglContext *ctx =
+ clutter_backend_get_cogl_context (clutter_get_default_backend ());
/* a stage is a top-level object */
CLUTTER_SET_PRIVATE_FLAGS (self, CLUTTER_IS_TOPLEVEL);
@@ -2283,6 +2298,18 @@ clutter_stage_init (ClutterStage *self)
priv->devices = g_hash_table_new (NULL, NULL);
priv->pick_id_pool = _clutter_id_pool_new (256);
+
+ color_buffer = cogl_texture_2d_new_with_size (ctx,
+ 1, 1,
+ COGL_PIXEL_FORMAT_RGB_888,
+ NULL);
+
+ /* 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 (COGL_TEXTURE (color_buffer));
+ cogl_object_unref (color_buffer);
}
/**
@@ -3506,6 +3533,10 @@ _clutter_stage_maybe_setup_viewport (ClutterStage *stage)
{
cogl_set_projection_matrix (&priv->projection);
+ cogl_push_framebuffer (COGL_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]