cogl-pixel-buffer: Add a fallback path
authorDamien Lespiau <damien.lespiau@intel.com>
Tue, 2 Feb 2010 12:59:51 +0000 (12:59 +0000)
committerDamien Lespiau <damien.lespiau@intel.com>
Mon, 8 Feb 2010 17:14:49 +0000 (17:14 +0000)
First, let's add a new public feature called, surprisingly,
COGL_FEATURE_PBOS to check the availability of PBOs and provide a
fallback path when running on older GL implementations or on OpenGL ES

In case the underlying OpenGL implementation does not provide PBOs, we
need a fallback path (a malloc'ed buffer). The CoglPixelBufer
constructors will instanciate a subclass of CoglBuffer that handles
map/unmap and set_data() with a malloc'ed buffer.

The public feature is useful to check before using set_data() on a
buffer as it will mean doing a memcpy() when not supporting PBOs (in
that case, it's better to create the texture directly instead of using a
CoglBuffer).

clutter/cogl/cogl/cogl-pixel-buffer.c
clutter/cogl/cogl/cogl-texture.c
clutter/cogl/cogl/cogl-types.h
clutter/cogl/cogl/driver/gl/cogl-feature-functions.h

index 43abf53..d4cbcee 100644 (file)
@@ -79,6 +79,7 @@
 static void _cogl_pixel_buffer_free (CoglPixelBuffer *buffer);
 
 static const CoglBufferVtable cogl_pixel_buffer_vtable;
+static const CoglBufferVtable cogl_malloc_pixel_buffer_vtable;
 
 /* we don't want to use the stock COGL_HANDLE_DEFINE * for 2 reasons:
  *   - it defines already deprecated symbols
@@ -147,10 +148,24 @@ cogl_pixel_buffer_new_EXP (guint size)
                            size,
                            COGL_BUFFER_USAGE_HINT_DRAW,
                            COGL_BUFFER_UPDATE_HINT_STATIC);
-  buffer->vtable = &cogl_pixel_buffer_vtable;
 
-  GE( glGenBuffers (1, &buffer->gl_handle) );
-  COGL_BUFFER_SET_FLAG (buffer, BUFFER_OBJECT);
+  if (cogl_features_available (COGL_FEATURE_PBOS))
+    {
+      /* PBOS */
+      buffer->vtable = &cogl_pixel_buffer_vtable;
+
+      GE( glGenBuffers (1, &buffer->gl_handle) );
+      COGL_BUFFER_SET_FLAG (buffer, BUFFER_OBJECT);
+    }
+  else
+    {
+      /* malloc fallback subclass */
+      buffer->vtable = &cogl_malloc_pixel_buffer_vtable;
+
+      /* create the buffer here as there's no point for a lazy allocation in
+       * the malloc case */
+      buffer->data = g_malloc (size);
+    }
 
   pixel_buffer->flags = COGL_PIXEL_BUFFER_FLAG_NONE;
 
@@ -315,3 +330,38 @@ static const CoglBufferVtable cogl_pixel_buffer_vtable =
   _cogl_pixel_buffer_unmap,
   _cogl_pixel_buffer_set_data,
 };
+
+/*
+ * Fallback path, buffer->data points to a malloc'ed buffer.
+ */
+
+static guchar *
+_cogl_malloc_pixel_buffer_map (CoglBuffer       *buffer,
+                               CoglBufferAccess  access)
+{
+  COGL_BUFFER_SET_FLAG (buffer, MAPPED);
+  return buffer->data;
+}
+
+static void
+_cogl_malloc_pixel_buffer_unmap (CoglBuffer *buffer)
+{
+  COGL_BUFFER_CLEAR_FLAG (buffer, MAPPED);
+}
+
+static gboolean
+_cogl_malloc_pixel_buffer_set_data (CoglBuffer   *buffer,
+                                    guint         offset,
+                                    const guchar *data,
+                                    guint         size)
+{
+  memcpy (buffer->data + offset, data, size);
+  return TRUE;
+}
+
+static const CoglBufferVtable cogl_malloc_pixel_buffer_vtable =
+{
+  _cogl_malloc_pixel_buffer_map,
+  _cogl_malloc_pixel_buffer_unmap,
+  _cogl_malloc_pixel_buffer_set_data,
+};
index f0093f0..9693a6e 100644 (file)
@@ -36,6 +36,7 @@
 #include "cogl-bitmap.h"
 #include "cogl-bitmap-private.h"
 #include "cogl-buffer-private.h"
