mirror of
https://github.com/brl/mutter.git
synced 2024-11-25 17:40:40 -05:00
attribute: Split out GL specific code
As part of an on-going effort to enable non-opengl drivers for Cogl this splits out the GL specific code in cogl-attribute.c into cogl/driver/gl/cogl-attribute-gl.c Reviewed-by: Neil Roberts <neil@linux.intel.com> (cherry picked from commit 7e20c39c47fa176aa5062867ff273bc2c41a2f22)
This commit is contained in:
parent
ae2b064fd7
commit
4efcd4e6a6
@ -150,6 +150,8 @@ cogl_driver_sources = \
|
||||
$(srcdir)/driver/gl/cogl-framebuffer-gl.c \
|
||||
$(srcdir)/driver/gl/cogl-texture-2d-gl-private.h \
|
||||
$(srcdir)/driver/gl/cogl-texture-2d-gl.c \
|
||||
$(srcdir)/driver/gl/cogl-attribute-gl-private.h \
|
||||
$(srcdir)/driver/gl/cogl-attribute-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 \
|
||||
|
@ -31,6 +31,7 @@
|
||||
#include "cogl-object-private.h"
|
||||
#include "cogl-attribute.h"
|
||||
#include "cogl-framebuffer.h"
|
||||
#include "cogl-pipeline-private.h"
|
||||
|
||||
typedef enum
|
||||
{
|
||||
@ -99,8 +100,12 @@ _cogl_attribute_immutable_ref (CoglAttribute *attribute);
|
||||
void
|
||||
_cogl_attribute_immutable_unref (CoglAttribute *attribute);
|
||||
|
||||
void
|
||||
_cogl_attribute_disable_cached_arrays (void);
|
||||
typedef struct
|
||||
{
|
||||
int unit;
|
||||
CoglPipelineFlushOptions options;
|
||||
uint32_t fallback_layers;
|
||||
} CoglFlushLayerState;
|
||||
|
||||
void
|
||||
_cogl_flush_attributes_state (CoglFramebuffer *framebuffer,
|
||||
|
@ -319,13 +319,6 @@ _cogl_attribute_free (CoglAttribute *attribute)
|
||||
g_slice_free (CoglAttribute, attribute);
|
||||
}
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int unit;
|
||||
CoglPipelineFlushOptions options;
|
||||
uint32_t fallback_layers;
|
||||
} ValidateLayerState;
|
||||
|
||||
static CoglBool
|
||||
validate_layer_cb (CoglPipeline *pipeline,
|
||||
int layer_index,
|
||||
@ -333,7 +326,7 @@ validate_layer_cb (CoglPipeline *pipeline,
|
||||
{
|
||||
CoglTexture *texture =
|
||||
cogl_pipeline_get_layer_texture (pipeline, layer_index);
|
||||
ValidateLayerState *state = user_data;
|
||||
CoglFlushLayerState *state = user_data;
|
||||
CoglBool status = TRUE;
|
||||
|
||||
/* invalid textures will be handled correctly in
|
||||
@ -382,171 +375,6 @@ validated:
|
||||
return status;
|
||||
}
|
||||
|
||||
typedef struct _ForeachChangedBitState
|
||||
{
|
||||
CoglContext *context;
|
||||
const CoglBitmask *new_bits;
|
||||
CoglPipeline *pipeline;
|
||||
} ForeachChangedBitState;
|
||||
|
||||
static CoglBool
|
||||
toggle_builtin_attribute_enabled_cb (int bit_num, void *user_data)
|
||||
{
|
||||
ForeachChangedBitState *state = user_data;
|
||||
CoglContext *context = state->context;
|
||||
|
||||
_COGL_RETURN_VAL_IF_FAIL (context->driver == COGL_DRIVER_GL ||
|
||||
context->driver == COGL_DRIVER_GLES1,
|
||||
FALSE);
|
||||
|
||||
#if defined (HAVE_COGL_GL) || defined (HAVE_COGL_GLES)
|
||||
{
|
||||
CoglBool enabled = _cogl_bitmask_get (state->new_bits, bit_num);
|
||||
GLenum cap;
|
||||
|
||||
switch (bit_num)
|
||||
{
|
||||
case COGL_ATTRIBUTE_NAME_ID_COLOR_ARRAY:
|
||||
cap = GL_COLOR_ARRAY;
|
||||
break;
|
||||
case COGL_ATTRIBUTE_NAME_ID_POSITION_ARRAY:
|
||||
cap = GL_VERTEX_ARRAY;
|
||||
break;
|
||||
case COGL_ATTRIBUTE_NAME_ID_NORMAL_ARRAY:
|
||||
cap = GL_NORMAL_ARRAY;
|
||||
break;
|
||||
}
|
||||
if (enabled)
|
||||
GE (context, glEnableClientState (cap));
|
||||
else
|
||||
GE (context, glDisableClientState (cap));
|
||||
}
|
||||
#endif
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static CoglBool
|
||||
toggle_texcood_attribute_enabled_cb (int bit_num, void *user_data)
|
||||
{
|
||||
ForeachChangedBitState *state = user_data;
|
||||
CoglContext *context = state->context;
|
||||
|
||||
_COGL_RETURN_VAL_IF_FAIL (context->driver == COGL_DRIVER_GL ||
|
||||
context->driver == COGL_DRIVER_GLES1,
|
||||
FALSE);
|
||||
|
||||
#if defined (HAVE_COGL_GL) || defined (HAVE_COGL_GLES)
|
||||
{
|
||||
CoglBool enabled = _cogl_bitmask_get (state->new_bits, bit_num);
|
||||
|
||||
GE( context, glClientActiveTexture (GL_TEXTURE0 + bit_num) );
|
||||
|
||||
if (enabled)
|
||||
GE( context, glEnableClientState (GL_TEXTURE_COORD_ARRAY) );
|
||||
else
|
||||
GE( context, glDisableClientState (GL_TEXTURE_COORD_ARRAY) );
|
||||
}
|
||||
#endif
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static CoglBool
|
||||
toggle_custom_attribute_enabled_cb (int bit_num, void *user_data)
|
||||
{
|
||||
ForeachChangedBitState *state = user_data;
|
||||
CoglBool enabled = _cogl_bitmask_get (state->new_bits, bit_num);
|
||||
CoglContext *context = state->context;
|
||||
|
||||
if (enabled)
|
||||
GE( context, glEnableVertexAttribArray (bit_num) );
|
||||
else
|
||||
GE( context, glDisableVertexAttribArray (bit_num) );
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
foreach_changed_bit_and_save (CoglContext *context,
|
||||
CoglBitmask *current_bits,
|
||||
const CoglBitmask *new_bits,
|
||||
CoglBitmaskForeachFunc callback,
|
||||
ForeachChangedBitState *state)
|
||||
{
|
||||
/* Get the list of bits that are different */
|
||||
_cogl_bitmask_clear_all (&context->changed_bits_tmp);
|
||||
_cogl_bitmask_set_bits (&context->changed_bits_tmp, current_bits);
|
||||
_cogl_bitmask_xor_bits (&context->changed_bits_tmp, new_bits);
|
||||
|
||||
/* Iterate over each bit to change */
|
||||
state->new_bits = new_bits;
|
||||
_cogl_bitmask_foreach (&context->changed_bits_tmp,
|
||||
callback,
|
||||
state);
|
||||
|
||||
/* Store the new values */
|
||||
_cogl_bitmask_clear_all (current_bits);
|
||||
_cogl_bitmask_set_bits (current_bits, new_bits);
|
||||
}
|
||||
|
||||
#ifdef COGL_PIPELINE_PROGEND_GLSL
|
||||
|
||||
static void
|
||||
setup_generic_attribute (CoglContext *context,
|
||||
CoglPipeline *pipeline,
|
||||
CoglAttribute *attribute,
|
||||
uint8_t *base)
|
||||
{
|
||||
int name_index = attribute->name_state->name_index;
|
||||
int attrib_location =
|
||||
_cogl_pipeline_progend_glsl_get_attrib_location (pipeline, name_index);
|
||||
if (attrib_location != -1)
|
||||
{
|
||||
GE( context, glVertexAttribPointer (attrib_location,
|
||||
attribute->n_components,
|
||||
attribute->type,
|
||||
attribute->normalized,
|
||||
attribute->stride,
|
||||
base + attribute->offset) );
|
||||
_cogl_bitmask_set (&context->enable_custom_attributes_tmp,
|
||||
attrib_location, TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* COGL_PIPELINE_PROGEND_GLSL */
|
||||
|
||||
static void
|
||||
apply_attribute_enable_updates (CoglContext *context,
|
||||
CoglPipeline *pipeline)
|
||||
{
|
||||
ForeachChangedBitState changed_bits_state;
|
||||
|
||||
changed_bits_state.context = context;
|
||||
changed_bits_state.new_bits = &context->enable_builtin_attributes_tmp;
|
||||
changed_bits_state.pipeline = pipeline;
|
||||
|
||||
foreach_changed_bit_and_save (context,
|
||||
&context->enabled_builtin_attributes,
|
||||
&context->enable_builtin_attributes_tmp,
|
||||
toggle_builtin_attribute_enabled_cb,
|
||||
&changed_bits_state);
|
||||
|
||||
changed_bits_state.new_bits = &context->enable_texcoord_attributes_tmp;
|
||||
foreach_changed_bit_and_save (context,
|
||||
&context->enabled_texcoord_attributes,
|
||||
&context->enable_texcoord_attributes_tmp,
|
||||
toggle_texcood_attribute_enabled_cb,
|
||||
&changed_bits_state);
|
||||
|
||||
changed_bits_state.new_bits = &context->enable_custom_attributes_tmp;
|
||||
foreach_changed_bit_and_save (context,
|
||||
&context->enabled_custom_attributes,
|
||||
&context->enable_custom_attributes_tmp,
|
||||
toggle_custom_attribute_enabled_cb,
|
||||
&changed_bits_state);
|
||||
}
|
||||
|
||||
void
|
||||
_cogl_flush_attributes_state (CoglFramebuffer *framebuffer,
|
||||
CoglPipeline *pipeline,
|
||||
@ -554,12 +382,8 @@ _cogl_flush_attributes_state (CoglFramebuffer *framebuffer,
|
||||
CoglAttribute **attributes,
|
||||
int n_attributes)
|
||||
{
|
||||
int i;
|
||||
CoglBool skip_gl_color = FALSE;
|
||||
CoglPipeline *copy = NULL;
|
||||
int n_tex_coord_attribs = 0;
|
||||
ValidateLayerState layers_state;
|
||||
CoglContext *ctx = framebuffer->context;
|
||||
CoglFlushLayerState layers_state;
|
||||
|
||||
if (!(flags & COGL_DRAW_SKIP_JOURNAL_FLUSH))
|
||||
_cogl_journal_flush (framebuffer->journal);
|
||||
@ -590,77 +414,6 @@ _cogl_flush_attributes_state (CoglFramebuffer *framebuffer,
|
||||
* when the framebuffer really does get drawn to. */
|
||||
_cogl_framebuffer_dirty (framebuffer);
|
||||
|
||||
/* Iterate the attributes to work out whether blending needs to be
|
||||
enabled and how many texture coords there are. We need to do this
|
||||
before flushing the pipeline. */
|
||||
for (i = 0; i < n_attributes; i++)
|
||||
switch (attributes[i]->name_state->name_id)
|
||||
{
|
||||
case COGL_ATTRIBUTE_NAME_ID_COLOR_ARRAY:
|
||||
if ((flags & COGL_DRAW_COLOR_ATTRIBUTE_IS_OPAQUE) == 0 &&
|
||||
!_cogl_pipeline_get_real_blend_enabled (pipeline))
|
||||
{
|
||||
CoglPipelineBlendEnable blend_enable =
|
||||
COGL_PIPELINE_BLEND_ENABLE_ENABLED;
|
||||
copy = cogl_pipeline_copy (pipeline);
|
||||
_cogl_pipeline_set_blend_enabled (copy, blend_enable);
|
||||
pipeline = copy;
|
||||
}
|
||||
skip_gl_color = TRUE;
|
||||
break;
|
||||
|
||||
case COGL_ATTRIBUTE_NAME_ID_TEXTURE_COORD_ARRAY:
|
||||
n_tex_coord_attribs++;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (G_UNLIKELY (layers_state.options.flags))
|
||||
{
|
||||
/* If we haven't already created a derived pipeline... */
|
||||
if (!copy)
|
||||
{
|
||||
copy = cogl_pipeline_copy (pipeline);
|
||||
pipeline = copy;
|
||||
}
|
||||
_cogl_pipeline_apply_overrides (pipeline, &layers_state.options);
|
||||
|
||||
/* TODO:
|
||||
* overrides = cogl_pipeline_get_data (pipeline,
|
||||
* last_overrides_key);
|
||||
* if (overrides)
|
||||
* {
|
||||
* age = cogl_pipeline_get_age (pipeline);
|
||||
* XXX: actually we also need to check for legacy_state
|
||||
* and blending overrides for use of glColorPointer...
|
||||
* if (overrides->ags != age ||
|
||||
* memcmp (&overrides->options, &options,
|
||||
* sizeof (options) != 0)
|
||||
* {
|
||||
* cogl_object_unref (overrides->weak_pipeline);
|
||||
* g_slice_free (Overrides, overrides);
|
||||
* overrides = NULL;
|
||||
* }
|
||||
* }
|
||||
* if (!overrides)
|
||||
* {
|
||||
* overrides = g_slice_new (Overrides);
|
||||
* overrides->weak_pipeline =
|
||||
* cogl_pipeline_weak_copy (pipeline);
|
||||
* _cogl_pipeline_apply_overrides (overrides->weak_pipeline,
|
||||
* &options);
|
||||
*
|
||||
* cogl_pipeline_set_data (pipeline, last_overrides_key,
|
||||
* weak_overrides,
|
||||
* free_overrides_cb,
|
||||
* NULL);
|
||||
* }
|
||||
* pipeline = overrides->weak_pipeline;
|
||||
*/
|
||||
}
|
||||
|
||||
if (G_UNLIKELY (!(flags & COGL_DRAW_SKIP_LEGACY_STATE)) &&
|
||||
G_UNLIKELY (ctx->legacy_state_set) &&
|
||||
_cogl_get_enable_legacy_state ())
|
||||
@ -674,124 +427,13 @@ _cogl_flush_attributes_state (CoglFramebuffer *framebuffer,
|
||||
_cogl_pipeline_apply_legacy_state (pipeline);
|
||||
}
|
||||
|
||||
_cogl_pipeline_flush_gl_state (pipeline,
|
||||
framebuffer,
|
||||
skip_gl_color,
|
||||
n_tex_coord_attribs);
|
||||
|
||||
_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);
|
||||
|
||||
/* Bind the attribute pointers. We need to do this after the
|
||||
* pipeline is flushed because when using GLSL that is the only
|
||||
* point when we can determine the attribute locations */
|
||||
|
||||
for (i = 0; i < n_attributes; i++)
|
||||
{
|
||||
CoglAttribute *attribute = attributes[i];
|
||||
CoglAttributeBuffer *attribute_buffer;
|
||||
CoglBuffer *buffer;
|
||||
uint8_t *base;
|
||||
|
||||
attribute_buffer = cogl_attribute_get_buffer (attribute);
|
||||
buffer = COGL_BUFFER (attribute_buffer);
|
||||
base = _cogl_buffer_bind (buffer, COGL_BUFFER_BIND_TARGET_ATTRIBUTE_BUFFER);
|
||||
|
||||
switch (attribute->name_state->name_id)
|
||||
{
|
||||
case COGL_ATTRIBUTE_NAME_ID_COLOR_ARRAY:
|
||||
#ifdef HAVE_COGL_GLES2
|
||||
if (ctx->driver == COGL_DRIVER_GLES2)
|
||||
setup_generic_attribute (ctx, pipeline, attribute, base);
|
||||
else
|
||||
#endif
|
||||
{
|
||||
_cogl_bitmask_set (&ctx->enable_builtin_attributes_tmp,
|
||||
COGL_ATTRIBUTE_NAME_ID_COLOR_ARRAY, TRUE);
|
||||
GE (ctx, glColorPointer (attribute->n_components,
|
||||
attribute->type,
|
||||
attribute->stride,
|
||||
base + attribute->offset));
|
||||
}
|
||||
break;
|
||||
case COGL_ATTRIBUTE_NAME_ID_NORMAL_ARRAY:
|
||||
#ifdef HAVE_COGL_GLES2
|
||||
if (ctx->driver == COGL_DRIVER_GLES2)
|
||||
setup_generic_attribute (ctx, pipeline, attribute, base);
|
||||
else
|
||||
#endif
|
||||
{
|
||||
_cogl_bitmask_set (&ctx->enable_builtin_attributes_tmp,
|
||||
COGL_ATTRIBUTE_NAME_ID_NORMAL_ARRAY, TRUE);
|
||||
GE (ctx, glNormalPointer (attribute->type,
|
||||
attribute->stride,
|
||||
base + attribute->offset));
|
||||
}
|
||||
break;
|
||||
case COGL_ATTRIBUTE_NAME_ID_TEXTURE_COORD_ARRAY:
|
||||
#ifdef HAVE_COGL_GLES2
|
||||
if (ctx->driver == COGL_DRIVER_GLES2)
|
||||
setup_generic_attribute (ctx, pipeline, attribute, base);
|
||||
else
|
||||
#endif
|
||||
{
|
||||
_cogl_bitmask_set (&ctx->enable_texcoord_attributes_tmp,
|
||||
attribute->name_state->texture_unit, TRUE);
|
||||
GE (ctx,
|
||||
glClientActiveTexture (GL_TEXTURE0 +
|
||||
attribute->name_state->texture_unit));
|
||||
GE (ctx, glTexCoordPointer (attribute->n_components,
|
||||
attribute->type,
|
||||
attribute->stride,
|
||||
base + attribute->offset));
|
||||
}
|
||||
break;
|
||||
case COGL_ATTRIBUTE_NAME_ID_POSITION_ARRAY:
|
||||
#ifdef HAVE_COGL_GLES2
|
||||
if (ctx->driver == COGL_DRIVER_GLES2)
|
||||
setup_generic_attribute (ctx, pipeline, attribute, base);
|
||||
else
|
||||
#endif
|
||||
{
|
||||
_cogl_bitmask_set (&ctx->enable_builtin_attributes_tmp,
|
||||
COGL_ATTRIBUTE_NAME_ID_POSITION_ARRAY, TRUE);
|
||||
GE (ctx, glVertexPointer (attribute->n_components,
|
||||
attribute->type,
|
||||
attribute->stride,
|
||||
base + attribute->offset));
|
||||
}
|
||||
break;
|
||||
case COGL_ATTRIBUTE_NAME_ID_CUSTOM_ARRAY:
|
||||
#ifdef COGL_PIPELINE_PROGEND_GLSL
|
||||
if (ctx->driver != COGL_DRIVER_GLES1)
|
||||
setup_generic_attribute (ctx, pipeline, attribute, base);
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
g_warning ("Unrecognised attribute type 0x%08x", attribute->type);
|
||||
}
|
||||
|
||||
_cogl_buffer_unbind (buffer);
|
||||
}
|
||||
|
||||
apply_attribute_enable_updates (ctx, pipeline);
|
||||
ctx->driver_vtable->flush_attributes_state (framebuffer,
|
||||
pipeline,
|
||||
&layers_state,
|
||||
flags,
|
||||
attributes,
|
||||
n_attributes);
|
||||
|
||||
if (copy)
|
||||
cogl_object_unref (copy);
|
||||
}
|
||||
|
||||
void
|
||||
_cogl_attribute_disable_cached_arrays (void)
|
||||
{
|
||||
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
|
||||
|
||||
_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);
|
||||
}
|
||||
|
@ -27,6 +27,7 @@
|
||||
#include "cogl-context.h"
|
||||
#include "cogl-offscreen.h"
|
||||
#include "cogl-framebuffer-private.h"
|
||||
#include "cogl-attribute-private.h"
|
||||
|
||||
typedef struct _CoglDriverVtable CoglDriverVtable;
|
||||
|
||||
@ -210,6 +211,17 @@ struct _CoglDriverVtable
|
||||
CoglPixelFormat format,
|
||||
unsigned int rowstride,
|
||||
uint8_t *data);
|
||||
|
||||
/* Prepares for drawing by flushing the journal, framebuffer state,
|
||||
* pipeline state and attribute state.
|
||||
*/
|
||||
void
|
||||
(* flush_attributes_state) (CoglFramebuffer *framebuffer,
|
||||
CoglPipeline *pipeline,
|
||||
CoglFlushLayerState *layer_state,
|
||||
CoglDrawFlags flags,
|
||||
CoglAttribute **attributes,
|
||||
int n_attributes);
|
||||
};
|
||||
|
||||
#endif /* __COGL_DRIVER_H */
|
||||
|
44
cogl/driver/gl/cogl-attribute-gl-private.h
Normal file
44
cogl/driver/gl/cogl-attribute-gl-private.h
Normal file
@ -0,0 +1,44 @@
|
||||
/*
|
||||
* 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_ATTRIBUTE_GL_PRIVATE_H_
|
||||
#define _COGL_ATTRIBUTE_GL_PRIVATE_H_
|
||||
|
||||
#include "cogl-types.h"
|
||||
#include "cogl-framebuffer.h"
|
||||
#include "cogl-attribute.h"
|
||||
#include "cogl-attribute-private.h"
|
||||
|
||||
void
|
||||
_cogl_gl_flush_attributes_state (CoglFramebuffer *framebuffer,
|
||||
CoglPipeline *pipeline,
|
||||
CoglFlushLayerState *layers_state,
|
||||
CoglDrawFlags flags,
|
||||
CoglAttribute **attributes,
|
||||
int n_attributes);
|
||||
|
||||
#endif /* _COGL_ATTRIBUTE_GL_PRIVATE_H_ */
|
398
cogl/driver/gl/cogl-attribute-gl.c
Normal file
398
cogl/driver/gl/cogl-attribute-gl.c
Normal file
@ -0,0 +1,398 @@
|
||||
/*
|
||||
* 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:
|
||||
* Neil Roberts <neil@linux.intel.com>
|
||||
* Robert Bragg <robert@linux.intel.com>
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "cogl-private.h"
|
||||
#include "cogl-pipeline-opengl-private.h"
|
||||
#include "cogl-error-private.h"
|
||||
#include "cogl-context-private.h"
|
||||
#include "cogl-attribute.h"
|
||||
#include "cogl-attribute-private.h"
|
||||
#include "cogl-attribute-gl-private.h"
|
||||
#include "cogl-pipeline-progend-glsl-private.h"
|
||||
|
||||
typedef struct _ForeachChangedBitState
|
||||
{
|
||||
CoglContext *context;
|
||||
const CoglBitmask *new_bits;
|
||||
CoglPipeline *pipeline;
|
||||
} ForeachChangedBitState;
|
||||
|
||||
static CoglBool
|
||||
toggle_builtin_attribute_enabled_cb (int bit_num, void *user_data)
|
||||
{
|
||||
ForeachChangedBitState *state = user_data;
|
||||
CoglContext *context = state->context;
|
||||
|
||||
_COGL_RETURN_VAL_IF_FAIL (context->driver == COGL_DRIVER_GL ||
|
||||
context->driver == COGL_DRIVER_GLES1,
|
||||
FALSE);
|
||||
|
||||
#if defined (HAVE_COGL_GL) || defined (HAVE_COGL_GLES)
|
||||
{
|
||||
CoglBool enabled = _cogl_bitmask_get (state->new_bits, bit_num);
|
||||
GLenum cap;
|
||||
|
||||
switch (bit_num)
|
||||
{
|
||||
case COGL_ATTRIBUTE_NAME_ID_COLOR_ARRAY:
|
||||
cap = GL_COLOR_ARRAY;
|
||||
break;
|
||||
case COGL_ATTRIBUTE_NAME_ID_POSITION_ARRAY:
|
||||
cap = GL_VERTEX_ARRAY;
|
||||
break;
|
||||
case COGL_ATTRIBUTE_NAME_ID_NORMAL_ARRAY:
|
||||
cap = GL_NORMAL_ARRAY;
|
||||
break;
|
||||
}
|
||||
if (enabled)
|
||||
GE (context, glEnableClientState (cap));
|
||||
else
|
||||
GE (context, glDisableClientState (cap));
|
||||
}
|
||||
#endif
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static CoglBool
|
||||
toggle_texcood_attribute_enabled_cb (int bit_num, void *user_data)
|
||||
{
|
||||
ForeachChangedBitState *state = user_data;
|
||||
CoglContext *context = state->context;
|
||||
|
||||
_COGL_RETURN_VAL_IF_FAIL (context->driver == COGL_DRIVER_GL ||
|
||||
context->driver == COGL_DRIVER_GLES1,
|
||||
FALSE);
|
||||
|
||||
#if defined (HAVE_COGL_GL) || defined (HAVE_COGL_GLES)
|
||||
{
|
||||
CoglBool enabled = _cogl_bitmask_get (state->new_bits, bit_num);
|
||||
|
||||
GE( context, glClientActiveTexture (GL_TEXTURE0 + bit_num) );
|
||||
|
||||
if (enabled)
|
||||
GE( context, glEnableClientState (GL_TEXTURE_COORD_ARRAY) );
|
||||
else
|
||||
GE( context, glDisableClientState (GL_TEXTURE_COORD_ARRAY) );
|
||||
}
|
||||
#endif
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static CoglBool
|
||||
toggle_custom_attribute_enabled_cb (int bit_num, void *user_data)
|
||||
{
|
||||
ForeachChangedBitState *state = user_data;
|
||||
CoglBool enabled = _cogl_bitmask_get (state->new_bits, bit_num);
|
||||
CoglContext *context = state->context;
|
||||
|
||||
if (enabled)
|
||||
GE( context, glEnableVertexAttribArray (bit_num) );
|
||||
else
|
||||
GE( context, glDisableVertexAttribArray (bit_num) );
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
foreach_changed_bit_and_save (CoglContext *context,
|
||||
CoglBitmask *current_bits,
|
||||
const CoglBitmask *new_bits,
|
||||
CoglBitmaskForeachFunc callback,
|
||||
ForeachChangedBitState *state)
|
||||
{
|
||||
/* Get the list of bits that are different */
|
||||
_cogl_bitmask_clear_all (&context->changed_bits_tmp);
|
||||
_cogl_bitmask_set_bits (&context->changed_bits_tmp, current_bits);
|
||||
_cogl_bitmask_xor_bits (&context->changed_bits_tmp, new_bits);
|
||||
|
||||
/* Iterate over each bit to change */
|
||||
state->new_bits = new_bits;
|
||||
_cogl_bitmask_foreach (&context->changed_bits_tmp,
|
||||
callback,
|
||||
state);
|
||||
|
||||
/* Store the new values */
|
||||
_cogl_bitmask_clear_all (current_bits);
|
||||
_cogl_bitmask_set_bits (current_bits, new_bits);
|
||||
}
|
||||
|
||||
#ifdef COGL_PIPELINE_PROGEND_GLSL
|
||||
|
||||
static void
|
||||
setup_generic_attribute (CoglContext *context,
|
||||
CoglPipeline *pipeline,
|
||||
CoglAttribute *attribute,
|
||||
uint8_t *base)
|
||||
{
|
||||
int name_index = attribute->name_state->name_index;
|
||||
int attrib_location =
|
||||
_cogl_pipeline_progend_glsl_get_attrib_location (pipeline, name_index);
|
||||
if (attrib_location != -1)
|
||||
{
|
||||
GE( context, glVertexAttribPointer (attrib_location,
|
||||
attribute->n_components,
|
||||
attribute->type,
|
||||
attribute->normalized,
|
||||
attribute->stride,
|
||||
base + attribute->offset) );
|
||||
_cogl_bitmask_set (&context->enable_custom_attributes_tmp,
|
||||
attrib_location, TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* COGL_PIPELINE_PROGEND_GLSL */
|
||||
|
||||
static void
|
||||
apply_attribute_enable_updates (CoglContext *context,
|
||||
CoglPipeline *pipeline)
|
||||
{
|
||||
ForeachChangedBitState changed_bits_state;
|
||||
|
||||
changed_bits_state.context = context;
|
||||
changed_bits_state.new_bits = &context->enable_builtin_attributes_tmp;
|
||||
changed_bits_state.pipeline = pipeline;
|
||||
|
||||
foreach_changed_bit_and_save (context,
|
||||
&context->enabled_builtin_attributes,
|
||||
&context->enable_builtin_attributes_tmp,
|
||||
toggle_builtin_attribute_enabled_cb,
|
||||
&changed_bits_state);
|
||||
|
||||
changed_bits_state.new_bits = &context->enable_texcoord_attributes_tmp;
|
||||
foreach_changed_bit_and_save (context,
|
||||
&context->enabled_texcoord_attributes,
|
||||
&context->enable_texcoord_attributes_tmp,
|
||||
toggle_texcood_attribute_enabled_cb,
|
||||
&changed_bits_state);
|
||||
|
||||
changed_bits_state.new_bits = &context->enable_custom_attributes_tmp;
|
||||
foreach_changed_bit_and_save (context,
|
||||
&context->enabled_custom_attributes,
|
||||
&context->enable_custom_attributes_tmp,
|
||||
toggle_custom_attribute_enabled_cb,
|
||||
&changed_bits_state);
|
||||
}
|
||||
|
||||
void
|
||||
_cogl_gl_flush_attributes_state (CoglFramebuffer *framebuffer,
|
||||
CoglPipeline *pipeline,
|
||||
CoglFlushLayerState *layers_state,
|
||||
CoglDrawFlags flags,
|
||||
CoglAttribute **attributes,
|
||||
int n_attributes)
|
||||
{
|
||||
CoglContext *ctx = framebuffer->context;
|
||||
int i;
|
||||
CoglBool skip_gl_color = FALSE;
|
||||
CoglPipeline *copy = NULL;
|
||||
int n_tex_coord_attribs = 0;
|
||||
|
||||
/* Iterate the attributes to work out whether blending needs to be
|
||||
enabled and how many texture coords there are. We need to do this
|
||||
before flushing the pipeline. */
|
||||
for (i = 0; i < n_attributes; i++)
|
||||
switch (attributes[i]->name_state->name_id)
|
||||
{
|
||||
case COGL_ATTRIBUTE_NAME_ID_COLOR_ARRAY:
|
||||
if ((flags & COGL_DRAW_COLOR_ATTRIBUTE_IS_OPAQUE) == 0 &&
|
||||
!_cogl_pipeline_get_real_blend_enabled (pipeline))
|
||||
{
|
||||
CoglPipelineBlendEnable blend_enable =
|
||||
COGL_PIPELINE_BLEND_ENABLE_ENABLED;
|
||||
copy = cogl_pipeline_copy (pipeline);
|
||||
_cogl_pipeline_set_blend_enabled (copy, blend_enable);
|
||||
pipeline = copy;
|
||||
}
|
||||
skip_gl_color = TRUE;
|
||||
break;
|
||||
|
||||
case COGL_ATTRIBUTE_NAME_ID_TEXTURE_COORD_ARRAY:
|
||||
n_tex_coord_attribs++;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (G_UNLIKELY (layers_state->options.flags))
|
||||
{
|
||||
/* If we haven't already created a derived pipeline... */
|
||||
if (!copy)
|
||||
{
|
||||
copy = cogl_pipeline_copy (pipeline);
|
||||
pipeline = copy;
|
||||
}
|
||||
_cogl_pipeline_apply_overrides (pipeline, &layers_state->options);
|
||||
|
||||
/* TODO:
|
||||
* overrides = cogl_pipeline_get_data (pipeline,
|
||||
* last_overrides_key);
|
||||
* if (overrides)
|
||||
* {
|
||||
* age = cogl_pipeline_get_age (pipeline);
|
||||
* XXX: actually we also need to check for legacy_state
|
||||
* and blending overrides for use of glColorPointer...
|
||||
* if (overrides->ags != age ||
|
||||
* memcmp (&overrides->options, &options,
|
||||
* sizeof (options) != 0)
|
||||
* {
|
||||
* cogl_object_unref (overrides->weak_pipeline);
|
||||
* g_slice_free (Overrides, overrides);
|
||||
* overrides = NULL;
|
||||
* }
|
||||
* }
|
||||
* if (!overrides)
|
||||
* {
|
||||
* overrides = g_slice_new (Overrides);
|
||||
* overrides->weak_pipeline =
|
||||
* cogl_pipeline_weak_copy (pipeline);
|
||||
* _cogl_pipeline_apply_overrides (overrides->weak_pipeline,
|
||||
* &options);
|
||||
*
|
||||
* cogl_pipeline_set_data (pipeline, last_overrides_key,
|
||||
* weak_overrides,
|
||||
* free_overrides_cb,
|
||||
* NULL);
|
||||
* }
|
||||
* pipeline = overrides->weak_pipeline;
|
||||
*/
|
||||
}
|
||||
|
||||
_cogl_pipeline_flush_gl_state (pipeline,
|
||||
framebuffer,
|
||||
skip_gl_color,
|
||||
n_tex_coord_attribs);
|
||||
|
||||
_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);
|
||||
|
||||
/* Bind the attribute pointers. We need to do this after the
|
||||
* pipeline is flushed because when using GLSL that is the only
|
||||
* point when we can determine the attribute locations */
|
||||
|
||||
for (i = 0; i < n_attributes; i++)
|
||||
{
|
||||
CoglAttribute *attribute = attributes[i];
|
||||
CoglAttributeBuffer *attribute_buffer;
|
||||
CoglBuffer *buffer;
|
||||
uint8_t *base;
|
||||
|
||||
attribute_buffer = cogl_attribute_get_buffer (attribute);
|
||||
buffer = COGL_BUFFER (attribute_buffer);
|
||||
base = _cogl_buffer_bind (buffer, COGL_BUFFER_BIND_TARGET_ATTRIBUTE_BUFFER);
|
||||
|
||||
switch (attribute->name_state->name_id)
|
||||
{
|
||||
case COGL_ATTRIBUTE_NAME_ID_COLOR_ARRAY:
|
||||
#ifdef HAVE_COGL_GLES2
|
||||
if (ctx->driver == COGL_DRIVER_GLES2)
|
||||
setup_generic_attribute (ctx, pipeline, attribute, base);
|
||||
else
|
||||
#endif
|
||||
{
|
||||
_cogl_bitmask_set (&ctx->enable_builtin_attributes_tmp,
|
||||
COGL_ATTRIBUTE_NAME_ID_COLOR_ARRAY, TRUE);
|
||||
GE (ctx, glColorPointer (attribute->n_components,
|
||||
attribute->type,
|
||||
attribute->stride,
|
||||
base + attribute->offset));
|
||||
}
|
||||
break;
|
||||
case COGL_ATTRIBUTE_NAME_ID_NORMAL_ARRAY:
|
||||
#ifdef HAVE_COGL_GLES2
|
||||
if (ctx->driver == COGL_DRIVER_GLES2)
|
||||
setup_generic_attribute (ctx, pipeline, attribute, base);
|
||||
else
|
||||
#endif
|
||||
{
|
||||
_cogl_bitmask_set (&ctx->enable_builtin_attributes_tmp,
|
||||
COGL_ATTRIBUTE_NAME_ID_NORMAL_ARRAY, TRUE);
|
||||
GE (ctx, glNormalPointer (attribute->type,
|
||||
attribute->stride,
|
||||
base + attribute->offset));
|
||||
}
|
||||
break;
|
||||
case COGL_ATTRIBUTE_NAME_ID_TEXTURE_COORD_ARRAY:
|
||||
#ifdef HAVE_COGL_GLES2
|
||||
if (ctx->driver == COGL_DRIVER_GLES2)
|
||||
setup_generic_attribute (ctx, pipeline, attribute, base);
|
||||
else
|
||||
#endif
|
||||
{
|
||||
_cogl_bitmask_set (&ctx->enable_texcoord_attributes_tmp,
|
||||
attribute->name_state->texture_unit, TRUE);
|
||||
GE (ctx,
|
||||
glClientActiveTexture (GL_TEXTURE0 +
|
||||
attribute->name_state->texture_unit));
|
||||
GE (ctx, glTexCoordPointer (attribute->n_components,
|
||||
attribute->type,
|
||||
attribute->stride,
|
||||
base + attribute->offset));
|
||||
}
|
||||
break;
|
||||
case COGL_ATTRIBUTE_NAME_ID_POSITION_ARRAY:
|
||||
#ifdef HAVE_COGL_GLES2
|
||||
if (ctx->driver == COGL_DRIVER_GLES2)
|
||||
setup_generic_attribute (ctx, pipeline, attribute, base);
|
||||
else
|
||||
#endif
|
||||
{
|
||||
_cogl_bitmask_set (&ctx->enable_builtin_attributes_tmp,
|
||||
COGL_ATTRIBUTE_NAME_ID_POSITION_ARRAY, TRUE);
|
||||
GE (ctx, glVertexPointer (attribute->n_components,
|
||||
attribute->type,
|
||||
attribute->stride,
|
||||
base + attribute->offset));
|
||||
}
|
||||
break;
|
||||
case COGL_ATTRIBUTE_NAME_ID_CUSTOM_ARRAY:
|
||||
#ifdef COGL_PIPELINE_PROGEND_GLSL
|
||||
if (ctx->driver != COGL_DRIVER_GLES1)
|
||||
setup_generic_attribute (ctx, pipeline, attribute, base);
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
g_warning ("Unrecognised attribute type 0x%08x", attribute->type);
|
||||
}
|
||||
|
||||
_cogl_buffer_unbind (buffer);
|
||||
}
|
||||
|
||||
apply_attribute_enable_updates (ctx, pipeline);
|
||||
|
||||
if (copy)
|
||||
cogl_object_unref (copy);
|
||||
}
|
@ -35,6 +35,7 @@
|
||||
#include "cogl-error-private.h"
|
||||
#include "cogl-framebuffer-gl-private.h"
|
||||
#include "cogl-texture-2d-gl-private.h"
|
||||
#include "cogl-attribute-gl-private.h"
|
||||
|
||||
static CoglBool
|
||||
_cogl_driver_pixel_format_from_gl_internal (CoglContext *context,
|
||||
@ -548,4 +549,5 @@ _cogl_driver_gl =
|
||||
_cogl_texture_2d_gl_generate_mipmap,
|
||||
_cogl_texture_2d_gl_copy_from_bitmap,
|
||||
_cogl_texture_2d_gl_get_data,
|
||||
_cogl_gl_flush_attributes_state,
|
||||
};
|
||||
|
@ -34,6 +34,7 @@
|
||||
#include "cogl-private.h"
|
||||
#include "cogl-framebuffer-gl-private.h"
|
||||
#include "cogl-texture-2d-gl-private.h"
|
||||
#include "cogl-attribute-gl-private.h"
|
||||
|
||||
#ifndef GL_UNSIGNED_INT_24_8
|
||||
#define GL_UNSIGNED_INT_24_8 0x84FA
|
||||
@ -366,4 +367,5 @@ _cogl_driver_gles =
|
||||
_cogl_texture_2d_gl_generate_mipmap,
|
||||
_cogl_texture_2d_gl_copy_from_bitmap,
|
||||
NULL, /* texture_2d_get_data */
|
||||
_cogl_gl_flush_attributes_state,
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user