From dae569b468c286ea23aa0e74e910232e025932db Mon Sep 17 00:00:00 2001 From: Robert Bragg Date: Thu, 24 Sep 2009 12:49:17 +0100 Subject: [PATCH] [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. --- clutter/clutter-debug.h | 35 +++++++-------- clutter/clutter-main.c | 94 ++++++++++++++++++++++++++++++++++++++--- 2 files changed, 106 insertions(+), 23 deletions(-) diff --git a/clutter/clutter-debug.h b/clutter/clutter-debug.h index 2a32f852c..d7493f3de 100644 --- a/clutter/clutter-debug.h +++ b/clutter/clutter-debug.h @@ -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 diff --git a/clutter/clutter-main.c b/clutter/clutter-main.c index 52193ecb1..ddb76ae79 100644 --- a/clutter/clutter-main.c +++ b/clutter/clutter-main.c @@ -38,6 +38,8 @@ #include #include +#include + #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);