[Cogl] [PATCH] buffer: splits out GL specific code
Robert Bragg
robert at sixbynine.org
Mon Sep 24 09:45:12 PDT 2012
From: Robert Bragg <robert at linux.intel.com>
As part of an on-going effort to be able to support non-opengl drivers
for Cogl this splits out the opengl specific code from cogl-buffer.c
into driver/gl/cogl-buffer-gl.c
---
cogl/Makefile.am | 2 +
cogl/cogl-bitmap.c | 1 +
cogl/cogl-buffer-private.h | 9 -
cogl/cogl-buffer.c | 254 +--------------------------
cogl/cogl-driver.h | 26 +++
cogl/driver/gl/cogl-attribute-gl.c | 1 +
cogl/driver/gl/cogl-buffer-gl-private.h | 62 +++++++
cogl/driver/gl/cogl-buffer-gl.c | 283 +++++++++++++++++++++++++++++++
cogl/driver/gl/cogl-framebuffer-gl.c | 1 +
cogl/driver/gl/gl/cogl-driver-gl.c | 6 +
cogl/driver/gl/gles/cogl-driver-gles.c | 6 +
11 files changed, 398 insertions(+), 253 deletions(-)
create mode 100644 cogl/driver/gl/cogl-buffer-gl-private.h
create mode 100644 cogl/driver/gl/cogl-buffer-gl.c
diff --git a/cogl/Makefile.am b/cogl/Makefile.am
index 7b07815..21ce227 100644
--- a/cogl/Makefile.am
+++ b/cogl/Makefile.am
@@ -148,6 +148,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-bitmap.c b/cogl/cogl-bitmap.c
index cee8c41..95267fa 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 <string.h>
diff --git a/cogl/cogl-buffer-private.h b/cogl/cogl-buffer-private.h
index 579be5a..59794cd 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 3fe954b..573db0f 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 527e5ff..7560ba0 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/driver/gl/cogl-attribute-gl.c b/cogl/driver/gl/cogl-attribute-gl.c
index 65fb6e8..5435adb 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
{
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 0000000..570e36c
--- /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
+ * <http://www.gnu.org/licenses/>.
+ *
+ *
+ *
+ * Authors:
+ * Robert Bragg <robert at linux.intel.com>
+ */
+
+#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 0000000..94f6936
--- /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 <http://www.gnu.org/licenses/>.
+ *
+ *
+ *
+ * Authors:
+ * Damien Lespiau <damien.lespiau at intel.com>
+ * Robert Bragg <robert at linux.intel.com>
+ */
+
+#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 addf15b..f2c22b2 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 <glib.h>
diff --git a/cogl/driver/gl/gl/cogl-driver-gl.c b/cogl/driver/gl/gl/cogl-driver-gl.c
index aadef36..add1f2c 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,
@@ -551,4 +552,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 e2dbee5..05262c9 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
@@ -369,4 +370,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,
};
--
1.7.7.6
More information about the Cogl
mailing list