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)
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
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) );
}
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) );
}
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;
}
if (!COGL_BUFFER_FLAG_IS_SET (buffer, MAPPED))
return;
- buffer->vtable->unmap (buffer);
+ buffer->vtable.unmap (buffer);
}
gboolean
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);
}
{
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; */
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,
-};