mirror of
https://github.com/brl/mutter.git
synced 2024-12-23 19:42:05 +00:00
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:
parent
bcf6a61d0b
commit
b1ecfbf720
@ -167,6 +167,8 @@ cogl_driver_sources += \
|
||||
$(srcdir)/driver/gl/cogl-attribute-gl.c \
|
||||
$(srcdir)/driver/gl/cogl-clip-stack-gl-private.h \
|
||||
$(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-private.h \
|
||||
$(srcdir)/driver/gl/cogl-pipeline-fragend-glsl.c \
|
||||
|
@ -384,6 +384,7 @@ _cogl_flush_attributes_state (CoglFramebuffer *framebuffer,
|
||||
{
|
||||
CoglContext *ctx = framebuffer->context;
|
||||
CoglFlushLayerState layers_state;
|
||||
CoglPipeline *copy = NULL;
|
||||
|
||||
if (!(flags & COGL_DRAW_SKIP_JOURNAL_FLUSH))
|
||||
_cogl_journal_flush (framebuffer->journal);
|
||||
@ -417,13 +418,9 @@ _cogl_flush_attributes_state (CoglFramebuffer *framebuffer,
|
||||
if (G_UNLIKELY (!(flags & COGL_DRAW_SKIP_LEGACY_STATE)) &&
|
||||
G_UNLIKELY (ctx->legacy_state_set) &&
|
||||
_cogl_get_enable_legacy_state ())
|
||||
{
|
||||
/* If we haven't already created a derived pipeline... */
|
||||
if (!copy)
|
||||
{
|
||||
copy = cogl_pipeline_copy (pipeline);
|
||||
pipeline = copy;
|
||||
}
|
||||
_cogl_pipeline_apply_legacy_state (pipeline);
|
||||
}
|
||||
|
||||
|
@ -32,6 +32,7 @@
|
||||
#include "cogl-buffer-private.h"
|
||||
#include "cogl-pixel-buffer.h"
|
||||
#include "cogl-context-private.h"
|
||||
#include "cogl-buffer-gl-private.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
|
@ -123,15 +123,6 @@ _cogl_buffer_initialize (CoglBuffer *buffer,
|
||||
void
|
||||
_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
|
||||
_cogl_buffer_get_usage_hint (CoglBuffer *buffer);
|
||||
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -229,6 +229,32 @@ struct _CoglDriverVtable
|
||||
void
|
||||
(* 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 */
|
||||
|
@ -50,6 +50,7 @@
|
||||
#include "cogl-private.h"
|
||||
#include "cogl1-context.h"
|
||||
#include "cogl-offscreen.h"
|
||||
#include "cogl-attribute-gl-private.h"
|
||||
|
||||
#ifdef COGL_GL_DEBUG
|
||||
/* GL error to string conversion */
|
||||
@ -446,7 +447,7 @@ cogl_begin_gl (void)
|
||||
cogl_pipeline_get_n_layers (pipeline));
|
||||
|
||||
/* Disable any cached vertex arrays */
|
||||
_cogl_attribute_disable_cached_arrays ();
|
||||
_cogl_gl_disable_all_attributes (ctx);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -41,4 +41,7 @@ _cogl_gl_flush_attributes_state (CoglFramebuffer *framebuffer,
|
||||
CoglAttribute **attributes,
|
||||
int n_attributes);
|
||||
|
||||
void
|
||||
_cogl_gl_disable_all_attributes (CoglContext *ctx);
|
||||
|
||||
#endif /* _COGL_ATTRIBUTE_GL_PRIVATE_H_ */
|
||||
|
@ -39,6 +39,7 @@
|
||||
#include "cogl-attribute-private.h"
|
||||
#include "cogl-attribute-gl-private.h"
|
||||
#include "cogl-pipeline-progend-glsl-private.h"
|
||||
#include "cogl-buffer-gl-private.h"
|
||||
|
||||
typedef struct _ForeachChangedBitState
|
||||
{
|
||||
@ -396,3 +397,16 @@ _cogl_gl_flush_attributes_state (CoglFramebuffer *framebuffer,
|
||||
if (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);
|
||||
}
|
||||
|
62
cogl/driver/gl/cogl-buffer-gl-private.h
Normal file
62
cogl/driver/gl/cogl-buffer-gl-private.h
Normal 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_ */
|
283
cogl/driver/gl/cogl-buffer-gl.c
Normal file
283
cogl/driver/gl/cogl-buffer-gl.c
Normal 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;
|
||||
}
|
@ -29,6 +29,7 @@
|
||||
#include "cogl-context-private.h"
|
||||
#include "cogl-framebuffer-private.h"
|
||||
#include "cogl-framebuffer-gl-private.h"
|
||||
#include "cogl-buffer-gl-private.h"
|
||||
#include "cogl-error-private.h"
|
||||
|
||||
#include <glib.h>
|
||||
|
@ -37,6 +37,7 @@
|
||||
#include "cogl-texture-2d-gl-private.h"
|
||||
#include "cogl-attribute-gl-private.h"
|
||||
#include "cogl-clip-stack-gl-private.h"
|
||||
#include "cogl-buffer-gl-private.h"
|
||||
|
||||
static CoglBool
|
||||
_cogl_driver_pixel_format_from_gl_internal (CoglContext *context,
|
||||
@ -552,4 +553,9 @@ _cogl_driver_gl =
|
||||
_cogl_texture_2d_gl_get_data,
|
||||
_cogl_gl_flush_attributes_state,
|
||||
_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,
|
||||
};
|
||||
|
@ -36,6 +36,7 @@
|
||||
#include "cogl-texture-2d-gl-private.h"
|
||||
#include "cogl-attribute-gl-private.h"
|
||||
#include "cogl-clip-stack-gl-private.h"
|
||||
#include "cogl-buffer-gl-private.h"
|
||||
|
||||
#ifndef GL_UNSIGNED_INT_24_8
|
||||
#define GL_UNSIGNED_INT_24_8 0x84FA
|
||||
@ -370,4 +371,9 @@ _cogl_driver_gles =
|
||||
NULL, /* texture_2d_get_data */
|
||||
_cogl_gl_flush_attributes_state,
|
||||
_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,
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user