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:
Robert Bragg 2012-09-19 22:32:25 +01:00
parent bcf6a61d0b
commit b1ecfbf720
14 changed files with 419 additions and 260 deletions

View File

@ -167,6 +167,8 @@ cogl_driver_sources += \
$(srcdir)/driver/gl/cogl-attribute-gl.c \ $(srcdir)/driver/gl/cogl-attribute-gl.c \
$(srcdir)/driver/gl/cogl-clip-stack-gl-private.h \ $(srcdir)/driver/gl/cogl-clip-stack-gl-private.h \
$(srcdir)/driver/gl/cogl-clip-stack-gl.c \ $(srcdir)/driver/gl/cogl-clip-stack-gl.c \
$(srcdir)/driver/gl/cogl-buffer-gl-private.h \
$(srcdir)/driver/gl/cogl-buffer-gl.c \
$(srcdir)/driver/gl/cogl-pipeline-opengl.c \ $(srcdir)/driver/gl/cogl-pipeline-opengl.c \
$(srcdir)/driver/gl/cogl-pipeline-opengl-private.h \ $(srcdir)/driver/gl/cogl-pipeline-opengl-private.h \
$(srcdir)/driver/gl/cogl-pipeline-fragend-glsl.c \ $(srcdir)/driver/gl/cogl-pipeline-fragend-glsl.c \

View File

