diff --git a/cogl/cogl-attribute-private.h b/cogl/cogl-attribute-private.h index 040784ed3..68ed52d0f 100644 --- a/cogl/cogl-attribute-private.h +++ b/cogl/cogl-attribute-private.h @@ -40,19 +40,26 @@ typedef enum COGL_ATTRIBUTE_NAME_ID_CUSTOM_ARRAY } CoglAttributeNameID; +typedef struct _CoglAttributeNameState +{ + char *name; + CoglAttributeNameID name_id; + int name_index; + gboolean normalized_default; + int texture_unit; +} CoglAttributeNameState; + struct _CoglAttribute { CoglObject _parent; CoglAttributeBuffer *attribute_buffer; - const char *name; - CoglAttributeNameID name_id; + const CoglAttributeNameState *name_state; gsize stride; gsize offset; int n_components; CoglAttributeType type; gboolean normalized; - unsigned int texture_unit; int immutable_ref; }; @@ -71,6 +78,16 @@ typedef enum COGL_DRAW_COLOR_ATTRIBUTE_IS_OPAQUE = 1 << 3 } CoglDrawFlags; +/* During CoglContext initialization we register the "cogl_color_in" + * attribute name so it gets a global name_index of 0. We need to know + * the name_index for "cogl_color_in" in + * _cogl_pipeline_flush_gl_state() */ +#define COGL_ATTRIBUTE_COLOR_NAME_INDEX 0 + +CoglAttributeNameState * +_cogl_attribute_register_attribute_name (CoglContext *context, + const char *name); + CoglAttribute * _cogl_attribute_immutable_ref (CoglAttribute *attribute); diff --git a/cogl/cogl-attribute.c b/cogl/cogl-attribute.c index ad525f6a1..1c73bc9cf 100644 --- a/cogl/cogl-attribute.c +++ b/cogl/cogl-attribute.c @@ -59,80 +59,11 @@ static void _cogl_attribute_free (CoglAttribute *attribute); COGL_OBJECT_DEFINE (Attribute, attribute); -#if 0 -gboolean -validate_gl_attribute (const char *name, - int n_components, - CoglAttributeNameID *name_id, - gboolean *normalized, - unsigned int *texture_unit) -{ - name = name + 3; /* skip past "gl_" */ - - *normalized = FALSE; - *texture_unit = 0; - - if (strcmp (name, "Vertex") == 0) - { - if (G_UNLIKELY (n_components == 1)) - { - g_critical ("glVertexPointer doesn't allow 1 component vertex " - "positions so we currently only support \"gl_Vertex\" " - "attributes where n_components == 2, 3 or 4"); - return FALSE; - } - *name_id = COGL_ATTRIBUTE_NAME_ID_POSITION_ARRAY; - } - else if (strcmp (name, "Color") == 0) - { - if (G_UNLIKELY (n_components != 3 && n_components != 4)) - { - g_critical ("glColorPointer expects 3 or 4 component colors so we " - "currently only support \"gl_Color\" attributes where " - "n_components == 3 or 4"); - return FALSE; - } - *name_id = COGL_ATTRIBUTE_NAME_ID_COLOR_ARRAY; - *normalized = TRUE; - } - else if (strncmp (name, "MultiTexCoord", strlen ("MultiTexCoord")) == 0) - { - if (sscanf (gl_attribute, "MultiTexCoord%u", texture_unit) != 1) - { - g_warning ("gl_MultiTexCoord attributes should include a\n" - "texture unit number, E.g. gl_MultiTexCoord0\n"); - unit = 0; - } - *name_id = COGL_ATTRIBUTE_NAME_ID_TEXTURE_COORD_ARRAY; - } - else if (strncmp (name, "Normal") == 0) - { - if (G_UNLIKELY (n_components != 3)) - { - g_critical ("glNormalPointer expects 3 component normals so we " - "currently only support \"gl_Normal\" attributes where " - "n_components == 3"); - return FALSE; - } - *name_id = COGL_ATTRIBUTE_NAME_ID_NORMAL_ARRAY; - *normalized = TRUE; - } - else - { - g_warning ("Unknown gl_* attribute name gl_%s\n", name); - return FALSE; - } - - return TRUE; -} -#endif - -gboolean -validate_cogl_attribute (const char *name, - int n_components, - CoglAttributeNameID *name_id, - gboolean *normalized, - unsigned int *texture_unit) +static gboolean +validate_cogl_attribute_name (const char *name, + CoglAttributeNameID *name_id, + gboolean *normalized, + int *texture_unit) { name = name + 5; /* skip "cogl_" */ @@ -140,26 +71,11 @@ validate_cogl_attribute (const char *name, *texture_unit = 0; if (strcmp (name, "position_in") == 0) - { - 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; - } - *name_id = COGL_ATTRIBUTE_NAME_ID_POSITION_ARRAY; - } + *name_id = COGL_ATTRIBUTE_NAME_ID_POSITION_ARRAY; else if (strcmp (name, "color_in") == 0) { - 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; - } *name_id = COGL_ATTRIBUTE_NAME_ID_COLOR_ARRAY; + *normalized = TRUE; } else if (strcmp (name, "tex_coord_in") == 0) *name_id = COGL_ATTRIBUTE_NAME_ID_TEXTURE_COORD_ARRAY; @@ -178,13 +94,6 @@ validate_cogl_attribute (const char *name, } else if (strcmp (name, "normal_in") == 0) { - 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; - } *name_id = COGL_ATTRIBUTE_NAME_ID_NORMAL_ARRAY; *normalized = TRUE; } @@ -197,6 +106,49 @@ validate_cogl_attribute (const char *name, return TRUE; } +CoglAttributeNameState * +_cogl_attribute_register_attribute_name (CoglContext *context, + const char *name) +{ + CoglAttributeNameState *name_state = g_new (CoglAttributeNameState, 1); + int name_index = context->n_attribute_names++; + + name_state->name = g_strdup (name); + name_state->name_index = name_index; + if (strncmp (name, "cogl_", 5) == 0) + { + if (!validate_cogl_attribute_name (name, + &name_state->name_id, + &name_state->normalized_default, + &name_state->texture_unit)) + goto error; + } + else + { + name_state->name_id = COGL_ATTRIBUTE_NAME_ID_CUSTOM_ARRAY; + name_state->normalized_default = FALSE; + name_state->texture_unit = 0; + } + + g_hash_table_insert (context->attribute_name_states_hash, + name_state->name, name_state); + + if (G_UNLIKELY (context->attribute_name_index_map == NULL)) + context->attribute_name_index_map = + g_array_new (FALSE, FALSE, sizeof (void *)); + + g_array_set_size (context->attribute_name_index_map, name_index + 1); + + g_array_index (context->attribute_name_index_map, + CoglAttributeNameState *, name_index) = name_state; + + return name_state; + +error: + g_free (name_state); + return NULL; +} + CoglAttribute * cogl_attribute_new (CoglAttributeBuffer *attribute_buffer, const char *name, @@ -206,8 +158,20 @@ cogl_attribute_new (CoglAttributeBuffer *attribute_buffer, CoglAttributeType type) { CoglAttribute *attribute = g_slice_new (CoglAttribute); - gboolean status; + /* FIXME: retrieve the context from the buffer */ + _COGL_GET_CONTEXT (ctx, NULL); + + attribute->name_state = + g_hash_table_lookup (ctx->attribute_name_states_hash, name); + if (!attribute->name_state) + { + CoglAttributeNameState *name_state = + _cogl_attribute_register_attribute_name (ctx, name); + if (!name_state) + goto error; + attribute->name_state = name_state; + } attribute->attribute_buffer = cogl_object_ref (attribute_buffer); attribute->stride = stride; attribute->offset = offset; @@ -215,71 +179,52 @@ cogl_attribute_new (CoglAttributeBuffer *attribute_buffer, attribute->type = type; attribute->immutable_ref = 0; - if (strncmp (name, "cogl_", 5) == 0) + if (attribute->name_state->name_id != COGL_ATTRIBUTE_NAME_ID_CUSTOM_ARRAY) { - const char *common_tex_coord_names[8] = { - "cogl_tex_coord0_in", - "cogl_tex_coord1_in", - "cogl_tex_coord2_in", - "cogl_tex_coord3_in", - "cogl_tex_coord4_in", - "cogl_tex_coord5_in", - "cogl_tex_coord6_in", - "cogl_tex_coord7_in" - }; - status = validate_cogl_attribute (name, - n_components, - &attribute->name_id, - &attribute->normalized, - &attribute->texture_unit); - - /* Avoid even the cost of g_intern_string() for the very common case - * attribute names...*/ - switch (attribute->name_id) + switch (attribute->name_state->name_id) { case COGL_ATTRIBUTE_NAME_ID_POSITION_ARRAY: - attribute->name = "cogl_position_in"; + 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: - attribute->name = "cogl_color_in"; + 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: - if (attribute->texture_unit < 8) - attribute->name = common_tex_coord_names[attribute->texture_unit]; - else - attribute->name = g_intern_string (name); break; case COGL_ATTRIBUTE_NAME_ID_NORMAL_ARRAY: - attribute->name = "cogl_normal_in"; + 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 0 - else if (strncmp (name, "gl_", 3) == 0) - status = validate_gl_attribute (attribute->name, - n_components, - &attribute->name_id, - &attribute->normalized, - &attribute->texture_unit); -#endif else - { - attribute->name = g_intern_string (name); - attribute->name_id = COGL_ATTRIBUTE_NAME_ID_CUSTOM_ARRAY; - attribute->normalized = FALSE; - attribute->texture_unit = 0; - status = TRUE; - } - - if (!status) - { - _cogl_attribute_free (attribute); - return NULL; - } + attribute->normalized = FALSE; return _cogl_attribute_object_new (attribute); + +error: + _cogl_attribute_free (attribute); + return NULL; } gboolean @@ -428,87 +373,216 @@ validated: return status; } -static gboolean -toggle_enabled_cb (int bit_num, void *user_data) +typedef struct _ForeachChangedBitState { - const CoglBitmask *new_values = user_data; - gboolean enabled = _cogl_bitmask_get (new_values, bit_num); + CoglContext *context; + const CoglBitmask *new_bits; + CoglPipeline *pipeline; +} ForeachChangedBitState; - _COGL_GET_CONTEXT (ctx, FALSE); +static gboolean +toggle_builtin_attribute_enabled_cb (int bit_num, void *user_data) +{ + ForeachChangedBitState *state = user_data; + CoglContext *context = state->context; + + _COGL_RETURN_VAL_IF_FAIL (context->driver == COGL_DRIVER_GL || + context->driver == COGL_DRIVER_GLES1, + FALSE); - if (ctx->driver == COGL_DRIVER_GLES2) - { - if (enabled) - GE( ctx, glEnableVertexAttribArray (bit_num) ); - else - GE( ctx, glDisableVertexAttribArray (bit_num) ); - } #if defined (HAVE_COGL_GL) || defined (HAVE_COGL_GLES) - else - { - GE( ctx, glClientActiveTexture (GL_TEXTURE0 + bit_num) ); + { + gboolean enabled = _cogl_bitmask_get (state->new_bits, bit_num); + GLenum cap; - if (enabled) - GE( ctx, glEnableClientState (GL_TEXTURE_COORD_ARRAY) ); - else - GE( ctx, glDisableClientState (GL_TEXTURE_COORD_ARRAY) ); - } + switch (bit_num) + { + case COGL_ATTRIBUTE_NAME_ID_COLOR_ARRAY: + cap = GL_COLOR_ARRAY; + break; + case COGL_ATTRIBUTE_NAME_ID_POSITION_ARRAY: + cap = GL_VERTEX_ARRAY; + break; + case COGL_ATTRIBUTE_NAME_ID_NORMAL_ARRAY: + cap = GL_NORMAL_ARRAY; + break; + } + if (enabled) + GE (context, glEnableClientState (cap)); + else + GE (context, glDisableClientState (cap)); + } #endif return TRUE; } -static void -set_enabled_arrays (CoglBitmask *value_cache, - const CoglBitmask *new_values) +static gboolean +toggle_texcood_attribute_enabled_cb (int bit_num, void *user_data) { - _COGL_GET_CONTEXT (ctx, NO_RETVAL); + ForeachChangedBitState *state = user_data; + CoglContext *context = state->context; - /* Get the list of bits that are different */ - _cogl_bitmask_clear_all (&ctx->arrays_to_change); - _cogl_bitmask_set_bits (&ctx->arrays_to_change, value_cache); - _cogl_bitmask_xor_bits (&ctx->arrays_to_change, new_values); + _COGL_RETURN_VAL_IF_FAIL (context->driver == COGL_DRIVER_GL || + context->driver == COGL_DRIVER_GLES1, + FALSE); - /* Iterate over each bit to change */ - _cogl_bitmask_foreach (&ctx->arrays_to_change, - toggle_enabled_cb, - (void *) new_values); +#if defined (HAVE_COGL_GL) || defined (HAVE_COGL_GLES) + { + gboolean enabled = _cogl_bitmask_get (state->new_bits, bit_num); - /* Store the new values */ - _cogl_bitmask_clear_all (value_cache); - _cogl_bitmask_set_bits (value_cache, new_values); + GE( context, glClientActiveTexture (GL_TEXTURE0 + bit_num) ); + + if (enabled) + GE( context, glEnableClientState (GL_TEXTURE_COORD_ARRAY) ); + else + GE( context, glDisableClientState (GL_TEXTURE_COORD_ARRAY) ); + } +#endif + + return TRUE; } -static CoglHandle -enable_gl_state (CoglDrawFlags flags, - CoglAttribute **attributes, - int n_attributes, - ValidateLayerState *state) +static gboolean +toggle_custom_attribute_enabled_cb (int bit_num, void *user_data) +{ + ForeachChangedBitState *state = user_data; + gboolean enabled = _cogl_bitmask_get (state->new_bits, bit_num); + CoglContext *context = state->context; + + if (enabled) + GE( context, glEnableVertexAttribArray (bit_num) ); + else + GE( context, glDisableVertexAttribArray (bit_num) ); + + return TRUE; +} + +static void +foreach_changed_bit_and_save (CoglContext *context, + CoglBitmask *current_bits, + const CoglBitmask *new_bits, + CoglBitmaskForeachFunc callback, + ForeachChangedBitState *state) +{ + /* Get the list of bits that are different */ + _cogl_bitmask_clear_all (&context->changed_bits_tmp); + _cogl_bitmask_set_bits (&context->changed_bits_tmp, current_bits); + _cogl_bitmask_xor_bits (&context->changed_bits_tmp, new_bits); + + /* Iterate over each bit to change */ + state->new_bits = new_bits; + _cogl_bitmask_foreach (&context->changed_bits_tmp, + callback, + state); + + /* Store the new values */ + _cogl_bitmask_clear_all (current_bits); + _cogl_bitmask_set_bits (current_bits, new_bits); +} + +static void +setup_generic_attribute (CoglContext *context, + CoglPipeline *pipeline, + CoglAttribute *attribute, + guint8 *base) +{ + int name_index = attribute->name_state->name_index; + int attrib_location = + _cogl_pipeline_progend_glsl_get_attrib_location (pipeline, name_index); + if (attrib_location != -1) + { + GE( context, glVertexAttribPointer (attrib_location, + attribute->n_components, + attribute->type, + attribute->normalized, + attribute->stride, + base + attribute->offset) ); + _cogl_bitmask_set (&context->enable_custom_attributes_tmp, + attrib_location, TRUE); + } +} + +static void +apply_attribute_enable_updates (CoglContext *context, + CoglPipeline *pipeline) +{ + ForeachChangedBitState changed_bits_state; + + changed_bits_state.context = context; + changed_bits_state.new_bits = &context->enable_builtin_attributes_tmp; + changed_bits_state.pipeline = pipeline; + + foreach_changed_bit_and_save (context, + &context->enabled_builtin_attributes, + &context->enable_builtin_attributes_tmp, + toggle_builtin_attribute_enabled_cb, + &changed_bits_state); + + changed_bits_state.new_bits = &context->enable_texcoord_attributes_tmp; + foreach_changed_bit_and_save (context, + &context->enabled_texcoord_attributes, + &context->enable_texcoord_attributes_tmp, + toggle_texcood_attribute_enabled_cb, + &changed_bits_state); + + changed_bits_state.new_bits = &context->enable_custom_attributes_tmp; + foreach_changed_bit_and_save (context, + &context->enabled_custom_attributes, + &context->enable_custom_attributes_tmp, + toggle_custom_attribute_enabled_cb, + &changed_bits_state); +} + +static CoglPipeline * +flush_state (CoglDrawFlags flags, + CoglAttribute **attributes, + int n_attributes, + ValidateLayerState *state) { CoglFramebuffer *framebuffer = cogl_get_draw_framebuffer (); int i; - GLuint generic_index = 0; - unsigned long enable_flags = 0; gboolean skip_gl_color = FALSE; - CoglPipeline *source; + CoglPipeline *source = cogl_get_source (); CoglPipeline *copy = NULL; int n_tex_coord_attribs = 0; _COGL_GET_CONTEXT (ctx, COGL_INVALID_HANDLE); + if (!(flags & COGL_DRAW_SKIP_JOURNAL_FLUSH)) + _cogl_journal_flush (framebuffer->journal, framebuffer); + + state->unit = 0; + state->options.flags = 0; + state->fallback_layers = 0; + + if (!(flags & COGL_DRAW_SKIP_PIPELINE_VALIDATION)) + cogl_pipeline_foreach_layer (cogl_get_source (), + validate_layer_cb, + state); + + /* NB: _cogl_framebuffer_flush_state may disrupt various state (such + * as the pipeline state) when flushing the clip stack, so should + * always be done first when preparing to draw. We need to do this + * before setting up the array pointers because setting up the clip + * stack can cause some drawing which would change the array + * pointers. */ + if (!(flags & COGL_DRAW_SKIP_FRAMEBUFFER_FLUSH)) + _cogl_framebuffer_flush_state (cogl_get_draw_framebuffer (), + _cogl_get_read_framebuffer (), + COGL_FRAMEBUFFER_STATE_ALL); + /* In cogl_read_pixels we have a fast-path when reading a single * pixel and the scene is just comprised of simple rectangles still * in the journal. For this optimization to work we need to track * when the framebuffer really does get drawn to. */ _cogl_framebuffer_dirty (framebuffer); - source = cogl_get_source (); - /* Iterate the attributes to work out whether blending needs to be enabled and how many texture coords there are. We need to do this before flushing the pipeline. */ for (i = 0; i < n_attributes; i++) - switch (attributes[i]->name_id) + switch (attributes[i]->name_state->name_id) { case COGL_ATTRIBUTE_NAME_ID_COLOR_ARRAY: if ((flags & COGL_DRAW_COLOR_ATTRIBUTE_IS_OPAQUE) == 0 && @@ -589,11 +663,13 @@ enable_gl_state (CoglDrawFlags flags, _cogl_pipeline_flush_gl_state (source, skip_gl_color, n_tex_coord_attribs); - _cogl_bitmask_clear_all (&ctx->temp_bitmask); + _cogl_bitmask_clear_all (&ctx->enable_builtin_attributes_tmp); + _cogl_bitmask_clear_all (&ctx->enable_texcoord_attributes_tmp); + _cogl_bitmask_clear_all (&ctx->enable_custom_attributes_tmp); /* Bind the attribute pointers. We need to do this after the - pipeline is flushed because on GLES2 that is the only point when - we can determine the attribute locations */ + * pipeline is flushed because when using GLSL that is the only + * point when we can determine the attribute locations */ for (i = 0; i < n_attributes; i++) { @@ -601,156 +677,77 @@ enable_gl_state (CoglDrawFlags flags, CoglAttributeBuffer *attribute_buffer; CoglBuffer *buffer; guint8 *base; -#ifdef HAVE_COGL_GLES2 - int attrib_location; -#endif attribute_buffer = cogl_attribute_get_buffer (attribute); buffer = COGL_BUFFER (attribute_buffer); base = _cogl_buffer_bind (buffer, COGL_BUFFER_BIND_TARGET_ATTRIBUTE_BUFFER); - switch (attribute->name_id) + switch (attribute->name_state->name_id) { case COGL_ATTRIBUTE_NAME_ID_COLOR_ARRAY: #ifdef HAVE_COGL_GLES2 if (ctx->driver == COGL_DRIVER_GLES2) - { - attrib_location = - _cogl_pipeline_progend_glsl_get_color_attribute (source); - if (attrib_location != -1) - { - GE( ctx, - glVertexAttribPointer (attrib_location, - attribute->n_components, - attribute->type, - TRUE, /* normalize */ - attribute->stride, - base + attribute->offset) ); - - _cogl_bitmask_set (&ctx->temp_bitmask, attrib_location, TRUE); - } - } + setup_generic_attribute (ctx, source, attribute, base); else #endif { - enable_flags |= COGL_ENABLE_COLOR_ARRAY; - /* GE (ctx, glEnableClientState (GL_COLOR_ARRAY)); */ + _cogl_bitmask_set (&ctx->enable_builtin_attributes_tmp, + COGL_ATTRIBUTE_NAME_ID_COLOR_ARRAY, TRUE); GE (ctx, glColorPointer (attribute->n_components, attribute->type, attribute->stride, base + attribute->offset)); - } - break; case COGL_ATTRIBUTE_NAME_ID_NORMAL_ARRAY: #ifdef HAVE_COGL_GLES2 if (ctx->driver == COGL_DRIVER_GLES2) - { - attrib_location = - _cogl_pipeline_progend_glsl_get_normal_attribute (source); - if (attrib_location != -1) - { - GE( ctx, - glVertexAttribPointer (attrib_location, - attribute->n_components, - attribute->type, - TRUE, /* normalize */ - attribute->stride, - base + attribute->offset) ); - _cogl_bitmask_set (&ctx->temp_bitmask, attrib_location, TRUE); - } - } + setup_generic_attribute (ctx, source, attribute, base); #endif -#if defined (HAVE_COGL_GL) || defined (HAVE_COGL_GLES) - if (ctx->driver != COGL_DRIVER_GLES2) { - /* FIXME: go through cogl cache to enable normal array */ - GE (ctx, glEnableClientState (GL_NORMAL_ARRAY)); + _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)); - } -#endif break; case COGL_ATTRIBUTE_NAME_ID_TEXTURE_COORD_ARRAY: #ifdef HAVE_COGL_GLES2 if (ctx->driver == COGL_DRIVER_GLES2) - { - attrib_location = - _cogl_pipeline_progend_glsl_get_tex_coord_attribute - (source, attribute->texture_unit); - if (attrib_location != -1) - { - GE( ctx, - glVertexAttribPointer (attrib_location, - attribute->n_components, - attribute->type, - FALSE, /* normalize */ - attribute->stride, - base + attribute->offset) ); - _cogl_bitmask_set (&ctx->temp_bitmask, attrib_location, TRUE); - } - } + setup_generic_attribute (ctx, source, attribute, base); else #endif { - GE (ctx, glClientActiveTexture (GL_TEXTURE0 + - attribute->texture_unit)); + _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)); - _cogl_bitmask_set (&ctx->temp_bitmask, - attribute->texture_unit, TRUE); - } break; case COGL_ATTRIBUTE_NAME_ID_POSITION_ARRAY: #ifdef HAVE_COGL_GLES2 if (ctx->driver == COGL_DRIVER_GLES2) - { - attrib_location = - _cogl_pipeline_progend_glsl_get_position_attribute (source); - if (attrib_location != -1) - { - GE( ctx, - glVertexAttribPointer (attrib_location, - attribute->n_components, - attribute->type, - FALSE, /* normalize */ - attribute->stride, - base + attribute->offset) ); - _cogl_bitmask_set (&ctx->temp_bitmask, attrib_location, TRUE); - } - } + setup_generic_attribute (ctx, source, attribute, base); else #endif { - enable_flags |= COGL_ENABLE_VERTEX_ARRAY; - /* GE (ctx, glEnableClientState (GL_VERTEX_ARRAY)); */ + _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: if (ctx->driver != COGL_DRIVER_GLES1) - { - /* FIXME: go through cogl cache to enable generic array. */ - /* FIXME: this is going to end up just using the builtins - on GLES 2 */ - GE (ctx, glEnableVertexAttribArray (generic_index++)); - GE (ctx, glVertexAttribPointer (generic_index, - attribute->n_components, - attribute->type, - attribute->normalized, - attribute->stride, - base + attribute->offset)); - } + setup_generic_attribute (ctx, source, attribute, base); break; default: g_warning ("Unrecognised attribute type 0x%08x", attribute->type); @@ -759,10 +756,7 @@ enable_gl_state (CoglDrawFlags flags, _cogl_buffer_unbind (buffer); } - /* Flush the state of the attribute arrays */ - set_enabled_arrays (&ctx->arrays_enabled, &ctx->temp_bitmask); - - _cogl_enable (enable_flags); + apply_attribute_enable_updates (ctx, source); return source; } @@ -772,60 +766,14 @@ _cogl_attribute_disable_cached_arrays (void) { _COGL_GET_CONTEXT (ctx, NO_RETVAL); - _cogl_bitmask_clear_all (&ctx->temp_bitmask); - set_enabled_arrays (&ctx->arrays_enabled, &ctx->temp_bitmask); -} + _cogl_bitmask_clear_all (&ctx->enable_builtin_attributes_tmp); + _cogl_bitmask_clear_all (&ctx->enable_texcoord_attributes_tmp); + _cogl_bitmask_clear_all (&ctx->enable_custom_attributes_tmp); -/* FIXME: we shouldn't be disabling state after drawing we should - * just disable the things not needed after enabling state. */ -static void -disable_gl_state (CoglAttribute **attributes, - int n_attributes, - CoglPipeline *source) -{ - GLuint generic_index = 0; - int i; - - _COGL_GET_CONTEXT (ctx, NO_RETVAL); - - if (G_UNLIKELY (source != cogl_get_source ())) - cogl_object_unref (source); - - for (i = 0; i < n_attributes; i++) - { - CoglAttribute *attribute = attributes[i]; - - switch (attribute->name_id) - { - case COGL_ATTRIBUTE_NAME_ID_COLOR_ARRAY: - /* GE (ctx, glDisableClientState (GL_COLOR_ARRAY)); */ - break; - case COGL_ATTRIBUTE_NAME_ID_NORMAL_ARRAY: - /* FIXME: go through cogl cache to enable normal array */ -#if defined(HAVE_COGL_GLES) || defined(HAVE_COGL_GL) - if (ctx->driver != COGL_DRIVER_GLES2) - GE (ctx, glDisableClientState (GL_NORMAL_ARRAY)); -#endif - break; - case COGL_ATTRIBUTE_NAME_ID_TEXTURE_COORD_ARRAY: - /* The enabled state of the texture coord arrays is - cached in ctx->enabled_texcoord_arrays so we don't - need to do anything here. The array will be disabled - by the next drawing primitive if it is not - required */ - break; - case COGL_ATTRIBUTE_NAME_ID_POSITION_ARRAY: - /* GE (ctx, glDisableClientState (GL_VERTEX_ARRAY)); */ - break; - case COGL_ATTRIBUTE_NAME_ID_CUSTOM_ARRAY: - if (ctx->driver != COGL_DRIVER_GLES1) - /* FIXME: go through cogl cache to enable generic array */ - GE (ctx, glDisableVertexAttribArray (generic_index++)); - break; - default: - g_warning ("Unrecognised attribute type 0x%08x", attribute->type); - } - } + /* XXX: we can pass a NULL source pipeline here because we know a + * source pipeline only needs to be referenced when enabling + * attributes. */ + apply_attribute_enable_updates (ctx, NULL); } #ifdef COGL_ENABLE_DEBUG @@ -1020,7 +968,8 @@ draw_wireframe (CoglVerticesMode mode, for (i = 0; i < n_attributes; i++) { - if (strcmp (attributes[i]->name, "cogl_position_in") == 0) + if (attributes[i]->name_state->name_id == + COGL_ATTRIBUTE_NAME_ID_POSITION_ARRAY) { position = attributes[i]; break; @@ -1073,37 +1022,6 @@ draw_wireframe (CoglVerticesMode mode, } #endif -static void -flush_state (CoglDrawFlags flags, - ValidateLayerState *state) -{ - if (!(flags & COGL_DRAW_SKIP_JOURNAL_FLUSH)) - { - CoglFramebuffer *framebuffer = cogl_get_draw_framebuffer (); - _cogl_journal_flush (framebuffer->journal, framebuffer); - } - - state->unit = 0; - state->options.flags = 0; - state->fallback_layers = 0; - - if (!(flags & COGL_DRAW_SKIP_PIPELINE_VALIDATION)) - cogl_pipeline_foreach_layer (cogl_get_source (), - validate_layer_cb, - state); - - /* NB: _cogl_framebuffer_flush_state may disrupt various state (such - * as the pipeline state) when flushing the clip stack, so should - * always be done first when preparing to draw. We need to do this - * before setting up the array pointers because setting up the clip - * stack can cause some drawing which would change the array - * pointers. */ - if (!(flags & COGL_DRAW_SKIP_FRAMEBUFFER_FLUSH)) - _cogl_framebuffer_flush_state (cogl_get_draw_framebuffer (), - _cogl_get_read_framebuffer (), - COGL_FRAMEBUFFER_STATE_ALL); -} - /* This can be called directly by the CoglJournal to draw attributes * skipping the implicit journal flush, the framebuffer flush and * pipeline validation. */ @@ -1120,15 +1038,12 @@ _cogl_draw_attributes (CoglVerticesMode mode, _COGL_GET_CONTEXT (ctx, NO_RETVAL); - flush_state (flags, &state); - - source = enable_gl_state (flags, attributes, n_attributes, &state); + source = flush_state (flags, attributes, n_attributes, &state); GE (ctx, glDrawArrays ((GLenum)mode, first_vertex, n_vertices)); - /* FIXME: we shouldn't be disabling state after drawing we should - * just disable the things not needed after enabling state. */ - disable_gl_state (attributes, n_attributes, source); + if (G_UNLIKELY (source != cogl_get_source ())) + cogl_object_unref (source); #ifdef COGL_ENABLE_DEBUG if (G_UNLIKELY (COGL_DEBUG_ENABLED (COGL_DEBUG_WIREFRAME))) @@ -1212,9 +1127,7 @@ _cogl_draw_indexed_attributes (CoglVerticesMode mode, _COGL_GET_CONTEXT (ctx, NO_RETVAL); - flush_state (flags, &state); - - source = enable_gl_state (flags, attributes, n_attributes, &state); + source = flush_state (flags, attributes, n_attributes, &state); buffer = COGL_BUFFER (cogl_indices_get_buffer (indices)); base = _cogl_buffer_bind (buffer, COGL_BUFFER_BIND_TARGET_INDEX_BUFFER); @@ -1241,9 +1154,8 @@ _cogl_draw_indexed_attributes (CoglVerticesMode mode, _cogl_buffer_unbind (buffer); - /* FIXME: we shouldn't be disabling state after drawing we should - * just disable the things not needed after enabling state. */ - disable_gl_state (attributes, n_attributes, source); + if (G_UNLIKELY (source != cogl_get_source ())) + cogl_object_unref (source); #ifdef COGL_ENABLE_DEBUG if (G_UNLIKELY (COGL_DEBUG_ENABLED (COGL_DEBUG_WIREFRAME))) diff --git a/cogl/cogl-context-private.h b/cogl/cogl-context-private.h index 9f2e17810..f8b9cf03b 100644 --- a/cogl/cogl-context-private.h +++ b/cogl/cogl-context-private.h @@ -72,8 +72,21 @@ struct _CoglContext CoglHandle default_layer_n; CoglHandle dummy_layer_dependant; - /* Enable cache */ - unsigned long enable_flags; + GHashTable *attribute_name_states_hash; + GArray *attribute_name_index_map; + int n_attribute_names; + + CoglBitmask enabled_builtin_attributes; + CoglBitmask enabled_texcoord_attributes; + CoglBitmask enabled_custom_attributes; + + /* These are temporary bitmasks that are used when disabling + * builtin,texcoord and custom attribute arrays. They are here just + * to avoid allocating new ones each time */ + CoglBitmask enable_builtin_attributes_tmp; + CoglBitmask enable_texcoord_attributes_tmp; + CoglBitmask enable_custom_attributes_tmp; + CoglBitmask changed_bits_tmp; gboolean legacy_backface_culling_enabled; @@ -129,16 +142,6 @@ struct _CoglContext gboolean current_pipeline_skip_gl_color; unsigned long current_pipeline_age; - /* Bitmask of attributes enabled. On GLES2 these are the vertex - attribute numbers and on regular GL these are only used for the - texture coordinate arrays */ - CoglBitmask arrays_enabled; - /* These are temporary bitmasks that are used when disabling - texcoord arrays. They are here just to avoid allocating new ones - each time */ - CoglBitmask arrays_to_change; - CoglBitmask temp_bitmask; - gboolean gl_blend_enable_cache; gboolean depth_test_enabled_cache; diff --git a/cogl/cogl-context.c b/cogl/cogl-context.c index f47453836..08b527eef 100644 --- a/cogl/cogl-context.c +++ b/cogl/cogl-context.c @@ -43,6 +43,7 @@ #include "cogl-framebuffer-private.h" #include "cogl-onscreen-private.h" #include "cogl2-path.h" +#include "cogl-attribute-private.h" #include @@ -129,7 +130,6 @@ cogl_context_new (CoglDisplay *display, { CoglContext *context; GLubyte default_texture_data[] = { 0xff, 0xff, 0xff, 0x0 }; - unsigned long enable_flags = 0; const CoglWinsysVtable *winsys; int i; @@ -221,6 +221,16 @@ cogl_context_new (CoglDisplay *display, g_assert_not_reached (); } + context->attribute_name_states_hash = + g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free); + context->attribute_name_index_map = NULL; + context->n_attribute_names = 0; + + /* The "cogl_color_in" attribute needs a deterministic name_index + * so we make sure it's the first attribute name we register */ + _cogl_attribute_register_attribute_name (context, "cogl_color_in"); + + context->uniform_names = g_ptr_array_new_with_free_func ((GDestroyNotify) g_free); context->uniform_name_hash = g_hash_table_new (g_str_hash, g_str_equal); @@ -234,7 +244,6 @@ cogl_context_new (CoglDisplay *display, _cogl_pipeline_init_state_hash_functions (); _cogl_pipeline_init_layer_state_hash_functions (); - context->enable_flags = 0; context->current_clip_stack_valid = FALSE; context->current_clip_stack = NULL; @@ -284,9 +293,13 @@ cogl_context_new (CoglDisplay *display, context->current_pipeline_changes_since_flush = 0; context->current_pipeline_skip_gl_color = FALSE; - _cogl_bitmask_init (&context->arrays_enabled); - _cogl_bitmask_init (&context->temp_bitmask); - _cogl_bitmask_init (&context->arrays_to_change); + _cogl_bitmask_init (&context->enabled_builtin_attributes); + _cogl_bitmask_init (&context->enable_builtin_attributes_tmp); + _cogl_bitmask_init (&context->enabled_texcoord_attributes); + _cogl_bitmask_init (&context->enable_texcoord_attributes_tmp); + _cogl_bitmask_init (&context->enabled_custom_attributes); + _cogl_bitmask_init (&context->enable_custom_attributes_tmp); + _cogl_bitmask_init (&context->changed_bits_tmp); context->max_texture_units = -1; context->max_activateable_texture_units = -1; @@ -385,7 +398,6 @@ cogl_context_new (CoglDisplay *display, cogl_push_source (context->opaque_color_pipeline); _cogl_pipeline_flush_gl_state (context->opaque_color_pipeline, FALSE, 0); - _cogl_enable (enable_flags); context->atlases = NULL; g_hook_list_init (&context->atlas_reorganize_callbacks, sizeof (GHook)); @@ -468,9 +480,13 @@ _cogl_context_free (CoglContext *context) g_slist_free (context->atlases); g_hook_list_clear (&context->atlas_reorganize_callbacks); - _cogl_bitmask_destroy (&context->arrays_enabled); - _cogl_bitmask_destroy (&context->temp_bitmask); - _cogl_bitmask_destroy (&context->arrays_to_change); + _cogl_bitmask_destroy (&context->enabled_builtin_attributes); + _cogl_bitmask_destroy (&context->enable_builtin_attributes_tmp); + _cogl_bitmask_destroy (&context->enabled_texcoord_attributes); + _cogl_bitmask_destroy (&context->enable_texcoord_attributes_tmp); + _cogl_bitmask_destroy (&context->enabled_custom_attributes); + _cogl_bitmask_destroy (&context->enable_custom_attributes_tmp); + _cogl_bitmask_destroy (&context->changed_bits_tmp); g_slist_free (context->texture_types); g_slist_free (context->buffer_types); @@ -490,6 +506,9 @@ _cogl_context_free (CoglContext *context) g_ptr_array_free (context->uniform_names, TRUE); g_hash_table_destroy (context->uniform_name_hash); + g_hash_table_destroy (context->attribute_name_states_hash); + g_array_free (context->attribute_name_index_map, TRUE); + g_byte_array_free (context->buffer_map_fallback_array, TRUE); cogl_object_unref (context->display); diff --git a/cogl/cogl-pipeline-opengl.c b/cogl/cogl-pipeline-opengl.c index 92d75ea20..aaf5ea8c5 100644 --- a/cogl/cogl-pipeline-opengl.c +++ b/cogl/cogl-pipeline-opengl.c @@ -1372,8 +1372,10 @@ done: int attribute; CoglPipeline *authority = _cogl_pipeline_get_authority (pipeline, COGL_PIPELINE_STATE_COLOR); + int name_index = COGL_ATTRIBUTE_COLOR_NAME_INDEX; - attribute = _cogl_pipeline_progend_glsl_get_color_attribute (pipeline); + attribute = + _cogl_pipeline_progend_glsl_get_attrib_location (pipeline, name_index); if (attribute != -1) GE (ctx, glVertexAttrib4f (attribute, diff --git a/cogl/cogl-pipeline-progend-glsl-private.h b/cogl/cogl-pipeline-progend-glsl-private.h index c100269b3..a08020492 100644 --- a/cogl/cogl-pipeline-progend-glsl-private.h +++ b/cogl/cogl-pipeline-progend-glsl-private.h @@ -33,22 +33,9 @@ extern const CoglPipelineProgend _cogl_pipeline_glsl_progend; -#ifdef HAVE_COGL_GLES2 - int -_cogl_pipeline_progend_glsl_get_position_attribute (CoglPipeline *pipeline); - -int -_cogl_pipeline_progend_glsl_get_color_attribute (CoglPipeline *pipeline); - -int -_cogl_pipeline_progend_glsl_get_normal_attribute (CoglPipeline *pipeline); - -int -_cogl_pipeline_progend_glsl_get_tex_coord_attribute (CoglPipeline *pipeline, - int unit); - -#endif /* HAVE_COGL_GLES2 */ +_cogl_pipeline_progend_glsl_get_attrib_location (CoglPipeline *pipeline, + int name_index); #endif /* __COGL_PIPELINE_PROGEND_GLSL_PRIVATE_H */ diff --git a/cogl/cogl-pipeline-progend-glsl.c b/cogl/cogl-pipeline-progend-glsl.c index 703cbea17..bc96cb83c 100644 --- a/cogl/cogl-pipeline-progend-glsl.c +++ b/cogl/cogl-pipeline-progend-glsl.c @@ -47,6 +47,7 @@ #include "cogl-pipeline-vertend-glsl-private.h" #include "cogl-pipeline-cache.h" #include "cogl-pipeline-state-private.h" +#include "cogl-attribute-private.h" #ifdef HAVE_COGL_GLES2 @@ -116,18 +117,6 @@ typedef struct unsigned long dirty_builtin_uniforms; GLint builtin_uniform_locations[G_N_ELEMENTS (builtin_uniforms)]; - /* Under GLES2 we can't use the builtin functions to set attribute - pointers such as the vertex position. Instead the vertex - attribute code needs to query the attribute numbers from the - progend backend */ - int position_attribute_location; - int color_attribute_location; - int normal_attribute_location; - int tex_coord0_attribute_location; - /* We only allocate this array if more than one tex coord attribute - is requested because most pipelines will only use one layer */ - GArray *tex_coord_attribute_locations; - GLint modelview_uniform; GLint projection_uniform; GLint mvp_uniform; @@ -148,6 +137,9 @@ typedef struct uniform is actually set */ GArray *uniform_locations; + /* Array of attribute locations. */ + GArray *attribute_locations; + UnitState *unit_state; } CoglPipelineProgramState; @@ -161,8 +153,6 @@ get_program_state (CoglPipeline *pipeline) #define UNIFORM_LOCATION_UNKNOWN -2 -#ifdef HAVE_COGL_GLES2 - #define ATTRIBUTE_LOCATION_UNKNOWN -2 /* Under GLES2 the vertex attribute API needs to query the attribute @@ -172,125 +162,66 @@ get_program_state (CoglPipeline *pipeline) cache. This should always be called after the pipeline is flushed so they can assert that the gl program is valid */ +/* All attributes names get internally mapped to a global set of + * sequential indices when they are setup which we need to need to + * then be able to map to a GL attribute location once we have + * a linked GLSL program */ + int -_cogl_pipeline_progend_glsl_get_position_attribute (CoglPipeline *pipeline) +_cogl_pipeline_progend_glsl_get_attrib_location (CoglPipeline *pipeline, + int name_index) { CoglPipelineProgramState *program_state = get_program_state (pipeline); + int *locations; _COGL_GET_CONTEXT (ctx, -1); _COGL_RETURN_VAL_IF_FAIL (program_state != NULL, -1); _COGL_RETURN_VAL_IF_FAIL (program_state->program != 0, -1); - if (program_state->position_attribute_location == ATTRIBUTE_LOCATION_UNKNOWN) - GE_RET( program_state->position_attribute_location, - ctx, glGetAttribLocation (program_state->program, - "cogl_position_in") ); + if (G_UNLIKELY (program_state->attribute_locations == NULL)) + program_state->attribute_locations = + g_array_new (FALSE, FALSE, sizeof (int)); - return program_state->position_attribute_location; -} - -int -_cogl_pipeline_progend_glsl_get_color_attribute (CoglPipeline *pipeline) -{ - CoglPipelineProgramState *program_state = get_program_state (pipeline); - - _COGL_GET_CONTEXT (ctx, -1); - - _COGL_RETURN_VAL_IF_FAIL (program_state != NULL, -1); - _COGL_RETURN_VAL_IF_FAIL (program_state->program != 0, -1); - - if (program_state->color_attribute_location == ATTRIBUTE_LOCATION_UNKNOWN) - GE_RET( program_state->color_attribute_location, - ctx, glGetAttribLocation (program_state->program, - "cogl_color_in") ); - - return program_state->color_attribute_location; -} - -int -_cogl_pipeline_progend_glsl_get_normal_attribute (CoglPipeline *pipeline) -{ - CoglPipelineProgramState *program_state = get_program_state (pipeline); - - _COGL_GET_CONTEXT (ctx, -1); - - _COGL_RETURN_VAL_IF_FAIL (program_state != NULL, -1); - _COGL_RETURN_VAL_IF_FAIL (program_state->program != 0, -1); - - if (program_state->normal_attribute_location == ATTRIBUTE_LOCATION_UNKNOWN) - GE_RET( program_state->normal_attribute_location, - ctx, glGetAttribLocation (program_state->program, - "cogl_normal_in") ); - - return program_state->normal_attribute_location; -} - -int -_cogl_pipeline_progend_glsl_get_tex_coord_attribute (CoglPipeline *pipeline, - int unit) -{ - CoglPipelineProgramState *program_state = get_program_state (pipeline); - - _COGL_GET_CONTEXT (ctx, -1); - - _COGL_RETURN_VAL_IF_FAIL (program_state != NULL, -1); - _COGL_RETURN_VAL_IF_FAIL (program_state->program != 0, -1); - - if (unit == 0) + if (G_UNLIKELY (program_state->attribute_locations->len <= name_index)) { - if (program_state->tex_coord0_attribute_location == - ATTRIBUTE_LOCATION_UNKNOWN) - GE_RET( program_state->tex_coord0_attribute_location, - ctx, glGetAttribLocation (program_state->program, - "cogl_tex_coord0_in") ); - - return program_state->tex_coord0_attribute_location; + int i = program_state->attribute_locations->len; + g_array_set_size (program_state->attribute_locations, name_index + 1); + for (; i < program_state->attribute_locations->len; i++) + g_array_index (program_state->attribute_locations, int, i) + = ATTRIBUTE_LOCATION_UNKNOWN; } - else + + locations = &g_array_index (program_state->attribute_locations, int, 0); + + if (locations[name_index] == ATTRIBUTE_LOCATION_UNKNOWN) { - char *name = g_strdup_printf ("cogl_tex_coord%i_in", unit); - int *locations; + CoglAttributeNameState *name_state = + g_array_index (ctx->attribute_name_index_map, + CoglAttributeNameState *, name_index); - if (program_state->tex_coord_attribute_locations == NULL) - program_state->tex_coord_attribute_locations = - g_array_new (FALSE, FALSE, sizeof (int)); - if (program_state->tex_coord_attribute_locations->len <= unit - 1) - { - int i = program_state->tex_coord_attribute_locations->len; - g_array_set_size (program_state->tex_coord_attribute_locations, unit); - for (; i < unit; i++) - g_array_index (program_state->tex_coord_attribute_locations, int, i) - = ATTRIBUTE_LOCATION_UNKNOWN; - } + _COGL_RETURN_VAL_IF_FAIL (name_state != NULL, 0); - locations = &g_array_index (program_state->tex_coord_attribute_locations, - int, 0); - - if (locations[unit - 1] == ATTRIBUTE_LOCATION_UNKNOWN) - GE_RET( locations[unit - 1], - ctx, glGetAttribLocation (program_state->program, name) ); - - g_free (name); - - return locations[unit - 1]; + GE_RET( locations[name_index], + ctx, glGetAttribLocation (program_state->program, + name_state->name) ); } + + return locations[name_index]; } static void clear_attribute_cache (CoglPipelineProgramState *program_state) { - program_state->position_attribute_location = ATTRIBUTE_LOCATION_UNKNOWN; - program_state->color_attribute_location = ATTRIBUTE_LOCATION_UNKNOWN; - program_state->normal_attribute_location = ATTRIBUTE_LOCATION_UNKNOWN; - program_state->tex_coord0_attribute_location = ATTRIBUTE_LOCATION_UNKNOWN; - if (program_state->tex_coord_attribute_locations) + if (program_state->attribute_locations) { - g_array_free (program_state->tex_coord_attribute_locations, TRUE); - program_state->tex_coord_attribute_locations = NULL; + g_array_free (program_state->attribute_locations, TRUE); + program_state->attribute_locations = NULL; } } +#ifdef HAVE_COGL_GLES2 + static void clear_flushed_matrix_stacks (CoglPipelineProgramState *program_state) { @@ -320,8 +251,8 @@ program_state_new (int n_layers) program_state->n_tex_coord_attribs = 0; program_state->unit_state = g_new (UnitState, n_layers); program_state->uniform_locations = NULL; + program_state->attribute_locations = NULL; #ifdef HAVE_COGL_GLES2 - program_state->tex_coord_attribute_locations = NULL; program_state->flushed_modelview_stack = NULL; program_state->flushed_modelview_is_identity = FALSE; program_state->flushed_projection_stack = NULL; @@ -347,12 +278,11 @@ destroy_program_state (void *user_data, if (--program_state->ref_count == 0) { + clear_attribute_cache (program_state); + #ifdef HAVE_COGL_GLES2 if (ctx->driver == COGL_DRIVER_GLES2) - { - clear_attribute_cache (program_state); - clear_flushed_matrix_stacks (program_state); - } + clear_flushed_matrix_stacks (program_state); #endif if (program_state->program) @@ -858,9 +788,12 @@ _cogl_pipeline_progend_glsl_end (CoglPipeline *pipeline, state.program_state = program_state; if (program_changed) - cogl_pipeline_foreach_layer (pipeline, - get_uniform_cb, - &state); + { + cogl_pipeline_foreach_layer (pipeline, + get_uniform_cb, + &state); + clear_attribute_cache (program_state); + } state.unit = 0; state.update_all = (program_changed || @@ -877,7 +810,6 @@ _cogl_pipeline_progend_glsl_end (CoglPipeline *pipeline, { int i; - clear_attribute_cache (program_state); clear_flushed_matrix_stacks (program_state); for (i = 0; i < G_N_ELEMENTS (builtin_uniforms); i++) diff --git a/cogl/cogl.c b/cogl/cogl.c index 46fd45e8a..cba3de7aa 100644 --- a/cogl/cogl.c +++ b/cogl/cogl.c @@ -141,69 +141,6 @@ cogl_clear (const CoglColor *color, unsigned long buffers) cogl_framebuffer_clear (cogl_get_draw_framebuffer (), buffers, color); } -#if defined (HAVE_COGL_GL) || defined (HAVE_COGL_GLES) - -static gboolean -toggle_client_flag (CoglContext *ctx, - unsigned long new_flags, - unsigned long flag, - GLenum gl_flag) -{ - _COGL_RETURN_VAL_IF_FAIL (ctx->driver != COGL_DRIVER_GLES2, FALSE); - - /* Toggles and caches a single client-side enable flag - * on or off by comparing to current state - */ - if (new_flags & flag) - { - if (!(ctx->enable_flags & flag)) - { - GE( ctx, glEnableClientState (gl_flag) ); - ctx->enable_flags |= flag; - return TRUE; - } - } - else if (ctx->enable_flags & flag) - { - GE( ctx, glDisableClientState (gl_flag) ); - ctx->enable_flags &= ~flag; - } - - return FALSE; -} - -#endif - -void -_cogl_enable (unsigned long flags) -{ - /* This function essentially caches glEnable state() in the - * hope of lessening number GL traffic. - */ - _COGL_GET_CONTEXT (ctx, NO_RETVAL); - -#if defined (HAVE_COGL_GL) || defined (HAVE_COGL_GLES) - if (ctx->driver != COGL_DRIVER_GLES2) - { - toggle_client_flag (ctx, flags, - COGL_ENABLE_VERTEX_ARRAY, - GL_VERTEX_ARRAY); - - toggle_client_flag (ctx, flags, - COGL_ENABLE_COLOR_ARRAY, - GL_COLOR_ARRAY); - } -#endif -} - -unsigned long -_cogl_get_enable (void) -{ - _COGL_GET_CONTEXT (ctx, 0); - - return ctx->enable_flags; -} - /* XXX: This API has been deprecated */ void cogl_set_depth_test_enabled (gboolean setting) @@ -645,7 +582,6 @@ cogl_read_pixels (int x, void cogl_begin_gl (void) { - unsigned long enable_flags = 0; CoglPipeline *pipeline; _COGL_GET_CONTEXT (ctx, NO_RETVAL); @@ -697,8 +633,6 @@ cogl_begin_gl (void) FALSE, cogl_pipeline_get_n_layers (pipeline)); - _cogl_enable (enable_flags); - /* Disable any cached vertex arrays */ _cogl_attribute_disable_cached_arrays (); }