[debug] Adds a dump-pick-buffers CLUTTER_DEBUG option

Now if you export CLUTTER_DEBUG=dump-pick-buffers clutter will write out a
png, e.g.  pick-buffer-00000.png, each time _clutter_to_pick() is called.
It's a rather crude way to debug the picking (realtime visualization in a
second stage would probably be nicer) but it we've used this approach
successfully numerous times when debugging Clutter picking issues so it
makes sense to have a debug option for it.
This commit is contained in:
Robert Bragg 2009-09-24 12:49:17 +01:00
parent 27ae9722de
commit dae569b468
2 changed files with 106 additions and 23 deletions

View File

@ -7,23 +7,24 @@
G_BEGIN_DECLS G_BEGIN_DECLS
typedef enum { typedef enum {
CLUTTER_DEBUG_MISC = 1 << 0, CLUTTER_DEBUG_MISC = 1 << 0,
CLUTTER_DEBUG_ACTOR = 1 << 1, CLUTTER_DEBUG_ACTOR = 1 << 1,
CLUTTER_DEBUG_TEXTURE = 1 << 2, CLUTTER_DEBUG_TEXTURE = 1 << 2,
CLUTTER_DEBUG_EVENT = 1 << 3, CLUTTER_DEBUG_EVENT = 1 << 3,
CLUTTER_DEBUG_PAINT = 1 << 4, CLUTTER_DEBUG_PAINT = 1 << 4,
CLUTTER_DEBUG_GL = 1 << 5, CLUTTER_DEBUG_GL = 1 << 5,
CLUTTER_DEBUG_ALPHA = 1 << 6, CLUTTER_DEBUG_ALPHA = 1 << 6,
CLUTTER_DEBUG_BEHAVIOUR = 1 << 7, CLUTTER_DEBUG_BEHAVIOUR = 1 << 7,
CLUTTER_DEBUG_PANGO = 1 << 8, CLUTTER_DEBUG_PANGO = 1 << 8,
CLUTTER_DEBUG_BACKEND = 1 << 9, CLUTTER_DEBUG_BACKEND = 1 << 9,
CLUTTER_DEBUG_SCHEDULER = 1 << 10, CLUTTER_DEBUG_SCHEDULER = 1 << 10,
CLUTTER_DEBUG_SCRIPT = 1 << 11, CLUTTER_DEBUG_SCRIPT = 1 << 11,
CLUTTER_DEBUG_SHADER = 1 << 12, CLUTTER_DEBUG_SHADER = 1 << 12,
CLUTTER_DEBUG_MULTISTAGE = 1 << 13, CLUTTER_DEBUG_MULTISTAGE = 1 << 13,
CLUTTER_DEBUG_ANIMATION = 1 << 14, CLUTTER_DEBUG_ANIMATION = 1 << 14,
CLUTTER_DEBUG_LAYOUT = 1 << 15, CLUTTER_DEBUG_LAYOUT = 1 << 15,
CLUTTER_DEBUG_NOP_PICKING = 1 << 16, CLUTTER_DEBUG_NOP_PICKING = 1 << 16,
CLUTTER_DEBUG_DUMP_PICK_BUFFERS = 1 << 17,
} ClutterDebugFlag; } ClutterDebugFlag;
#ifdef CLUTTER_ENABLE_DEBUG #ifdef CLUTTER_ENABLE_DEBUG

View File

