[cogl vertex buffers] Give indices a CoglHandle so they are shareable

Previously indices were tightly bound to a particular Cogl vertex buffer
but we would like to be able to share indices so now we have
cogl_vertex_buffer_indices_new () which returns a CoglHandle.

In particular we could like to have a shared set of indices for drawing
lists of quads that can be shared between the pango renderer and the
Cogl journal.
This commit is contained in:
Robert Bragg 2009-05-28 12:49:29 +01:00
parent f0849fc3e2
commit be826ed4e7
4 changed files with 46 additions and 108 deletions

View File

@ -303,10 +303,7 @@ typedef enum _CoglIndicesType
} CoglIndicesType; } CoglIndicesType;
/** /**
* cogl_vertex_buffer_add_indices: * cogl_vertex_buffer_indices_new:
* @handle: A vertex buffer handle
* @min_index: Specifies the minimum vertex index contained in indices
* @max_index: Specifies the maximum vertex index contained in indices
* @indices_type: a #CoglIndicesType specifying the data type used for * @indices_type: a #CoglIndicesType specifying the data type used for
* the indices. * the indices.
* @indices_array: Specifies the address of your array of indices * @indices_array: Specifies the address of your array of indices
@ -317,19 +314,11 @@ typedef enum _CoglIndicesType
* array allows you to reference vertices multiple times, for example * array allows you to reference vertices multiple times, for example
* during triangle strips. * during triangle strips.
* *
* You should aim to use the smallest data type possible and correctly reflect * Returns: A CoglHandle for the indices which you can pass to
* the range of index values in the {min,max}_index arguments. This allows Cogl * cogl_vertex_buffer_draw_elements().
* to optimize the internal storage used for the indices and reduce the demand
* for memory bandwidth.
*
* Returns: An identifier (greater than 0) for the indices which you can
* pass to cogl_vertex_buffer_draw_elements().
*/ */
int CoglHandle
cogl_vertex_buffer_add_indices (CoglHandle handle, cogl_vertex_buffer_indices_new (CoglIndicesType indices_type,
int min_index,
int max_index,
CoglIndicesType indices_type,
const void *indices_array, const void *indices_array,
int indices_len); int indices_len);
@ -352,16 +341,17 @@ cogl_vertex_buffer_delete_indices (CoglHandle handle,
* @handle: A vertex buffer handle * @handle: A vertex buffer handle
* @mode: A #CoglVerticesMode specifying how the vertices should be * @mode: A #CoglVerticesMode specifying how the vertices should be
* interpreted. * interpreted.
* @indices_id: The identifier for a an array of indices previously added to * @indices: A CoglHandle for a set of indices allocated via
* the given Cogl vertex buffer using * cogl_vertex_buffer_indices_new ()
* cogl_vertex_buffer_add_indices(). * @min_index: Specifies the minimum vertex index contained in indices
* @max_index: Specifies the maximum vertex index contained in indices
* @indices_offset: An offset into named indices. The offset marks the first * @indices_offset: An offset into named indices. The offset marks the first
* index to use for drawing. * index to use for drawing.
* @count: Specifies the number of vertices you want to draw. * @count: Specifies the number of vertices you want to draw.
* *
* This function lets you use an array of indices to specify the vertices * This function lets you use an array of indices to specify the vertices
* within your vertex buffer that you want to draw. The indices themselves * within your vertex buffer that you want to draw. The indices themselves
* are given by calling cogl_vertex_buffer_add_indices () * are created by calling cogl_vertex_buffer_indices_new ()
* *
* Any un-submitted attribute changes are automatically submitted before * Any un-submitted attribute changes are automatically submitted before
* drawing. * drawing.
@ -369,7 +359,9 @@ cogl_vertex_buffer_delete_indices (CoglHandle handle,
void void
cogl_vertex_buffer_draw_elements (CoglHandle handle, cogl_vertex_buffer_draw_elements (CoglHandle handle,
CoglVerticesMode mode, CoglVerticesMode mode,
int indices_id, CoglHandle indices,
int min_index,
int max_index,
int indices_offset, int indices_offset,
int count); int count);

View File

@ -139,14 +139,13 @@ typedef struct _CoglVertexBufferVBO
typedef struct _CoglVertexBufferIndices typedef struct _CoglVertexBufferIndices
{ {
int id; CoglHandleObject _parent;
/* Note: this is a pointer to handle fallbacks. It normally holds /* Note: this is a pointer to handle fallbacks. It normally holds
* a GLuint VBO name, but when the driver doesn't support VBOs then * a GLuint VBO name, but when the driver doesn't support VBOs then
* this simply points to an malloc'd buffer. */ * this simply points to an malloc'd buffer. */
void *vbo_name; void *vbo_name;
GLenum type; GLenum type;
GLuint min_index;
GLuint max_index;
} CoglVertexBufferIndices; } CoglVertexBufferIndices;
typedef struct _CoglVertexBuffer typedef struct _CoglVertexBuffer
@ -160,8 +159,6 @@ typedef struct _CoglVertexBuffer
* modifying a buffer. */ * modifying a buffer. */
GList *new_attributes; /*!< attributes pending submission */ GList *new_attributes; /*!< attributes pending submission */
GList *indices; /*!< A list of associated index arrays */
} CoglVertexBuffer; } CoglVertexBuffer;
#endif /* __COGL_VERTEX_BUFFER_H */ #endif /* __COGL_VERTEX_BUFFER_H */

