[cogl/wip/glsl-unified: 4/4] attribute: Adds support for constant CoglAttributes



commit 63cc8c7107393fe5e4ef56260b95eef001ff093b
Author: Robert Bragg <robert linux intel com>
Date:   Mon Aug 6 21:19:27 2012 +0100

    attribute: Adds support for constant CoglAttributes
    
    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             |   24 ++-
 cogl/cogl-attribute.c                     |  245 ++++++++++++++++++++--
 cogl/cogl-attribute.h                     |  325 +++++++++++++++++++++++++++++
 cogl/driver/gl/cogl-attribute-gl.c        |  272 ++++++++++++++++--------
 cogl/gl-prototypes/cogl-fixed-functions.h |    8 +
 5 files changed, 763 insertions(+), 111 deletions(-)
---
diff --git a/cogl/cogl-attribute-private.h b/cogl/cogl-attribute-private.h
index b4adaa8..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
 {
@@ -48,21 +49,32 @@ typedef struct _CoglAttributeNameState
   CoglAttributeNameID name_id;
   int name_index;
   CoglBool normalized_default;
-  int texture_unit;
+  int layer_number;
 } CoglAttributeNameState;
 
 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 6e40f54..ae1805f 100644
--- a/cogl/cogl-attribute.c
+++ b/cogl/cogl-attribute.c
@@ -64,12 +64,12 @@ validate_cogl_attribute_name (const char *name,
                               char **real_attribute_name,
                               CoglAttributeNameID *name_id,
                               CoglBool *normalized,
-                              int *texture_unit)
+                              int *layer_number)
 {
   name = name + 5; /* skip "cogl_" */
 
   *normalized = FALSE;
-  *texture_unit = 0;
+  *layer_number = 0;
 
   if (strcmp (name, "position_in") == 0)
     *name_id = COGL_ATTRIBUTE_NAME_ID_POSITION_ARRAY;
@@ -86,7 +86,7 @@ validate_cogl_attribute_name (const char *name,
   else if (strncmp (name, "tex_coord", strlen ("tex_coord")) == 0)
     {
       char *endptr;
-      *texture_unit = strtoul (name + 9, &endptr, 10);
+      *layer_number = strtoul (name + 9, &endptr, 10);
       if (strcmp (endptr, "_in") != 0)
 	{
 	  g_warning ("Texture coordinate attributes should either be named "
@@ -126,14 +126,14 @@ _cogl_attribute_register_attribute_name (CoglContext *context,
                                          &name_state->name,
                                          &name_state->name_id,
                                          &name_state->normalized_default,
-                                         &name_state->texture_unit))
+                                         &name_state->layer_number))
         goto error;
     }
   else
     {
       name_state->name_id = COGL_ATTRIBUTE_NAME_ID_CUSTOM_ARRAY;
       name_state->normalized_default = FALSE;
-      name_state->texture_unit = 0;
+      name_state->layer_number = 0;
     }
 
   if (name_state->name == NULL)
@@ -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,
+                           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,
+                              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,
+                              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,
+                              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,
+                                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,
+                                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,
+                                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..577f138 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,
+                              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,
+                              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,
+                              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,
+                                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,
+                                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,
+                                float *matrix4x4,
+                                CoglBool transpose);
+
+/**
  * cogl_attribute_set_normalized:
  * @attribute: A #CoglAttribute
  * @normalized: The new value for the normalized property.
@@ -204,6 +515,20 @@ cogl_attribute_set_buffer (CoglAttribute *attribute,
                            CoglAttributeBuffer *attribute_buffer);
 
 /**
+ * cogl_attribute_new_constf:
+ * @context: A #CoglContext
+ * @name: The name of the attribute (used to reference it from GLSL)
+ * @value: A single component float value
+ *
+ * Stability: unstable
+ * Since: 2.0
+ */
+CoglAttribute *
+cogl_attribute_new_const1f (CoglContext *context,
+                            const char *name,
+                            float value);
+
+/**
  * cogl_is_attribute:
  * @object: A #CoglObject
  *
diff --git a/cogl/driver/gl/cogl-attribute-gl.c b/cogl/driver/gl/cogl-attribute-gl.c
index 0c21d12..9c4da9b 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)
 {
@@ -311,85 +469,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
-            {
-              _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 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,



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]