cogl-pixel-buffer: Add a fallback path

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).
This commit is contained in:
Damien Lespiau 2010-02-02 12:59:51 +00:00
parent cf960cfb3d
commit ca80e8802b
4 changed files with 87 additions and 14 deletions

View File

@ -79,6 +79,7 @@
static void _cogl_pixel_buffer_free (CoglPixelBuffer *buffer); static void _cogl_pixel_buffer_free (CoglPixelBuffer *buffer);
static const CoglBufferVtable cogl_pixel_buffer_vtable; 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: /* we don't want to use the stock COGL_HANDLE_DEFINE * for 2 reasons:
* - it defines already deprecated symbols * - it defines already deprecated symbols
@ -147,10 +148,24 @@ cogl_pixel_buffer_new_EXP (guint size)
size, size,
COGL_BUFFER_USAGE_HINT_DRAW, COGL_BUFFER_USAGE_HINT_DRAW,
COGL_BUFFER_UPDATE_HINT_STATIC); COGL_BUFFER_UPDATE_HINT_STATIC);
buffer->vtable = &cogl_pixel_buffer_vtable;
GE( glGenBuffers (1, &buffer->gl_handle) ); if (cogl_features_available (COGL_FEATURE_PBOS))
COGL_BUFFER_SET_FLAG (buffer, BUFFER_OBJECT); {
/* 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; 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_unmap,
_cogl_pixel_buffer_set_data, _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,
};

View File

@ -36,6 +36,7 @@
#include "cogl-bitmap.h" #include "cogl-bitmap.h"
#include "cogl-bitmap-private.h" #include "cogl-bitmap-private.h"
#include "cogl-buffer-private.h" #include "cogl-buffer-private.h"
#include "cogl-pixel-buffer-private.h"
#include "cogl-texture-private.h" #include "cogl-texture-private.h"
#include "cogl-texture-driver.h" #include "cogl-texture-driver.h"
#include "cogl-texture-2d-sliced-private.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); cogl_buffer = COGL_BUFFER (buffer);
pixel_buffer = COGL_PIXEL_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) if (rowstride == 0)
rowstride = width * _cogl_get_format_bpp (format); rowstride = width * _cogl_get_format_bpp (format);
@ -493,16 +496,29 @@ cogl_texture_new_from_buffer_EXP (CoglHandle buffer,
return COGL_INVALID_HANDLE; return COGL_INVALID_HANDLE;
} }
/* Wrap the data into a bitmap */ if (cogl_features_available (COGL_FEATURE_PBOS))
bitmap.width = width; {
bitmap.height = height; /* Wrap the data into a bitmap */
bitmap.data = GUINT_TO_POINTER (offset); bitmap.width = width;
bitmap.format = format; bitmap.height = height;
bitmap.rowstride = rowstride; bitmap.data = GUINT_TO_POINTER (offset);
bitmap.format = format;
bitmap.rowstride = rowstride;
_cogl_buffer_bind (cogl_buffer, GL_PIXEL_UNPACK_BUFFER); _cogl_buffer_bind (cogl_buffer, GL_PIXEL_UNPACK_BUFFER);
texture = cogl_texture_new_from_bitmap (&bitmap, flags, internal_format); texture = cogl_texture_new_from_bitmap (&bitmap, flags, internal_format);
_cogl_buffer_bind (NULL, GL_PIXEL_UNPACK_BUFFER); _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; return texture;
} }

View File

@ -194,6 +194,7 @@ typedef enum { /*< prefix=COGL_PIXEL_FORMAT >*/
* @COGL_FEATURE_FOUR_CLIP_PLANES: At least 4 clip planes available * @COGL_FEATURE_FOUR_CLIP_PLANES: At least 4 clip planes available
* @COGL_FEATURE_STENCIL_BUFFER: Stencil buffer support * @COGL_FEATURE_STENCIL_BUFFER: Stencil buffer support
* @COGL_FEATURE_VBOS: VBO support * @COGL_FEATURE_VBOS: VBO support
* @COGL_FEATURE_PBOS: PBO support
* *
* Flags for the supported features. * Flags for the supported features.
* *
@ -211,7 +212,8 @@ typedef enum
COGL_FEATURE_OFFSCREEN_BLIT = (1 << 8), COGL_FEATURE_OFFSCREEN_BLIT = (1 << 8),
COGL_FEATURE_FOUR_CLIP_PLANES = (1 << 9), COGL_FEATURE_FOUR_CLIP_PLANES = (1 << 9),
COGL_FEATURE_STENCIL_BUFFER = (1 << 10), COGL_FEATURE_STENCIL_BUFFER = (1 << 10),
COGL_FEATURE_VBOS = (1 << 11) COGL_FEATURE_VBOS = (1 << 11),
COGL_FEATURE_PBOS = (1 << 12)
} CoglFeatureFlags; } CoglFeatureFlags;
/** /**

View File

@ -99,6 +99,11 @@ COGL_FEATURE_FUNCTION (void, glRenderbufferStorageMultisample,
GLsizei width, GLsizei width,
GLsizei height)) GLsizei height))
COGL_FEATURE_END () 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 /* The function names in OpenGL 2.0 are different so we can't easily
just check for GL 2.0 */ just check for GL 2.0 */