View File

@ -201,8 +201,10 @@
#endif /* HAVE_COGL_GL */ #endif /* HAVE_COGL_GL */
static void _cogl_vertex_buffer_free (CoglVertexBuffer *buffer); static void _cogl_vertex_buffer_free (CoglVertexBuffer *buffer);
static void _cogl_vertex_buffer_indices_free (CoglVertexBufferIndices *buffer_indices);
COGL_HANDLE_DEFINE (VertexBuffer, vertex_buffer); COGL_HANDLE_DEFINE (VertexBuffer, vertex_buffer);
COGL_HANDLE_DEFINE (VertexBufferIndices, vertex_buffer_indices);
CoglHandle CoglHandle
cogl_vertex_buffer_new (guint n_vertices) cogl_vertex_buffer_new (guint n_vertices)
@ -214,8 +216,6 @@ cogl_vertex_buffer_new (guint n_vertices)
buffer->submitted_vbos = NULL; buffer->submitted_vbos = NULL;
buffer->new_attributes = NULL; buffer->new_attributes = NULL;
buffer->indices = NULL;
/* return COGL_INVALID_HANDLE; */ /* return COGL_INVALID_HANDLE; */
return _cogl_vertex_buffer_handle_new (buffer); return _cogl_vertex_buffer_handle_new (buffer);
} }
@ -1741,22 +1741,6 @@ cogl_vertex_buffer_draw (CoglHandle handle,
disable_state_for_drawing_buffer (buffer); disable_state_for_drawing_buffer (buffer);
} }
static void
free_vertex_buffer_indices (CoglVertexBufferIndices *indices)
{
gboolean fallback =
(cogl_get_features () & COGL_FEATURE_VBOS) ? FALSE : TRUE;
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
if (fallback)
g_free (indices->vbo_name);
else
GE (glDeleteBuffers (1, (GLuint *)&indices->vbo_name));
g_slice_free (CoglVertexBufferIndices, indices);
}
static int static int
get_indices_type_size (GLuint indices_type) get_indices_type_size (GLuint indices_type)
{ {
@ -1771,34 +1755,19 @@ get_indices_type_size (GLuint indices_type)
} }
} }
int CoglHandle
cogl_vertex_buffer_add_indices (CoglHandle handle, cogl_vertex_buffer_indices_new (CoglIndicesType indices_type,
int min_index,
int max_index,
CoglIndicesType indices_type,
const void *indices_array, const void *indices_array,
int indices_len) int indices_len)
{ {
CoglVertexBuffer *buffer;
gboolean fallback = gboolean fallback =
(cogl_get_features () & COGL_FEATURE_VBOS) ? FALSE : TRUE; (cogl_get_features () & COGL_FEATURE_VBOS) ? FALSE : TRUE;
size_t indices_bytes; size_t indices_bytes;
CoglVertexBufferIndices *indices; CoglVertexBufferIndices *indices;
static int next_indices_id = 1;
_COGL_GET_CONTEXT (ctx, 0); _COGL_GET_CONTEXT (ctx, 0);
if (!cogl_is_vertex_buffer (handle))
return 0;
buffer = _cogl_vertex_buffer_pointer_from_handle (handle);
indices = g_slice_alloc (sizeof (CoglVertexBufferIndices)); indices = g_slice_alloc (sizeof (CoglVertexBufferIndices));
indices->id = next_indices_id;
indices->min_index = min_index;
indices->max_index = max_index;
if (indices_type == COGL_INDICES_TYPE_UNSIGNED_BYTE) if (indices_type == COGL_INDICES_TYPE_UNSIGNED_BYTE)
indices->type = GL_UNSIGNED_BYTE; indices->type = GL_UNSIGNED_BYTE;
@ -1829,39 +1798,31 @@ cogl_vertex_buffer_add_indices (CoglHandle handle,
GE (glBindBuffer (GL_ELEMENT_ARRAY_BUFFER, 0)); GE (glBindBuffer (GL_ELEMENT_ARRAY_BUFFER, 0));
} }
buffer->indices = g_list_prepend (buffer->indices, indices); return _cogl_vertex_buffer_indices_handle_new (indices);
return next_indices_id++;
} }
void void
cogl_vertex_buffer_delete_indices (CoglHandle handle, _cogl_vertex_buffer_indices_free (CoglVertexBufferIndices *indices)
int indices_id)
{ {
CoglVertexBuffer *buffer; gboolean fallback =
GList *l; (cogl_get_features () & COGL_FEATURE_VBOS) ? FALSE : TRUE;
if (!cogl_is_vertex_buffer (handle)) _COGL_GET_CONTEXT (ctx, NO_RETVAL);
return;
buffer = _cogl_vertex_buffer_pointer_from_handle (handle); if (fallback)
g_free (indices->vbo_name);
else
GE (glDeleteBuffers (1, (GLuint *)&indices->vbo_name));
for (l = buffer->indices; l; l = l->next) g_slice_free (CoglVertexBufferIndices, indices);
{
CoglVertexBufferIndices *current_indices = l->data;
if (current_indices->id == indices_id)
{
free_vertex_buffer_indices (l->data);
buffer->indices = g_list_delete_link (buffer->indices, l);
return;
}
}
} }
void void
cogl_vertex_buffer_draw_elements (CoglHandle handle, cogl_vertex_buffer_draw_elements (CoglHandle handle,
CoglVerticesMode mode, CoglVerticesMode mode,
int indices_id, CoglHandle indices_handle,
int min_index,
int max_index,
int indices_offset, int indices_offset,
int count) int count)
{ {
@ -1869,7 +1830,6 @@ cogl_vertex_buffer_draw_elements (CoglHandle handle,
gboolean fallback = gboolean fallback =
(cogl_get_features () & COGL_FEATURE_VBOS) ? FALSE : TRUE; (cogl_get_features () & COGL_FEATURE_VBOS) ? FALSE : TRUE;
size_t byte_offset; size_t byte_offset;
GList *l;
CoglVertexBufferIndices *indices = NULL; CoglVertexBufferIndices *indices = NULL;
_COGL_GET_CONTEXT (ctx, NO_RETVAL); _COGL_GET_CONTEXT (ctx, NO_RETVAL);
@ -1879,22 +1839,15 @@ cogl_vertex_buffer_draw_elements (CoglHandle handle,
buffer = _cogl_vertex_buffer_pointer_from_handle (handle); buffer = _cogl_vertex_buffer_pointer_from_handle (handle);
if (!cogl_is_vertex_buffer_indices (indices_handle))
return;
indices = _cogl_vertex_buffer_indices_pointer_from_handle (indices_handle);
cogl_clip_ensure (); cogl_clip_ensure ();
_cogl_current_matrix_state_flush (); _cogl_current_matrix_state_flush ();
enable_state_for_drawing_buffer (buffer); enable_state_for_drawing_buffer (buffer);
for (l = buffer->indices; l; l = l->next)
{
CoglVertexBufferIndices *current_indices = l->data;
if (current_indices->id == indices_id)
{
indices = current_indices;
break;
}
}
if (!indices)
return;
byte_offset = indices_offset * get_indices_type_size (indices->type); byte_offset = indices_offset * get_indices_type_size (indices->type);
if (fallback) if (fallback)
byte_offset = (size_t)(((char *)indices->vbo_name) + byte_offset); byte_offset = (size_t)(((char *)indices->vbo_name) + byte_offset);
@ -1903,7 +1856,7 @@ cogl_vertex_buffer_draw_elements (CoglHandle handle,
GPOINTER_TO_UINT (indices->vbo_name))); GPOINTER_TO_UINT (indices->vbo_name)));
/* FIXME: flush cogl cache */ /* FIXME: flush cogl cache */
GE (glDrawRangeElements (mode, indices->min_index, indices->max_index, GE (glDrawRangeElements (mode, min_index, max_index,
count, indices->type, (void *)byte_offset)); count, indices->type, (void *)byte_offset));
disable_state_for_drawing_buffer (buffer); disable_state_for_drawing_buffer (buffer);
@ -1924,10 +1877,6 @@ _cogl_vertex_buffer_free (CoglVertexBuffer *buffer)
cogl_vertex_buffer_attribute_free (tmp->data); cogl_vertex_buffer_attribute_free (tmp->data);
g_list_free (buffer->new_attributes); g_list_free (buffer->new_attributes);
for (tmp = buffer->indices; tmp != NULL; tmp = tmp->next)
free_vertex_buffer_indices (tmp->data);
g_list_free (buffer->indices);
g_slice_free (CoglVertexBuffer, buffer); g_slice_free (CoglVertexBuffer, buffer);
} }

