cogl-buffer: Move malloc fallback logic into CoglBuffer
authorRobert Bragg <robert@linux.intel.com>
Tue, 6 Jul 2010 00:21:43 +0000 (01:21 +0100)
committerRobert Bragg <robert@linux.intel.com>
Wed, 7 Jul 2010 13:08:11 +0000 (14:08 +0100)
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
clutter/cogl/cogl/cogl-buffer.c
clutter/cogl/cogl/cogl-pixel-array.c

index acf2c63..4a727fd 100644 (file)
@@ -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);
@@ -136,12 +137,6 @@ 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);
 
 GLenum
index a4e9e66..6e8f5d4 100644 (file)
@@ -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);
 }
index e984681..f9cd864 100644 (file)
@@ -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,
-};