[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;
/**
* cogl_vertex_buffer_add_indices:
* @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
* cogl_vertex_buffer_indices_new:
* @indices_type: a #CoglIndicesType specifying the data type used for
* the 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
* during triangle strips.
*
* You should aim to use the smallest data type possible and correctly reflect
* the range of index values in the {min,max}_index arguments. This allows Cogl
* 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().
* Returns: A CoglHandle for the indices which you can pass to
* cogl_vertex_buffer_draw_elements().
*/
int
cogl_vertex_buffer_add_indices (CoglHandle handle,
int min_index,
int max_index,
CoglIndicesType indices_type,
CoglHandle
cogl_vertex_buffer_indices_new (CoglIndicesType indices_type,
const void *indices_array,
int indices_len);
@ -352,16 +341,17 @@ cogl_vertex_buffer_delete_indices (CoglHandle handle,
* @handle: A vertex buffer handle
* @mode: A #CoglVerticesMode specifying how the vertices should be
* interpreted.
* @indices_id: The identifier for a an array of indices previously added to
* the given Cogl vertex buffer using
* cogl_vertex_buffer_add_indices().
* @indices: A CoglHandle for a set of indices allocated via
* cogl_vertex_buffer_indices_new ()
* @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
* index to use for drawing.
* @count: Specifies the number of vertices you want to draw.
*
* 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
* 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
* drawing.
@ -369,7 +359,9 @@ cogl_vertex_buffer_delete_indices (CoglHandle handle,
void
cogl_vertex_buffer_draw_elements (CoglHandle handle,
CoglVerticesMode mode,
int indices_id,
CoglHandle indices,
int min_index,
int max_index,
int indices_offset,
int count);

View File

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

View File

@ -201,8 +201,10 @@
#endif /* HAVE_COGL_GL */
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 (VertexBufferIndices, vertex_buffer_indices);
CoglHandle
cogl_vertex_buffer_new (guint n_vertices)
@ -214,8 +216,6 @@ cogl_vertex_buffer_new (guint n_vertices)
buffer->submitted_vbos = NULL;
buffer->new_attributes = NULL;
buffer->indices = NULL;
/* return COGL_INVALID_HANDLE; */
return _cogl_vertex_buffer_handle_new (buffer);
}
@ -1741,22 +1741,6 @@ cogl_vertex_buffer_draw (CoglHandle handle,
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
get_indices_type_size (GLuint indices_type)
{
@ -1771,34 +1755,19 @@ get_indices_type_size (GLuint indices_type)
}
}
int
cogl_vertex_buffer_add_indices (CoglHandle handle,
int min_index,
int max_index,
CoglIndicesType indices_type,
CoglHandle
cogl_vertex_buffer_indices_new (CoglIndicesType indices_type,
const void *indices_array,
int indices_len)
{
CoglVertexBuffer *buffer;
gboolean fallback =
(cogl_get_features () & COGL_FEATURE_VBOS) ? FALSE : TRUE;
size_t indices_bytes;
CoglVertexBufferIndices *indices;
static int next_indices_id = 1;
_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->id = next_indices_id;
indices->min_index = min_index;
indices->max_index = max_index;
if (indices_type == COGL_INDICES_TYPE_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));
}
buffer->indices = g_list_prepend (buffer->indices, indices);
return next_indices_id++;
return _cogl_vertex_buffer_indices_handle_new (indices);
}
void
cogl_vertex_buffer_delete_indices (CoglHandle handle,
int indices_id)
_cogl_vertex_buffer_indices_free (CoglVertexBufferIndices *indices)
{
CoglVertexBuffer *buffer;
GList *l;
gboolean fallback =
(cogl_get_features () & COGL_FEATURE_VBOS) ? FALSE : TRUE;
if (!cogl_is_vertex_buffer (handle))
return;
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
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)
{
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;
}
}
g_slice_free (CoglVertexBufferIndices, indices);
}
void
cogl_vertex_buffer_draw_elements (CoglHandle handle,
CoglVerticesMode mode,
int indices_id,
CoglHandle indices_handle,
int min_index,
int max_index,
int indices_offset,
int count)
{
@ -1869,7 +1830,6 @@ cogl_vertex_buffer_draw_elements (CoglHandle handle,
gboolean fallback =
(cogl_get_features () & COGL_FEATURE_VBOS) ? FALSE : TRUE;
size_t byte_offset;
GList *l;
CoglVertexBufferIndices *indices = NULL;
_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);
if (!cogl_is_vertex_buffer_indices (indices_handle))
return;
indices = _cogl_vertex_buffer_indices_pointer_from_handle (indices_handle);
cogl_clip_ensure ();
_cogl_current_matrix_state_flush ();
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);
if (fallback)
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)));
/* 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));
disable_state_for_drawing_buffer (buffer);
@ -1924,10 +1877,6 @@ _cogl_vertex_buffer_free (CoglVertexBuffer *buffer)
cogl_vertex_buffer_attribute_free (tmp->data);
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);
}

View File

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