[Cogl] [PATCH] attribute: Split out GL specific code
Robert Bragg
robert at sixbynine.org
Mon Sep 24 07:48:29 PDT 2012
From: Robert Bragg <robert at linux.intel.com>
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
---
cogl/Makefile.am | 2 +
cogl/cogl-attribute-private.h | 9 +-
cogl/cogl-attribute.c | 377 +--------------------------
cogl/cogl-driver.h | 12 +
cogl/driver/gl/cogl-attribute-gl-private.h | 44 +++
cogl/driver/gl/cogl-attribute-gl.c | 398 ++++++++++++++++++++++++++++
cogl/driver/gl/gl/cogl-driver-gl.c | 2 +
cogl/driver/gl/gles/cogl-driver-gles.c | 2 +
8 files changed, 475 insertions(+), 371 deletions(-)
create mode 100644 cogl/driver/gl/cogl-attribute-gl-private.h
create mode 100644 cogl/driver/gl/cogl-attribute-gl.c
diff --git a/cogl/Makefile.am b/cogl/Makefile.am
index 6c43b96..7495446 100644
--- a/cogl/Makefile.am
+++ b/cogl/Makefile.am
@@ -127,6 +127,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 \
diff --git a/cogl/cogl-attribute-private.h b/cogl/cogl-attribute-private.h
index 09b41f4..b4adaa8 100644
--- a/cogl/cogl-attribute-private.h
+++ b/cogl/cogl-attribute-private.h
@@ -31,6 +31,7 @@
#include "cogl-object-private.h"
#include "cogl-attribute.h"
#include "cogl-framebuffer.h"
+#include "cogl-pipeline-private.h"
typedef enum
{
@@ -98,8 +99,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,
diff --git a/cogl/cogl-attribute.c b/cogl/cogl-attribute.c
index 3c4cc33..6e40f54 100644
--- a/cogl/cogl-attribute.c
+++ b/cogl/cogl-attribute.c
@@ -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,195 +414,10 @@ _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;
- */
- }
-
- _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);
-}
-
-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);
+ ctx->driver_vtable->flush_attributes_state (framebuffer,
+ pipeline,
+ &layers_state,
+ flags,
+ attributes,
+ n_attributes);
}
diff --git a/cogl/cogl-driver.h b/cogl/cogl-driver.h
index bfedbff..bea53cd 100644
--- a/cogl/cogl-driver.h
+++ b/cogl/cogl-driver.h
@@ -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 */
diff --git a/cogl/driver/gl/cogl-attribute-gl-private.h b/cogl/driver/gl/cogl-attribute-gl-private.h
new file mode 100644
index 0000000..405e43d
--- /dev/null
+++ b/cogl/driver/gl/cogl-attribute-gl-private.h
@@ -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 at 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_ */
diff --git a/cogl/driver/gl/cogl-attribute-gl.c b/cogl/driver/gl/cogl-attribute-gl.c
new file mode 100644
index 0000000..3391f48
--- /dev/null
+++ b/cogl/driver/gl/cogl-attribute-gl.c
@@ -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 at linux.intel.com>
+ * Robert Bragg <robert at 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);
+}
diff --git a/cogl/driver/gl/gl/cogl-driver-gl.c b/cogl/driver/gl/gl/cogl-driver-gl.c
index 32bd294..c4674e3 100644
--- a/cogl/driver/gl/gl/cogl-driver-gl.c
+++ b/cogl/driver/gl/gl/cogl-driver-gl.c
@@ -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,
@@ -547,4 +548,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,
};
diff --git a/cogl/driver/gl/gles/cogl-driver-gles.c b/cogl/driver/gl/gles/cogl-driver-gles.c
index eb799a9..b5487fb 100644
--- a/cogl/driver/gl/gles/cogl-driver-gles.c
+++ b/cogl/driver/gl/gles/cogl-driver-gles.c
@@ -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
@@ -365,4 +366,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,
};
--
1.7.7.6
More information about the Cogl
mailing list