[cogl-vertex-buffer] Add cogl_vertex_buffer_indices_get_for_quads
This function can be used as an efficient way of drawing groups of quads without using GL_QUADS. It generates a VBO containing the indices needed to render using pairs of GL_TRIANGLES. The VBO is globally cached so that it only needs to be uploaded whenever more indices are requested than ever before.
This commit is contained in:
parent
2f319ad839
commit
39cb36ba01
@ -394,6 +394,46 @@ cogl_vertex_buffer_ref (CoglHandle handle);
|
|||||||
void
|
void
|
||||||
cogl_vertex_buffer_unref (CoglHandle handle);
|
cogl_vertex_buffer_unref (CoglHandle handle);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* cogl_vertex_buffer_indices_get_for_quads:
|
||||||
|
* @n_indices: the number of indices in the vertex buffer.
|
||||||
|
*
|
||||||
|
* Creates a vertex buffer containing the indices needed to draw pairs
|
||||||
|
* of triangles from a list of vertices grouped as quads. There will
|
||||||
|
* be at least @n_indices entries in the buffer (but there may be
|
||||||
|
* more).
|
||||||
|
*
|
||||||
|
* The indices will follow this pattern:
|
||||||
|
*
|
||||||
|
* 0, 1, 2, 0, 2, 3, 4, 5, 6, 4, 6, 7 ... etc
|
||||||
|
*
|
||||||
|
* For example, if you submit vertices for a quad like this:
|
||||||
|
*
|
||||||
|
* |[
|
||||||
|
* 0 3
|
||||||
|
* ########
|
||||||
|
* # #
|
||||||
|
* # #
|
||||||
|
* ########
|
||||||
|
* 1 2
|
||||||
|
* ]|
|
||||||
|
*
|
||||||
|
* Then you can request 6 indices to render two triangles like this:
|
||||||
|
*
|
||||||
|
* |[
|
||||||
|
* 0 0 3
|
||||||
|
* ## ########
|
||||||
|
* # ## ## #
|
||||||
|
* # ## ## #
|
||||||
|
* ######## ##
|
||||||
|
* 1 2 2
|
||||||
|
* ]|
|
||||||
|
*
|
||||||
|
* Returns: A %CoglHandle containing the indices. The handled is
|
||||||
|
* owned by Cogl and should not be modified or unref'd.
|
||||||
|
*/
|
||||||
|
CoglHandle
|
||||||
|
cogl_vertex_buffer_indices_get_for_quads (guint n_indices);
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|
||||||
|
@ -1880,3 +1880,83 @@ _cogl_vertex_buffer_free (CoglVertexBuffer *buffer)
|
|||||||
g_slice_free (CoglVertexBuffer, buffer);
|
g_slice_free (CoglVertexBuffer, buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CoglHandle
|
||||||
|
cogl_vertex_buffer_indices_get_for_quads (guint n_indices)
|
||||||
|
{
|
||||||
|
_COGL_GET_CONTEXT (ctx, COGL_INVALID_HANDLE);
|
||||||
|
|
||||||
|
/* Check if the indices would fit in a byte array */
|
||||||
|
if (n_indices <= 256 / 4 * 6)
|
||||||
|
{
|
||||||
|
/* Generate the byte array if we haven't already */
|
||||||
|
if (ctx->quad_indices_byte == COGL_INVALID_HANDLE)
|
||||||
|
{
|
||||||
|
guint8 *byte_array = g_malloc (256 / 4 * 6 * sizeof (guint8));
|
||||||
|
guint8 *p = byte_array;
|
||||||
|
int i, vert_num = 0;
|
||||||
|
|
||||||
|
for (i = 0; i < 256 / 4; i++)
|
||||||
|
{
|
||||||
|
*(p++) = vert_num + 0;
|
||||||
|
*(p++) = vert_num + 1;
|
||||||
|
*(p++) = vert_num + 2;
|
||||||
|
*(p++) = vert_num + 0;
|
||||||
|
*(p++) = vert_num + 2;
|
||||||
|
*(p++) = vert_num + 3;
|
||||||
|
vert_num += 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx->quad_indices_byte
|
||||||
|
= cogl_vertex_buffer_indices_new (COGL_INDICES_TYPE_UNSIGNED_BYTE,
|
||||||
|
byte_array,
|
||||||
|
256 / 4 * 6);
|
||||||
|
|
||||||
|
g_free (byte_array);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ctx->quad_indices_byte;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (ctx->quad_indices_short_len < n_indices)
|
||||||
|
{
|
||||||
|
guint16 *short_array;
|
||||||
|
guint16 *p;
|
||||||
|
int i, vert_num = 0;
|
||||||
|
|
||||||
|
if (ctx->quad_indices_short != COGL_INVALID_HANDLE)
|
||||||
|
cogl_handle_unref (ctx->quad_indices_short);
|
||||||
|
/* Pick a power of two >= MAX (512, n_indices) */
|
||||||
|
if (ctx->quad_indices_short_len == 0)
|
||||||
|
ctx->quad_indices_short_len = 512;
|
||||||
|
while (ctx->quad_indices_short_len < n_indices)
|
||||||
|
ctx->quad_indices_short_len *= 2;
|
||||||
|
|
||||||
|
/* Over-allocate to generate a whole number of quads */
|
||||||
|
p = short_array = g_malloc ((ctx->quad_indices_short_len
|
||||||
|
+ 5) / 6 * 6
|
||||||
|
* sizeof (guint16));
|
||||||
|
|
||||||
|
/* Fill in the complete quads */
|
||||||
|
for (i = 0; i < ctx->quad_indices_short_len; i += 6)
|
||||||
|
{
|
||||||
|
*(p++) = vert_num + 0;
|
||||||
|
*(p++) = vert_num + 1;
|
||||||
|
*(p++) = vert_num + 2;
|
||||||
|
*(p++) = vert_num + 0;
|
||||||
|
*(p++) = vert_num + 2;
|
||||||
|
*(p++) = vert_num + 3;
|
||||||
|
vert_num += 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx->quad_indices_short
|
||||||
|
= cogl_vertex_buffer_indices_new (COGL_INDICES_TYPE_UNSIGNED_SHORT,
|
||||||
|
short_array,
|
||||||
|
ctx->quad_indices_short_len);
|
||||||
|
|
||||||
|
g_free (short_array);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ctx->quad_indices_short;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -313,6 +313,7 @@ CoglIndicesType
|
|||||||
cogl_vertex_buffer_add_indices
|
cogl_vertex_buffer_add_indices
|
||||||
cogl_vertex_buffer_delete_indices
|
cogl_vertex_buffer_delete_indices
|
||||||
cogl_vertex_buffer_draw_elements
|
cogl_vertex_buffer_draw_elements
|
||||||
|
cogl_vertex_buffer_indices_get_for_quads
|
||||||
<SUBSECTION Private>
|
<SUBSECTION Private>
|
||||||
CoglVertexBufferAttribFlags
|
CoglVertexBufferAttribFlags
|
||||||
COGL_VERTEX_BUFFER_ATTRIB_FLAG_GL_TYPE_MASK
|
COGL_VERTEX_BUFFER_ATTRIB_FLAG_GL_TYPE_MASK
|
||||||
|
@ -171,6 +171,10 @@ cogl_create_context ()
|
|||||||
_cogl_material_get_cogl_enable_flags (_context->source_material);
|
_cogl_material_get_cogl_enable_flags (_context->source_material);
|
||||||
cogl_enable (enable_flags);
|
cogl_enable (enable_flags);
|
||||||
|
|
||||||
|
_context->quad_indices_byte = COGL_INVALID_HANDLE;
|
||||||
|
_context->quad_indices_short = COGL_INVALID_HANDLE;
|
||||||
|
_context->quad_indices_short_len = 0;
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -207,6 +211,11 @@ _cogl_destroy_context ()
|
|||||||
if (_context->current_layers)
|
if (_context->current_layers)
|
||||||
g_array_free (_context->current_layers, TRUE);
|
g_array_free (_context->current_layers, TRUE);
|
||||||
|
|
||||||
|
if (_context->quad_indices_byte)
|
||||||
|
cogl_handle_unref (_context->quad_indices_byte);
|
||||||
|
if (_context->quad_indices_short)
|
||||||
|
cogl_handle_unref (_context->quad_indices_short);
|
||||||
|
|
||||||
g_free (_context);
|
g_free (_context);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -102,6 +102,12 @@ typedef struct
|
|||||||
floatVec2 path_nodes_max;
|
floatVec2 path_nodes_max;
|
||||||
CoglHandle stencil_material;
|
CoglHandle stencil_material;
|
||||||
|
|
||||||
|
/* Pre-generated VBOs containing indices to generate GL_TRIANGLES
|
||||||
|
out of a vertex array of quads */
|
||||||
|
CoglHandle quad_indices_byte;
|
||||||
|
guint quad_indices_short_len;
|
||||||
|
CoglHandle quad_indices_short;
|
||||||
|
|
||||||
/* Relying on glext.h to define these */
|
/* Relying on glext.h to define these */
|
||||||
COGL_PFNGLGENRENDERBUFFERSEXTPROC pf_glGenRenderbuffersEXT;
|
COGL_PFNGLGENRENDERBUFFERSEXTPROC pf_glGenRenderbuffersEXT;
|
||||||
COGL_PFNGLDELETERENDERBUFFERSEXTPROC pf_glDeleteRenderbuffersEXT;
|
COGL_PFNGLDELETERENDERBUFFERSEXTPROC pf_glDeleteRenderbuffersEXT;
|
||||||
|
@ -129,6 +129,10 @@ cogl_create_context ()
|
|||||||
_cogl_material_get_cogl_enable_flags (_context->source_material);
|
_cogl_material_get_cogl_enable_flags (_context->source_material);
|
||||||
cogl_enable (enable_flags);
|
cogl_enable (enable_flags);
|
||||||
|
|
||||||
|
_context->quad_indices_byte = COGL_INVALID_HANDLE;
|
||||||
|
_context->quad_indices_short = COGL_INVALID_HANDLE;
|
||||||
|
_context->quad_indices_short_len = 0;
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -165,6 +169,11 @@ _cogl_destroy_context ()
|
|||||||
if (_context->current_layers)
|
if (_context->current_layers)
|
||||||
g_array_free (_context->current_layers, TRUE);
|
g_array_free (_context->current_layers, TRUE);
|
||||||
|
|
||||||
|
if (_context->quad_indices_byte)
|
||||||
|
cogl_handle_unref (_context->quad_indices_byte);
|
||||||
|
if (_context->quad_indices_short)
|
||||||
|
cogl_handle_unref (_context->quad_indices_short);
|
||||||
|
|
||||||
g_free (_context);
|
g_free (_context);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -104,6 +104,12 @@ typedef struct
|
|||||||
floatVec2 path_nodes_max;
|
floatVec2 path_nodes_max;
|
||||||
CoglHandle stencil_material;
|
CoglHandle stencil_material;
|
||||||
|
|
||||||
|
/* Pre-generated VBOs containing indices to generate GL_TRIANGLES
|
||||||
|
out of a vertex array of quads */
|
||||||
|
CoglHandle quad_indices_byte;
|
||||||
|
guint quad_indices_short_len;
|
||||||
|
CoglHandle quad_indices_short;
|
||||||
|
|
||||||
#ifdef HAVE_COGL_GLES2
|
#ifdef HAVE_COGL_GLES2
|
||||||
CoglGles2Wrapper gles2;
|
CoglGles2Wrapper gles2;
|
||||||
|
|
||||||
@ -111,7 +117,6 @@ typedef struct
|
|||||||
supported */
|
supported */
|
||||||
GLint viewport_store[4];
|
GLint viewport_store[4];
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
} CoglContext;
|
} CoglContext;
|
||||||
|
|
||||||
CoglContext *
|
CoglContext *
|
||||||
|
Loading…
Reference in New Issue
Block a user