From a4d3208eb57ddb3cc7eea61534b5187663d7507c Mon Sep 17 00:00:00 2001 From: Robert Bragg Date: Tue, 16 Nov 2010 13:06:08 +0000 Subject: [PATCH] debug: Adds a COGL_DEBUG=wireframe option This adds a COGL_DEBUG=wireframe option to visualize the underlying geometry of the primitives being drawn via Cogl. This works for triangle list, triangle fan, triangle strip and quad (internal only) primitives. It also works for indexed vertex arrays. --- clutter/cogl/cogl/cogl-debug-options.h | 5 + clutter/cogl/cogl/cogl-debug.c | 3 +- clutter/cogl/cogl/cogl-debug.h | 3 +- clutter/cogl/cogl/cogl-vertex-attribute.c | 243 ++++++++++++++++++++++++++++++ 4 files changed, 252 insertions(+), 2 deletions(-) diff --git a/clutter/cogl/cogl/cogl-debug-options.h b/clutter/cogl/cogl/cogl-debug-options.h index 1c0bd5b..e2fdbdb 100644 --- a/clutter/cogl/cogl/cogl-debug-options.h +++ b/clutter/cogl/cogl/cogl-debug-options.h @@ -77,6 +77,11 @@ OPT (RECTANGLES, "rectangles", "Outline rectangles", "Add wire outlines for all rectangular geometry") +OPT (WIREFRAME, + "Visualize", + "wireframe", + "Show wireframes", + "Add wire outlines for all geometry") OPT (DISABLE_BATCHING, "Root Cause", "disable-batching", diff --git a/clutter/cogl/cogl/cogl-debug.c b/clutter/cogl/cogl/cogl-debug.c index 94c276a..fe7ba5f 100644 --- a/clutter/cogl/cogl/cogl-debug.c +++ b/clutter/cogl/cogl/cogl-debug.c @@ -70,7 +70,8 @@ static const GDebugKey cogl_behavioural_debug_keys[] = { { "disable-arbfp", COGL_DEBUG_DISABLE_ARBFP}, { "disable-glsl", COGL_DEBUG_DISABLE_GLSL}, { "disable-blending", COGL_DEBUG_DISABLE_BLENDING}, - { "disable-npot-textures", COGL_DEBUG_DISABLE_NPOT_TEXTURES} + { "disable-npot-textures", COGL_DEBUG_DISABLE_NPOT_TEXTURES}, + { "wireframe", COGL_DEBUG_WIREFRAME} }; static const int n_cogl_behavioural_debug_keys = G_N_ELEMENTS (cogl_behavioural_debug_keys); diff --git a/clutter/cogl/cogl/cogl-debug.h b/clutter/cogl/cogl/cogl-debug.h index 9a390b4..459ec74 100644 --- a/clutter/cogl/cogl/cogl-debug.h +++ b/clutter/cogl/cogl/cogl-debug.h @@ -56,7 +56,8 @@ typedef enum { COGL_DEBUG_DISABLE_BLENDING = 1 << 23, COGL_DEBUG_TEXTURE_PIXMAP = 1 << 24, COGL_DEBUG_BITMAP = 1 << 25, - COGL_DEBUG_DISABLE_NPOT_TEXTURES = 1 << 26 + COGL_DEBUG_DISABLE_NPOT_TEXTURES = 1 << 26, + COGL_DEBUG_WIREFRAME = 1 << 27 } CoglDebugFlags; #ifdef COGL_ENABLE_DEBUG diff --git a/clutter/cogl/cogl/cogl-vertex-attribute.c b/clutter/cogl/cogl/cogl-vertex-attribute.c index cc4ad79..416c9b2 100644 --- a/clutter/cogl/cogl/cogl-vertex-attribute.c +++ b/clutter/cogl/cogl/cogl-vertex-attribute.c @@ -642,6 +642,239 @@ disable_gl_state (CoglVertexAttribute **attributes, } } +#ifdef COGL_ENABLE_DEBUG +static int +get_index (void *indices, + CoglIndicesType type, + int _index) +{ + if (!indices) + return _index; + + switch (type) + { + case COGL_INDICES_TYPE_UNSIGNED_BYTE: + return ((guint8 *)indices)[_index]; + case COGL_INDICES_TYPE_UNSIGNED_SHORT: + return ((guint16 *)indices)[_index]; + case COGL_INDICES_TYPE_UNSIGNED_INT: + return ((guint32 *)indices)[_index]; + } + + g_return_val_if_reached (0); +} + +static void +add_line (void *vertices, + void *indices, + CoglIndicesType indices_type, + CoglVertexAttribute *attribute, + int start, + int end, + CoglP3Vertex *lines, + int *n_line_vertices) +{ + int start_index = get_index (indices, indices_type, start); + int end_index = get_index (indices, indices_type, end); + float *v0 = (float *)((guint8 *)vertices + start_index * attribute->stride); + float *v1 = (float *)((guint8 *)vertices + end_index * attribute->stride); + float *o = (float *)(&lines[*n_line_vertices]); + int i; + + for (i = 0; i < attribute->n_components; i++) + *(o++) = *(v0++); + for (;i < 3; i++) + *(o++) = 0; + + for (i = 0; i < attribute->n_components; i++) + *(o++) = *(v1++); + for (;i < 3; i++) + *(o++) = 0; + + *n_line_vertices += 2; +} + +static CoglP3Vertex * +get_wire_lines (CoglVertexAttribute *attribute, + CoglVerticesMode mode, + int n_vertices_in, + int *n_vertices_out, + CoglIndices *_indices) +{ + CoglVertexArray *vertex_array = cogl_vertex_attribute_get_array (attribute); + void *vertices; + CoglIndexArray *index_array; + void *indices; + CoglIndicesType indices_type; + int i; + int n_lines; + CoglP3Vertex *out; + + vertices = cogl_buffer_map (COGL_BUFFER (vertex_array), + COGL_BUFFER_ACCESS_READ, 0); + if (_indices) + { + index_array = cogl_indices_get_array (_indices); + indices = cogl_buffer_map (COGL_BUFFER (index_array), + COGL_BUFFER_ACCESS_READ, 0); + indices_type = cogl_indices_get_type (_indices); + } + else + indices = NULL; + + *n_vertices_out = 0; + + if (mode == COGL_VERTICES_MODE_TRIANGLES && + (n_vertices_in % 3) == 0) + { + n_lines = n_vertices_in; + out = g_new (CoglP3Vertex, n_lines * 2); + for (i = 0; i < n_vertices_in; i += 3) + { + add_line (vertices, indices, indices_type, attribute, + i, i+1, out, n_vertices_out); + add_line (vertices, indices, indices_type, attribute, + i+1, i+2, out, n_vertices_out); + add_line (vertices, indices, indices_type, attribute, + i+2, i, out, n_vertices_out); + } + } + else if (mode == COGL_VERTICES_MODE_TRIANGLE_FAN && + n_vertices_in >= 3) + { + n_lines = 2 * n_vertices_in - 3; + out = g_new (CoglP3Vertex, n_lines * 2); + + add_line (vertices, indices, indices_type, attribute, + 0, 1, out, n_vertices_out); + add_line (vertices, indices, indices_type, attribute, + 1, 2, out, n_vertices_out); + add_line (vertices, indices, indices_type, attribute, + 0, 2, out, n_vertices_out); + + for (i = 3; i < n_vertices_in; i++) + { + add_line (vertices, indices, indices_type, attribute, + i - 1, i, out, n_vertices_out); + add_line (vertices, indices, indices_type, attribute, + 0, i, out, n_vertices_out); + } + } + else if (mode == COGL_VERTICES_MODE_TRIANGLE_STRIP && + n_vertices_in >= 3) + { + n_lines = 2 * n_vertices_in - 3; + out = g_new (CoglP3Vertex, n_lines * 2); + + add_line (vertices, indices, indices_type, attribute, + 0, 1, out, n_vertices_out); + add_line (vertices, indices, indices_type, attribute, + 1, 2, out, n_vertices_out); + add_line (vertices, indices, indices_type, attribute, + 0, 2, out, n_vertices_out); + + for (i = 3; i < n_vertices_in; i++) + { + add_line (vertices, indices, indices_type, attribute, + i - 1, i, out, n_vertices_out); + add_line (vertices, indices, indices_type, attribute, + i - 2, i, out, n_vertices_out); + } + } + /* In the journal we are a bit sneaky and actually use GL_QUADS + * which isn't actually a valid CoglVerticesMode! */ +#ifdef HAVE_COGL_GL + else if (mode == GL_QUADS && (n_vertices_in % 4) == 0) + { + n_lines = n_vertices_in; + out = g_new (CoglP3Vertex, n_lines * 2); + + for (i = 0; i < n_vertices_in; i += 4) + { + add_line (vertices, indices, indices_type, attribute, + i, i + 1, out, n_vertices_out); + add_line (vertices, indices, indices_type, attribute, + i + 1, i + 2, out, n_vertices_out); + add_line (vertices, indices, indices_type, attribute, + i + 2, i + 3, out, n_vertices_out); + add_line (vertices, indices, indices_type, attribute, + i + 3, i, out, n_vertices_out); + } + } +#endif + + if (vertices) + cogl_buffer_unmap (COGL_BUFFER (vertex_array)); + if (indices) + cogl_buffer_unmap (COGL_BUFFER (index_array)); + return out; +} + +static void +draw_wireframe (CoglVerticesMode mode, + int first_vertex, + int n_vertices, + CoglVertexAttribute **attributes, + CoglIndices *indices) +{ + CoglVertexAttribute *position = NULL; + int i; + int n_line_vertices; + static CoglPipeline *wire_pipeline; + CoglVertexAttribute *wire_attribute[2]; + CoglP3Vertex *lines; + CoglVertexArray *array; + + for (i = 0; attributes[i]; i++) + { + if (strcmp (attributes[i]->name, "cogl_position_in") == 0) + { + position = attributes[i]; + break; + } + } + if (!position) + return; + + lines = get_wire_lines (position, + mode, + n_vertices, + &n_line_vertices, + indices); + array = cogl_vertex_array_new (sizeof (CoglP3Vertex) * n_line_vertices, + lines); + wire_attribute[0] = + cogl_vertex_attribute_new (array, "cogl_position_in", + sizeof (CoglP3Vertex), + 0, + 3, + COGL_VERTEX_ATTRIBUTE_TYPE_FLOAT); + wire_attribute[1] = NULL; + cogl_object_unref (array); + + if (!wire_pipeline) + { + wire_pipeline = cogl_pipeline_new (); + cogl_pipeline_set_color4ub (wire_pipeline, + 0x00, 0xff, 0x00, 0xff); + } + + cogl_push_source (wire_pipeline); + + /* temporarily disable the wireframe to avoid recursion! */ + cogl_debug_flags &= ~COGL_DEBUG_WIREFRAME; + _cogl_draw_vertex_attributes_array (COGL_VERTICES_MODE_LINES, + 0, + n_line_vertices, + wire_attribute); + cogl_debug_flags |= COGL_DEBUG_WIREFRAME; + + cogl_pop_source (); + + cogl_object_unref (wire_attribute[0]); +} +#endif + static void _cogl_draw_vertex_attributes_array_real (CoglVerticesMode mode, int first_vertex, @@ -656,6 +889,11 @@ _cogl_draw_vertex_attributes_array_real (CoglVerticesMode mode, /* FIXME: we shouldn't be disabling state after drawing we should * just disable the things not needed after enabling state. */ disable_gl_state (attributes, source); + +#ifdef COGL_ENABLE_DEBUG + if (G_UNLIKELY (cogl_debug_flags & COGL_DEBUG_WIREFRAME)) + draw_wireframe (mode, first_vertex, n_vertices, attributes, NULL); +#endif } /* This can be used by the CoglJournal to draw attributes skipping the @@ -798,6 +1036,11 @@ _cogl_draw_indexed_vertex_attributes_array_real (CoglVerticesMode mode, /* FIXME: we shouldn't be disabling state after drawing we should * just disable the things not needed after enabling state. */ disable_gl_state (attributes, source); + +#ifdef COGL_ENABLE_DEBUG + if (G_UNLIKELY (cogl_debug_flags & COGL_DEBUG_WIREFRAME)) + draw_wireframe (mode, first_vertex, n_vertices, attributes, indices); +#endif } void -- 2.7.4