diff --git a/cogl/cogl-attribute-private.h b/cogl/cogl-attribute-private.h index beb5609b6..d38f4e6cc 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 edcfb83f0..81a75782c 100644 --- a/cogl/cogl-attribute.c +++ b/cogl/cogl-attribute.c @@ -158,6 +158,48 @@ error: return NULL; } +static CoglBool +validate_n_components (const CoglAttributeNameState *name_state, + int n_components) +{ + switch (name_state->name_id) + { + case COGL_ATTRIBUTE_NAME_ID_POSITION_ARRAY: + if (G_UNLIKELY (n_components == 1)) + { + g_critical ("glVertexPointer doesn't allow 1 component vertex " + "positions so we currently only support \"cogl_vertex\" " + "attributes where n_components == 2, 3 or 4"); + return FALSE; + } + break; + case COGL_ATTRIBUTE_NAME_ID_COLOR_ARRAY: + if (G_UNLIKELY (n_components != 3 && n_components != 4)) + { + g_critical ("glColorPointer expects 3 or 4 component colors so we " + "currently only support \"cogl_color\" attributes where " + "n_components == 3 or 4"); + return FALSE; + } + break; + case COGL_ATTRIBUTE_NAME_ID_TEXTURE_COORD_ARRAY: + break; + case COGL_ATTRIBUTE_NAME_ID_NORMAL_ARRAY: + if (G_UNLIKELY (n_components != 3)) + { + g_critical ("glNormalPointer expects 3 component normals so we " + "currently only support \"cogl_normal\" attributes " + "where n_components == 3"); + return FALSE; + } + break; + case COGL_ATTRIBUTE_NAME_ID_CUSTOM_ARRAY: + return TRUE; + } + + return TRUE; +} + CoglAttribute * cogl_attribute_new (CoglAttributeBuffer *attribute_buffer, const char *name, @@ -167,9 +209,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,50 +224,21 @@ 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) { - switch (attribute->name_state->name_id) - { - case COGL_ATTRIBUTE_NAME_ID_POSITION_ARRAY: - if (G_UNLIKELY (n_components == 1)) - { - g_critical ("glVertexPointer doesn't allow 1 component vertex " - "positions so we currently only support \"cogl_vertex\" " - "attributes where n_components == 2, 3 or 4"); - return FALSE; - } - break; - case COGL_ATTRIBUTE_NAME_ID_COLOR_ARRAY: - if (G_UNLIKELY (n_components != 3 && n_components != 4)) - { - g_critical ("glColorPointer expects 3 or 4 component colors so we " - "currently only support \"cogl_color\" attributes where " - "n_components == 3 or 4"); - return FALSE; - } - break; - case COGL_ATTRIBUTE_NAME_ID_TEXTURE_COORD_ARRAY: - break; - case COGL_ATTRIBUTE_NAME_ID_NORMAL_ARRAY: - if (G_UNLIKELY (n_components != 3)) - { - g_critical ("glNormalPointer expects 3 component normals so we " - "currently only support \"cogl_normal\" attributes " - "where n_components == 3"); - return FALSE; - } - break; - default: - g_warn_if_reached (); - } - attribute->normalized = attribute->name_state->normalized_default; + if (!validate_n_components (attribute->name_state, n_components)) + return NULL; + attribute->normalized = + attribute->name_state->normalized_default; } else attribute->normalized = FALSE; @@ -236,6 +250,206 @@ 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; + } + + if (!validate_n_components (attribute->name_state, n_components)) + goto error; + + 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, /* 2 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, /* 3 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, /* 4 column vector */ + FALSE, /* no transpose */ + matrix4x4); +} + CoglBool cogl_attribute_get_normalized (CoglAttribute *attribute) { @@ -272,8 +486,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 +496,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 129d4cea2..580446e87 100644 --- a/cogl/cogl-attribute.h +++ b/cogl/cogl-attribute.h @@ -141,6 +141,317 @@ cogl_attribute_new (CoglAttributeBuffer *attribute_buffer, int components, 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: + * + * [| + * attribute 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: + * + * [| + * attribute 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: + * + * [| + * attribute 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: + * + * [| + * attribute 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: + * + * [| + * attribute 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: + * + * [| + * attribute 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: + * + * [| + * attribute 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: + * + * [| + * attribute 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: + * + * [| + * attribute 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: + * + * [| + * attribute 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 diff --git a/cogl/driver/gl/cogl-attribute-gl.c b/cogl/driver/gl/cogl-attribute-gl.c index ce90e4a3c..9210b954c 100644 --- a/cogl/driver/gl/cogl-attribute-gl.c +++ b/cogl/driver/gl/cogl-attribute-gl.c @@ -152,29 +152,187 @@ 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 - if (pipeline->progend == COGL_PIPELINE_PROGEND_GLSL) - setup_generic_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); + attribute_buffer = cogl_attribute_get_buffer (attribute); + buffer = COGL_BUFFER (attribute_buffer); + base = _cogl_buffer_gl_bind (buffer, + COGL_BUFFER_BIND_TARGET_ATTRIBUTE_BUFFER); - _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 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_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_buffered_attribute (ctx, pipeline, attribute, base); + + _cogl_buffer_gl_unbind (buffer); + } + else + { + if (pipeline->progend == COGL_PIPELINE_PROGEND_GLSL) + setup_generic_const_attribute (ctx, pipeline, attribute); + else + 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 6ac3c92a2..7e5ab8e8a 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,