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)
This commit is contained in:
@ -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)
|
||||
{
|
||||
|
Reference in New Issue
Block a user