diff --git a/cogl/Makefile.am b/cogl/Makefile.am index f7719e18b..40c375a4e 100644 --- a/cogl/Makefile.am +++ b/cogl/Makefile.am @@ -150,6 +150,8 @@ cogl_driver_sources = \ $(srcdir)/driver/gl/cogl-framebuffer-gl.c \ $(srcdir)/driver/gl/cogl-texture-2d-gl-private.h \ $(srcdir)/driver/gl/cogl-texture-2d-gl.c \ + $(srcdir)/driver/gl/cogl-attribute-gl-private.h \ + $(srcdir)/driver/gl/cogl-attribute-gl.c \ $(srcdir)/driver/gl/cogl-pipeline-opengl.c \ $(srcdir)/driver/gl/cogl-pipeline-opengl-private.h \ $(srcdir)/driver/gl/cogl-pipeline-fragend-glsl.c \ diff --git a/cogl/cogl-attribute-private.h b/cogl/cogl-attribute-private.h index 6271aab63..a5d7d843e 100644 --- a/cogl/cogl-attribute-private.h +++ b/cogl/cogl-attribute-private.h @@ -31,6 +31,7 @@ #include "cogl-object-private.h" #include "cogl-attribute.h" #include "cogl-framebuffer.h" +#include "cogl-pipeline-private.h" typedef enum { @@ -99,8 +100,12 @@ _cogl_attribute_immutable_ref (CoglAttribute *attribute); void _cogl_attribute_immutable_unref (CoglAttribute *attribute); -void -_cogl_attribute_disable_cached_arrays (void); +typedef struct +{ + int unit; + CoglPipelineFlushOptions options; + uint32_t fallback_layers; +} CoglFlushLayerState; void _cogl_flush_attributes_state (CoglFramebuffer *framebuffer, diff --git a/cogl/cogl-attribute.c b/cogl/cogl-attribute.c index 57e285dbc..ff0549b57 100644 --- a/cogl/cogl-attribute.c +++ b/cogl/cogl-attribute.c @@ -319,13 +319,6 @@ _cogl_attribute_free (CoglAttribute *attribute) g_slice_free (CoglAttribute, attribute); } -typedef struct -{ - int unit; - CoglPipelineFlushOptions options; - uint32_t fallback_layers; -} ValidateLayerState; - static CoglBool validate_layer_cb (CoglPipeline *pipeline, int layer_index, @@ -333,7 +326,7 @@ validate_layer_cb (CoglPipeline *pipeline, { CoglTexture *texture = cogl_pipeline_get_layer_texture (pipeline, layer_index); - ValidateLayerState *state = user_data; + CoglFlushLayerState *state = user_data; CoglBool status = TRUE; /* invalid textures will be handled correctly in @@ -382,171 +375,6 @@ validated: return status; } -typedef struct _ForeachChangedBitState -{ - CoglContext *context; - const CoglBitmask *new_bits; - CoglPipeline *pipeline; -} ForeachChangedBitState; - -static CoglBool -toggle_builtin_attribute_enabled_cb (int bit_num, void *user_data) -{ - ForeachChangedBitState *state = user_data; - CoglContext *context = state->context; - - _COGL_RETURN_VAL_IF_FAIL (context->driver == COGL_DRIVER_GL || - context->driver == COGL_DRIVER_GLES1, - FALSE); - -#if defined (HAVE_COGL_GL) || defined (HAVE_COGL_GLES) - { - CoglBool enabled = _cogl_bitmask_get (state->new_bits, bit_num); - GLenum cap; - - switch (bit_num) - { - case COGL_ATTRIBUTE_NAME_ID_COLOR_ARRAY: - cap = GL_COLOR_ARRAY; - break; - case COGL_ATTRIBUTE_NAME_ID_POSITION_ARRAY: - cap = GL_VERTEX_ARRAY; - break; - case COGL_ATTRIBUTE_NAME_ID_NORMAL_ARRAY: - cap = GL_NORMAL_ARRAY; - break; - } - if (enabled) - GE (context, glEnableClientState (cap)); - else - GE (context, glDisableClientState (cap)); - } -#endif - - return TRUE; -} - -static CoglBool -toggle_texcood_attribute_enabled_cb (int bit_num, void *user_data) -{ - ForeachChangedBitState *state = user_data; - CoglContext *context = state->context; - - _COGL_RETURN_VAL_IF_FAIL (context->driver == COGL_DRIVER_GL || - context->driver == COGL_DRIVER_GLES1, - FALSE); - -#if defined (HAVE_COGL_GL) || defined (HAVE_COGL_GLES) - { - CoglBool enabled = _cogl_bitmask_get (state->new_bits, bit_num); - - GE( context, glClientActiveTexture (GL_TEXTURE0 + bit_num) ); - - if (enabled) - GE( context, glEnableClientState (GL_TEXTURE_COORD_ARRAY) ); - else - GE( context, glDisableClientState (GL_TEXTURE_COORD_ARRAY) ); - } -#endif - - return TRUE; -} - -static CoglBool -toggle_custom_attribute_enabled_cb (int bit_num, void *user_data) -{ - ForeachChangedBitState *state = user_data; - CoglBool enabled = _cogl_bitmask_get (state->new_bits, bit_num); - CoglContext *context = state->context; - - if (enabled) - GE( context, glEnableVertexAttribArray (bit_num) ); - else - GE( context, glDisableVertexAttribArray (bit_num) ); - - return TRUE; -} - -static void -foreach_changed_bit_and_save (CoglContext *context, - CoglBitmask *current_bits, - const CoglBitmask *new_bits, - CoglBitmaskForeachFunc callback, - ForeachChangedBitState *state) -{ - /* Get the list of bits that are different */ - _cogl_bitmask_clear_all (&context->changed_bits_tmp); - _cogl_bitmask_set_bits (&context->changed_bits_tmp, current_bits); - _cogl_bitmask_xor_bits (&context->changed_bits_tmp, new_bits); - - /* Iterate over each bit to change */ - state->new_bits = new_bits; - _cogl_bitmask_foreach (&context->changed_bits_tmp, - callback, - state); - - /* Store the new values */ - _cogl_bitmask_clear_all (current_bits); - _cogl_bitmask_set_bits (current_bits, new_bits); -} - -#ifdef COGL_PIPELINE_PROGEND_GLSL - -static void -setup_generic_attribute (CoglContext *context, - CoglPipeline *pipeline, - CoglAttribute *attribute, - uint8_t *base) -{ - int name_index = attribute->name_state->name_index; - int attrib_location = - _cogl_pipeline_progend_glsl_get_attrib_location (pipeline, name_index); - if (attrib_location != -1) - { - GE( context, glVertexAttribPointer (attrib_location, - attribute->n_components, - attribute->type, - attribute->normalized, - attribute->stride, - base + attribute->offset) ); - _cogl_bitmask_set (&context->enable_custom_attributes_tmp, - attrib_location, TRUE); - } -} - -#endif /* COGL_PIPELINE_PROGEND_GLSL */ - -static void -apply_attribute_enable_updates (CoglContext *context, - CoglPipeline *pipeline) -{ - ForeachChangedBitState changed_bits_state; - - changed_bits_state.context = context; - changed_bits_state.new_bits = &context->enable_builtin_attributes_tmp; - changed_bits_state.pipeline = pipeline; - - foreach_changed_bit_and_save (context, - &context->enabled_builtin_attributes, - &context->enable_builtin_attributes_tmp, - toggle_builtin_attribute_enabled_cb, - &changed_bits_state); - - changed_bits_state.new_bits = &context->enable_texcoord_attributes_tmp; - foreach_changed_bit_and_save (context, - &context->enabled_texcoord_attributes, - &context->enable_texcoord_attributes_tmp, - toggle_texcood_attribute_enabled_cb, - &changed_bits_state); - - changed_bits_state.new_bits = &context->enable_custom_attributes_tmp; - foreach_changed_bit_and_save (context, - &context->enabled_custom_attributes, - &context->enable_custom_attributes_tmp, - toggle_custom_attribute_enabled_cb, - &changed_bits_state); -} - void _cogl_flush_attributes_state (CoglFramebuffer *framebuffer, CoglPipeline *pipeline, @@ -554,12 +382,8 @@ _cogl_flush_attributes_state (CoglFramebuffer *framebuffer, CoglAttribute **attributes, int n_attributes) { - int i; - CoglBool skip_gl_color = FALSE; - CoglPipeline *copy = NULL; - int n_tex_coord_attribs = 0; - ValidateLayerState layers_state; CoglContext *ctx = framebuffer->context; + CoglFlushLayerState layers_state; if (!(flags & COGL_DRAW_SKIP_JOURNAL_FLUSH)) _cogl_journal_flush (framebuffer->journal); @@ -590,77 +414,6 @@ _cogl_flush_attributes_state (CoglFramebuffer *framebuffer, * when the framebuffer really does get drawn to. */ _cogl_framebuffer_dirty (framebuffer); - /* Iterate the attributes to work out whether blending needs to be - enabled and how many texture coords there are. We need to do this - before flushing the pipeline. */ - for (i = 0; i < n_attributes; i++) - switch (attributes[i]->name_state->name_id) - { - case COGL_ATTRIBUTE_NAME_ID_COLOR_ARRAY: - if ((flags & COGL_DRAW_COLOR_ATTRIBUTE_IS_OPAQUE) == 0 && - !_cogl_pipeline_get_real_blend_enabled (pipeline)) - { - CoglPipelineBlendEnable blend_enable = - COGL_PIPELINE_BLEND_ENABLE_ENABLED; - copy = cogl_pipeline_copy (pipeline); - _cogl_pipeline_set_blend_enabled (copy, blend_enable); - pipeline = copy; - } - skip_gl_color = TRUE; - break; - - case COGL_ATTRIBUTE_NAME_ID_TEXTURE_COORD_ARRAY: - n_tex_coord_attribs++; - break; - - default: - break; - } - - if (G_UNLIKELY (layers_state.options.flags)) - { - /* If we haven't already created a derived pipeline... */ - if (!copy) - { - copy = cogl_pipeline_copy (pipeline); - pipeline = copy; - } - _cogl_pipeline_apply_overrides (pipeline, &layers_state.options); - - /* TODO: - * overrides = cogl_pipeline_get_data (pipeline, - * last_overrides_key); - * if (overrides) - * { - * age = cogl_pipeline_get_age (pipeline); - * XXX: actually we also need to check for legacy_state - * and blending overrides for use of glColorPointer... - * if (overrides->ags != age || - * memcmp (&overrides->options, &options, - * sizeof (options) != 0) - * { - * cogl_object_unref (overrides->weak_pipeline); - * g_slice_free (Overrides, overrides); - * overrides = NULL; - * } - * } - * if (!overrides) - * { - * overrides = g_slice_new (Overrides); - * overrides->weak_pipeline = - * cogl_pipeline_weak_copy (pipeline); - * _cogl_pipeline_apply_overrides (overrides->weak_pipeline, - * &options); - * - * cogl_pipeline_set_data (pipeline, last_overrides_key, - * weak_overrides, - * free_overrides_cb, - * NULL); - * } - * pipeline = overrides->weak_pipeline; - */ - } - if (G_UNLIKELY (!(flags & COGL_DRAW_SKIP_LEGACY_STATE)) && G_UNLIKELY (ctx->legacy_state_set) && _cogl_get_enable_legacy_state ()) @@ -674,124 +427,13 @@ _cogl_flush_attributes_state (CoglFramebuffer *framebuffer, _cogl_pipeline_apply_legacy_state (pipeline); } - _cogl_pipeline_flush_gl_state (pipeline, - framebuffer, - skip_gl_color, - n_tex_coord_attribs); - - _cogl_bitmask_clear_all (&ctx->enable_builtin_attributes_tmp); - _cogl_bitmask_clear_all (&ctx->enable_texcoord_attributes_tmp); - _cogl_bitmask_clear_all (&ctx->enable_custom_attributes_tmp); - - /* Bind the attribute pointers. We need to do this after the - * pipeline is flushed because when using GLSL that is the only - * point when we can determine the attribute locations */ - - for (i = 0; i < n_attributes; i++) - { - CoglAttribute *attribute = attributes[i]; - CoglAttributeBuffer *attribute_buffer; - CoglBuffer *buffer; - uint8_t *base; - - attribute_buffer = cogl_attribute_get_buffer (attribute); - buffer = COGL_BUFFER (attribute_buffer); - base = _cogl_buffer_bind (buffer, COGL_BUFFER_BIND_TARGET_ATTRIBUTE_BUFFER); - - switch (attribute->name_state->name_id) - { - case COGL_ATTRIBUTE_NAME_ID_COLOR_ARRAY: -#ifdef HAVE_COGL_GLES2 - if (ctx->driver == COGL_DRIVER_GLES2) - setup_generic_attribute (ctx, pipeline, attribute, base); - else -#endif - { - _cogl_bitmask_set (&ctx->enable_builtin_attributes_tmp, - COGL_ATTRIBUTE_NAME_ID_COLOR_ARRAY, TRUE); - GE (ctx, glColorPointer (attribute->n_components, - attribute->type, - attribute->stride, - base + attribute->offset)); - } - break; - case COGL_ATTRIBUTE_NAME_ID_NORMAL_ARRAY: -#ifdef HAVE_COGL_GLES2 - if (ctx->driver == COGL_DRIVER_GLES2) - setup_generic_attribute (ctx, pipeline, attribute, base); - else -#endif - { - _cogl_bitmask_set (&ctx->enable_builtin_attributes_tmp, - COGL_ATTRIBUTE_NAME_ID_NORMAL_ARRAY, TRUE); - GE (ctx, glNormalPointer (attribute->type, - attribute->stride, - base + attribute->offset)); - } - break; - case COGL_ATTRIBUTE_NAME_ID_TEXTURE_COORD_ARRAY: -#ifdef HAVE_COGL_GLES2 - if (ctx->driver == COGL_DRIVER_GLES2) - setup_generic_attribute (ctx, pipeline, attribute, base); - else -#endif - { - _cogl_bitmask_set (&ctx->enable_texcoord_attributes_tmp, - attribute->name_state->texture_unit, TRUE); - GE (ctx, - glClientActiveTexture (GL_TEXTURE0 + - attribute->name_state->texture_unit)); - GE (ctx, glTexCoordPointer (attribute->n_components, - attribute->type, - attribute->stride, - base + attribute->offset)); - } - break; - case COGL_ATTRIBUTE_NAME_ID_POSITION_ARRAY: -#ifdef HAVE_COGL_GLES2 - if (ctx->driver == COGL_DRIVER_GLES2) - setup_generic_attribute (ctx, pipeline, attribute, base); - else -#endif - { - _cogl_bitmask_set (&ctx->enable_builtin_attributes_tmp, - COGL_ATTRIBUTE_NAME_ID_POSITION_ARRAY, TRUE); - GE (ctx, glVertexPointer (attribute->n_components, - attribute->type, - attribute->stride, - base + attribute->offset)); - } - break; - case COGL_ATTRIBUTE_NAME_ID_CUSTOM_ARRAY: -#ifdef COGL_PIPELINE_PROGEND_GLSL - if (ctx->driver != COGL_DRIVER_GLES1) - setup_generic_attribute (ctx, pipeline, attribute, base); -#endif - break; - default: - g_warning ("Unrecognised attribute type 0x%08x", attribute->type); - } - - _cogl_buffer_unbind (buffer); - } - - apply_attribute_enable_updates (ctx, pipeline); + ctx->driver_vtable->flush_attributes_state (framebuffer, + pipeline, + &layers_state, + flags, + attributes, + n_attributes); if (copy) cogl_object_unref (copy); } - -void -_cogl_attribute_disable_cached_arrays (void) -{ - _COGL_GET_CONTEXT (ctx, NO_RETVAL); - - _cogl_bitmask_clear_all (&ctx->enable_builtin_attributes_tmp); - _cogl_bitmask_clear_all (&ctx->enable_texcoord_attributes_tmp); - _cogl_bitmask_clear_all (&ctx->enable_custom_attributes_tmp); - - /* XXX: we can pass a NULL source pipeline here because we know a - * source pipeline only needs to be referenced when enabling - * attributes. */ - apply_attribute_enable_updates (ctx, NULL); -} diff --git a/cogl/cogl-driver.h b/cogl/cogl-driver.h index bfedbff8f..bea53cd64 100644 --- a/cogl/cogl-driver.h +++ b/cogl/cogl-driver.h @@ -27,6 +27,7 @@ #include "cogl-context.h" #include "cogl-offscreen.h" #include "cogl-framebuffer-private.h" +#include "cogl-attribute-private.h" typedef struct _CoglDriverVtable CoglDriverVtable; @@ -210,6 +211,17 @@ struct _CoglDriverVtable CoglPixelFormat format, unsigned int rowstride, uint8_t *data); + + /* Prepares for drawing by flushing the journal, framebuffer state, + * pipeline state and attribute state. + */ + void + (* flush_attributes_state) (CoglFramebuffer *framebuffer, + CoglPipeline *pipeline, + CoglFlushLayerState *layer_state, + CoglDrawFlags flags, + CoglAttribute **attributes, + int n_attributes); }; #endif /* __COGL_DRIVER_H */ diff --git a/cogl/driver/gl/cogl-attribute-gl-private.h b/cogl/driver/gl/cogl-attribute-gl-private.h new file mode 100644 index 000000000..405e43d27 --- /dev/null +++ b/cogl/driver/gl/cogl-attribute-gl-private.h @@ -0,0 +1,44 @@ +/* + * Cogl + * + * An object oriented GL/GLES Abstraction/Utility Layer + * + * Copyright (C) 2012 Intel Corporation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see + * . + * + * + * + * Authors: + * Robert Bragg + */ + +#ifndef _COGL_ATTRIBUTE_GL_PRIVATE_H_ +#define _COGL_ATTRIBUTE_GL_PRIVATE_H_ + +#include "cogl-types.h" +#include "cogl-framebuffer.h" +#include "cogl-attribute.h" +#include "cogl-attribute-private.h" + +void +_cogl_gl_flush_attributes_state (CoglFramebuffer *framebuffer, + CoglPipeline *pipeline, + CoglFlushLayerState *layers_state, + CoglDrawFlags flags, + CoglAttribute **attributes, + int n_attributes); + +#endif /* _COGL_ATTRIBUTE_GL_PRIVATE_H_ */ diff --git a/cogl/driver/gl/cogl-attribute-gl.c b/cogl/driver/gl/cogl-attribute-gl.c new file mode 100644 index 000000000..3391f48d5 --- /dev/null +++ b/cogl/driver/gl/cogl-attribute-gl.c @@ -0,0 +1,398 @@ +/* + * Cogl + * + * An object oriented GL/GLES Abstraction/Utility Layer + * + * Copyright (C) 2010,2011,2012 Intel Corporation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + * + * + * + * Authors: + * Neil Roberts + * Robert Bragg + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +#include "cogl-private.h" +#include "cogl-pipeline-opengl-private.h" +#include "cogl-error-private.h" +#include "cogl-context-private.h" +#include "cogl-attribute.h" +#include "cogl-attribute-private.h" +#include "cogl-attribute-gl-private.h" +#include "cogl-pipeline-progend-glsl-private.h" + +typedef struct _ForeachChangedBitState +{ + CoglContext *context; + const CoglBitmask *new_bits; + CoglPipeline *pipeline; +} ForeachChangedBitState; + +static CoglBool +toggle_builtin_attribute_enabled_cb (int bit_num, void *user_data) +{ + ForeachChangedBitState *state = user_data; + CoglContext *context = state->context; + + _COGL_RETURN_VAL_IF_FAIL (context->driver == COGL_DRIVER_GL || + context->driver == COGL_DRIVER_GLES1, + FALSE); + +#if defined (HAVE_COGL_GL) || defined (HAVE_COGL_GLES) + { + CoglBool enabled = _cogl_bitmask_get (state->new_bits, bit_num); + GLenum cap; + + switch (bit_num) + { + case COGL_ATTRIBUTE_NAME_ID_COLOR_ARRAY: + cap = GL_COLOR_ARRAY; + break; + case COGL_ATTRIBUTE_NAME_ID_POSITION_ARRAY: + cap = GL_VERTEX_ARRAY; + break; + case COGL_ATTRIBUTE_NAME_ID_NORMAL_ARRAY: + cap = GL_NORMAL_ARRAY; + break; + } + if (enabled) + GE (context, glEnableClientState (cap)); + else + GE (context, glDisableClientState (cap)); + } +#endif + + return TRUE; +} + +static CoglBool +toggle_texcood_attribute_enabled_cb (int bit_num, void *user_data) +{ + ForeachChangedBitState *state = user_data; + CoglContext *context = state->context; + + _COGL_RETURN_VAL_IF_FAIL (context->driver == COGL_DRIVER_GL || + context->driver == COGL_DRIVER_GLES1, + FALSE); + +#if defined (HAVE_COGL_GL) || defined (HAVE_COGL_GLES) + { + CoglBool enabled = _cogl_bitmask_get (state->new_bits, bit_num); + + GE( context, glClientActiveTexture (GL_TEXTURE0 + bit_num) ); + + if (enabled) + GE( context, glEnableClientState (GL_TEXTURE_COORD_ARRAY) ); + else + GE( context, glDisableClientState (GL_TEXTURE_COORD_ARRAY) ); + } +#endif + + return TRUE; +} + +static CoglBool +toggle_custom_attribute_enabled_cb (int bit_num, void *user_data) +{ + ForeachChangedBitState *state = user_data; + CoglBool enabled = _cogl_bitmask_get (state->new_bits, bit_num); + CoglContext *context = state->context; + + if (enabled) + GE( context, glEnableVertexAttribArray (bit_num) ); + else + GE( context, glDisableVertexAttribArray (bit_num) ); + + return TRUE; +} + +static void +foreach_changed_bit_and_save (CoglContext *context, + CoglBitmask *current_bits, + const CoglBitmask *new_bits, + CoglBitmaskForeachFunc callback, + ForeachChangedBitState *state) +{ + /* Get the list of bits that are different */ + _cogl_bitmask_clear_all (&context->changed_bits_tmp); + _cogl_bitmask_set_bits (&context->changed_bits_tmp, current_bits); + _cogl_bitmask_xor_bits (&context->changed_bits_tmp, new_bits); + + /* Iterate over each bit to change */ + state->new_bits = new_bits; + _cogl_bitmask_foreach (&context->changed_bits_tmp, + callback, + state); + + /* Store the new values */ + _cogl_bitmask_clear_all (current_bits); + _cogl_bitmask_set_bits (current_bits, new_bits); +} + +#ifdef COGL_PIPELINE_PROGEND_GLSL + +static void +setup_generic_attribute (CoglContext *context, + CoglPipeline *pipeline, + CoglAttribute *attribute, + uint8_t *base) +{ + int name_index = attribute->name_state->name_index; + int attrib_location = + _cogl_pipeline_progend_glsl_get_attrib_location (pipeline, name_index); + if (attrib_location != -1) + { + GE( context, glVertexAttribPointer (attrib_location, + attribute->n_components, + attribute->type, + attribute->normalized, + attribute->stride, + base + attribute->offset) ); + _cogl_bitmask_set (&context->enable_custom_attributes_tmp, + attrib_location, TRUE); + } +} + +#endif /* COGL_PIPELINE_PROGEND_GLSL */ + +static void +apply_attribute_enable_updates (CoglContext *context, + CoglPipeline *pipeline) +{ + ForeachChangedBitState changed_bits_state; + + changed_bits_state.context = context; + changed_bits_state.new_bits = &context->enable_builtin_attributes_tmp; + changed_bits_state.pipeline = pipeline; + + foreach_changed_bit_and_save (context, + &context->enabled_builtin_attributes, + &context->enable_builtin_attributes_tmp, + toggle_builtin_attribute_enabled_cb, + &changed_bits_state); + + changed_bits_state.new_bits = &context->enable_texcoord_attributes_tmp; + foreach_changed_bit_and_save (context, + &context->enabled_texcoord_attributes, + &context->enable_texcoord_attributes_tmp, + toggle_texcood_attribute_enabled_cb, + &changed_bits_state); + + changed_bits_state.new_bits = &context->enable_custom_attributes_tmp; + foreach_changed_bit_and_save (context, + &context->enabled_custom_attributes, + &context->enable_custom_attributes_tmp, + toggle_custom_attribute_enabled_cb, + &changed_bits_state); +} + +void +_cogl_gl_flush_attributes_state (CoglFramebuffer *framebuffer, + CoglPipeline *pipeline, + CoglFlushLayerState *layers_state, + CoglDrawFlags flags, + CoglAttribute **attributes, + int n_attributes) +{ + CoglContext *ctx = framebuffer->context; + int i; + CoglBool skip_gl_color = FALSE; + CoglPipeline *copy = NULL; + int n_tex_coord_attribs = 0; + + /* Iterate the attributes to work out whether blending needs to be + enabled and how many texture coords there are. We need to do this + before flushing the pipeline. */ + for (i = 0; i < n_attributes; i++) + switch (attributes[i]->name_state->name_id) + { + case COGL_ATTRIBUTE_NAME_ID_COLOR_ARRAY: + if ((flags & COGL_DRAW_COLOR_ATTRIBUTE_IS_OPAQUE) == 0 && + !_cogl_pipeline_get_real_blend_enabled (pipeline)) + { + CoglPipelineBlendEnable blend_enable = + COGL_PIPELINE_BLEND_ENABLE_ENABLED; + copy = cogl_pipeline_copy (pipeline); + _cogl_pipeline_set_blend_enabled (copy, blend_enable); + pipeline = copy; + } + skip_gl_color = TRUE; + break; + + case COGL_ATTRIBUTE_NAME_ID_TEXTURE_COORD_ARRAY: + n_tex_coord_attribs++; + break; + + default: + break; + } + + if (G_UNLIKELY (layers_state->options.flags)) + { + /* If we haven't already created a derived pipeline... */ + if (!copy) + { + copy = cogl_pipeline_copy (pipeline); + pipeline = copy; + } + _cogl_pipeline_apply_overrides (pipeline, &layers_state->options); + + /* TODO: + * overrides = cogl_pipeline_get_data (pipeline, + * last_overrides_key); + * if (overrides) + * { + * age = cogl_pipeline_get_age (pipeline); + * XXX: actually we also need to check for legacy_state + * and blending overrides for use of glColorPointer... + * if (overrides->ags != age || + * memcmp (&overrides->options, &options, + * sizeof (options) != 0) + * { + * cogl_object_unref (overrides->weak_pipeline); + * g_slice_free (Overrides, overrides); + * overrides = NULL; + * } + * } + * if (!overrides) + * { + * overrides = g_slice_new (Overrides); + * overrides->weak_pipeline = + * cogl_pipeline_weak_copy (pipeline); + * _cogl_pipeline_apply_overrides (overrides->weak_pipeline, + * &options); + * + * cogl_pipeline_set_data (pipeline, last_overrides_key, + * weak_overrides, + * free_overrides_cb, + * NULL); + * } + * pipeline = overrides->weak_pipeline; + */ + } + + _cogl_pipeline_flush_gl_state (pipeline, + framebuffer, + skip_gl_color, + n_tex_coord_attribs); + + _cogl_bitmask_clear_all (&ctx->enable_builtin_attributes_tmp); + _cogl_bitmask_clear_all (&ctx->enable_texcoord_attributes_tmp); + _cogl_bitmask_clear_all (&ctx->enable_custom_attributes_tmp); + + /* Bind the attribute pointers. We need to do this after the + * pipeline is flushed because when using GLSL that is the only + * point when we can determine the attribute locations */ + + for (i = 0; i < n_attributes; i++) + { + CoglAttribute *attribute = attributes[i]; + CoglAttributeBuffer *attribute_buffer; + CoglBuffer *buffer; + uint8_t *base; + + attribute_buffer = cogl_attribute_get_buffer (attribute); + buffer = COGL_BUFFER (attribute_buffer); + base = _cogl_buffer_bind (buffer, COGL_BUFFER_BIND_TARGET_ATTRIBUTE_BUFFER); + + switch (attribute->name_state->name_id) + { + case COGL_ATTRIBUTE_NAME_ID_COLOR_ARRAY: +#ifdef HAVE_COGL_GLES2 + if (ctx->driver == COGL_DRIVER_GLES2) + setup_generic_attribute (ctx, pipeline, attribute, base); + else +#endif + { + _cogl_bitmask_set (&ctx->enable_builtin_attributes_tmp, + COGL_ATTRIBUTE_NAME_ID_COLOR_ARRAY, TRUE); + GE (ctx, glColorPointer (attribute->n_components, + attribute->type, + attribute->stride, + base + attribute->offset)); + } + break; + case COGL_ATTRIBUTE_NAME_ID_NORMAL_ARRAY: +#ifdef HAVE_COGL_GLES2 + if (ctx->driver == COGL_DRIVER_GLES2) + setup_generic_attribute (ctx, pipeline, attribute, base); + else +#endif + { + _cogl_bitmask_set (&ctx->enable_builtin_attributes_tmp, + COGL_ATTRIBUTE_NAME_ID_NORMAL_ARRAY, TRUE); + GE (ctx, glNormalPointer (attribute->type, + attribute->stride, + base + attribute->offset)); + } + break; + case COGL_ATTRIBUTE_NAME_ID_TEXTURE_COORD_ARRAY: +#ifdef HAVE_COGL_GLES2 + if (ctx->driver == COGL_DRIVER_GLES2) + setup_generic_attribute (ctx, pipeline, attribute, base); + else +#endif + { + _cogl_bitmask_set (&ctx->enable_texcoord_attributes_tmp, + attribute->name_state->texture_unit, TRUE); + GE (ctx, + glClientActiveTexture (GL_TEXTURE0 + + attribute->name_state->texture_unit)); + GE (ctx, glTexCoordPointer (attribute->n_components, + attribute->type, + attribute->stride, + base + attribute->offset)); + } + break; + case COGL_ATTRIBUTE_NAME_ID_POSITION_ARRAY: +#ifdef HAVE_COGL_GLES2 + if (ctx->driver == COGL_DRIVER_GLES2) + setup_generic_attribute (ctx, pipeline, attribute, base); + else +#endif + { + _cogl_bitmask_set (&ctx->enable_builtin_attributes_tmp, + COGL_ATTRIBUTE_NAME_ID_POSITION_ARRAY, TRUE); + GE (ctx, glVertexPointer (attribute->n_components, + attribute->type, + attribute->stride, + base + attribute->offset)); + } + break; + case COGL_ATTRIBUTE_NAME_ID_CUSTOM_ARRAY: +#ifdef COGL_PIPELINE_PROGEND_GLSL + if (ctx->driver != COGL_DRIVER_GLES1) + setup_generic_attribute (ctx, pipeline, attribute, base); +#endif + break; + default: + g_warning ("Unrecognised attribute type 0x%08x", attribute->type); + } + + _cogl_buffer_unbind (buffer); + } + + apply_attribute_enable_updates (ctx, pipeline); + + if (copy) + cogl_object_unref (copy); +} diff --git a/cogl/driver/gl/gl/cogl-driver-gl.c b/cogl/driver/gl/gl/cogl-driver-gl.c index 7bb172637..761f87a65 100644 --- a/cogl/driver/gl/gl/cogl-driver-gl.c +++ b/cogl/driver/gl/gl/cogl-driver-gl.c @@ -35,6 +35,7 @@ #include "cogl-error-private.h" #include "cogl-framebuffer-gl-private.h" #include "cogl-texture-2d-gl-private.h" +#include "cogl-attribute-gl-private.h" static CoglBool _cogl_driver_pixel_format_from_gl_internal (CoglContext *context, @@ -548,4 +549,5 @@ _cogl_driver_gl = _cogl_texture_2d_gl_generate_mipmap, _cogl_texture_2d_gl_copy_from_bitmap, _cogl_texture_2d_gl_get_data, + _cogl_gl_flush_attributes_state, }; diff --git a/cogl/driver/gl/gles/cogl-driver-gles.c b/cogl/driver/gl/gles/cogl-driver-gles.c index b8c0168d9..02a167645 100644 --- a/cogl/driver/gl/gles/cogl-driver-gles.c +++ b/cogl/driver/gl/gles/cogl-driver-gles.c @@ -34,6 +34,7 @@ #include "cogl-private.h" #include "cogl-framebuffer-gl-private.h" #include "cogl-texture-2d-gl-private.h" +#include "cogl-attribute-gl-private.h" #ifndef GL_UNSIGNED_INT_24_8 #define GL_UNSIGNED_INT_24_8 0x84FA @@ -366,4 +367,5 @@ _cogl_driver_gles = _cogl_texture_2d_gl_generate_mipmap, _cogl_texture_2d_gl_copy_from_bitmap, NULL, /* texture_2d_get_data */ + _cogl_gl_flush_attributes_state, };