diff --git a/cogl/Makefile.am b/cogl/Makefile.am index 2b5315056..33f581796 100644 --- a/cogl/Makefile.am +++ b/cogl/Makefile.am @@ -167,6 +167,8 @@ cogl_driver_sources += \ $(srcdir)/driver/gl/cogl-attribute-gl.c \ $(srcdir)/driver/gl/cogl-clip-stack-gl-private.h \ $(srcdir)/driver/gl/cogl-clip-stack-gl.c \ + $(srcdir)/driver/gl/cogl-buffer-gl-private.h \ + $(srcdir)/driver/gl/cogl-buffer-gl.c \ $(srcdir)/driver/gl/cogl-pipeline-opengl.c \ $(srcdir)/driver/gl/cogl-pipeline-opengl-private.h \ $(srcdir)/driver/gl/cogl-pipeline-fragend-glsl.c \ diff --git a/cogl/cogl-attribute.c b/cogl/cogl-attribute.c index ff0549b57..ad68ff638 100644 --- a/cogl/cogl-attribute.c +++ b/cogl/cogl-attribute.c @@ -384,6 +384,7 @@ _cogl_flush_attributes_state (CoglFramebuffer *framebuffer, { CoglContext *ctx = framebuffer->context; CoglFlushLayerState layers_state; + CoglPipeline *copy = NULL; if (!(flags & COGL_DRAW_SKIP_JOURNAL_FLUSH)) _cogl_journal_flush (framebuffer->journal); @@ -418,12 +419,8 @@ _cogl_flush_attributes_state (CoglFramebuffer *framebuffer, G_UNLIKELY (ctx->legacy_state_set) && _cogl_get_enable_legacy_state ()) { - /* If we haven't already created a derived pipeline... */ - if (!copy) - { - copy = cogl_pipeline_copy (pipeline); - pipeline = copy; - } + copy = cogl_pipeline_copy (pipeline); + pipeline = copy; _cogl_pipeline_apply_legacy_state (pipeline); } diff --git a/cogl/cogl-bitmap.c b/cogl/cogl-bitmap.c index a39307e43..ff00020de 100644 --- a/cogl/cogl-bitmap.c +++ b/cogl/cogl-bitmap.c @@ -32,6 +32,7 @@ #include "cogl-buffer-private.h" #include "cogl-pixel-buffer.h" #include "cogl-context-private.h" +#include "cogl-buffer-gl-private.h" #include diff --git a/cogl/cogl-buffer-private.h b/cogl/cogl-buffer-private.h index 579be5a57..59794cd20 100644 --- a/cogl/cogl-buffer-private.h +++ b/cogl/cogl-buffer-private.h @@ -123,15 +123,6 @@ _cogl_buffer_initialize (CoglBuffer *buffer, void _cogl_buffer_fini (CoglBuffer *buffer); -/* TODO: split these GL specific bind and unbind functions out into - * some GL specific file. */ -void * -_cogl_buffer_gl_bind (CoglBuffer *buffer, - CoglBufferBindTarget target); - -void -_cogl_buffer_gl_unbind (CoglBuffer *buffer); - CoglBufferUsageHint _cogl_buffer_get_usage_hint (CoglBuffer *buffer); diff --git a/cogl/cogl-buffer.c b/cogl/cogl-buffer.c index 3fe954b33..573db0fed 100644 --- a/cogl/cogl-buffer.c +++ b/cogl/cogl-buffer.c @@ -44,32 +44,6 @@ #include "cogl-object-private.h" #include "cogl-pixel-buffer-private.h" -/* - * GL/GLES compatibility defines for the buffer API: - */ - -#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 -#ifndef GL_READ_ONLY -#define GL_READ_ONLY 0x88B8 -#endif -#ifndef GL_WRITE_ONLY -#define GL_WRITE_ONLY 0x88B9 -#endif -#ifndef GL_READ_WRITE -#define GL_READ_WRITE 0x88BA -#endif - /* XXX: * The CoglObject macros don't support any form of inheritance, so for * now we implement the CoglObject support for the CoglBuffer @@ -100,168 +74,6 @@ cogl_is_buffer (void *object) return FALSE; } -static GLenum -convert_bind_target_to_gl_target (CoglBufferBindTarget target) -{ - switch (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_ATTRIBUTE_BUFFER: - return GL_ARRAY_BUFFER; - case COGL_BUFFER_BIND_TARGET_INDEX_BUFFER: - return GL_ELEMENT_ARRAY_BUFFER; - default: - g_return_val_if_reached (COGL_BUFFER_BIND_TARGET_PIXEL_UNPACK); - } -} - -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 -_cogl_buffer_hints_to_gl_enum (CoglBuffer *buffer) -{ - /* usage hint is always DRAW for now */ - switch (buffer->update_hint) - { - case COGL_BUFFER_UPDATE_HINT_STATIC: - return GL_STATIC_DRAW; - case COGL_BUFFER_UPDATE_HINT_DYNAMIC: - return GL_DYNAMIC_DRAW; - - case COGL_BUFFER_UPDATE_HINT_STREAM: - /* OpenGL ES 1.1 only knows about STATIC_DRAW and DYNAMIC_DRAW */ -#if defined(HAVE_COGL_GL) || defined(HAVE_COGL_GLES2) - if (buffer->context->driver != COGL_DRIVER_GLES1) - return GL_STREAM_DRAW; -#else - return GL_DYNAMIC_DRAW; -#endif - } - - g_assert_not_reached (); -} - -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); - - GE( buffer->context, glBufferData (gl_target, - buffer->size, - NULL, - gl_enum) ); - buffer->store_created = TRUE; -} - -static void * -bo_map (CoglBuffer *buffer, - CoglBufferAccess access, - CoglBufferMapHint hints) -{ - uint8_t *data; - CoglBufferBindTarget target; - GLenum gl_target; - CoglContext *ctx = buffer->context; - - if ((access & COGL_BUFFER_ACCESS_READ) && - !cogl_has_feature (ctx, COGL_FEATURE_ID_MAP_BUFFER_FOR_READ)) - return NULL; - if ((access & COGL_BUFFER_ACCESS_WRITE) && - !cogl_has_feature (ctx, COGL_FEATURE_ID_MAP_BUFFER_FOR_WRITE)) - return NULL; - - target = buffer->last_target; - _cogl_buffer_bind_no_create (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 (!buffer->store_created || (hints & COGL_BUFFER_MAP_HINT_DISCARD)) - bo_recreate_store (buffer); - - GE_RET( data, ctx, glMapBuffer (gl_target, - _cogl_buffer_access_to_gl_enum (access)) ); - if (data) - buffer->flags |= COGL_BUFFER_FLAG_MAPPED; - - _cogl_buffer_unbind (buffer); - - return data; -} - -static void -bo_unmap (CoglBuffer *buffer) -{ - CoglContext *ctx = buffer->context; - - _cogl_buffer_bind_no_create (buffer, buffer->last_target); - - GE( ctx, glUnmapBuffer (convert_bind_target_to_gl_target - (buffer->last_target)) ); - buffer->flags &= ~COGL_BUFFER_FLAG_MAPPED; - - _cogl_buffer_unbind (buffer); -} - -static CoglBool -bo_set_data (CoglBuffer *buffer, - unsigned int offset, - const void *data, - unsigned int size) -{ - CoglBufferBindTarget target; - GLenum gl_target; - CoglContext *ctx = buffer->context; - - target = buffer->last_target; - _cogl_buffer_bind (buffer, target); - - gl_target = convert_bind_target_to_gl_target (target); - - GE( ctx, glBufferSubData (gl_target, offset, size, data) ); - - _cogl_buffer_unbind (buffer); - - return TRUE; -} - /* * Fallback path, buffer->data points to a malloc'ed buffer. */ @@ -293,7 +105,7 @@ malloc_set_data (CoglBuffer *buffer, void _cogl_buffer_initialize (CoglBuffer *buffer, - CoglContext *context, + CoglContext *ctx, size_t size, CoglBufferBindTarget default_target, CoglBufferUsageHint usage_hint, @@ -301,7 +113,7 @@ _cogl_buffer_initialize (CoglBuffer *buffer, { CoglBool use_malloc = FALSE; - buffer->context = context; + buffer->context = ctx; buffer->flags = COGL_BUFFER_FLAG_NONE; buffer->store_created = FALSE; buffer->size = size; @@ -314,13 +126,13 @@ _cogl_buffer_initialize (CoglBuffer *buffer, if (default_target == COGL_BUFFER_BIND_TARGET_PIXEL_PACK || default_target == COGL_BUFFER_BIND_TARGET_PIXEL_UNPACK) { - if (!(context->private_feature_flags & COGL_PRIVATE_FEATURE_PBOS)) + if (!(ctx->private_feature_flags & COGL_PRIVATE_FEATURE_PBOS)) use_malloc = TRUE; } else if (default_target == COGL_BUFFER_BIND_TARGET_ATTRIBUTE_BUFFER || default_target == COGL_BUFFER_BIND_TARGET_INDEX_BUFFER) { - if (!(context->private_feature_flags & COGL_PRIVATE_FEATURE_VBOS)) + if (!(ctx->private_feature_flags & COGL_PRIVATE_FEATURE_VBOS)) use_malloc = TRUE; } @@ -334,11 +146,12 @@ _cogl_buffer_initialize (CoglBuffer *buffer, } else { - buffer->vtable.map = bo_map; - buffer->vtable.unmap = bo_unmap; - buffer->vtable.set_data = bo_set_data; + buffer->vtable.map = ctx->driver_vtable->buffer_map; + buffer->vtable.unmap = ctx->driver_vtable->buffer_unmap; + buffer->vtable.set_data = ctx->driver_vtable->buffer_set_data; + + ctx->driver_vtable->buffer_create (buffer); - GE( context, glGenBuffers (1, &buffer->gl_handle) ); buffer->flags |= COGL_BUFFER_FLAG_BUFFER_OBJECT; } } @@ -350,58 +163,11 @@ _cogl_buffer_fini (CoglBuffer *buffer) _COGL_RETURN_IF_FAIL (buffer->immutable_ref == 0); if (buffer->flags & COGL_BUFFER_FLAG_BUFFER_OBJECT) - GE( buffer->context, glDeleteBuffers (1, &buffer->gl_handle) ); + buffer->context->driver_vtable->buffer_destroy (buffer); else g_free (buffer->data); } -GLenum -_cogl_buffer_access_to_gl_enum (CoglBufferAccess access) -{ - if ((access & COGL_BUFFER_ACCESS_READ_WRITE) == COGL_BUFFER_ACCESS_READ_WRITE) - return GL_READ_WRITE; - else if (access & COGL_BUFFER_ACCESS_WRITE) - return GL_WRITE_ONLY; - else - return GL_READ_ONLY; -} - -void * -_cogl_buffer_gl_bind (CoglBuffer *buffer, CoglBufferBindTarget target) -{ - void *ret; - - ret = _cogl_buffer_bind_no_create (buffer, 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->flags & COGL_BUFFER_FLAG_BUFFER_OBJECT) && - !buffer->store_created) - bo_recreate_store (buffer); - - return ret; -} - -void -_cogl_buffer_gl_unbind (CoglBuffer *buffer) -{ - CoglContext *ctx = buffer->context; - - _COGL_RETURN_IF_FAIL (buffer != NULL); - - /* the unbind should pair up with a previous bind */ - _COGL_RETURN_IF_FAIL (ctx->current_buffer[buffer->last_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, 0) ); - } - - ctx->current_buffer[buffer->last_target] = NULL; -} - unsigned int cogl_buffer_get_size (CoglBuffer *buffer) { diff --git a/cogl/cogl-driver.h b/cogl/cogl-driver.h index 527e5ffaa..7560ba08a 100644 --- a/cogl/cogl-driver.h +++ b/cogl/cogl-driver.h @@ -229,6 +229,32 @@ struct _CoglDriverVtable void (* clip_stack_flush) (CoglClipStack *stack, CoglFramebuffer *framebuffer); + /* Enables the driver to create some meta data to represent a buffer + * but with no corresponding storage allocated yet. + */ + void + (* buffer_create) (CoglBuffer *buffer); + + void + (* buffer_destroy) (CoglBuffer *buffer); + + /* Maps a buffer into the CPU */ + void * + (* buffer_map) (CoglBuffer *buffer, + CoglBufferAccess access, + CoglBufferMapHint hints); + + /* Unmaps a buffer */ + void + (* buffer_unmap) (CoglBuffer *buffer); + + /* Uploads data to the buffer without needing to map it necessarily + */ + CoglBool + (* buffer_set_data) (CoglBuffer *buffer, + unsigned int offset, + const void *data, + unsigned int size); }; #endif /* __COGL_DRIVER_H */ diff --git a/cogl/cogl.c b/cogl/cogl.c index 5ccfcfb50..998a47865 100644 --- a/cogl/cogl.c +++ b/cogl/cogl.c @@ -50,6 +50,7 @@ #include "cogl-private.h" #include "cogl1-context.h" #include "cogl-offscreen.h" +#include "cogl-attribute-gl-private.h" #ifdef COGL_GL_DEBUG /* GL error to string conversion */ @@ -446,7 +447,7 @@ cogl_begin_gl (void) cogl_pipeline_get_n_layers (pipeline)); /* Disable any cached vertex arrays */ - _cogl_attribute_disable_cached_arrays (); + _cogl_gl_disable_all_attributes (ctx); } void diff --git a/cogl/driver/gl/cogl-attribute-gl-private.h b/cogl/driver/gl/cogl-attribute-gl-private.h index 405e43d27..752f60317 100644 --- a/cogl/driver/gl/cogl-attribute-gl-private.h +++ b/cogl/driver/gl/cogl-attribute-gl-private.h @@ -41,4 +41,7 @@ _cogl_gl_flush_attributes_state (CoglFramebuffer *framebuffer, CoglAttribute **attributes, int n_attributes); +void +_cogl_gl_disable_all_attributes (CoglContext *ctx); + #endif /* _COGL_ATTRIBUTE_GL_PRIVATE_H_ */ diff --git a/cogl/driver/gl/cogl-attribute-gl.c b/cogl/driver/gl/cogl-attribute-gl.c index 65fb6e84d..3b9a47521 100644 --- a/cogl/driver/gl/cogl-attribute-gl.c +++ b/cogl/driver/gl/cogl-attribute-gl.c @@ -39,6 +39,7 @@ #include "cogl-attribute-private.h" #include "cogl-attribute-gl-private.h" #include "cogl-pipeline-progend-glsl-private.h" +#include "cogl-buffer-gl-private.h" typedef struct _ForeachChangedBitState { @@ -396,3 +397,16 @@ _cogl_gl_flush_attributes_state (CoglFramebuffer *framebuffer, if (copy) cogl_object_unref (copy); } + +void +_cogl_gl_disable_all_attributes (CoglContext *ctx) +{ + _cogl_bitmask_clear_all (&ctx->enable_builtin_attributes_tmp); + _cogl_bitmask_clear_all (&ctx->enable_texcoord_attributes_tmp); + _cogl_bitmask_clear_all (&ctx->enable_custom_attributes_tmp); + + /* XXX: we can pass a NULL source pipeline here because we know a + * source pipeline only needs to be referenced when enabling + * attributes. */ + apply_attribute_enable_updates (ctx, NULL); +} diff --git a/cogl/driver/gl/cogl-buffer-gl-private.h b/cogl/driver/gl/cogl-buffer-gl-private.h new file mode 100644 index 000000000..570e36cca --- /dev/null +++ b/cogl/driver/gl/cogl-buffer-gl-private.h @@ -0,0 +1,62 @@ +/* + * Cogl + * + * An object oriented GL/GLES Abstraction/Utility Layer + * + * Copyright (C) 2012 Intel Corporation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see + * . + * + * + * + * Authors: + * Robert Bragg + */ + +#ifndef _COGL_BUFFER_GL_PRIVATE_H_ +#define _COGL_BUFFER_GL_PRIVATE_H_ + +#include "cogl-types.h" +#include "cogl-context.h" +#include "cogl-buffer.h" +#include "cogl-buffer-private.h" + +void +_cogl_buffer_gl_create (CoglBuffer *buffer); + +void +_cogl_buffer_gl_destroy (CoglBuffer *buffer); + +void * +_cogl_buffer_gl_map (CoglBuffer *buffer, + CoglBufferAccess access, + CoglBufferMapHint hints); + +void +_cogl_buffer_gl_unmap (CoglBuffer *buffer); + +CoglBool +_cogl_buffer_gl_set_data (CoglBuffer *buffer, + unsigned int offset, + const void *data, + unsigned int size); + +void * +_cogl_buffer_gl_bind (CoglBuffer *buffer, CoglBufferBindTarget target); + +void +_cogl_buffer_gl_unbind (CoglBuffer *buffer); + +#endif /* _COGL_BUFFER_GL_PRIVATE_H_ */ diff --git a/cogl/driver/gl/cogl-buffer-gl.c b/cogl/driver/gl/cogl-buffer-gl.c new file mode 100644 index 000000000..94f693636 --- /dev/null +++ b/cogl/driver/gl/cogl-buffer-gl.c @@ -0,0 +1,283 @@ +/* + * Cogl + * + * An object oriented GL/GLES Abstraction/Utility Layer + * + * Copyright (C) 2010,2011,2012 Intel Corporation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + * + * + * + * Authors: + * Damien Lespiau + * Robert Bragg + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "cogl-context-private.h" +#include "cogl-buffer-gl-private.h" + +/* + * GL/GLES compatibility defines for the buffer API: + */ + +#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 +#ifndef GL_READ_ONLY +#define GL_READ_ONLY 0x88B8 +#endif +#ifndef GL_WRITE_ONLY +#define GL_WRITE_ONLY 0x88B9 +#endif +#ifndef GL_READ_WRITE +#define GL_READ_WRITE 0x88BA +#endif + + +void +_cogl_buffer_gl_create (CoglBuffer *buffer) +{ + CoglContext *ctx = buffer->context; + + GE (ctx, glGenBuffers (1, &buffer->gl_handle)); +} + +void +_cogl_buffer_gl_destroy (CoglBuffer *buffer) +{ + GE( buffer->context, glDeleteBuffers (1, &buffer->gl_handle) ); +} + +static GLenum +update_hints_to_gl_enum (CoglBuffer *buffer) +{ + /* usage hint is always DRAW for now */ + switch (buffer->update_hint) + { + case COGL_BUFFER_UPDATE_HINT_STATIC: + return GL_STATIC_DRAW; + case COGL_BUFFER_UPDATE_HINT_DYNAMIC: + return GL_DYNAMIC_DRAW; + + case COGL_BUFFER_UPDATE_HINT_STREAM: + /* OpenGL ES 1.1 only knows about STATIC_DRAW and DYNAMIC_DRAW */ +#if defined(HAVE_COGL_GL) || defined(HAVE_COGL_GLES2) + if (buffer->context->driver != COGL_DRIVER_GLES1) + return GL_STREAM_DRAW; +#else + return GL_DYNAMIC_DRAW; +#endif + } + + g_assert_not_reached (); +} + +static GLenum +convert_bind_target_to_gl_target (CoglBufferBindTarget target) +{ + switch (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_ATTRIBUTE_BUFFER: + return GL_ARRAY_BUFFER; + case COGL_BUFFER_BIND_TARGET_INDEX_BUFFER: + return GL_ELEMENT_ARRAY_BUFFER; + default: + g_return_val_if_reached (COGL_BUFFER_BIND_TARGET_PIXEL_UNPACK); + } +} + +static void +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 = update_hints_to_gl_enum (buffer); + + GE( buffer->context, glBufferData (gl_target, + buffer->size, + NULL, + gl_enum) ); + buffer->store_created = TRUE; +} + +GLenum +_cogl_buffer_access_to_gl_enum (CoglBufferAccess access) +{ + if ((access & COGL_BUFFER_ACCESS_READ_WRITE) == COGL_BUFFER_ACCESS_READ_WRITE) + return GL_READ_WRITE; + else if (access & COGL_BUFFER_ACCESS_WRITE) + return GL_WRITE_ONLY; + else + return GL_READ_ONLY; +} + +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; +} + +void * +_cogl_buffer_gl_map (CoglBuffer *buffer, + CoglBufferAccess access, + CoglBufferMapHint hints) +{ + uint8_t *data; + CoglBufferBindTarget target; + GLenum gl_target; + CoglContext *ctx = buffer->context; + + if ((access & COGL_BUFFER_ACCESS_READ) && + !cogl_has_feature (ctx, COGL_FEATURE_ID_MAP_BUFFER_FOR_READ)) + return NULL; + if ((access & COGL_BUFFER_ACCESS_WRITE) && + !cogl_has_feature (ctx, COGL_FEATURE_ID_MAP_BUFFER_FOR_WRITE)) + return NULL; + + target = buffer->last_target; + _cogl_buffer_bind_no_create (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 (!buffer->store_created || (hints & COGL_BUFFER_MAP_HINT_DISCARD)) + recreate_store (buffer); + + GE_RET( data, ctx, glMapBuffer (gl_target, + _cogl_buffer_access_to_gl_enum (access)) ); + if (data) + buffer->flags |= COGL_BUFFER_FLAG_MAPPED; + + _cogl_buffer_gl_unbind (buffer); + + return data; +} + +void +_cogl_buffer_gl_unmap (CoglBuffer *buffer) +{ + CoglContext *ctx = buffer->context; + + _cogl_buffer_bind_no_create (buffer, buffer->last_target); + + GE( ctx, glUnmapBuffer (convert_bind_target_to_gl_target + (buffer->last_target)) ); + buffer->flags &= ~COGL_BUFFER_FLAG_MAPPED; + + _cogl_buffer_gl_unbind (buffer); +} + +CoglBool +_cogl_buffer_gl_set_data (CoglBuffer *buffer, + unsigned int offset, + const void *data, + unsigned int size) +{ + CoglBufferBindTarget target; + GLenum gl_target; + CoglContext *ctx = buffer->context; + + target = buffer->last_target; + _cogl_buffer_gl_bind (buffer, target); + + gl_target = convert_bind_target_to_gl_target (target); + + GE( ctx, glBufferSubData (gl_target, offset, size, data) ); + + _cogl_buffer_gl_unbind (buffer); + + return TRUE; +} + +void * +_cogl_buffer_gl_bind (CoglBuffer *buffer, CoglBufferBindTarget target) +{ + void *ret; + + ret = _cogl_buffer_bind_no_create (buffer, 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->flags & COGL_BUFFER_FLAG_BUFFER_OBJECT) && + !buffer->store_created) + recreate_store (buffer); + + return ret; +} + +void +_cogl_buffer_gl_unbind (CoglBuffer *buffer) +{ + CoglContext *ctx = buffer->context; + + _COGL_RETURN_IF_FAIL (buffer != NULL); + + /* the unbind should pair up with a previous bind */ + _COGL_RETURN_IF_FAIL (ctx->current_buffer[buffer->last_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, 0) ); + } + + ctx->current_buffer[buffer->last_target] = NULL; +} diff --git a/cogl/driver/gl/cogl-framebuffer-gl.c b/cogl/driver/gl/cogl-framebuffer-gl.c index addf15bc8..f2c22b262 100644 --- a/cogl/driver/gl/cogl-framebuffer-gl.c +++ b/cogl/driver/gl/cogl-framebuffer-gl.c @@ -29,6 +29,7 @@ #include "cogl-context-private.h" #include "cogl-framebuffer-private.h" #include "cogl-framebuffer-gl-private.h" +#include "cogl-buffer-gl-private.h" #include "cogl-error-private.h" #include diff --git a/cogl/driver/gl/gl/cogl-driver-gl.c b/cogl/driver/gl/gl/cogl-driver-gl.c index 6692807d7..b3da2e7d8 100644 --- a/cogl/driver/gl/gl/cogl-driver-gl.c +++ b/cogl/driver/gl/gl/cogl-driver-gl.c @@ -37,6 +37,7 @@ #include "cogl-texture-2d-gl-private.h" #include "cogl-attribute-gl-private.h" #include "cogl-clip-stack-gl-private.h" +#include "cogl-buffer-gl-private.h" static CoglBool _cogl_driver_pixel_format_from_gl_internal (CoglContext *context, @@ -552,4 +553,9 @@ _cogl_driver_gl = _cogl_texture_2d_gl_get_data, _cogl_gl_flush_attributes_state, _cogl_clip_stack_gl_flush, + _cogl_buffer_gl_create, + _cogl_buffer_gl_destroy, + _cogl_buffer_gl_map, + _cogl_buffer_gl_unmap, + _cogl_buffer_gl_set_data, }; diff --git a/cogl/driver/gl/gles/cogl-driver-gles.c b/cogl/driver/gl/gles/cogl-driver-gles.c index 485e2b1a7..c6d5f50cc 100644 --- a/cogl/driver/gl/gles/cogl-driver-gles.c +++ b/cogl/driver/gl/gles/cogl-driver-gles.c @@ -36,6 +36,7 @@ #include "cogl-texture-2d-gl-private.h" #include "cogl-attribute-gl-private.h" #include "cogl-clip-stack-gl-private.h" +#include "cogl-buffer-gl-private.h" #ifndef GL_UNSIGNED_INT_24_8 #define GL_UNSIGNED_INT_24_8 0x84FA @@ -370,4 +371,9 @@ _cogl_driver_gles = NULL, /* texture_2d_get_data */ _cogl_gl_flush_attributes_state, _cogl_clip_stack_gl_flush, + _cogl_buffer_gl_create, + _cogl_buffer_gl_destroy, + _cogl_buffer_gl_map, + _cogl_buffer_gl_unmap, + _cogl_buffer_gl_set_data, };