diff --git a/clutter/cogl/cogl/cogl-debug-options.h b/clutter/cogl/cogl/cogl-debug-options.h index 1c0bd5bee..e2fdbdb19 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 94c276a91..fe7ba5fe4 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 9a390b4a8..459ec743c 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 cc4ad7942..416c9b2bc 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