diff --git a/cogl/cogl-pixel-buffer.c b/cogl/cogl-pixel-buffer.c index 43abf533a..d4cbcee72 100644 --- a/cogl/cogl-pixel-buffer.c +++ b/cogl/cogl-pixel-buffer.c @@ -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, +}; diff --git a/cogl/cogl-texture.c b/cogl/cogl-texture.c index f0093f086..9693a6ed6 100644 --- a/cogl/cogl-texture.c +++ b/cogl/cogl-texture.c @@ -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; + 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); + _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; } diff --git a/cogl/cogl-types.h b/cogl/cogl-types.h index 4ce1502f3..816d240e4 100644 --- a/cogl/cogl-types.h +++ b/cogl/cogl-types.h @@ -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; /** diff --git a/cogl/driver/gl/cogl-feature-functions.h b/cogl/driver/gl/cogl-feature-functions.h index 29efc9e23..5547a60c1 100644 --- a/cogl/driver/gl/cogl-feature-functions.h +++ b/cogl/driver/gl/cogl-feature-functions.h @@ -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 */