summaryrefslogtreecommitdiff
path: root/cogl/cogl-buffer.c
diff options
context:
space:
mode:
authorRobert Bragg <robert@linux.intel.com>2010-07-06 01:21:43 +0100
committerRobert Bragg <robert@linux.intel.com>2010-07-07 14:08:11 +0100
commita17dfcf1c26ccab01fc73c4354a986fbfedf117d (patch)
tree78794f8afda7d2210ce939d6def59aa7dbd0ed6a /cogl/cogl-buffer.c
parentf8d58446a81cde3080665d93784b8fad3048e2cc (diff)
downloadcogl-a17dfcf1c26ccab01fc73c4354a986fbfedf117d.tar.gz
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.
Diffstat (limited to 'cogl/cogl-buffer.c')
-rw-r--r--cogl/cogl-buffer.c201
1 files changed, 173 insertions, 28 deletions
diff --git a/cogl/cogl-buffer.c b/cogl/cogl-buffer.c
index a4e9e66c..6e8f5d42 100644
--- a/cogl/cogl-buffer.c
+++ b/cogl/cogl-buffer.c
@@ -112,9 +112,160 @@ cogl_is_buffer (const 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_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);
+ }
+}
+
+static guint8 *
+bo_map (CoglBuffer *buffer,
+ CoglBufferAccess access,
+ CoglBufferMapHint hints)
+{
+#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)
@@ -127,36 +278,30 @@ _cogl_buffer_initialize (CoglBuffer *buffer,
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));
-}
+ if (use_malloc)
+ {
+ buffer->vtable.map = malloc_map;
+ buffer->vtable.unmap = malloc_unmap;
+ buffer->vtable.set_data = malloc_set_data;
-GLenum
-_cogl_buffer_get_last_gl_target (CoglBuffer *buffer)
-{
- switch (buffer->last_target)
+ buffer->data = g_malloc (size);
+ }
+ else
{
- 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);
+ 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);
}
}
-CoglBufferBindTarget
-_cogl_buffer_get_last_bind_target (CoglBuffer *buffer)
+void
+_cogl_buffer_fini (CoglBuffer *buffer)
{
- return buffer->last_target;
+ 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);
}