[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