[cogl/cogl-1.14: 23/174] buffer: splits out GL specific code



commit b1ecfbf720839d2ded5d7fc113903797d15f414c
Author: Robert Bragg <robert linux intel com>
Date:   Wed Sep 19 22:32:25 2012 +0100

    buffer: splits out GL specific code
    
    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
    
    Reviewed-by: Neil Roberts <neil linux intel com>
    
    (cherry picked from commit 4d7094a979ff2cbbe4054f4a44ca05fc41a9e447)

 cogl/Makefile.am                           |    2 +
 cogl/cogl-attribute.c                      |    9 +-
 cogl/cogl-bitmap.c                         |    1 +
 cogl/cogl-buffer-private.h                 |    9 -
 cogl/cogl-buffer.c                         |  254 +------------------------
 cogl/cogl-driver.h                         |   26 +++
 cogl/cogl.c                                |    3 +-
 cogl/driver/gl/cogl-attribute-gl-private.h |    3 +
 cogl/driver/gl/cogl-attribute-gl.c         |   14 ++
 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 +
 14 files changed, 419 insertions(+), 260 deletions(-)
---
diff --git a/cogl/Makefile.am b/cogl/Makefile.am
index 2b53150..33f5817 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 ff0549b..ad68ff6 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 a39307e..ff00020 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/cogl.c b/cogl/cogl.c
index 5ccfcfb..998a478 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 405e43d..752f603 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 65fb6e8..3b9a475 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 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 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 intel com>
+ *   Robert Bragg <robert 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 6692807..b3da2e7 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 485e2b1..c6d5f50 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,
   };



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]