cogl-buffer: Create the buffer store when bound

Whenever the buffer is bound with _cogl_buffer_bind Cogl now ensures
the buffer's data store has been created. Previously it would only
ensure it was created when it was first mapped or when the first data
was set on it. This is necessary if we are going to use CoglBuffers
for retrieving data from GL. In that case the buffer won't be mapped
or have data set on it before it is used.

Reviewed-by: Robert Bragg <robert@linux.intel.com>
This commit is contained in:
Neil Roberts 2012-02-25 19:14:25 +00:00
parent 1b47ff0dfe
commit 2501899044

View File

@ -118,6 +118,34 @@ convert_bind_target_to_gl_target (CoglBufferBindTarget target)
} }
} }
static void *
_cogl_buffer_bind_no_create (CoglBuffer *buffer,
CoglBufferBindTarget target)
{
CoglContext *ctx = buffer->context;
_COGL_RETURN_VAL_IF_FAIL (buffer != NULL, NULL);
/* Don't allow binding the buffer to multiple targets at the same time */
_COGL_RETURN_VAL_IF_FAIL (ctx->current_buffer[buffer->last_target] != buffer,
NULL);
/* Don't allow nesting binds to the same target */
_COGL_RETURN_VAL_IF_FAIL (ctx->current_buffer[target] == NULL, NULL);
buffer->last_target = target;
ctx->current_buffer[target] = buffer;
if (buffer->flags & COGL_BUFFER_FLAG_BUFFER_OBJECT)
{
GLenum gl_target = convert_bind_target_to_gl_target (buffer->last_target);
GE( ctx, glBindBuffer (gl_target, buffer->gl_handle) );
return NULL;
}
else
return buffer->data;
}
static GLenum static GLenum
_cogl_buffer_hints_to_gl_enum (CoglBufferUsageHint usage_hint, _cogl_buffer_hints_to_gl_enum (CoglBufferUsageHint usage_hint,
CoglBufferUpdateHint update_hint) CoglBufferUpdateHint update_hint)
@ -136,6 +164,25 @@ _cogl_buffer_hints_to_gl_enum (CoglBufferUsageHint usage_hint,
return GL_STATIC_DRAW; return GL_STATIC_DRAW;
} }
static void
bo_recreate_store (CoglBuffer *buffer)
{
GLenum gl_target;
GLenum gl_enum;
/* This assumes the buffer is already bound */
gl_target = convert_bind_target_to_gl_target (buffer->last_target);
gl_enum = _cogl_buffer_hints_to_gl_enum (buffer->usage_hint,
buffer->update_hint);
GE( buffer->context, glBufferData (gl_target,
buffer->size,
NULL,
gl_enum) );
buffer->store_created = TRUE;
}
static void * static void *
bo_map (CoglBuffer *buffer, bo_map (CoglBuffer *buffer,
CoglBufferAccess access, CoglBufferAccess access,
@ -154,7 +201,7 @@ bo_map (CoglBuffer *buffer,
return NULL; return NULL;
target = buffer->last_target; target = buffer->last_target;
_cogl_buffer_bind (buffer, target); _cogl_buffer_bind_no_create (buffer, target);
gl_target = convert_bind_target_to_gl_target (target); gl_target = convert_bind_target_to_gl_target (target);
@ -162,19 +209,7 @@ bo_map (CoglBuffer *buffer,
* lazily allows the user of the CoglBuffer to set a hint before the * lazily allows the user of the CoglBuffer to set a hint before the
* store is created. */ * store is created. */
if (!buffer->store_created || (hints & COGL_BUFFER_MAP_HINT_DISCARD)) if (!buffer->store_created || (hints & COGL_BUFFER_MAP_HINT_DISCARD))
{ bo_recreate_store (buffer);
GLenum gl_enum;
gl_enum = _cogl_buffer_hints_to_gl_enum (buffer->usage_hint,
buffer->update_hint);
GE( ctx, glBufferData (gl_target,
buffer->size,
NULL,
gl_enum) );
buffer->store_created = TRUE;
}
GE_RET( data, ctx, glMapBuffer (gl_target, GE_RET( data, ctx, glMapBuffer (gl_target,
_cogl_buffer_access_to_gl_enum (access)) ); _cogl_buffer_access_to_gl_enum (access)) );
@ -191,7 +226,7 @@ bo_unmap (CoglBuffer *buffer)
{ {
CoglContext *ctx = buffer->context; CoglContext *ctx = buffer->context;
_cogl_buffer_bind (buffer, buffer->last_target); _cogl_buffer_bind_no_create (buffer, buffer->last_target);
GE( ctx, glUnmapBuffer (convert_bind_target_to_gl_target GE( ctx, glUnmapBuffer (convert_bind_target_to_gl_target
(buffer->last_target)) ); (buffer->last_target)) );
@ -215,20 +250,6 @@ bo_set_data (CoglBuffer *buffer,
gl_target = convert_bind_target_to_gl_target (target); gl_target = convert_bind_target_to_gl_target (target);
/* create an empty store if we don't have one yet. creating the store
* lazily allows the user of the CoglBuffer to set a hint before the
* store is created. */
if (!buffer->store_created)
{
GLenum gl_enum = _cogl_buffer_hints_to_gl_enum (buffer->usage_hint,
buffer->update_hint);
GE( ctx, glBufferData (gl_target,
buffer->size,
NULL,
gl_enum) );
buffer->store_created = TRUE;
}
GE( ctx, glBufferSubData (gl_target, offset, size, data) ); GE( ctx, glBufferSubData (gl_target, offset, size, data) );
_cogl_buffer_unbind (buffer); _cogl_buffer_unbind (buffer);
@ -331,28 +352,18 @@ _cogl_buffer_access_to_gl_enum (CoglBufferAccess access)
void * void *
_cogl_buffer_bind (CoglBuffer *buffer, CoglBufferBindTarget target) _cogl_buffer_bind (CoglBuffer *buffer, CoglBufferBindTarget target)
{ {
CoglContext *ctx = buffer->context; void *ret;
_COGL_RETURN_VAL_IF_FAIL (buffer != NULL, NULL); ret = _cogl_buffer_bind_no_create (buffer, target);
/* Don't allow binding the buffer to multiple targets at the same time */ /* create an empty store if we don't have one yet. creating the store
_COGL_RETURN_VAL_IF_FAIL (ctx->current_buffer[buffer->last_target] != buffer, * lazily allows the user of the CoglBuffer to set a hint before the
NULL); * store is created. */
if ((buffer->flags & COGL_BUFFER_FLAG_BUFFER_OBJECT) &&
!buffer->store_created)
bo_recreate_store (buffer);
/* Don't allow nesting binds to the same target */ return ret;
_COGL_RETURN_VAL_IF_FAIL (ctx->current_buffer[target] == NULL, NULL);
buffer->last_target = target;
ctx->current_buffer[target] = buffer;
if (buffer->flags & COGL_BUFFER_FLAG_BUFFER_OBJECT)
{
GLenum gl_target = convert_bind_target_to_gl_target (buffer->last_target);
GE( ctx, glBindBuffer (gl_target, buffer->gl_handle) );
return NULL;
}
else
return buffer->data;
} }
void void