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

View File

@ -38,6 +38,8 @@
#include <glib/gi18n-lib.h>
#include <locale.h>
#include <gdk-pixbuf/gdk-pixbuf.h>
#include "clutter-event.h"
#include "clutter-backend.h"
#include "clutter-main.h"
@ -95,7 +97,8 @@ static const GDebugKey clutter_debug_keys[] = {
{ "multistage", CLUTTER_DEBUG_MULTISTAGE },
{ "animation", CLUTTER_DEBUG_ANIMATION },
{ "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 */
@ -336,6 +339,13 @@ _clutter_id_to_color (guint id, ClutterColor *col)
col->green = green;
col->blue = blue;
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
@ -350,9 +360,22 @@ _clutter_pixel_to_id (guchar pixel[4])
/* reduce the pixel components to the number of bits actually used of the
* 8bits.
*/
red = pixel[0] >> (8 - ctx->fb_r_mask);
green = pixel[1] >> (8 - ctx->fb_g_mask);
blue = pixel[2] >> (8 - ctx->fb_b_mask);
if (G_UNLIKELY (clutter_debug_flags & CLUTTER_DEBUG_DUMP_PICK_BUFFERS))
{
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' */
red = red >> (ctx->fb_r_mask - ctx->fb_r_mask_used);
@ -366,6 +389,58 @@ _clutter_pixel_to_id (guchar pixel[4])
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 *
_clutter_do_pick (ClutterStage *stage,
gint x,
@ -389,7 +464,9 @@ _clutter_do_pick (ClutterStage *stage,
/* needed for when a context switch happens */
_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_disable_fog ();
cogl_clear (&white,
@ -407,7 +484,9 @@ _clutter_do_pick (ClutterStage *stage,
context->pick_mode = mode;
clutter_actor_paint (CLUTTER_ACTOR (stage));
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 */
glGetIntegerv(GL_VIEWPORT, viewport);
@ -418,6 +497,9 @@ _clutter_do_pick (ClutterStage *stage,
/* Read the color of the screen co-ords 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 */
if (dither_was_on)
glEnable (GL_DITHER);