[Cogl] [PATCH] attribute: Adds support for constant CoglAttributes

Robert Bragg robert at sixbynine.org
Fri Sep 28 07:57:31 PDT 2012


From: Robert Bragg <robert at linux.intel.com>

This makes it possible to create vertex attributes that efficiently
represent constant values without duplicating the constant for every
vertex. This adds the following new constructors for constant
attributes:

  cogl_attribute_new_const_1f
  cogl_attribute_new_const_2fv
  cogl_attribute_new_const_3fv
  cogl_attribute_new_const_4fv
  cogl_attribute_new_const_2f
  cogl_attribute_new_const_3f
  cogl_attribute_new_const_4f
  cogl_attribute_new_const_2x2fv
  cogl_attribute_new_const_3x3fv
  cogl_attribute_new_const_4x4fv
---
 cogl/cogl-attribute-private.h             |   22 ++-
 cogl/cogl-attribute.c                     |  235 ++++++++++++++++++++--
 cogl/cogl-attribute.h                     |  311 +++++++++++++++++++++++++++++
 cogl/driver/gl/cogl-attribute-gl.c        |  275 +++++++++++++++++--------
 cogl/gl-prototypes/cogl-fixed-functions.h |    8 +
 5 files changed, 743 insertions(+), 108 deletions(-)

diff --git a/cogl/cogl-attribute-private.h b/cogl/cogl-attribute-private.h
index 8aeee23..943934f 100644
--- a/cogl/cogl-attribute-private.h
+++ b/cogl/cogl-attribute-private.h
@@ -32,6 +32,7 @@
 #include "cogl-attribute.h"
 #include "cogl-framebuffer.h"
 #include "cogl-pipeline-private.h"
+#include "cogl-boxed-value.h"
 
 typedef enum
 {
@@ -55,14 +56,25 @@ struct _CoglAttribute
 {
   CoglObject _parent;
 
-  CoglAttributeBuffer *attribute_buffer;
   const CoglAttributeNameState *name_state;
-  size_t stride;
-  size_t offset;
-  int n_components;
-  CoglAttributeType type;
   CoglBool normalized;
 
+  CoglBool is_buffered;
+
+  union {
+    struct {
+      CoglAttributeBuffer *attribute_buffer;
+      size_t stride;
+      size_t offset;
+      int n_components;
+      CoglAttributeType type;
+    } buffered;
+    struct {
+      CoglContext *context;
+      CoglBoxedValue boxed;
+    } constant;
+  } d;
+
   int immutable_ref;
 };
 
diff --git a/cogl/cogl-attribute.c b/cogl/cogl-attribute.c
index 8f3fd1e..3982dca 100644
--- a/cogl/cogl-attribute.c
+++ b/cogl/cogl-attribute.c
@@ -167,9 +167,10 @@ cogl_attribute_new (CoglAttributeBuffer *attribute_buffer,
                     CoglAttributeType type)
 {
   CoglAttribute *attribute = g_slice_new (CoglAttribute);
+  CoglBuffer *buffer = COGL_BUFFER (attribute_buffer);
+  CoglContext *ctx = buffer->context;
 
-  /* FIXME: retrieve the context from the buffer */
-  _COGL_GET_CONTEXT (ctx, NULL);
+  attribute->is_buffered = TRUE;
 
   attribute->name_state =
     g_hash_table_lookup (ctx->attribute_name_states_hash, name);
@@ -181,11 +182,13 @@ cogl_attribute_new (CoglAttributeBuffer *attribute_buffer,
         goto error;
       attribute->name_state = name_state;
     }
-  attribute->attribute_buffer = cogl_object_ref (attribute_buffer);
-  attribute->stride = stride;
-  attribute->offset = offset;
-  attribute->n_components = n_components;
-  attribute->type = type;
+
+  attribute->d.buffered.attribute_buffer = cogl_object_ref (attribute_buffer);
+  attribute->d.buffered.stride = stride;
+  attribute->d.buffered.offset = offset;
+  attribute->d.buffered.n_components = n_components;
+  attribute->d.buffered.type = type;
+
   attribute->immutable_ref = 0;
 
   if (attribute->name_state->name_id != COGL_ATTRIBUTE_NAME_ID_CUSTOM_ARRAY)
@@ -224,7 +227,8 @@ cogl_attribute_new (CoglAttributeBuffer *attribute_buffer,
         default:
           g_warn_if_reached ();
         }
-      attribute->normalized = attribute->name_state->normalized_default;
+      attribute->normalized =
+        attribute->name_state->normalized_default;
     }
   else
     attribute->normalized = FALSE;
@@ -236,6 +240,203 @@ error:
   return NULL;
 }
 
