mirror of
https://github.com/brl/mutter.git
synced 2024-11-29 19:40:43 -05:00
cogl-buffer: Track the last used bind target in CoglBuffer
This makes CoglBuffer track the last used bind target as a private property. This is later used when binding a buffer to map instead of always using the PIXEL_UNPACK target. This also adds some additional sanity checks that code doesn't try to nest binds to the same target or bind a buffer to multiple targets at the same time.
This commit is contained in:
parent
7571cc1923
commit
e98ee6665b
@ -75,11 +75,22 @@ typedef enum {
|
|||||||
COGL_BUFFER_USAGE_HINT_VERTICES
|
COGL_BUFFER_USAGE_HINT_VERTICES
|
||||||
} CoglBufferUsageHint;
|
} CoglBufferUsageHint;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
COGL_BUFFER_BIND_TARGET_PIXEL_PACK,
|
||||||
|
COGL_BUFFER_BIND_TARGET_PIXEL_UNPACK,
|
||||||
|
COGL_BUFFER_BIND_TARGET_VERTEX_ARRAY,
|
||||||
|
COGL_BUFFER_BIND_TARGET_VERTEX_INDICES_ARRAY,
|
||||||
|
|
||||||
|
COGL_BUFFER_BIND_TARGET_COUNT
|
||||||
|
} CoglBufferBindTarget;
|
||||||
|
|
||||||
struct _CoglBuffer
|
struct _CoglBuffer
|
||||||
{
|
{
|
||||||
CoglObject _parent;
|
CoglObject _parent;
|
||||||
const CoglBufferVtable *vtable;
|
const CoglBufferVtable *vtable;
|
||||||
|
|
||||||
|
CoglBufferBindTarget last_target;
|
||||||
|
|
||||||
CoglBufferFlags flags;
|
CoglBufferFlags flags;
|
||||||
|
|
||||||
GLuint gl_handle; /* OpenGL handle */
|
GLuint gl_handle; /* OpenGL handle */
|
||||||
@ -107,6 +118,7 @@ _cogl_buffer_register_buffer_type (GQuark type);
|
|||||||
void
|
void
|
||||||
_cogl_buffer_initialize (CoglBuffer *buffer,
|
_cogl_buffer_initialize (CoglBuffer *buffer,
|
||||||
unsigned int size,
|
unsigned int size,
|
||||||
|
CoglBufferBindTarget default_target,
|
||||||
CoglBufferUsageHint usage_hint,
|
CoglBufferUsageHint usage_hint,
|
||||||
CoglBufferUpdateHint update_hint);
|
CoglBufferUpdateHint update_hint);
|
||||||
|
|
||||||
@ -115,11 +127,20 @@ _cogl_buffer_fini (CoglBuffer *buffer);
|
|||||||
|
|
||||||
void
|
void
|
||||||
_cogl_buffer_bind (CoglBuffer *buffer,
|
_cogl_buffer_bind (CoglBuffer *buffer,
|
||||||
GLenum target);
|
CoglBufferBindTarget target);
|
||||||
|
|
||||||
|
void
|
||||||
|
_cogl_buffer_unbind (CoglBuffer *buffer);
|
||||||
|
|
||||||
CoglBufferUsageHint
|
CoglBufferUsageHint
|
||||||
_cogl_buffer_get_usage_hint (CoglBuffer *buffer);
|
_cogl_buffer_get_usage_hint (CoglBuffer *buffer);
|
||||||
|
|
||||||
|
GLenum
|
||||||
|
_cogl_buffer_get_last_gl_target (CoglBuffer *buffer);
|
||||||
|
|
||||||
|
CoglBufferBindTarget
|
||||||
|
_cogl_buffer_get_last_bind_target (CoglBuffer *buffer);
|
||||||
|
|
||||||
GLenum
|
GLenum
|
||||||
_cogl_buffer_access_to_gl_enum (CoglBufferAccess access);
|
_cogl_buffer_access_to_gl_enum (CoglBufferAccess access);
|
||||||
|
|
||||||
|
@ -59,9 +59,6 @@
|
|||||||
#define glDeleteBuffers ctx->drv.pf_glDeleteBuffers
|
#define glDeleteBuffers ctx->drv.pf_glDeleteBuffers
|
||||||
#define glMapBuffer ctx->drv.pf_glMapBuffer
|
#define glMapBuffer ctx->drv.pf_glMapBuffer
|
||||||
#define glUnmapBuffer ctx->drv.pf_glUnmapBuffer
|
#define glUnmapBuffer ctx->drv.pf_glUnmapBuffer
|
||||||
#ifndef GL_ARRAY_BUFFER
|
|
||||||
#define GL_ARRAY_BUFFER GL_ARRAY_BUFFER_ARB
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#elif defined (HAVE_COGL_GLES2)
|
#elif defined (HAVE_COGL_GLES2)
|
||||||
|
|
||||||
@ -69,6 +66,19 @@
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef GL_PIXEL_PACK_BUFFER
|
||||||
|
#define GL_PIXEL_PACK_BUFFER 0x88EB
|
||||||
|
#endif
|
||||||
|
#ifndef GL_PIXEL_UNPACK_BUFFER
|
||||||
|
#define GL_PIXEL_UNPACK_BUFFER 0x88EC
|
||||||
|
#endif
|
||||||
|
#ifndef GL_ARRAY_BUFFER
|
||||||
|
#define GL_ARRAY_BUFFER 0x8892
|
||||||
|
#endif
|
||||||
|
#ifndef GL_ELEMENT_ARRAY_BUFFER
|
||||||
|
#define GL_ARRAY_BUFFER 0x8893
|
||||||
|
#endif
|
||||||
|
|
||||||
/* XXX:
|
/* XXX:
|
||||||
* The CoglHandle macros don't support any form of inheritance, so for
|
* The CoglHandle macros don't support any form of inheritance, so for
|
||||||
* now we implement the CoglObject support for the CoglBuffer
|
* now we implement the CoglObject support for the CoglBuffer
|
||||||
@ -105,6 +115,7 @@ cogl_is_buffer (const void *object)
|
|||||||
void
|
void
|
||||||
_cogl_buffer_initialize (CoglBuffer *buffer,
|
_cogl_buffer_initialize (CoglBuffer *buffer,
|
||||||
unsigned int size,
|
unsigned int size,
|
||||||
|
CoglBufferBindTarget default_target,
|
||||||
CoglBufferUsageHint usage_hint,
|
CoglBufferUsageHint usage_hint,
|
||||||
CoglBufferUpdateHint update_hint)
|
CoglBufferUpdateHint update_hint)
|
||||||
{
|
{
|
||||||
@ -112,6 +123,7 @@ _cogl_buffer_initialize (CoglBuffer *buffer,
|
|||||||
|
|
||||||
buffer->flags = COGL_BUFFER_FLAG_NONE;
|
buffer->flags = COGL_BUFFER_FLAG_NONE;
|
||||||
buffer->size = size;
|
buffer->size = size;
|
||||||
|
buffer->last_target = default_target;
|
||||||
buffer->usage_hint = usage_hint;
|
buffer->usage_hint = usage_hint;
|
||||||
buffer->update_hint = update_hint;
|
buffer->update_hint = update_hint;
|
||||||
buffer->data = NULL;
|
buffer->data = NULL;
|
||||||
@ -124,6 +136,30 @@ _cogl_buffer_fini (CoglBuffer *buffer)
|
|||||||
cogl_buffer_unmap (buffer);
|
cogl_buffer_unmap (buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GLenum
|
||||||
|
_cogl_buffer_get_last_gl_target (CoglBuffer *buffer)
|
||||||
|
{
|
||||||
|
switch (buffer->last_target)
|
||||||
|
{
|
||||||
|
case COGL_BUFFER_BIND_TARGET_PIXEL_PACK:
|
||||||
|
return GL_PIXEL_PACK_BUFFER;
|
||||||
|
case COGL_BUFFER_BIND_TARGET_PIXEL_UNPACK:
|
||||||
|
return GL_PIXEL_UNPACK_BUFFER;
|
||||||
|
case COGL_BUFFER_BIND_TARGET_VERTEX_ARRAY:
|
||||||
|
return GL_ARRAY_BUFFER;
|
||||||
|
case COGL_BUFFER_BIND_TARGET_VERTEX_INDICES_ARRAY:
|
||||||
|
return GL_ELEMENT_ARRAY_BUFFER;
|
||||||
|
default:
|
||||||
|
g_return_val_if_reached (COGL_BUFFER_BIND_TARGET_PIXEL_UNPACK);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CoglBufferBindTarget
|
||||||
|
_cogl_buffer_get_last_bind_target (CoglBuffer *buffer)
|
||||||
|
{
|
||||||
|
return buffer->last_target;
|
||||||
|
}
|
||||||
|
|
||||||
/* OpenGL ES 1.1 and 2 have a GL_OES_mapbuffer extension that is able to map
|
/* OpenGL ES 1.1 and 2 have a GL_OES_mapbuffer extension that is able to map
|
||||||
* VBOs for write only, we don't support that in CoglBuffer */
|
* VBOs for write only, we don't support that in CoglBuffer */
|
||||||
#if defined (COGL_HAS_GLES)
|
#if defined (COGL_HAS_GLES)
|
||||||
@ -132,6 +168,7 @@ _cogl_buffer_access_to_gl_enum (CoglBufferAccess access)
|
|||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#else
|
#else
|
||||||
GLenum
|
GLenum
|
||||||
_cogl_buffer_access_to_gl_enum (CoglBufferAccess access)
|
_cogl_buffer_access_to_gl_enum (CoglBufferAccess access)
|
||||||
@ -174,27 +211,46 @@ _cogl_buffer_hints_to_gl_enum (CoglBufferUsageHint usage_hint,
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
void
|
void
|
||||||
_cogl_buffer_bind (CoglBuffer *buffer,
|
_cogl_buffer_bind (CoglBuffer *buffer, CoglBufferBindTarget target)
|
||||||
GLenum target)
|
|
||||||
{
|
{
|
||||||
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
|
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
|
||||||
|
|
||||||
/* Don't bind again an already bound pbo */
|
g_return_if_fail (buffer != NULL);
|
||||||
if (ctx->current_pbo == buffer)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (buffer && COGL_BUFFER_FLAG_IS_SET (buffer, BUFFER_OBJECT))
|
/* Don't allow binding the buffer to multiple targets at the same time */
|
||||||
|
g_return_if_fail (ctx->current_buffer[buffer->last_target] != buffer);
|
||||||
|
|
||||||
|
/* Don't allow nesting binds to the same target */
|
||||||
|
g_return_if_fail (ctx->current_buffer[target] == NULL);
|
||||||
|
|
||||||
|
buffer->last_target = target;
|
||||||
|
|
||||||
|
if (COGL_BUFFER_FLAG_IS_SET (buffer, BUFFER_OBJECT))
|
||||||
{
|
{
|
||||||
GE( glBindBuffer (target, buffer->gl_handle) );
|
GLenum gl_target = _cogl_buffer_get_last_gl_target (buffer);
|
||||||
}
|
GE( glBindBuffer (gl_target, buffer->gl_handle) );
|
||||||
else if (buffer == NULL &&
|
|
||||||
ctx->current_pbo &&
|
|
||||||
COGL_BUFFER_FLAG_IS_SET (ctx->current_pbo, BUFFER_OBJECT))
|
|
||||||
{
|
|
||||||
GE( glBindBuffer (target, 0) );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx->current_pbo = buffer;
|
ctx->current_buffer[target] = buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
_cogl_buffer_unbind (CoglBuffer *buffer)
|
||||||
|
{
|
||||||
|
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
|
||||||
|
|
||||||
|
g_return_if_fail (buffer != NULL);
|
||||||
|
|
||||||
|
/* the unbind should pair up with a previous bind */
|
||||||
|
g_return_if_fail (ctx->current_buffer[buffer->last_target] == buffer);
|
||||||
|
|
||||||
|
if (COGL_BUFFER_FLAG_IS_SET (buffer, BUFFER_OBJECT))
|
||||||
|
{
|
||||||
|
GLenum gl_target = _cogl_buffer_get_last_gl_target (buffer);
|
||||||
|
GE( glBindBuffer (gl_target, 0) );
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx->current_buffer[buffer->last_target] = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int
|
unsigned int
|
||||||
|
@ -57,6 +57,7 @@ cogl_create_context (void)
|
|||||||
GLubyte default_texture_data[] = { 0xff, 0xff, 0xff, 0x0 };
|
GLubyte default_texture_data[] = { 0xff, 0xff, 0xff, 0x0 };
|
||||||
unsigned long enable_flags = 0;
|
unsigned long enable_flags = 0;
|
||||||
CoglHandle window_buffer;
|
CoglHandle window_buffer;
|
||||||
|
int i;
|
||||||
|
|
||||||
if (_context != NULL)
|
if (_context != NULL)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
@ -148,6 +149,9 @@ cogl_create_context (void)
|
|||||||
|
|
||||||
_context->legacy_depth_test_enabled = FALSE;
|
_context->legacy_depth_test_enabled = FALSE;
|
||||||
|
|
||||||
|
for (i = 0; i < COGL_BUFFER_BIND_TARGET_COUNT; i++)
|
||||||
|
_context->current_buffer[i] = NULL;
|
||||||
|
|
||||||
_context->framebuffer_stack = _cogl_create_framebuffer_stack ();
|
_context->framebuffer_stack = _cogl_create_framebuffer_stack ();
|
||||||
|
|
||||||
window_buffer = _cogl_onscreen_new ();
|
window_buffer = _cogl_onscreen_new ();
|
||||||
@ -204,8 +208,6 @@ cogl_create_context (void)
|
|||||||
_context->atlas = NULL;
|
_context->atlas = NULL;
|
||||||
_context->atlas_texture = COGL_INVALID_HANDLE;
|
_context->atlas_texture = COGL_INVALID_HANDLE;
|
||||||
|
|
||||||
_context->current_pbo = NULL;
|
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -118,9 +118,7 @@ typedef struct
|
|||||||
|
|
||||||
gboolean legacy_depth_test_enabled;
|
gboolean legacy_depth_test_enabled;
|
||||||
|
|
||||||
/* PBOs */
|
CoglBuffer *current_buffer[COGL_BUFFER_BIND_TARGET_COUNT];
|
||||||
/* This can be used to check if a pbo is bound */
|
|
||||||
CoglBuffer *current_pbo;
|
|
||||||
|
|
||||||
/* Framebuffers */
|
/* Framebuffers */
|
||||||
GSList *framebuffer_stack;
|
GSList *framebuffer_stack;
|
||||||
|
@ -58,7 +58,6 @@ struct _CoglPixelArray
|
|||||||
|
|
||||||
CoglPixelArrayFlags flags;
|
CoglPixelArrayFlags flags;
|
||||||
|
|
||||||
GLenum gl_target;
|
|
||||||
CoglPixelFormat format;
|
CoglPixelFormat format;
|
||||||
unsigned int width;
|
unsigned int width;
|
||||||
unsigned int height;
|
unsigned int height;
|
||||||
|
@ -98,6 +98,7 @@ _cogl_pixel_array_new (unsigned int size)
|
|||||||
/* parent's constructor */
|
/* parent's constructor */
|
||||||
_cogl_buffer_initialize (buffer,
|
_cogl_buffer_initialize (buffer,
|
||||||
size,
|
size,
|
||||||
|
COGL_BUFFER_BIND_TARGET_PIXEL_UNPACK,
|
||||||
COGL_BUFFER_USAGE_HINT_TEXTURE,
|
COGL_BUFFER_USAGE_HINT_TEXTURE,
|
||||||
COGL_BUFFER_UPDATE_HINT_STATIC);
|
COGL_BUFFER_UPDATE_HINT_STATIC);
|
||||||
|
|
||||||
@ -181,16 +182,16 @@ _cogl_pixel_array_map (CoglBuffer *buffer,
|
|||||||
CoglBufferMapHint hints)
|
CoglBufferMapHint hints)
|
||||||
{
|
{
|
||||||
CoglPixelArray *pixel_array = COGL_PIXEL_ARRAY (buffer);
|
CoglPixelArray *pixel_array = COGL_PIXEL_ARRAY (buffer);
|
||||||
GLenum gl_target;
|
|
||||||
guint8 *data;
|
guint8 *data;
|
||||||
|
CoglBufferBindTarget target;
|
||||||
|
GLenum gl_target;
|
||||||
|
|
||||||
_COGL_GET_CONTEXT (ctx, NULL);
|
_COGL_GET_CONTEXT (ctx, NULL);
|
||||||
|
|
||||||
/* we determine the target lazily, on the first map */
|
target = _cogl_buffer_get_last_bind_target (buffer);
|
||||||
gl_target = GL_PIXEL_UNPACK_BUFFER;
|
_cogl_buffer_bind (buffer, target);
|
||||||
pixel_array->gl_target = gl_target;
|
|
||||||
|
|
||||||
_cogl_buffer_bind (buffer, gl_target);
|
gl_target = _cogl_buffer_get_last_gl_target (buffer);
|
||||||
|
|
||||||
/* create an empty store if we don't have one yet. creating the store
|
/* 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
|
* lazily allows the user of the CoglBuffer to set a hint before the
|
||||||
@ -211,7 +212,7 @@ _cogl_pixel_array_map (CoglBuffer *buffer,
|
|||||||
if (data)
|
if (data)
|
||||||
COGL_BUFFER_SET_FLAG (buffer, MAPPED);
|
COGL_BUFFER_SET_FLAG (buffer, MAPPED);
|
||||||
|
|
||||||
_cogl_buffer_bind (NULL, gl_target);
|
_cogl_buffer_unbind (buffer);
|
||||||
|
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
@ -219,16 +220,17 @@ _cogl_pixel_array_map (CoglBuffer *buffer,
|
|||||||
static void
|
static void
|
||||||
_cogl_pixel_array_unmap (CoglBuffer *buffer)
|
_cogl_pixel_array_unmap (CoglBuffer *buffer)
|
||||||
{
|
{
|
||||||
CoglPixelArray *pixel_array = COGL_PIXEL_ARRAY (buffer);
|
CoglBufferBindTarget target;
|
||||||
|
|
||||||
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
|
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
|
||||||
|
|
||||||
_cogl_buffer_bind (buffer, pixel_array->gl_target);
|
target = _cogl_buffer_get_last_bind_target (buffer);
|
||||||
|
_cogl_buffer_bind (buffer, target);
|
||||||
|
|
||||||
GE( glUnmapBuffer (pixel_array->gl_target) );
|
GE( glUnmapBuffer (_cogl_buffer_get_last_gl_target (buffer)) );
|
||||||
COGL_BUFFER_CLEAR_FLAG (buffer, MAPPED);
|
COGL_BUFFER_CLEAR_FLAG (buffer, MAPPED);
|
||||||
|
|
||||||
_cogl_buffer_bind (NULL, pixel_array->gl_target);
|
_cogl_buffer_unbind (buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
@ -238,19 +240,22 @@ _cogl_pixel_array_set_data (CoglBuffer *buffer,
|
|||||||
unsigned int size)
|
unsigned int size)
|
||||||
{
|
{
|
||||||
CoglPixelArray *pixel_array = COGL_PIXEL_ARRAY (buffer);
|
CoglPixelArray *pixel_array = COGL_PIXEL_ARRAY (buffer);
|
||||||
|
CoglBufferBindTarget target;
|
||||||
|
GLenum gl_target;
|
||||||
|
|
||||||
_COGL_GET_CONTEXT (ctx, FALSE);
|
_COGL_GET_CONTEXT (ctx, FALSE);
|
||||||
|
|
||||||
pixel_array->gl_target = GL_PIXEL_UNPACK_BUFFER;
|
target = _cogl_buffer_get_last_bind_target (buffer);
|
||||||
|
_cogl_buffer_bind (buffer, target);
|
||||||
|
|
||||||
_cogl_buffer_bind (buffer, pixel_array->gl_target);
|
gl_target = _cogl_buffer_get_last_gl_target (buffer);
|
||||||
|
|
||||||
/* create an empty store if we don't have one yet. creating the store
|
/* 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
|
* lazily allows the user of the CoglBuffer to set a hint before the
|
||||||
* store is created. */
|
* store is created. */
|
||||||
if (!COGL_PIXEL_ARRAY_FLAG_IS_SET (pixel_array, STORE_CREATED))
|
if (!COGL_PIXEL_ARRAY_FLAG_IS_SET (pixel_array, STORE_CREATED))
|
||||||
{
|
{
|
||||||
GE( glBufferData (pixel_array->gl_target,
|
GE( glBufferData (gl_target,
|
||||||
buffer->size,
|
buffer->size,
|
||||||
NULL,
|
NULL,
|
||||||
_cogl_buffer_hints_to_gl_enum (buffer->usage_hint,
|
_cogl_buffer_hints_to_gl_enum (buffer->usage_hint,
|
||||||
@ -258,9 +263,9 @@ _cogl_pixel_array_set_data (CoglBuffer *buffer,
|
|||||||
COGL_PIXEL_ARRAY_SET_FLAG (pixel_array, STORE_CREATED);
|
COGL_PIXEL_ARRAY_SET_FLAG (pixel_array, STORE_CREATED);
|
||||||
}
|
}
|
||||||
|
|
||||||
GE( glBufferSubData (pixel_array->gl_target, offset, size, data) );
|
GE( glBufferSubData (gl_target, offset, size, data) );
|
||||||
|
|
||||||
_cogl_buffer_bind (NULL, pixel_array->gl_target);
|
_cogl_buffer_unbind (buffer);
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
@ -581,9 +581,10 @@ cogl_texture_new_from_buffer_EXP (CoglHandle buffer,
|
|||||||
bitmap.format = format;
|
bitmap.format = format;
|
||||||
bitmap.rowstride = rowstride;
|
bitmap.rowstride = rowstride;
|
||||||
|
|
||||||
_cogl_buffer_bind (cogl_buffer, GL_PIXEL_UNPACK_BUFFER);
|
_cogl_buffer_bind (cogl_buffer,
|
||||||
|
COGL_BUFFER_BIND_TARGET_PIXEL_UNPACK);
|
||||||
texture = cogl_texture_new_from_bitmap (&bitmap, flags, internal_format);
|
texture = cogl_texture_new_from_bitmap (&bitmap, flags, internal_format);
|
||||||
_cogl_buffer_bind (NULL, GL_PIXEL_UNPACK_BUFFER);
|
_cogl_buffer_unbind (cogl_buffer);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
Reference in New Issue
Block a user