@ -38,6 +38,8 @@
#include <glib/gi18n-lib.h> #include <glib/gi18n-lib.h>
#include <locale.h> #include <locale.h>
#include <gdk-pixbuf/gdk-pixbuf.h>
#include "clutter-event.h" #include "clutter-event.h"
#include "clutter-backend.h" #include "clutter-backend.h"
#include "clutter-main.h" #include "clutter-main.h"
@ -95,7 +97,8 @@ static const GDebugKey clutter_debug_keys[] = {
{ "multistage", CLUTTER_DEBUG_MULTISTAGE }, { "multistage", CLUTTER_DEBUG_MULTISTAGE },
{ "animation", CLUTTER_DEBUG_ANIMATION }, { "animation", CLUTTER_DEBUG_ANIMATION },
{ "layout", CLUTTER_DEBUG_LAYOUT }, { "layout", CLUTTER_DEBUG_LAYOUT },
{ "nop-picking", CLUTTER_DEBUG_NOP_PICKING } { "nop-picking", CLUTTER_DEBUG_NOP_PICKING },
{ "dump-pick-buffers", CLUTTER_DEBUG_DUMP_PICK_BUFFERS }
}; };
#endif /* CLUTTER_ENABLE_DEBUG */ #endif /* CLUTTER_ENABLE_DEBUG */
@ -336,6 +339,13 @@ _clutter_id_to_color (guint id, ClutterColor *col)
col->green = green; col->green = green;
col->blue = blue; col->blue = blue;
col->alpha = 0xff; col->alpha = 0xff;
if (G_UNLIKELY (clutter_debug_flags & CLUTTER_DEBUG_DUMP_PICK_BUFFERS))
{
col->red = (col->red << 4) | (col->red >> 4);
col->green = (col->green << 4) | (col->green >> 4);
col->blue = (col->blue << 4) | (col->blue >> 4);
}
} }
guint guint
@ -350,9 +360,22 @@ _clutter_pixel_to_id (guchar pixel[4])
/* reduce the pixel components to the number of bits actually used of the /* reduce the pixel components to the number of bits actually used of the
* 8bits. * 8bits.
*/ */
red = pixel[0] >> (8 - ctx->fb_r_mask); if (G_UNLIKELY (clutter_debug_flags & CLUTTER_DEBUG_DUMP_PICK_BUFFERS))
green = pixel[1] >> (8 - ctx->fb_g_mask); {
blue = pixel[2] >> (8 - ctx->fb_b_mask); guchar tmp;
tmp = ((pixel[0] << 4) | (pixel[0] >> 4));
red = tmp >> (8 - ctx->fb_r_mask);
tmp = ((pixel[1] << 4) | (pixel[1] >> 4));
green = tmp >> (8 - ctx->fb_g_mask);
tmp = ((pixel[2] << 4) | (pixel[2] >> 4));
blue = tmp >> (8 - ctx->fb_b_mask);
}
else
{
red = pixel[0] >> (8 - ctx->fb_r_mask);
green = pixel[1] >> (8 - ctx->fb_g_mask);
blue = pixel[2] >> (8 - ctx->fb_b_mask);
}
/* divide potentially by two if 'fuzzy' */ /* divide potentially by two if 'fuzzy' */
red = red >> (ctx->fb_r_mask - ctx->fb_r_mask_used); red = red >> (ctx->fb_r_mask - ctx->fb_r_mask_used);
@ -366,6 +389,58 @@ _clutter_pixel_to_id (guchar pixel[4])
return id; return id;
} }
static void
pixbuf_free (guchar *pixels, gpointer data)
{
g_free (pixels);
}
static void
read_pixels_to_file (char *filename_stem,
int x,
int y,
int width,
int height)
{
GLubyte *data;
GdkPixbuf *pixbuf;
static int read_count = 0;
GdkPixbuf *flipped;
data = g_malloc (4 * width * height);
glReadPixels (0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, data);
pixbuf = gdk_pixbuf_new_from_data (data,
GDK_COLORSPACE_RGB,
TRUE, /* has alpha */
8, /* bits per sample */
width, /* width */
height, /* height */
width * 4, /* rowstride */
pixbuf_free, /* callback to free data */
NULL); /* callback data */
if (pixbuf)
{
flipped = gdk_pixbuf_flip (pixbuf, FALSE);
g_object_unref (pixbuf);
}
if (flipped)
{
char *filename =
g_strdup_printf ("%s-%05d.png", filename_stem, read_count);
GError *error = NULL;
if (!gdk_pixbuf_save (flipped, 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 (flipped);
read_count++;
}
}
ClutterActor * ClutterActor *
_clutter_do_pick (ClutterStage *stage, _clutter_do_pick (ClutterStage *stage,
gint x, gint x,
@ -389,7 +464,9 @@ _clutter_do_pick (ClutterStage *stage,
/* needed for when a context switch happens */ /* needed for when a context switch happens */
_clutter_stage_maybe_setup_viewport (stage); _clutter_stage_maybe_setup_viewport (stage);
cogl_clip_push_window_rect (x, y, 1, 1); if (G_LIKELY (!(clutter_debug_flags & CLUTTER_DEBUG_DUMP_PICK_BUFFERS)))
cogl_clip_push_window_rect (x, y, 1, 1);
cogl_color_set_from_4ub (&white, 255, 255, 255, 255); cogl_color_set_from_4ub (&white, 255, 255, 255, 255);
cogl_disable_fog (); cogl_disable_fog ();
cogl_clear (&white, cogl_clear (&white,
@ -407,7 +484,9 @@ _clutter_do_pick (ClutterStage *stage,
context->pick_mode = mode; context->pick_mode = mode;
clutter_actor_paint (CLUTTER_ACTOR (stage)); clutter_actor_paint (CLUTTER_ACTOR (stage));
context->pick_mode = CLUTTER_PICK_NONE; context->pick_mode = CLUTTER_PICK_NONE;
cogl_clip_pop ();
if (G_LIKELY (!(clutter_debug_flags & CLUTTER_DEBUG_DUMP_PICK_BUFFERS)))
cogl_clip_pop ();
/* Calls should work under both GL and GLES, note GLES needs RGBA */ /* Calls should work under both GL and GLES, note GLES needs RGBA */
glGetIntegerv(GL_VIEWPORT, viewport); glGetIntegerv(GL_VIEWPORT, viewport);
@ -418,6 +497,9 @@ _clutter_do_pick (ClutterStage *stage,
/* Read the color of the screen co-ords pixel */ /* Read the color of the screen co-ords pixel */
glReadPixels (x, viewport[3] - y -1, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixel); glReadPixels (x, viewport[3] - y -1, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixel);
if (G_UNLIKELY (clutter_debug_flags & CLUTTER_DEBUG_DUMP_PICK_BUFFERS))
read_pixels_to_file ("pick-buffer", 0, 0, viewport[2], viewport[3]);
/* Restore whether GL_DITHER was enabled */ /* Restore whether GL_DITHER was enabled */
if (dither_was_on) if (dither_was_on)
glEnable (GL_DITHER); glEnable (GL_DITHER);