@ -384,6 +384,7 @@ _cogl_flush_attributes_state (CoglFramebuffer *framebuffer,
{ {
CoglContext *ctx = framebuffer->context; CoglContext *ctx = framebuffer->context;
CoglFlushLayerState layers_state; CoglFlushLayerState layers_state;
CoglPipeline *copy = NULL;
if (!(flags & COGL_DRAW_SKIP_JOURNAL_FLUSH)) if (!(flags & COGL_DRAW_SKIP_JOURNAL_FLUSH))
_cogl_journal_flush (framebuffer->journal); _cogl_journal_flush (framebuffer->journal);
@ -418,12 +419,8 @@ _cogl_flush_attributes_state (CoglFramebuffer *framebuffer,
G_UNLIKELY (ctx->legacy_state_set) && G_UNLIKELY (ctx->legacy_state_set) &&
_cogl_get_enable_legacy_state ()) _cogl_get_enable_legacy_state ())
{ {
/* If we haven't already created a derived pipeline... */ copy = cogl_pipeline_copy (pipeline);
if (!copy) pipeline = copy;
{
copy = cogl_pipeline_copy (pipeline);
pipeline = copy;
}
_cogl_pipeline_apply_legacy_state (pipeline); _cogl_pipeline_apply_legacy_state (pipeline);
} }

View File

@ -32,6 +32,7 @@
#include "cogl-buffer-private.h" #include "cogl-buffer-private.h"
#include "cogl-pixel-buffer.h" #include "cogl-pixel-buffer.h"
#include "cogl-context-private.h" #include "cogl-context-private.h"
#include "cogl-buffer-gl-private.h"
#include <string.h> #include <string.h>

View File

@ -123,15 +123,6 @@ _cogl_buffer_initialize (CoglBuffer *buffer,
void void
_cogl_buffer_fini (CoglBuffer *buffer); _cogl_buffer_fini (CoglBuffer *buffer);
/* TODO: split these GL specific bind and unbind functions out into
* some GL specific file. */
void *
_cogl_buffer_gl_bind (CoglBuffer *buffer,
CoglBufferBindTarget target);
void
_cogl_buffer_gl_unbind (CoglBuffer *buffer);
CoglBufferUsageHint CoglBufferUsageHint
_cogl_buffer_get_usage_hint (CoglBuffer *buffer); _cogl_buffer_get_usage_hint (CoglBuffer *buffer);

View File

@ -44,32 +44,6 @@
#include "cogl-object-private.h" #include "cogl-object-private.h"
#include "cogl-pixel-buffer-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: /* XXX:
* The CoglObject macros don't support any form of inheritance, so for * The CoglObject macros don't support any form of inheritance, so for
* now we implement the CoglObject support for the CoglBuffer * now we implement the CoglObject support for the CoglBuffer
@ -100,168 +74,6 @@ cogl_is_buffer (void *object)
return FALSE; 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. * Fallback path, buffer->data points to a malloc'ed buffer.
*/ */
@ -293,7 +105,7 @@ malloc_set_data (CoglBuffer *buffer,
void void
_cogl_buffer_initialize (CoglBuffer *buffer, _cogl_buffer_initialize (CoglBuffer *buffer,
CoglContext *context, CoglContext *ctx,
size_t size, size_t size,
CoglBufferBindTarget default_target, CoglBufferBindTarget default_target,
CoglBufferUsageHint usage_hint, CoglBufferUsageHint usage_hint,
@ -301,7 +113,7 @@ _cogl_buffer_initialize (CoglBuffer *buffer,
{ {
CoglBool use_malloc = FALSE; CoglBool use_malloc = FALSE;
buffer->context = context; buffer->context = ctx;
buffer->flags = COGL_BUFFER_FLAG_NONE; buffer->flags = COGL_BUFFER_FLAG_NONE;
buffer->store_created = FALSE; buffer->store_created = FALSE;
buffer->size = size; buffer->size = size;
@ -314,13 +126,13 @@ _cogl_buffer_initialize (CoglBuffer *buffer,
if (default_target == COGL_BUFFER_BIND_TARGET_PIXEL_PACK || if (default_target == COGL_BUFFER_BIND_TARGET_PIXEL_PACK ||
default_target == COGL_BUFFER_BIND_TARGET_PIXEL_UNPACK) 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; use_malloc = TRUE;
} }
else if (default_target == COGL_BUFFER_BIND_TARGET_ATTRIBUTE_BUFFER || else if (default_target == COGL_BUFFER_BIND_TARGET_ATTRIBUTE_BUFFER ||
default_target == COGL_BUFFER_BIND_TARGET_INDEX_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; use_malloc = TRUE;
} }
@ -334,11 +146,12 @@ _cogl_buffer_initialize (CoglBuffer *buffer,
} }
else else
{ {
buffer->vtable.map = bo_map; buffer->vtable.map = ctx->driver_vtable->buffer_map;
buffer->vtable.unmap = bo_unmap; buffer->vtable.unmap = ctx->driver_vtable->buffer_unmap;
buffer->vtable.set_data = bo_set_data; 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; buffer->flags |= COGL_BUFFER_FLAG_BUFFER_OBJECT;
} }
} }
@ -350,58 +163,11 @@ _cogl_buffer_fini (CoglBuffer *buffer)
_COGL_RETURN_IF_FAIL (buffer->immutable_ref == 0); _COGL_RETURN_IF_FAIL (buffer->immutable_ref == 0);
if (buffer->flags & COGL_BUFFER_FLAG_BUFFER_OBJECT) if (buffer->flags & COGL_BUFFER_FLAG_BUFFER_OBJECT)
GE( buffer->context, glDeleteBuffers (1, &buffer->gl_handle) ); buffer->context->driver_vtable->buffer_destroy (buffer);
else else
g_free (buffer->data); 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 unsigned int
cogl_buffer_get_size (CoglBuffer *buffer) cogl_buffer_get_size (CoglBuffer *buffer)
{ {

View File

@ -229,6 +229,32 @@ struct _CoglDriverVtable
void void
(* clip_stack_flush) (CoglClipStack *stack, CoglFramebuffer *framebuffer); (* clip_stack_flush) (CoglClipStack *stack, CoglFramebuffer *framebuffer);
/* Enables the driver to create some meta data to represent a buffer
* but with no corresponding storage allocated yet.
*/
void
(* buffer_create) (CoglBuffer *buffer);
void
(* buffer_destroy) (CoglBuffer *buffer);
/* Maps a buffer into the CPU */
void *
(* buffer_map) (CoglBuffer *buffer,
CoglBufferAccess access,
CoglBufferMapHint hints);
/* Unmaps a buffer */
void
(* buffer_unmap) (CoglBuffer *buffer);
/* Uploads data to the buffer without needing to map it necessarily
*/
CoglBool
(* buffer_set_data) (CoglBuffer *buffer,
unsigned int offset,
const void *data,
unsigned int size);
}; };
#endif /* __COGL_DRIVER_H */ #endif /* __COGL_DRIVER_H */

View File

@ -50,6 +50,7 @@
#include "cogl-private.h" #include "cogl-private.h"
#include "cogl1-context.h" #include "cogl1-context.h"
#include "cogl-offscreen.h" #include "cogl-offscreen.h"
#include "cogl-attribute-gl-private.h"
#ifdef COGL_GL_DEBUG #ifdef COGL_GL_DEBUG
/* GL error to string conversion */ /* GL error to string conversion */
@ -446,7 +447,7 @@ cogl_begin_gl (void)
cogl_pipeline_get_n_layers (pipeline)); cogl_pipeline_get_n_layers (pipeline));
/* Disable any cached vertex arrays */ /* Disable any cached vertex arrays */
_cogl_attribute_disable_cached_arrays (); _cogl_gl_disable_all_attributes (ctx);
} }
void void

View File

@ -41,4 +41,7 @@ _cogl_gl_flush_attributes_state (CoglFramebuffer *framebuffer,
CoglAttribute **attributes, CoglAttribute **attributes,
int n_attributes); int n_attributes);
void
_cogl_gl_disable_all_attributes (CoglContext *ctx);
#endif /* _COGL_ATTRIBUTE_GL_PRIVATE_H_ */ #endif /* _COGL_ATTRIBUTE_GL_PRIVATE_H_ */

View File

@ -39,6 +39,7 @@
#include "cogl-attribute-private.h" #include "cogl-attribute-private.h"
#include "cogl-attribute-gl-private.h" #include "cogl-attribute-gl-private.h"
#include "cogl-pipeline-progend-glsl-private.h" #include "cogl-pipeline-progend-glsl-private.h"
#include "cogl-buffer-gl-private.h"
typedef struct _ForeachChangedBitState typedef struct _ForeachChangedBitState
{ {
@ -396,3 +397,16 @@ _cogl_gl_flush_attributes_state (CoglFramebuffer *framebuffer,
if (copy) if (copy)
cogl_object_unref (copy); cogl_object_unref (copy);
} }
void
_cogl_gl_disable_all_attributes (CoglContext *ctx)
{
_cogl_bitmask_clear_all (&ctx->enable_builtin_attributes_tmp);
_cogl_bitmask_clear_all (&ctx->enable_texcoord_attributes_tmp);
_cogl_bitmask_clear_all (&ctx->enable_custom_attributes_tmp);
/* XXX: we can pass a NULL source pipeline here because we know a
* source pipeline only needs to be referenced when enabling
* attributes. */
apply_attribute_enable_updates (ctx, NULL);
}

View File

@ -0,0 +1,62 @@
/*
* Cogl
*
* An object oriented GL/GLES Abstraction/Utility Layer
*
* Copyright (C) 2012 Intel Corporation.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see
* <http://www.gnu.org/licenses/>.
*
*
*
* Authors:
* Robert Bragg <robert@linux.intel.com>
*/
#ifndef _COGL_BUFFER_GL_PRIVATE_H_
#define _COGL_BUFFER_GL_PRIVATE_H_
#include "cogl-types.h"
#include "cogl-context.h"
#include "cogl-buffer.h"
#include "cogl-buffer-private.h"
void
_cogl_buffer_gl_create (CoglBuffer *buffer);
void
_cogl_buffer_gl_destroy (CoglBuffer *buffer);
void *
_cogl_buffer_gl_map (CoglBuffer *buffer,
CoglBufferAccess access,
CoglBufferMapHint hints);
void
_cogl_buffer_gl_unmap (CoglBuffer *buffer);
CoglBool
_cogl_buffer_gl_set_data (CoglBuffer *buffer,
unsigned int offset,
const void *data,
unsigned int size);
void *
_cogl_buffer_gl_bind (CoglBuffer *buffer, CoglBufferBindTarget target);
void
_cogl_buffer_gl_unbind (CoglBuffer *buffer);
#endif /* _COGL_BUFFER_GL_PRIVATE_H_ */

View File

@ -0,0 +1,283 @@
/*
* Cogl
*
* An object oriented GL/GLES Abstraction/Utility Layer
*
* Copyright (C) 2010,2011,2012 Intel Corporation.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
*
*
* Authors:
* Damien Lespiau <damien.lespiau@intel.com>
* Robert Bragg <robert@linux.intel.com>
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "cogl-context-private.h"
#include "cogl-buffer-gl-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
void
_cogl_buffer_gl_create (CoglBuffer *buffer)
{
CoglContext *ctx = buffer->context;
GE (ctx, glGenBuffers (1, &buffer->gl_handle));
}
void
_cogl_buffer_gl_destroy (CoglBuffer *buffer)
{
GE( buffer->context, glDeleteBuffers (1, &buffer->gl_handle) );
}
static GLenum
update_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 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
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 = update_hints_to_gl_enum (buffer);
GE( buffer->context, glBufferData (gl_target,
buffer->size,
NULL,
gl_enum) );
buffer->store_created = TRUE;
}
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;
}
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;
}
void *
_cogl_buffer_gl_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))
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_gl_unbind (buffer);
return data;
}
void
_cogl_buffer_gl_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_gl_unbind (buffer);
}
CoglBool
_cogl_buffer_gl_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_gl_bind (buffer, target);
gl_target = convert_bind_target_to_gl_target (target);
GE( ctx, glBufferSubData (gl_target, offset, size, data) );
_cogl_buffer_gl_unbind (buffer);
return TRUE;
}
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)
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;
}

View File

@ -29,6 +29,7 @@
#include "cogl-context-private.h" #include "cogl-context-private.h"
#include "cogl-framebuffer-private.h" #include "cogl-framebuffer-private.h"
#include "cogl-framebuffer-gl-private.h" #include "cogl-framebuffer-gl-private.h"
#include "cogl-buffer-gl-private.h"
#include "cogl-error-private.h" #include "cogl-error-private.h"
#include <glib.h> #include <glib.h>

View File

@ -37,6 +37,7 @@
#include "cogl-texture-2d-gl-private.h" #include "cogl-texture-2d-gl-private.h"
#include "cogl-attribute-gl-private.h" #include "cogl-attribute-gl-private.h"
#include "cogl-clip-stack-gl-private.h" #include "cogl-clip-stack-gl-private.h"
#include "cogl-buffer-gl-private.h"
static CoglBool static CoglBool
_cogl_driver_pixel_format_from_gl_internal (CoglContext *context, _cogl_driver_pixel_format_from_gl_internal (CoglContext *context,
@ -552,4 +553,9 @@ _cogl_driver_gl =
_cogl_texture_2d_gl_get_data, _cogl_texture_2d_gl_get_data,
_cogl_gl_flush_attributes_state, _cogl_gl_flush_attributes_state,
_cogl_clip_stack_gl_flush, _cogl_clip_stack_gl_flush,
_cogl_buffer_gl_create,
_cogl_buffer_gl_destroy,
_cogl_buffer_gl_map,
_cogl_buffer_gl_unmap,
_cogl_buffer_gl_set_data,
}; };

View File

@ -36,6 +36,7 @@
#include "cogl-texture-2d-gl-private.h" #include "cogl-texture-2d-gl-private.h"
#include "cogl-attribute-gl-private.h" #include "cogl-attribute-gl-private.h"
#include "cogl-clip-stack-gl-private.h" #include "cogl-clip-stack-gl-private.h"
#include "cogl-buffer-gl-private.h"
#ifndef GL_UNSIGNED_INT_24_8 #ifndef GL_UNSIGNED_INT_24_8
#define GL_UNSIGNED_INT_24_8 0x84FA #define GL_UNSIGNED_INT_24_8 0x84FA
@ -370,4 +371,9 @@ _cogl_driver_gles =
NULL, /* texture_2d_get_data */ NULL, /* texture_2d_get_data */
_cogl_gl_flush_attributes_state, _cogl_gl_flush_attributes_state,
_cogl_clip_stack_gl_flush, _cogl_clip_stack_gl_flush,
_cogl_buffer_gl_create,
_cogl_buffer_gl_destroy,
_cogl_buffer_gl_map,
_cogl_buffer_gl_unmap,
_cogl_buffer_gl_set_data,
}; };