View File

@ -49,7 +49,7 @@ typedef struct _TestState
GLubyte *quad_mesh_colors; GLubyte *quad_mesh_colors;
GLushort *static_indices; GLushort *static_indices;
guint n_static_indices; guint n_static_indices;
int indices_id; CoglHandle indices;
ClutterTimeline *timeline; ClutterTimeline *timeline;
} TestState; } TestState;
@ -141,7 +141,10 @@ on_paint (ClutterActor *actor, TestState *state)
cogl_set_source_color4ub (0xff, 0x00, 0x00, 0xff); cogl_set_source_color4ub (0xff, 0x00, 0x00, 0xff);
cogl_vertex_buffer_draw_elements (state->buffer, cogl_vertex_buffer_draw_elements (state->buffer,
COGL_VERTICES_MODE_TRIANGLE_STRIP, COGL_VERTICES_MODE_TRIANGLE_STRIP,
state->indices_id, state->indices,
0, /* min index */
(MESH_WIDTH + 1) *
(MESH_HEIGHT + 1), /* max index */
0, /* indices offset */ 0, /* indices offset */
state->n_static_indices); state->n_static_indices);
} }
@ -220,12 +223,8 @@ init_static_index_arrays (TestState *state)
#undef MESH_INDEX #undef MESH_INDEX
state->indices_id = state->indices =
cogl_vertex_buffer_add_indices (state->buffer, cogl_vertex_buffer_indices_new (COGL_INDICES_TYPE_UNSIGNED_SHORT,
0, /* min index */
(MESH_WIDTH + 1) *
(MESH_HEIGHT + 1), /* max index */
COGL_INDICES_TYPE_UNSIGNED_SHORT,
state->static_indices, state->static_indices,
state->n_static_indices); state->n_static_indices);
} }
@ -376,6 +375,7 @@ test_cogl_vertex_buffer_main (int argc, char *argv[])
clutter_main (); clutter_main ();
cogl_handle_unref (state.buffer); cogl_handle_unref (state.buffer);
cogl_handle_unref (state.indices);
g_source_remove (idle_source); g_source_remove (idle_source);