+static CoglAttribute *
+_cogl_attribute_new_const (CoglContext *context,
+                           const char *name,
+                           int n_components,
+                           int n_columns,
+                           CoglBool transpose,
+                           const float *value)
+{
+  CoglAttribute *attribute = g_slice_new (CoglAttribute);
+
+  attribute->name_state =
+    g_hash_table_lookup (context->attribute_name_states_hash, name);
+  if (!attribute->name_state)
+    {
+      CoglAttributeNameState *name_state =
+        _cogl_attribute_register_attribute_name (context, name);
+      if (!name_state)
+        goto error;
+      attribute->name_state = name_state;
+    }
+
+  attribute->is_buffered = FALSE;
+  attribute->normalized = FALSE;
+
+  attribute->d.constant.context = cogl_object_ref (context);
+
+  attribute->d.constant.boxed.v.array = NULL;
+
+  if (n_columns == 1)
+    {
+      _cogl_boxed_value_set_float (&attribute->d.constant.boxed,
+                                   n_components,
+                                   1,
+                                   value);
+    }
+  else
+    {
+      /* FIXME: Up until GL[ES] 3 only square matrices were supported
+       * and we don't currently expose non-square matrices in Cogl.
+       */
+      _COGL_RETURN_VAL_IF_FAIL (n_columns == n_components, NULL);
+      _cogl_boxed_value_set_matrix (&attribute->d.constant.boxed,
+                                    n_columns,
+                                    1,
+                                    transpose,
+                                    value);
+    }
+
+  return _cogl_attribute_object_new (attribute);
+
+error:
+  _cogl_attribute_free (attribute);
+  return NULL;
+}
+
+CoglAttribute *
+cogl_attribute_new_const_1f (CoglContext *context,
+                             const char *name,
+                             float value)
+{
+  return _cogl_attribute_new_const (context,
+                                    name,
+                                    1, /* n_components */
+                                    1, /* 1 column vector */
+                                    FALSE, /* no transpose */
+                                    &value);
+}
+
+CoglAttribute *
+cogl_attribute_new_const_2fv (CoglContext *context,
+                              const char *name,
+                              const float *value)
+{
+  return _cogl_attribute_new_const (context,
+                                    name,
+                                    2, /* n_components */
+                                    1, /* 1 column vector */
+                                    FALSE, /* no transpose */
+                                    value);
+}
+
+CoglAttribute *
+cogl_attribute_new_const_3fv (CoglContext *context,
+                              const char *name,
+                              const float *value)
+{
+  return _cogl_attribute_new_const (context,
+                                    name,
+                                    3, /* n_components */
+                                    1, /* 1 column vector */
+                                    FALSE, /* no transpose */
+                                    value);
+}
+
+CoglAttribute *
+cogl_attribute_new_const_4fv (CoglContext *context,
+                              const char *name,
+                              const float *value)
+{
+  return _cogl_attribute_new_const (context,
+                                    name,
+                                    4, /* n_components */
+                                    1, /* 1 column vector */
+                                    FALSE, /* no transpose */
+                                    value);
+}
+
+CoglAttribute *
+cogl_attribute_new_const_2f (CoglContext *context,
+                             const char *name,
+                             float component0,
+                             float component1)
+{
+  float vec2[2] = { component0, component1 };
+  return _cogl_attribute_new_const (context,
+                                    name,
+                                    2, /* n_components */
+                                    1, /* 1 column vector */
+                                    FALSE, /* no transpose */
+                                    vec2);
+}
+
+CoglAttribute *
+cogl_attribute_new_const_3f (CoglContext *context,
+                             const char *name,
+                             float component0,
+                             float component1,
+                             float component2)
+{
+  float vec3[3] = { component0, component1, component2 };
+  return _cogl_attribute_new_const (context,
+                                    name,
+                                    3, /* n_components */
+                                    1, /* 1 column vector */
+                                    FALSE, /* no transpose */
+                                    vec3);
+}
+
+CoglAttribute *
+cogl_attribute_new_const_4f (CoglContext *context,
+                             const char *name,
+                             float component0,
+                             float component1,
+                             float component2,
+                             float component3)
+{
+  float vec4[4] = { component0, component1, component2, component3 };
+  return _cogl_attribute_new_const (context,
+                                    name,
+                                    4, /* n_components */
+                                    1, /* 1 column vector */
+                                    FALSE, /* no transpose */
+                                    vec4);
+}
+
+CoglAttribute *
+cogl_attribute_new_const_2x2fv (CoglContext *context,
+                                const char *name,
+                                const float *matrix2x2,
+                                CoglBool transpose)
+{
+  return _cogl_attribute_new_const (context,
+                                    name,
+                                    2, /* n_components */
+                                    2, /* 1 column vector */
+                                    FALSE, /* no transpose */
+                                    matrix2x2);
+}
+
+CoglAttribute *
+cogl_attribute_new_const_3x3fv (CoglContext *context,
+                                const char *name,
+                                const float *matrix3x3,
+                                CoglBool transpose)
+{
+  return _cogl_attribute_new_const (context,
+                                    name,
+                                    3, /* n_components */
+                                    3, /* 1 column vector */
+                                    FALSE, /* no transpose */
+                                    matrix3x3);
+}
+
+CoglAttribute *
+cogl_attribute_new_const_4x4fv (CoglContext *context,
+                                const char *name,
+                                const float *matrix4x4,
+                                CoglBool transpose)
+{
+  return _cogl_attribute_new_const (context,
+                                    name,
+                                    4, /* n_components */
+                                    4, /* 1 column vector */
+                                    FALSE, /* no transpose */
+                                    matrix4x4);
+}
+
 CoglBool
 cogl_attribute_get_normalized (CoglAttribute *attribute)
 {
@@ -272,8 +473,9 @@ CoglAttributeBuffer *
 cogl_attribute_get_buffer (CoglAttribute *attribute)
 {
   _COGL_RETURN_VAL_IF_FAIL (cogl_is_attribute (attribute), NULL);
+  _COGL_RETURN_VAL_IF_FAIL (attribute->is_buffered, NULL);
 
-  return attribute->attribute_buffer;
+  return attribute->d.buffered.attribute_buffer;
 }
 
 void
@@ -281,40 +483,45 @@ cogl_attribute_set_buffer (CoglAttribute *attribute,
                            CoglAttributeBuffer *attribute_buffer)
 {
   _COGL_RETURN_IF_FAIL (cogl_is_attribute (attribute));
+  _COGL_RETURN_IF_FAIL (attribute->is_buffered);
 
   if (G_UNLIKELY (attribute->immutable_ref))
     warn_about_midscene_changes ();
 
   cogl_object_ref (attribute_buffer);
 
-  cogl_object_unref (attribute->attribute_buffer);
-  attribute->attribute_buffer = attribute_buffer;
+  cogl_object_unref (attribute->d.buffered.attribute_buffer);
+  attribute->d.buffered.attribute_buffer = attribute_buffer;
 }
 
 CoglAttribute *
 _cogl_attribute_immutable_ref (CoglAttribute *attribute)
 {
+  CoglBuffer *buffer = COGL_BUFFER (attribute->d.buffered.attribute_buffer);
+
   _COGL_RETURN_VAL_IF_FAIL (cogl_is_attribute (attribute), NULL);
 
   attribute->immutable_ref++;
-  _cogl_buffer_immutable_ref (COGL_BUFFER (attribute->attribute_buffer));
+  _cogl_buffer_immutable_ref (buffer);
   return attribute;
 }
 
 void
 _cogl_attribute_immutable_unref (CoglAttribute *attribute)
 {
+  CoglBuffer *buffer = COGL_BUFFER (attribute->d.buffered.attribute_buffer);
+
   _COGL_RETURN_IF_FAIL (cogl_is_attribute (attribute));
   _COGL_RETURN_IF_FAIL (attribute->immutable_ref > 0);
 
   attribute->immutable_ref--;
-  _cogl_buffer_immutable_unref (COGL_BUFFER (attribute->attribute_buffer));
+  _cogl_buffer_immutable_unref (buffer);
 }
 
 static void
 _cogl_attribute_free (CoglAttribute *attribute)
 {
-  cogl_object_unref (attribute->attribute_buffer);
+  cogl_object_unref (attribute->d.buffered.attribute_buffer);
 
   g_slice_free (CoglAttribute, attribute);
 }
diff --git a/cogl/cogl-attribute.h b/cogl/cogl-attribute.h
index 60ffaba..a034d45 100644
--- a/cogl/cogl-attribute.h
+++ b/cogl/cogl-attribute.h
@@ -142,6 +142,317 @@ cogl_attribute_new (CoglAttributeBuffer *attribute_buffer,
                     CoglAttributeType type);
 
 /**
+ * cogl_attribute_new_const_1f:
+ * @context: A #CoglContext
+ * @name: The name of the attribute (used to reference it from GLSL)
+ * @value: The constant value for the attribute
+ *
+ * Creates a new, single component, attribute whose value remains
+ * constant across all the vertices of a primitive without needing to
+ * duplicate the value for each vertex.
+ *
+ * The constant @value is a single precision floating point scalar
+ * which should have a corresponding declaration in GLSL code like:
+ *
+ * [|
+ * varying float name;
+ * |]
+ *
+ * Returns: A newly allocated #CoglAttribute representing the given
+ *          constant @value.
+ */
+CoglAttribute *
+cogl_attribute_new_const_1f (CoglContext *context,
+                             const char *name,
+                             float value);
+
+/**
+ * cogl_attribute_new_const_2f:
+ * @context: A #CoglContext
+ * @name: The name of the attribute (used to reference it from GLSL)
+ * @constant0: The first component of a 2 component vector
+ * @constant1: The second component of a 2 component vector
+ *
+ * Creates a new, 2 component, attribute whose value remains
+ * constant across all the vertices of a primitive without needing to
+ * duplicate the value for each vertex.
+ *
+ * The constants (@component0, @component1) represent a 2 component
+ * float vector which should have a corresponding declaration in GLSL
+ * code like:
+ *
+ * [|
+ * varying vec2 name;
+ * |]
+ *
+ * Returns: A newly allocated #CoglAttribute representing the given
+ *          constant vector.
+ */
+CoglAttribute *
+cogl_attribute_new_const_2f (CoglContext *context,
+                             const char *name,
+                             float component0,
+                             float component1);
+
+/**
+ * cogl_attribute_new_const_3f:
+ * @context: A #CoglContext
+ * @name: The name of the attribute (used to reference it from GLSL)
+ * @constant0: The first component of a 3 component vector
+ * @constant1: The second component of a 3 component vector
+ * @constant2: The third component of a 3 component vector
+ *
+ * Creates a new, 3 component, attribute whose value remains
+ * constant across all the vertices of a primitive without needing to
+ * duplicate the value for each vertex.
+ *
+ * The constants (@component0, @component1, @component2) represent a 3
+ * component float vector which should have a corresponding
+ * declaration in GLSL code like:
+ *
+ * [|
+ * varying vec3 name;
+ * |]
+ *
+ * unless the built in name "cogl_normal_in" is being used where no
+ * explicit GLSL declaration need be made.
+ *
+ * Returns: A newly allocated #CoglAttribute representing the given
+ *          constant vector.
+ */
+CoglAttribute *
+cogl_attribute_new_const_3f (CoglContext *context,
+                             const char *name,
+                             float component0,
+                             float component1,
+                             float component2);
+
+/**
+ * cogl_attribute_new_const_4f:
+ * @context: A #CoglContext
+ * @name: The name of the attribute (used to reference it from GLSL)
+ * @constant0: The first component of a 4 component vector
+ * @constant1: The second component of a 4 component vector
+ * @constant2: The third component of a 4 component vector
+ * @constant3: The fourth component of a 4 component vector
+ *
+ * Creates a new, 4 component, attribute whose value remains
+ * constant across all the vertices of a primitive without needing to
+ * duplicate the value for each vertex.
+ *
+ * The constants (@component0, @component1, @component2, @constant3)
+ * represent a 4 component float vector which should have a
+ * corresponding declaration in GLSL code like:
+ *
+ * [|
+ * varying vec4 name;
+ * |]
+ *
+ * unless one of the built in names "cogl_color_in",
+ * "cogl_tex_coord0_in or "cogl_tex_coord1_in" etc is being used where
+ * no explicit GLSL declaration need be made.
+ *
+ * Returns: A newly allocated #CoglAttribute representing the given
+ *          constant vector.
+ */
+CoglAttribute *
+cogl_attribute_new_const_4f (CoglContext *context,
+                             const char *name,
+                             float component0,
+                             float component1,
+                             float component2,
+                             float component3);
+
+/**
+ * cogl_attribute_new_const_2fv:
+ * @context: A #CoglContext
+ * @name: The name of the attribute (used to reference it from GLSL)
+ * @value: A pointer to a 2 component float vector
+ *
+ * Creates a new, 2 component, attribute whose value remains
+ * constant across all the vertices of a primitive without needing to
+ * duplicate the value for each vertex.
+ *
+ * The constants (value[0], value[1]) represent a 2 component float
+ * vector which should have a corresponding declaration in GLSL code
+ * like:
+ *
+ * [|
+ * varying vec2 name;
+ * |]
+ *
+ * Returns: A newly allocated #CoglAttribute representing the given
+ *          constant vector.
+ */
+CoglAttribute *
+cogl_attribute_new_const_2fv (CoglContext *context,
+                              const char *name,
+                              const float *value);
+
+/**
+ * cogl_attribute_new_const_3fv:
+ * @context: A #CoglContext
+ * @name: The name of the attribute (used to reference it from GLSL)
+ * @value: A pointer to a 3 component float vector
+ *
+ * Creates a new, 3 component, attribute whose value remains
+ * constant across all the vertices of a primitive without needing to
+ * duplicate the value for each vertex.
+ *
+ * The constants (value[0], value[1], value[2]) represent a 3
+ * component float vector which should have a corresponding
+ * declaration in GLSL code like:
+ *
+ * [|
+ * varying vec3 name;
+ * |]
+ *
+ * unless the built in name "cogl_normal_in" is being used where no
+ * explicit GLSL declaration need be made.
+ *
+ * Returns: A newly allocated #CoglAttribute representing the given
+ *          constant vector.
+ */
+CoglAttribute *
+cogl_attribute_new_const_3fv (CoglContext *context,
+                              const char *name,
+                              const float *value);
+
+/**
+ * cogl_attribute_new_const_4fv:
+ * @context: A #CoglContext
+ * @name: The name of the attribute (used to reference it from GLSL)
+ * @value: A pointer to a 4 component float vector
+ *
+ * Creates a new, 4 component, attribute whose value remains
+ * constant across all the vertices of a primitive without needing to
+ * duplicate the value for each vertex.
+ *
+ * The constants (value[0], value[1], value[2], value[3]) represent a
+ * 4 component float vector which should have a corresponding
+ * declaration in GLSL code like:
+ *
+ * [|
+ * varying vec4 name;
+ * |]
+ *
+ * unless one of the built in names "cogl_color_in",
+ * "cogl_tex_coord0_in or "cogl_tex_coord1_in" etc is being used where
+ * no explicit GLSL declaration need be made.
+ *
+ * Returns: A newly allocated #CoglAttribute representing the given
+ *          constant vector.
+ */
+CoglAttribute *
+cogl_attribute_new_const_4fv (CoglContext *context,
+                              const char *name,
+                              const float *value);
+
+/**
+ * cogl_attribute_new_const_2x2fv:
+ * @context: A #CoglContext
+ * @name: The name of the attribute (used to reference it from GLSL)
+ * @matrix2x2: A pointer to a 2 by 2 matrix
+ * @transpose: Whether the matrix should be transposed on upload or
+ *             not
+ *
+ * Creates a new matrix attribute whose value remains constant
+ * across all the vertices of a primitive without needing to duplicate
+ * the value for each vertex.
+ *
+ * @matrix2x2 represent a square 2 by 2 matrix specified in
+ * column-major order (each pair of consecutive numbers represents a
+ * column) which should have a corresponding declaration in GLSL code
+ * like:
+ *
+ * [|
+ * varying mat2 name;
+ * |]
+ *
+ * If @transpose is %TRUE then all matrix components are rotated
+ * around the diagonal of the matrix such that the first column
+ * becomes the first row and the second column becomes the second row.
+ *
+ * Returns: A newly allocated #CoglAttribute representing the given
+ *          constant matrix.
+ */
+CoglAttribute *
+cogl_attribute_new_const_2x2fv (CoglContext *context,
+                                const char *name,
+                                const float *matrix2x2,
+                                CoglBool transpose);
+
+/**
+ * cogl_attribute_new_const_3x3fv:
+ * @context: A #CoglContext
+ * @name: The name of the attribute (used to reference it from GLSL)
+ * @matrix3x3: A pointer to a 3 by 3 matrix
+ * @transpose: Whether the matrix should be transposed on upload or
+ *             not
+ *
+ * Creates a new matrix attribute whose value remains constant
+ * across all the vertices of a primitive without needing to duplicate
+ * the value for each vertex.
+ *
+ * @matrix3x3 represent a square 3 by 3 matrix specified in
+ * column-major order (each triple of consecutive numbers represents a
+ * column) which should have a corresponding declaration in GLSL code
+ * like:
+ *
+ * [|
+ * varying mat3 name;
+ * |]
+ *
+ * If @transpose is %TRUE then all matrix components are rotated
+ * around the diagonal of the matrix such that the first column
+ * becomes the first row and the second column becomes the second row
+ * etc.
+ *
+ * Returns: A newly allocated #CoglAttribute representing the given
+ *          constant matrix.
+ */
+CoglAttribute *
+cogl_attribute_new_const_3x3fv (CoglContext *context,
+                                const char *name,
+                                const float *matrix3x3,
+                                CoglBool transpose);
+
+/**
+ * cogl_attribute_new_const_4x4fv:
+ * @context: A #CoglContext
+ * @name: The name of the attribute (used to reference it from GLSL)
+ * @matrix4x4: A pointer to a 4 by 4 matrix
+ * @transpose: Whether the matrix should be transposed on upload or
+ *             not
+ *
+ * Creates a new matrix attribute whose value remains constant
+ * across all the vertices of a primitive without needing to duplicate
+ * the value for each vertex.
+ *
+ * @matrix4x4 represent a square 4 by 4 matrix specified in
+ * column-major order (each 4-tuple of consecutive numbers represents a
+ * column) which should have a corresponding declaration in GLSL code
+ * like:
+ *
+ * [|
+ * varying mat4 name;
+ * |]
+ *
+ * If @transpose is %TRUE then all matrix components are rotated
+ * around the diagonal of the matrix such that the first column
+ * becomes the first row and the second column becomes the second row
+ * etc.
+ *
+ * Returns: A newly allocated #CoglAttribute representing the given
+ *          constant matrix.
+ */
+CoglAttribute *
+cogl_attribute_new_const_4x4fv (CoglContext *context,
+                                const char *name,
+                                const float *matrix4x4,
+                                CoglBool transpose);
+
+/**
  * cogl_attribute_set_normalized:
  * @attribute: A #CoglAttribute
  * @normalized: The new value for the normalized property.
diff --git a/cogl/driver/gl/cogl-attribute-gl.c b/cogl/driver/gl/cogl-attribute-gl.c
index 34a4499..c85b179 100644
--- a/cogl/driver/gl/cogl-attribute-gl.c
+++ b/cogl/driver/gl/cogl-attribute-gl.c
@@ -152,30 +152,188 @@ foreach_changed_bit_and_save (CoglContext *context,
 #ifdef COGL_PIPELINE_PROGEND_GLSL
 
 static void
-setup_generic_attribute (CoglContext *context,
-                         CoglPipeline *pipeline,
-                         CoglAttribute *attribute,
-                         uint8_t *base)
+setup_generic_buffered_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)
+
+  if (attrib_location == -1)
+    return;
+
+  GE( context, glVertexAttribPointer (attrib_location,
+                                      attribute->d.buffered.n_components,
+                                      attribute->d.buffered.type,
+                                      attribute->normalized,
+                                      attribute->d.buffered.stride,
+                                      base + attribute->d.buffered.offset) );
+  _cogl_bitmask_set (&context->enable_custom_attributes_tmp,
+                     attrib_location, TRUE);
+}
+
+static void
+setup_generic_const_attribute (CoglContext *context,
+                               CoglPipeline *pipeline,
+                               CoglAttribute *attribute)
+{
+  int name_index = attribute->name_state->name_index;
+  int attrib_location =
+    _cogl_pipeline_progend_glsl_get_attrib_location (pipeline, name_index);
+  int columns;
+  int i;
+
+  if (attrib_location == -1)
+    return;
+
+  if (attribute->d.constant.boxed.type == COGL_BOXED_MATRIX)
+    columns = attribute->d.constant.boxed.size;
+  else
+    columns = 1;
+
+  /* Note: it's ok to access a COGL_BOXED_FLOAT as a matrix with only
+   * one column... */
+
+  switch (attribute->d.constant.boxed.size)
     {
-      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);
+    case 1:
+      GE( context, glVertexAttrib1fv (attrib_location,
+                                      attribute->d.constant.boxed.v.matrix));
+      break;
+    case 2:
+      for (i = 0; i < columns; i++)
+        GE( context, glVertexAttrib2fv (attrib_location + i,
+                                        attribute->d.constant.boxed.v.matrix));
+      break;
+    case 3:
+      for (i = 0; i < columns; i++)
+        GE( context, glVertexAttrib3fv (attrib_location + i,
+                                        attribute->d.constant.boxed.v.matrix));
+      break;
+    case 4:
+      for (i = 0; i < columns; i++)
+        GE( context, glVertexAttrib4fv (attrib_location + i,
+                                        attribute->d.constant.boxed.v.matrix));
+      break;
+    default:
+      g_warn_if_reached ();
     }
 }
 
 #endif /* COGL_PIPELINE_PROGEND_GLSL */
 
 static void