+#include "cogl-pixel-buffer-private.h"
 #include "cogl-texture-private.h"
 #include "cogl-texture-driver.h"
 #include "cogl-texture-2d-sliced-private.h"
@@ -476,7 +477,9 @@ cogl_texture_new_from_buffer_EXP (CoglHandle       buffer,
   cogl_buffer = COGL_BUFFER (buffer);
   pixel_buffer = COGL_PIXEL_BUFFER (buffer);
 
-  /* Rowstride from width if not given */
+  /* Rowstride from CoglBuffer or even width * bpp if not given */
+  if (rowstride == 0)
+    rowstride = pixel_buffer->stride;
   if (rowstride == 0)
     rowstride = width * _cogl_get_format_bpp (format);
 
@@ -493,16 +496,29 @@ cogl_texture_new_from_buffer_EXP (CoglHandle       buffer,
       return COGL_INVALID_HANDLE;
     }
 
-  /* Wrap the data into a bitmap */
-  bitmap.width = width;
-  bitmap.height = height;
-  bitmap.data = GUINT_TO_POINTER (offset);
-  bitmap.format = format;
-  bitmap.rowstride = rowstride;
-
-  _cogl_buffer_bind (cogl_buffer, GL_PIXEL_UNPACK_BUFFER);
-  texture =  cogl_texture_new_from_bitmap (&bitmap, flags, internal_format);
-  _cogl_buffer_bind (NULL, GL_PIXEL_UNPACK_BUFFER);
+  if (cogl_features_available (COGL_FEATURE_PBOS))
+    {
+      /* Wrap the data into a bitmap */
+      bitmap.width = width;
+      bitmap.height = height;
+      bitmap.data = GUINT_TO_POINTER (offset);
+      bitmap.format = format;
+      bitmap.rowstride = rowstride;
+
+      _cogl_buffer_bind (cogl_buffer, GL_PIXEL_UNPACK_BUFFER);
+      texture =  cogl_texture_new_from_bitmap (&bitmap, flags, internal_format);
+      _cogl_buffer_bind (NULL, GL_PIXEL_UNPACK_BUFFER);
+    }
+  else
+    {
+      texture = cogl_texture_new_from_data (width,
+                                           height,
+                                            flags,
+                                            format,
+                                            internal_format,
+                                            rowstride,
+                                            cogl_buffer->data);
+    }
 
   return texture;
 }
index 4ce1502..816d240 100644 (file)
@@ -194,6 +194,7 @@ typedef enum { /*< prefix=COGL_PIXEL_FORMAT >*/
  * @COGL_FEATURE_FOUR_CLIP_PLANES: At least 4 clip planes available
  * @COGL_FEATURE_STENCIL_BUFFER: Stencil buffer support
  * @COGL_FEATURE_VBOS: VBO support
+ * @COGL_FEATURE_PBOS: PBO support
  *
  * Flags for the supported features.
  *
@@ -211,7 +212,8 @@ typedef enum
   COGL_FEATURE_OFFSCREEN_BLIT         = (1 << 8),
   COGL_FEATURE_FOUR_CLIP_PLANES       = (1 << 9),
   COGL_FEATURE_STENCIL_BUFFER         = (1 << 10),
-  COGL_FEATURE_VBOS                  = (1 << 11)
+  COGL_FEATURE_VBOS                  = (1 << 11),
+  COGL_FEATURE_PBOS                  = (1 << 12)
 } CoglFeatureFlags;
 
 /**
index 29efc9e..5547a60 100644 (file)
@@ -99,6 +99,11 @@ COGL_FEATURE_FUNCTION (void, glRenderbufferStorageMultisample,
                         GLsizei               width,
                         GLsizei               height))
 COGL_FEATURE_END ()
+COGL_FEATURE_BEGIN (read_pixels_async, 2, 1,
+                    "EXT\0",
+                    "pixel_buffer_object\0",
+                    COGL_FEATURE_PBOS)
+COGL_FEATURE_END ()
 
 /* The function names in OpenGL 2.0 are different so we can't easily
    just check for GL 2.0 */