From 2e0d2cf055050c0dd27841e639a4c98cd182919f Mon Sep 17 00:00:00 2001 From: Robert Bragg Date: Tue, 6 Jul 2010 01:21:43 +0100 Subject: [PATCH] cogl-buffer: Move malloc fallback logic into CoglBuffer Since we'll want to share the fallback logic with CoglVertexArray this moves the malloc based fallback (for when OpenGL doesn't support vertex or pixel buffer objects) into cogl-buffer.c. --- clutter/cogl/cogl/cogl-buffer-private.h | 9 +- clutter/cogl/cogl/cogl-buffer.c | 213 ++++++++++++++++++++---- clutter/cogl/cogl/cogl-pixel-array.c | 183 +------------------- 3 files changed, 188 insertions(+), 217 deletions(-) diff --git a/clutter/cogl/cogl/cogl-buffer-private.h b/clutter/cogl/cogl/cogl-buffer-private.h index acf2c63d4..4a727fd81 100644 --- a/clutter/cogl/cogl/cogl-buffer-private.h +++ b/clutter/cogl/cogl/cogl-buffer-private.h @@ -87,7 +87,7 @@ typedef enum { struct _CoglBuffer { CoglObject _parent; - const CoglBufferVtable *vtable; + CoglBufferVtable vtable; CoglBufferBindTarget last_target; @@ -118,6 +118,7 @@ _cogl_buffer_register_buffer_type (GQuark type); void _cogl_buffer_initialize (CoglBuffer *buffer, unsigned int size, + gboolean use_malloc, CoglBufferBindTarget default_target, CoglBufferUsageHint usage_hint, CoglBufferUpdateHint update_hint); @@ -135,12 +136,6 @@ _cogl_buffer_unbind (CoglBuffer *buffer); CoglBufferUsageHint _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 _cogl_buffer_access_to_gl_enum (CoglBufferAccess access); diff --git a/clutter/cogl/cogl/cogl-buffer.c b/clutter/cogl/cogl/cogl-buffer.c index a4e9e66c5..6e8f5d42a 100644 --- a/clutter/cogl/cogl/cogl-buffer.c +++ b/clutter/cogl/cogl/cogl-buffer.c @@ -112,33 +112,10 @@ cogl_is_buffer (const void *object) return FALSE; } -void -_cogl_buffer_initialize (CoglBuffer *buffer, - unsigned int size, - CoglBufferBindTarget default_target, - CoglBufferUsageHint usage_hint, - CoglBufferUpdateHint update_hint) +static GLenum +convert_bind_target_to_gl_target (CoglBufferBindTarget target) { - _COGL_GET_CONTEXT (ctx, NO_RETVAL); - - buffer->flags = COGL_BUFFER_FLAG_NONE; - buffer->size = size; - buffer->last_target = default_target; - buffer->usage_hint = usage_hint; - buffer->update_hint = update_hint; - buffer->data = NULL; -} - -void -_cogl_buffer_fini (CoglBuffer *buffer) -{ - g_return_if_fail (!COGL_BUFFER_FLAG_IS_SET (buffer, MAPPED)); -} - -GLenum -_cogl_buffer_get_last_gl_target (CoglBuffer *buffer) -{ - switch (buffer->last_target) + switch (target) { case COGL_BUFFER_BIND_TARGET_PIXEL_PACK: return GL_PIXEL_PACK_BUFFER; @@ -153,10 +130,178 @@ _cogl_buffer_get_last_gl_target (CoglBuffer *buffer) } } -CoglBufferBindTarget -_cogl_buffer_get_last_bind_target (CoglBuffer *buffer) +static guint8 * +bo_map (CoglBuffer *buffer, + CoglBufferAccess access, + CoglBufferMapHint hints) { - return buffer->last_target; +#ifndef COGL_HAS_GLES + + CoglPixelArray *pixel_array = COGL_PIXEL_ARRAY (buffer); + guint8 *data; + CoglBufferBindTarget target; + GLenum gl_target; + + _COGL_GET_CONTEXT (ctx, NULL); + + target = buffer->last_target; + _cogl_buffer_bind (buffer, 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 (!COGL_PIXEL_ARRAY_FLAG_IS_SET (pixel_array, STORE_CREATED) || + (hints & COGL_BUFFER_MAP_HINT_DISCARD)) + { + GE( glBufferData (gl_target, + buffer->size, + NULL, + _cogl_buffer_hints_to_gl_enum (buffer->usage_hint, + buffer->update_hint)) ); + COGL_PIXEL_ARRAY_SET_FLAG (pixel_array, STORE_CREATED); + } + + GE_RET( data, glMapBuffer (gl_target, + _cogl_buffer_access_to_gl_enum (access)) ); + if (data) + COGL_BUFFER_SET_FLAG (buffer, MAPPED); + + _cogl_buffer_unbind (buffer); + + return data; + +#else /* COGL_HAS_GLES */ + + return NULL; + +#endif /* COGL_HAS_GLES */ +} + +static void +bo_unmap (CoglBuffer *buffer) +{ +#ifndef COGL_HAS_GLES + _COGL_GET_CONTEXT (ctx, NO_RETVAL); + + _cogl_buffer_bind (buffer, buffer->last_target); + + GE( glUnmapBuffer (convert_bind_target_to_gl_target (buffer->last_target)) ); + COGL_BUFFER_CLEAR_FLAG (buffer, MAPPED); + + _cogl_buffer_unbind (buffer); +#else + g_return_if_reached (); +#endif +} + +static gboolean +bo_set_data (CoglBuffer *buffer, + unsigned int offset, + const guint8 *data, + unsigned int size) +{ + CoglPixelArray *pixel_array = COGL_PIXEL_ARRAY (buffer); + CoglBufferBindTarget target; + GLenum gl_target; + + _COGL_GET_CONTEXT (ctx, FALSE); + + target = buffer->last_target; + _cogl_buffer_bind (buffer, 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 (!COGL_PIXEL_ARRAY_FLAG_IS_SET (pixel_array, STORE_CREATED)) + { + GE( glBufferData (gl_target, + buffer->size, + NULL, + _cogl_buffer_hints_to_gl_enum (buffer->usage_hint, + buffer->update_hint)) ); + COGL_PIXEL_ARRAY_SET_FLAG (pixel_array, STORE_CREATED); + } + + GE( glBufferSubData (gl_target, offset, size, data) ); + + _cogl_buffer_unbind (buffer); + + return TRUE; +} + +/* + * Fallback path, buffer->data points to a malloc'ed buffer. + */ + +static guint8 * +malloc_map (CoglBuffer *buffer, + CoglBufferAccess access, + CoglBufferMapHint hints) +{ + COGL_BUFFER_SET_FLAG (buffer, MAPPED); + return buffer->data; +} + +static void +malloc_unmap (CoglBuffer *buffer) +{ + COGL_BUFFER_CLEAR_FLAG (buffer, MAPPED); +} + +static gboolean +malloc_set_data (CoglBuffer *buffer, + unsigned int offset, + const guint8 *data, + unsigned int size) +{ + memcpy (buffer->data + offset, data, size); + return TRUE; +} + +void +_cogl_buffer_initialize (CoglBuffer *buffer, + unsigned int size, + gboolean use_malloc, + CoglBufferBindTarget default_target, + CoglBufferUsageHint usage_hint, + CoglBufferUpdateHint update_hint) +{ + _COGL_GET_CONTEXT (ctx, NO_RETVAL); + + buffer->flags = COGL_BUFFER_FLAG_NONE; + buffer->size = size; + buffer->last_target = default_target; + buffer->usage_hint = usage_hint; + buffer->update_hint = update_hint; + buffer->data = NULL; + + if (use_malloc) + { + buffer->vtable.map = malloc_map; + buffer->vtable.unmap = malloc_unmap; + buffer->vtable.set_data = malloc_set_data; + + buffer->data = g_malloc (size); + } + else + { + buffer->vtable.map = bo_map; + buffer->vtable.unmap = bo_unmap; + buffer->vtable.set_data = bo_set_data; + + GE( glGenBuffers (1, &buffer->gl_handle) ); + COGL_BUFFER_SET_FLAG (buffer, BUFFER_OBJECT); + } +} + +void +_cogl_buffer_fini (CoglBuffer *buffer) +{ + g_return_if_fail (!COGL_BUFFER_FLAG_IS_SET (buffer, MAPPED)); } /* OpenGL ES 1.1 and 2 have a GL_OES_mapbuffer extension that is able to map @@ -226,7 +371,7 @@ _cogl_buffer_bind (CoglBuffer *buffer, CoglBufferBindTarget target) if (COGL_BUFFER_FLAG_IS_SET (buffer, BUFFER_OBJECT)) { - GLenum gl_target = _cogl_buffer_get_last_gl_target (buffer); + GLenum gl_target = convert_bind_target_to_gl_target (buffer->last_target); GE( glBindBuffer (gl_target, buffer->gl_handle) ); } @@ -245,7 +390,7 @@ _cogl_buffer_unbind (CoglBuffer *buffer) if (COGL_BUFFER_FLAG_IS_SET (buffer, BUFFER_OBJECT)) { - GLenum gl_target = _cogl_buffer_get_last_gl_target (buffer); + GLenum gl_target = convert_bind_target_to_gl_target (buffer->last_target); GE( glBindBuffer (gl_target, 0) ); } @@ -294,7 +439,7 @@ cogl_buffer_map (CoglBuffer *buffer, if (COGL_BUFFER_FLAG_IS_SET (buffer, MAPPED)) return buffer->data; - buffer->data = buffer->vtable->map (buffer, access, hints); + buffer->data = buffer->vtable.map (buffer, access, hints); return buffer->data; } @@ -307,7 +452,7 @@ cogl_buffer_unmap (CoglBuffer *buffer) if (!COGL_BUFFER_FLAG_IS_SET (buffer, MAPPED)) return; - buffer->vtable->unmap (buffer); + buffer->vtable.unmap (buffer); } gboolean @@ -322,5 +467,5 @@ cogl_buffer_set_data (CoglBuffer *buffer, if (G_UNLIKELY((offset + size) > buffer->size)) return FALSE; - return buffer->vtable->set_data (buffer, offset, data, size); + return buffer->vtable.set_data (buffer, offset, data, size); } diff --git a/clutter/cogl/cogl/cogl-pixel-array.c b/clutter/cogl/cogl/cogl-pixel-array.c index e98468110..f9cd86453 100644 --- a/clutter/cogl/cogl/cogl-pixel-array.c +++ b/clutter/cogl/cogl/cogl-pixel-array.c @@ -92,37 +92,23 @@ _cogl_pixel_array_new (unsigned int size) { CoglPixelArray *pixel_array = g_slice_new0 (CoglPixelArray); CoglBuffer *buffer = COGL_BUFFER (pixel_array); + gboolean use_malloc; _COGL_GET_CONTEXT (ctx, COGL_INVALID_HANDLE); + if (!cogl_features_available (COGL_FEATURE_PBOS)) + use_malloc = TRUE; + else + use_malloc = FALSE; + /* parent's constructor */ _cogl_buffer_initialize (buffer, size, + use_malloc, COGL_BUFFER_BIND_TARGET_PIXEL_UNPACK, COGL_BUFFER_USAGE_HINT_TEXTURE, COGL_BUFFER_UPDATE_HINT_STATIC); -/* malloc version only for GLES */ -#if !defined (COGL_HAS_GLES) - if (cogl_features_available (COGL_FEATURE_PBOS)) - { - /* PBOS */ - buffer->vtable = &cogl_pixel_array_vtable; - - GE( glGenBuffers (1, &buffer->gl_handle) ); - COGL_BUFFER_SET_FLAG (buffer, BUFFER_OBJECT); - } - else -#endif - { - /* malloc fallback subclass */ - buffer->vtable = &cogl_malloc_pixel_array_vtable; - - /* create the buffer here as there's no point for a lazy allocation in - * the malloc case */ - buffer->data = g_malloc (size); - } - pixel_array->flags = COGL_PIXEL_ARRAY_FLAG_NONE; /* return COGL_INVALID_HANDLE; */ @@ -175,158 +161,3 @@ _cogl_pixel_array_free (CoglPixelArray *buffer) g_slice_free (CoglPixelArray, buffer); } -#if !defined (COGL_HAS_GLES) -static guint8 * -_cogl_pixel_array_map (CoglBuffer *buffer, - CoglBufferAccess access, - CoglBufferMapHint hints) -{ - CoglPixelArray *pixel_array = COGL_PIXEL_ARRAY (buffer); - guint8 *data; - CoglBufferBindTarget target; - GLenum gl_target; - - _COGL_GET_CONTEXT (ctx, NULL); - - target = _cogl_buffer_get_last_bind_target (buffer); - _cogl_buffer_bind (buffer, target); - - gl_target = _cogl_buffer_get_last_gl_target (buffer); - - /* 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 (!COGL_PIXEL_ARRAY_FLAG_IS_SET (pixel_array, STORE_CREATED) || - (hints & COGL_BUFFER_MAP_HINT_DISCARD)) - { - GE( glBufferData (gl_target, - buffer->size, - NULL, - _cogl_buffer_hints_to_gl_enum (buffer->usage_hint, - buffer->update_hint)) ); - COGL_PIXEL_ARRAY_SET_FLAG (pixel_array, STORE_CREATED); - } - - GE_RET( data, glMapBuffer (gl_target, - _cogl_buffer_access_to_gl_enum (access)) ); - if (data) - COGL_BUFFER_SET_FLAG (buffer, MAPPED); - - _cogl_buffer_unbind (buffer); - - return data; -} - -static void -_cogl_pixel_array_unmap (CoglBuffer *buffer) -{ - CoglBufferBindTarget target; - - _COGL_GET_CONTEXT (ctx, NO_RETVAL); - - target = _cogl_buffer_get_last_bind_target (buffer); - _cogl_buffer_bind (buffer, target); - - GE( glUnmapBuffer (_cogl_buffer_get_last_gl_target (buffer)) ); - COGL_BUFFER_CLEAR_FLAG (buffer, MAPPED); - - _cogl_buffer_unbind (buffer); -} - -static gboolean -_cogl_pixel_array_set_data (CoglBuffer *buffer, - unsigned int offset, - const guint8 *data, - unsigned int size) -{ - CoglPixelArray *pixel_array = COGL_PIXEL_ARRAY (buffer); - CoglBufferBindTarget target; - GLenum gl_target; - - _COGL_GET_CONTEXT (ctx, FALSE); - - target = _cogl_buffer_get_last_bind_target (buffer); - _cogl_buffer_bind (buffer, target); - - gl_target = _cogl_buffer_get_last_gl_target (buffer); - - /* 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 (!COGL_PIXEL_ARRAY_FLAG_IS_SET (pixel_array, STORE_CREATED)) - { - GE( glBufferData (gl_target, - buffer->size, - NULL, - _cogl_buffer_hints_to_gl_enum (buffer->usage_hint, - buffer->update_hint)) ); - COGL_PIXEL_ARRAY_SET_FLAG (pixel_array, STORE_CREATED); - } - - GE( glBufferSubData (gl_target, offset, size, data) ); - - _cogl_buffer_unbind (buffer); - - return TRUE; -} - -#if 0 -gboolean -cogl_pixel_array_set_region (CoglPixelArray *buffer, - guint8 *data, - unsigned int src_width, - unsigned int src_height, - unsigned int src_rowstride, - unsigned int dst_x, - unsigned int dst_y) -{ - if (!cogl_is_pixel_array (buffer)) - return FALSE; - - return TRUE; -} -#endif - -static const CoglBufferVtable cogl_pixel_array_vtable = -{ - _cogl_pixel_array_map, - _cogl_pixel_array_unmap, - _cogl_pixel_array_set_data, -}; -#endif - -/* - * Fallback path, buffer->data points to a malloc'ed buffer. - */ - -static guint8 * -_cogl_malloc_pixel_array_map (CoglBuffer *buffer, - CoglBufferAccess access, - CoglBufferMapHint hints) -{ - COGL_BUFFER_SET_FLAG (buffer, MAPPED); - return buffer->data; -} - -static void -_cogl_malloc_pixel_array_unmap (CoglBuffer *buffer) -{ - COGL_BUFFER_CLEAR_FLAG (buffer, MAPPED); -} - -static gboolean -_cogl_malloc_pixel_array_set_data (CoglBuffer *buffer, - unsigned int offset, - const guint8 *data, - unsigned int size) -{ - memcpy (buffer->data + offset, data, size); - return TRUE; -} - -static const CoglBufferVtable cogl_malloc_pixel_array_vtable = -{ - _cogl_malloc_pixel_array_map, - _cogl_malloc_pixel_array_unmap, - _cogl_malloc_pixel_array_set_data, -};