+setup_legacy_buffered_attribute (CoglContext *ctx,
+                                 CoglPipeline *pipeline,
+                                 CoglAttribute *attribute,
+                                 uint8_t *base)
+{
+  switch (attribute->name_state->name_id)
+    {
+    case COGL_ATTRIBUTE_NAME_ID_COLOR_ARRAY:
+      _cogl_bitmask_set (&ctx->enable_builtin_attributes_tmp,
+                         COGL_ATTRIBUTE_NAME_ID_COLOR_ARRAY, TRUE);
+      GE (ctx, glColorPointer (attribute->d.buffered.n_components,
+                               attribute->d.buffered.type,
+                               attribute->d.buffered.stride,
+                               base + attribute->d.buffered.offset));
+      break;
+    case COGL_ATTRIBUTE_NAME_ID_NORMAL_ARRAY:
+      _cogl_bitmask_set (&ctx->enable_builtin_attributes_tmp,
+                         COGL_ATTRIBUTE_NAME_ID_NORMAL_ARRAY, TRUE);
+      GE (ctx, glNormalPointer (attribute->d.buffered.type,
+                                attribute->d.buffered.stride,
+                                base + attribute->d.buffered.offset));
+      break;
+    case COGL_ATTRIBUTE_NAME_ID_TEXTURE_COORD_ARRAY:
+      {
+        int layer_number = attribute->name_state->layer_number;
+        CoglPipelineLayer *layer =
+          _cogl_pipeline_get_layer (pipeline, layer_number);
+        int unit = _cogl_pipeline_layer_get_unit_index (layer);
+
+        _cogl_bitmask_set (&ctx->enable_texcoord_attributes_tmp, unit, TRUE);
+
+        GE (ctx, glClientActiveTexture (GL_TEXTURE0 + unit));
+        GE (ctx, glTexCoordPointer (attribute->d.buffered.n_components,
+                                    attribute->d.buffered.type,
+                                    attribute->d.buffered.stride,
+                                    base + attribute->d.buffered.offset));
+        break;
+      }
+    case COGL_ATTRIBUTE_NAME_ID_POSITION_ARRAY:
+      _cogl_bitmask_set (&ctx->enable_builtin_attributes_tmp,
+                         COGL_ATTRIBUTE_NAME_ID_POSITION_ARRAY, TRUE);
+      GE (ctx, glVertexPointer (attribute->d.buffered.n_components,
+                                attribute->d.buffered.type,
+                                attribute->d.buffered.stride,
+                                base + attribute->d.buffered.offset));
+      break;
+    case COGL_ATTRIBUTE_NAME_ID_CUSTOM_ARRAY:
+#ifdef COGL_PIPELINE_PROGEND_GLSL
+      if (ctx->driver != COGL_DRIVER_GLES1)
+        setup_generic_buffered_attribute (ctx, pipeline, attribute, base);
+#endif
+      break;
+    default:
+      g_warn_if_reached ();
+    }
+}
+
+static void
+setup_legacy_const_attribute (CoglContext *ctx,
+                              CoglPipeline *pipeline,
+                              CoglAttribute *attribute)
+{
+#ifdef COGL_PIPELINE_PROGEND_GLSL
+  if (attribute->name_state->name_id == COGL_ATTRIBUTE_NAME_ID_CUSTOM_ARRAY)
+    {
+      if (ctx->driver != COGL_DRIVER_GLES1)
+        setup_generic_const_attribute (ctx, pipeline, attribute);
+    }
+  else
+#endif
+    {
+      float vector[4] = { 0, 0, 0, 1 };
+      float *boxed = attribute->d.constant.boxed.v.float_value;
+      int n_components = attribute->d.constant.boxed.size;
+      int i;
+
+      for (i = 0; i < n_components; i++)
+        vector[i] = boxed[i];
+
+      switch (attribute->name_state->name_id)
+        {
+        case COGL_ATTRIBUTE_NAME_ID_COLOR_ARRAY:
+          GE (ctx, glColor4f (vector[0], vector[1], vector[2], vector[3]));
+          break;
+        case COGL_ATTRIBUTE_NAME_ID_NORMAL_ARRAY:
+          GE (ctx, glNormal3f (vector[0], vector[1], vector[2]));
+          break;
+        case COGL_ATTRIBUTE_NAME_ID_TEXTURE_COORD_ARRAY:
+          {
+            int layer_number = attribute->name_state->layer_number;
+            CoglPipelineLayer *layer =
+              _cogl_pipeline_get_layer (pipeline, layer_number);
+            int unit = _cogl_pipeline_layer_get_unit_index (layer);
+
+            GE (ctx, glClientActiveTexture (GL_TEXTURE0 + unit));
+
+            GE (ctx, glMultiTexCoord4f (vector[0], vector[1], vector[2], vector[3]));
+            break;
+          }
+        case COGL_ATTRIBUTE_NAME_ID_POSITION_ARRAY:
+          GE (ctx, glVertex4f (vector[0], vector[1], vector[2], vector[3]));
+          break;
+        default:
+          g_warn_if_reached ();
+        }
+    }
+}
+
+static void
 apply_attribute_enable_updates (CoglContext *context,
                                 CoglPipeline *pipeline)
 {
@@ -305,88 +463,27 @@ _cogl_gl_flush_attributes_state (CoglFramebuffer *framebuffer,
       CoglBuffer *buffer;
       uint8_t *base;
 
-      attribute_buffer = cogl_attribute_get_buffer (attribute);
-      buffer = COGL_BUFFER (attribute_buffer);
-      base = _cogl_buffer_gl_bind (buffer, COGL_BUFFER_BIND_TARGET_ATTRIBUTE_BUFFER);
-
-      switch (attribute->name_state->name_id)
+      if (attribute->is_buffered)
         {
-        case COGL_ATTRIBUTE_NAME_ID_COLOR_ARRAY:
-#ifdef COGL_PIPELINE_PROGEND_GLSL
-          if (pipeline->progend == COGL_PIPELINE_PROGEND_GLSL)
-            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 COGL_PIPELINE_PROGEND_GLSL
-          if (pipeline->progend == COGL_PIPELINE_PROGEND_GLSL)
-            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 COGL_PIPELINE_PROGEND_GLSL
+          attribute_buffer = cogl_attribute_get_buffer (attribute);
+          buffer = COGL_BUFFER (attribute_buffer);
+          base = _cogl_buffer_gl_bind (buffer,
+                                       COGL_BUFFER_BIND_TARGET_ATTRIBUTE_BUFFER);
+
           if (pipeline->progend == COGL_PIPELINE_PROGEND_GLSL)
-            setup_generic_attribute (ctx, pipeline, attribute, base);
+            setup_generic_buffered_attribute (ctx, pipeline, attribute, base);
           else
-#endif
-            {
-              int layer_number = attribute->name_state->layer_number;
-              CoglPipelineLayer *layer =
-                _cogl_pipeline_get_layer (pipeline, layer_number);
-              int unit = _cogl_pipeline_layer_get_unit_index (layer);
-
-              _cogl_bitmask_set (&ctx->enable_texcoord_attributes_tmp,
-                                 unit, TRUE);
-              GE (ctx, glClientActiveTexture (GL_TEXTURE0 + unit));
-              GE (ctx, glTexCoordPointer (attribute->n_components,
-                                          attribute->type,
-                                          attribute->stride,
-                                          base + attribute->offset));
-            }
-          break;
-        case COGL_ATTRIBUTE_NAME_ID_POSITION_ARRAY:
-#ifdef COGL_PIPELINE_PROGEND_GLSL
+            setup_legacy_buffered_attribute (ctx, pipeline, attribute, base);
+
+          _cogl_buffer_gl_unbind (buffer);
+        }
+      else
+        {
           if (pipeline->progend == COGL_PIPELINE_PROGEND_GLSL)
-            setup_generic_attribute (ctx, pipeline, attribute, base);
+            setup_generic_const_attribute (ctx, pipeline, attribute);
           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 (pipeline->progend == COGL_PIPELINE_PROGEND_GLSL)
-            setup_generic_attribute (ctx, pipeline, attribute, base);
-#endif
-          break;
-        default:
-          g_warning ("Unrecognised attribute type 0x%08x", attribute->type);
+            setup_legacy_const_attribute (ctx, pipeline, attribute);
         }
-
-      _cogl_buffer_gl_unbind (buffer);
     }
 
   apply_attribute_enable_updates (ctx, pipeline);
diff --git a/cogl/gl-prototypes/cogl-fixed-functions.h b/cogl/gl-prototypes/cogl-fixed-functions.h
index 6ac3c92..7e5ab8e 100644
--- a/cogl/gl-prototypes/cogl-fixed-functions.h
+++ b/cogl/gl-prototypes/cogl-fixed-functions.h
@@ -72,6 +72,8 @@ COGL_EXT_FUNCTION (void, glTexEnvfv,
                    (GLenum target, GLenum pname, const GLfloat *params))
 COGL_EXT_FUNCTION (void, glColor4ub,
                    (GLubyte red, GLubyte green, GLubyte blue, GLubyte alpha))
+COGL_EXT_FUNCTION (void, glColor4f,
+                   (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha))
 COGL_EXT_FUNCTION (void, glColorPointer,
                    (GLint size,
                     GLenum type,
@@ -85,8 +87,12 @@ COGL_EXT_FUNCTION (void, glLoadIdentity,
                    (void))
 COGL_EXT_FUNCTION (void, glMatrixMode,
                    (GLenum mode))
+COGL_EXT_FUNCTION (void, glNormal3f,
+                   (GLfloat x, GLfloat y, GLfloat z))
 COGL_EXT_FUNCTION (void, glNormalPointer,
                    (GLenum type, GLsizei stride, const GLvoid *pointer))
+COGL_EXT_FUNCTION (void, glMultiTexCoord4f,
+                   (GLfloat s, GLfloat t, GLfloat r, GLfloat q))
 COGL_EXT_FUNCTION (void, glTexCoordPointer,
                    (GLint size,
                     GLenum type,
@@ -96,6 +102,8 @@ COGL_EXT_FUNCTION (void, glTexEnvi,
                    (GLenum target,
                     GLenum pname,
                     GLint param))
+COGL_EXT_FUNCTION (void, glVertex4f,
+                   (GLfloat x, GLfloat y, GLfloat z, GLfloat w))
 COGL_EXT_FUNCTION (void, glVertexPointer,
                    (GLint size,
                     GLenum type,
-- 
1.7.7.6



More information about the Cogl mailing list