From 74cd43e01caeee7c0f81ebffa06b1e2932e7e089 Mon Sep 17 00:00:00 2001 From: Neil Roberts Date: Fri, 20 Feb 2009 15:56:57 +0000 Subject: [PATCH] [cogl-gles2-wrapper] Convert texture unit settings to be a static sized array Previously the texture unit settings were stored in growable GArrays and every time a new texture unit was encountered it would expand the arrays. However the array wasn't copied when stored in a CoglGles2WrapperSettings struct so all settings had the same array. This meant that it wouldn't detect that a different program is needed if a texture unit is disabled or enabled. The texture unit settings arrays are all now a fixed size and the enabledness of each unit is stored in a bit mask. Therefore the settings can just be copied around by assignment as before. This puts a limit on the number of texture units accessible by Cogl but I think it is worth it to make the code simpler and more efficient. The material API already poses a limit on the number of texture units it can use. --- gles/cogl-gles2-wrapper.c | 438 ++++++++++++++++++-------------------- gles/cogl-gles2-wrapper.h | 36 ++-- 2 files changed, 226 insertions(+), 248 deletions(-) diff --git a/gles/cogl-gles2-wrapper.c b/gles/cogl-gles2-wrapper.c index 5551ceb16..e7a4619f9 100644 --- a/gles/cogl-gles2-wrapper.c +++ b/gles/cogl-gles2-wrapper.c @@ -107,6 +107,40 @@ cogl_gles2_wrapper_create_shader (GLenum type, const char *source) return shader; } +static void +initialize_texture_units (CoglGles2Wrapper *w) +{ + /* We save the active texture unit since we may need to temporarily + * change this to initialise each new texture unit and we want to + * restore the active unit afterwards */ + int initial_active_unit = w->active_texture_unit; + GLint prev_mode; + int i; + + /* We will need to set the matrix mode to GL_TEXTURE to + * initialise any new texture units, so we save the current + * mode for restoring afterwards */ + GE( cogl_wrap_glGetIntegerv (CGL_MATRIX_MODE, &prev_mode)); + + for (i = 0; i < COGL_GLES2_MAX_TEXTURE_UNITS; i++) + { + CoglGles2WrapperTextureUnit *new_unit; + + new_unit = w->texture_units + i; + memset (new_unit, 0, sizeof (CoglGles2WrapperTextureUnit)); + + w->active_texture_unit = i; + GE( cogl_wrap_glMatrixMode (GL_TEXTURE)); + GE( cogl_wrap_glLoadIdentity ()); + } + + GE( cogl_wrap_glMatrixMode ((GLenum) prev_mode)); + + w->settings.texture_units = 0; + + w->active_texture_unit = initial_active_unit; +} + void cogl_gles2_wrapper_init (CoglGles2Wrapper *wrapper) { @@ -120,9 +154,6 @@ cogl_gles2_wrapper_init (CoglGles2Wrapper *wrapper) cogl_wrap_glMatrixMode (GL_MODELVIEW); cogl_wrap_glLoadIdentity (); - wrapper->texture_units = - g_array_new (FALSE, FALSE, sizeof (CoglGles2WrapperTextureUnit *)); - /* The gl*ActiveTexture wrappers will initialise the texture * stack for the texture unit when it's first activated */ cogl_wrap_glActiveTexture (GL_TEXTURE0); @@ -139,6 +170,8 @@ cogl_gles2_wrapper_init (CoglGles2Wrapper *wrapper) /* Initialize alpha testing */ cogl_wrap_glDisable (GL_ALPHA_TEST); cogl_wrap_glAlphaFunc (GL_ALWAYS, 0.0f); + + initialize_texture_units (wrapper); } static gboolean @@ -147,17 +180,11 @@ cogl_gles2_settings_equal (const CoglGles2WrapperSettings *a, gboolean vertex_tests, gboolean fragment_tests) { + if (a->texture_units != b->texture_units) + return FALSE; + if (fragment_tests) { - int i; - for (i = 0; i < a->n_texture_units; i++) - { - if (a->texture_units[i].enabled != b->texture_units[i].enabled) - return FALSE; - if (a->texture_units[i].alpha_only != b->texture_units[i].alpha_only) - return FALSE; - } - if (a->alpha_test_enabled != b->alpha_test_enabled) return FALSE; if (a->alpha_test_enabled && a->alpha_test_func != b->alpha_test_func) @@ -181,6 +208,7 @@ cogl_gles2_get_vertex_shader (const CoglGles2WrapperSettings *settings) CoglGles2WrapperShader *shader; GSList *node; int i; + int n_texture_units = 0; _COGL_GET_GLES2_WRAPPER (w, NULL); @@ -195,43 +223,47 @@ cogl_gles2_get_vertex_shader (const CoglGles2WrapperSettings *settings) /* Otherwise create a new shader */ shader_source = g_string_new (cogl_fixed_vertex_shader_per_vertex_attribs); - for (i = 0; i < settings->n_texture_units; i++) - { - if (!settings->texture_units[i].enabled) - continue; + for (i = 0; i < COGL_GLES2_MAX_TEXTURE_UNITS; i++) + if (COGL_GLES2_TEXTURE_UNIT_IS_ENABLED (settings->texture_units, i)) g_string_append_printf (shader_source, "attribute vec4 multi_tex_coord_attrib%d;\n", i); - } + + /* Find the biggest enabled texture unit index */ + for (i = 0; i < COGL_GLES2_MAX_TEXTURE_UNITS; i++) + if (COGL_GLES2_TEXTURE_UNIT_IS_ENABLED (settings->texture_units, i)) + n_texture_units = i + 1; g_string_append (shader_source, cogl_fixed_vertex_shader_transform_matrices); - g_string_append_printf (shader_source, - "uniform mat4 texture_matrix[%d];\n", - settings->n_texture_units); - g_string_append (shader_source, cogl_fixed_vertex_shader_output_variables); - g_string_append_printf (shader_source, - "varying vec2 tex_coord[%d];", - settings->n_texture_units); + + if (n_texture_units > 0) + { + g_string_append_printf (shader_source, + "uniform mat4 texture_matrix[%d];\n", + n_texture_units); + + g_string_append_printf (shader_source, + "varying vec2 tex_coord[%d];", + n_texture_units); + } g_string_append (shader_source, cogl_fixed_vertex_shader_fogging_options); g_string_append (shader_source, cogl_fixed_vertex_shader_main_start); - for (i = 0; i < settings->n_texture_units; i++) - { - if (!settings->texture_units[i].enabled) - continue; - - g_string_append_printf (shader_source, - "transformed_tex_coord = " - "texture_matrix[%d] " - " * multi_tex_coord_attrib%d;\n", - i, i); - g_string_append_printf (shader_source, - "tex_coord[%d] = transformed_tex_coord.st " - " / transformed_tex_coord.q;\n", - i); - } + for (i = 0; i < COGL_GLES2_MAX_TEXTURE_UNITS; i++) + if (COGL_GLES2_TEXTURE_UNIT_IS_ENABLED (settings->texture_units, i)) + { + g_string_append_printf (shader_source, + "transformed_tex_coord = " + "texture_matrix[%d] " + " * multi_tex_coord_attrib%d;\n", + i, i); + g_string_append_printf (shader_source, + "tex_coord[%d] = transformed_tex_coord.st " + " / transformed_tex_coord.q;\n", + i); + } g_string_append (shader_source, cogl_fixed_vertex_shader_frag_color_start); @@ -285,6 +317,7 @@ cogl_gles2_get_fragment_shader (const CoglGles2WrapperSettings *settings) CoglGles2WrapperShader *shader; GSList *node; int i; + int n_texture_units = 0; _COGL_GET_GLES2_WRAPPER (w, NULL); @@ -299,15 +332,24 @@ cogl_gles2_get_fragment_shader (const CoglGles2WrapperSettings *settings) /* Otherwise create a new shader */ shader_source = g_string_new (cogl_fixed_fragment_shader_variables_start); - g_string_append (shader_source, cogl_fixed_fragment_shader_inputs); - g_string_append_printf (shader_source, - "varying vec2 tex_coord[%d];\n", - settings->n_texture_units); + /* Find the biggest enabled texture unit index */ + for (i = 0; i < COGL_GLES2_MAX_TEXTURE_UNITS; i++) + if (COGL_GLES2_TEXTURE_UNIT_IS_ENABLED (settings->texture_units, i)) + n_texture_units = i + 1; - g_string_append (shader_source, cogl_fixed_fragment_shader_texturing_options); - g_string_append_printf (shader_source, - "uniform sampler2D texture_unit[%d];\n", - settings->n_texture_units); + g_string_append (shader_source, cogl_fixed_fragment_shader_inputs); + + if (n_texture_units > 0) + { + g_string_append_printf (shader_source, + "varying vec2 tex_coord[%d];\n", + n_texture_units); + + g_string_append (shader_source, cogl_fixed_fragment_shader_texturing_options); + g_string_append_printf (shader_source, + "uniform sampler2D texture_unit[%d];\n", + n_texture_units); + } g_string_append (shader_source, cogl_fixed_fragment_shader_fogging_options); @@ -318,37 +360,30 @@ cogl_gles2_get_fragment_shader (const CoglGles2WrapperSettings *settings) /* This pointless extra variable is needed to work around an apparent bug in the PowerVR drivers. Without it the alpha blending seems to stop working */ - /* g_string_append (shader_source, "gl_FragColor = frag_color;\n"); - */ g_string_append (shader_source, "vec4 frag_color_copy = frag_color;\n"); g_string_append (shader_source, "gl_FragColor = frag_color;\n"); - for (i = 0; i < settings->n_texture_units; i++) - { - if (settings->texture_units[i].alpha_only) - { - /* If the texture only has an alpha channel (eg, with the textures - from the pango renderer) then the RGB components will be - black. We want to use the RGB from the current color in that - case */ - g_string_append_printf ( - shader_source, - "gl_FragColor.a *= " - "texture2D (texture_unit[%d], tex_coord[%d]).a;\n", - i, i); - } - else - { - g_string_append_printf ( - shader_source, - "gl_FragColor *= " - "texture2D (texture_unit[%d], tex_coord[%d]);\n", - i, i); - } - } - if (i == 0) - g_string_append (shader_source, "gl_FragColor = frag_color;\n"); + for (i = 0; i < n_texture_units; i++) + if (COGL_GLES2_TEXTURE_UNIT_IS_ENABLED (settings->texture_units, i)) + { + if (COGL_GLES2_TEXTURE_UNIT_IS_ALPHA_ONLY (settings->texture_units, i)) + /* If the texture only has an alpha channel (eg, with the textures + from the pango renderer) then the RGB components will be + black. We want to use the RGB from the current color in that + case */ + g_string_append_printf (shader_source, + "gl_FragColor.a *= " + "texture2D (texture_unit[%d], " + "tex_coord[%d]).a;\n", + i, i); + else + g_string_append_printf (shader_source, + "gl_FragColor *= " + "texture2D (texture_unit[%d], " + "tex_coord[%d]);\n", + i, i); + } if (settings->fog_enabled) g_string_append (shader_source, cogl_fixed_fragment_shader_fog); @@ -418,31 +453,31 @@ cogl_gles2_wrapper_get_locations (GLuint program, uniforms->modelview_matrix_uniform = glGetUniformLocation (program, "modelview_matrix"); - uniforms->texture_matrix_uniforms = - g_array_new (FALSE, FALSE, sizeof (GLint)); - uniforms->texture_sampler_uniforms = - g_array_new (FALSE, FALSE, sizeof (GLint)); - attribs->multi_texture_coords = - g_array_new (FALSE, FALSE, sizeof (GLint)); - for (i = 0; i < settings->n_texture_units; i++) - { - char *matrix_var_name = g_strdup_printf ("texture_matrix[%d]", i); - char *sampler_var_name = g_strdup_printf ("texture_unit[%d]", i); - char *tex_coord_var_name = - g_strdup_printf ("multi_tex_coord_attrib%d", i); - GLint location; + for (i = 0; i < COGL_GLES2_MAX_TEXTURE_UNITS; i++) + if (COGL_GLES2_TEXTURE_UNIT_IS_ENABLED (settings->texture_units, i)) + { + char *matrix_var_name = g_strdup_printf ("texture_matrix[%d]", i); + char *sampler_var_name = g_strdup_printf ("texture_unit[%d]", i); + char *tex_coord_var_name = + g_strdup_printf ("multi_tex_coord_attrib%d", i); - location = glGetUniformLocation (program, matrix_var_name); - g_array_append_val (uniforms->texture_matrix_uniforms, location); - location = glGetUniformLocation (program, sampler_var_name); - g_array_append_val (uniforms->texture_sampler_uniforms, location); - location = glGetAttribLocation (program, tex_coord_var_name); - g_array_append_val (attribs->multi_texture_coords, location); + uniforms->texture_matrix_uniforms[i] + = glGetUniformLocation (program, matrix_var_name); + uniforms->texture_sampler_uniforms[i] + = glGetUniformLocation (program, sampler_var_name); + attribs->multi_texture_coords[i] + = glGetAttribLocation (program, tex_coord_var_name); - g_free (tex_coord_var_name); - g_free (sampler_var_name); - g_free (matrix_var_name); - } + g_free (tex_coord_var_name); + g_free (sampler_var_name); + g_free (matrix_var_name); + } + else + { + uniforms->texture_matrix_uniforms[i] = -1; + uniforms->texture_sampler_uniforms[i] = -1; + attribs->multi_texture_coords[i] = -1; + } uniforms->fog_density_uniform = glGetUniformLocation (program, "fog_density"); @@ -633,9 +668,7 @@ cogl_gles2_wrapper_update_matrix (CoglGles2Wrapper *wrapper, GLenum matrix_num) case GL_TEXTURE: wrapper->dirty_uniforms |= COGL_GLES2_DIRTY_TEXTURE_MATRICES; - texture_unit = g_array_index (wrapper->texture_units, - CoglGles2WrapperTextureUnit *, - wrapper->active_texture_unit); + texture_unit = wrapper->texture_units + wrapper->active_texture_unit; texture_unit->dirty_matrix = 1; break; } @@ -671,9 +704,7 @@ cogl_wrap_glPushMatrix () case GL_TEXTURE: { CoglGles2WrapperTextureUnit *texture_unit; - texture_unit = g_array_index (w->texture_units, - CoglGles2WrapperTextureUnit *, - w->active_texture_unit); + texture_unit = w->texture_units + w->active_texture_unit; src = texture_unit->texture_stack + texture_unit->texture_stack_pos * 16; texture_unit->texture_stack_pos = (texture_unit->texture_stack_pos + 1) @@ -709,9 +740,7 @@ cogl_wrap_glPopMatrix () break; case GL_TEXTURE: - texture_unit = g_array_index (w->texture_units, - CoglGles2WrapperTextureUnit *, - w->active_texture_unit); + texture_unit = w->texture_units + w->active_texture_unit; texture_unit->texture_stack_pos = (texture_unit->texture_stack_pos - 1) & (COGL_GLES2_TEXTURE_STACK_SIZE - 1); break; @@ -744,10 +773,7 @@ cogl_gles2_get_matrix_stack_top (CoglGles2Wrapper *wrapper) return wrapper->projection_stack + wrapper->projection_stack_pos * 16; case GL_TEXTURE: - - texture_unit = g_array_index (wrapper->texture_units, - CoglGles2WrapperTextureUnit *, - wrapper->active_texture_unit); + texture_unit = wrapper->texture_units + wrapper->active_texture_unit; return texture_unit->texture_stack + texture_unit->texture_stack_pos * 16; } @@ -951,9 +977,7 @@ cogl_wrap_glTexCoordPointer (GLint size, GLenum type, GLsizei stride, active_unit = w->active_client_texture_unit; - texture_unit = g_array_index (w->texture_units, - CoglGles2WrapperTextureUnit *, - active_unit); + texture_unit = w->texture_units + active_unit; texture_unit->texture_coords_size = size; texture_unit->texture_coords_type = type; texture_unit->texture_coords_stride = stride; @@ -1109,16 +1133,12 @@ cogl_wrap_prepare_for_draw (void) /* TODO - we should probably have a per unit dirty flag too */ - for (i = 0; i < program->uniforms.texture_matrix_uniforms->len; i++) + for (i = 0; i < COGL_GLES2_MAX_TEXTURE_UNITS; i++) { CoglGles2WrapperTextureUnit *texture_unit; - GLint uniform = - g_array_index (program->uniforms.texture_matrix_uniforms, - GLint, i); + GLint uniform = program->uniforms.texture_matrix_uniforms[i]; - texture_unit = g_array_index (w->texture_units, - CoglGles2WrapperTextureUnit *, - i); + texture_unit = w->texture_units + i; if (uniform != -1) glUniformMatrix4fv (uniform, 1, GL_FALSE, texture_unit->texture_stack @@ -1147,11 +1167,9 @@ cogl_wrap_prepare_for_draw (void) /* TODO - we should probably have a per unit dirty flag too */ - for (i = 0; i < program->uniforms.texture_sampler_uniforms->len; i++) + for (i = 0; i < COGL_GLES2_MAX_TEXTURE_UNITS; i++) { - GLint uniform = - g_array_index (program->uniforms.texture_sampler_uniforms, - GLint, i); + GLint uniform = program->uniforms.texture_sampler_uniforms[i]; if (uniform != -1) glUniform1i (uniform, i); @@ -1194,33 +1212,27 @@ cogl_wrap_prepare_for_draw (void) int i; /* TODO - coverage test */ - for (i = 0; i < w->settings.n_texture_units; i++) - { - GLint tex_coord_var_index; - CoglGles2WrapperTextureUnit *texture_unit; + for (i = 0; i < COGL_GLES2_MAX_TEXTURE_UNITS; i++) + if (COGL_GLES2_TEXTURE_UNIT_IS_ENABLED (w->settings.texture_units, i)) + { + GLint tex_coord_var_index; + CoglGles2WrapperTextureUnit *texture_unit; - if (!w->settings.texture_units[i].enabled) - continue; + texture_unit = w->texture_units + w->active_texture_unit; + if (!texture_unit->texture_coords_enabled) + continue; - texture_unit = g_array_index (w->texture_units, - CoglGles2WrapperTextureUnit *, - w->active_texture_unit); - if (!texture_unit->texture_coords_enabled) - continue; + /* TODO - we should probably have a per unit dirty flag too */ - /* TODO - we should probably have a per unit dirty flag too */ - - /* TODO - coverage test */ - tex_coord_var_index = - g_array_index (program->attributes.multi_texture_coords, - GLint, i); - glVertexAttribPointer (tex_coord_var_index, - texture_unit->texture_coords_size, - texture_unit->texture_coords_type, - GL_FALSE, - texture_unit->texture_coords_stride, - texture_unit->texture_coords_pointer); - } + /* TODO - coverage test */ + tex_coord_var_index = program->attributes.multi_texture_coords[i]; + glVertexAttribPointer (tex_coord_var_index, + texture_unit->texture_coords_size, + texture_unit->texture_coords_type, + GL_FALSE, + texture_unit->texture_coords_stride, + texture_unit->texture_coords_pointer); + } } if (w->dirty_vertex_attrib_enables) @@ -1231,22 +1243,22 @@ cogl_wrap_prepare_for_draw (void) /* TODO - we should probably have a per unit dirty flag too */ - for (i = 0; i < w->texture_units->len; i++) + for (i = 0; i < COGL_GLES2_MAX_TEXTURE_UNITS; i++) { - CoglGles2WrapperTextureUnit *texture_unit = - g_array_index (w->texture_units, - CoglGles2WrapperTextureUnit *, - w->active_texture_unit); - if (texture_unit->texture_coords_enabled) - glEnableVertexAttribArray ( - g_array_index (program->attributes.multi_texture_coords, - GLint, i)); - else - glDisableVertexAttribArray ( - g_array_index (program->attributes.multi_texture_coords, - GLint, i)); - w->dirty_vertex_attrib_enables = 0; + CoglGles2WrapperTextureUnit *texture_unit + = w->texture_units + w->active_texture_unit; + GLint attrib = program->attributes.multi_texture_coords[i]; + + if (attrib != -1) + { + if (texture_unit->texture_coords_enabled) + glEnableVertexAttribArray (attrib); + else + glDisableVertexAttribArray (attrib); + } } + + w->dirty_vertex_attrib_enables = 0; } } @@ -1278,10 +1290,15 @@ cogl_gles2_wrapper_bind_texture (GLenum target, GLuint texture, /* We need to keep track of whether the texture is alpha-only because the emulation of GL_MODULATE needs to work differently in that case */ - _COGL_GLES2_CHANGE_SETTING ( - w, texture_units[w->active_texture_unit].alpha_only, - internal_format == GL_ALPHA); - + if (COGL_GLES2_TEXTURE_UNIT_IS_ALPHA_ONLY (w->settings.texture_units, + w->active_texture_unit) + != (internal_format == GL_ALPHA)) + { + COGL_GLES2_TEXTURE_UNIT_SET_ALPHA_ONLY (w->settings.texture_units, + w->active_texture_unit, + internal_format == GL_ALPHA); + w->settings_dirty = TRUE; + } } void @@ -1292,66 +1309,14 @@ cogl_wrap_glTexEnvi (GLenum target, GLenum pname, GLfloat param) nothing needs to be done here. */ } -static void -realize_texture_units (CoglGles2Wrapper *w, int texture_unit_index) -{ - /* We save the active texture unit since we may need to temporarily - * change this to initialise each new texture unit and we want to - * restore the active unit afterwards */ - int initial_active_unit = w->active_texture_unit; - - if (texture_unit_index >= w->settings.n_texture_units) - { - int n_new_texture_units = - texture_unit_index + 1 - w->settings.n_texture_units; - GLint prev_mode; - int i; - - w->settings.texture_units = - g_realloc (w->settings.texture_units, - texture_unit_index + 1 - * sizeof (CoglGles2WrapperTextureUnitSettings)); - - /* We will need to set the matrix mode to GL_TEXTURE to - * initialise any new texture units, so we save the current - * mode for restoring afterwards */ - GE( cogl_wrap_glGetIntegerv (CGL_MATRIX_MODE, &prev_mode)); - - for (i = 0; i < n_new_texture_units; i++) - { - CoglGles2WrapperTextureUnit *new_unit; - CoglGles2WrapperTextureUnitSettings *new_unit_settings; - - new_unit = g_new0 (CoglGles2WrapperTextureUnit, 1); - g_array_append_val (w->texture_units, new_unit); - - w->active_texture_unit = i; - GE( cogl_wrap_glMatrixMode (GL_TEXTURE)); - GE( cogl_wrap_glLoadIdentity ()); - - new_unit_settings = - &w->settings.texture_units[w->settings.n_texture_units + i]; - new_unit_settings->enabled = FALSE; - new_unit_settings->alpha_only = FALSE; - } - - GE( cogl_wrap_glMatrixMode ((GLenum)prev_mode)); - - w->settings.n_texture_units = w->texture_units->len; - } - - w->active_texture_unit = initial_active_unit; -} - void cogl_wrap_glClientActiveTexture (GLenum texture) { int texture_unit_index = texture - GL_TEXTURE0; _COGL_GET_GLES2_WRAPPER (w, NO_RETVAL); - w->active_client_texture_unit = texture_unit_index; - - realize_texture_units (w, texture_unit_index); + if (texture_unit_index < COGL_GLES2_MAX_TEXTURE_UNITS) + w->active_client_texture_unit = texture_unit_index; } void @@ -1360,9 +1325,8 @@ cogl_wrap_glActiveTexture (GLenum texture) int texture_unit_index = texture - GL_TEXTURE0; _COGL_GET_GLES2_WRAPPER (w, NO_RETVAL); - w->active_texture_unit = texture_unit_index; - - realize_texture_units (w, texture_unit_index); + if (texture_unit_index < COGL_GLES2_MAX_TEXTURE_UNITS) + w->active_texture_unit = texture_unit_index; } void @@ -1373,8 +1337,14 @@ cogl_wrap_glEnable (GLenum cap) switch (cap) { case GL_TEXTURE_2D: - _COGL_GLES2_CHANGE_SETTING ( - w, texture_units[w->active_texture_unit].enabled, TRUE); + if (!COGL_GLES2_TEXTURE_UNIT_IS_ENABLED (w->settings.texture_units, + w->active_texture_unit)) + { + COGL_GLES2_TEXTURE_UNIT_SET_ENABLED (w->settings.texture_units, + w->active_texture_unit, + TRUE); + w->settings_dirty = TRUE; + } break; case GL_FOG: @@ -1398,8 +1368,14 @@ cogl_wrap_glDisable (GLenum cap) switch (cap) { case GL_TEXTURE_2D: - _COGL_GLES2_CHANGE_SETTING ( - w, texture_units[w->active_texture_unit].enabled, FALSE); + if (COGL_GLES2_TEXTURE_UNIT_IS_ENABLED (w->settings.texture_units, + w->active_texture_unit)) + { + COGL_GLES2_TEXTURE_UNIT_SET_ENABLED (w->settings.texture_units, + w->active_texture_unit, + FALSE); + w->settings_dirty = TRUE; + } break; case GL_FOG: @@ -1429,9 +1405,7 @@ cogl_wrap_glEnableClientState (GLenum array) case GL_TEXTURE_COORD_ARRAY: /* TODO - review if this should be in w->settings? */ - texture_unit = g_array_index (w->texture_units, - CoglGles2WrapperTextureUnit *, - w->active_texture_unit); + texture_unit = w->texture_units + w->active_texture_unit; if (texture_unit->texture_coords_enabled != 1) { texture_unit->texture_coords_enabled = 1; @@ -1461,9 +1435,7 @@ cogl_wrap_glDisableClientState (GLenum array) break; case GL_TEXTURE_COORD_ARRAY: - texture_unit = g_array_index (w->texture_units, - CoglGles2WrapperTextureUnit *, - w->active_texture_unit); + texture_unit = w->texture_units + w->active_texture_unit; /* TODO - review if this should be in w->settings? */ if (texture_unit->texture_coords_enabled != 0) { diff --git a/gles/cogl-gles2-wrapper.h b/gles/cogl-gles2-wrapper.h index 4ae3370ab..ec6860b03 100644 --- a/gles/cogl-gles2-wrapper.h +++ b/gles/cogl-gles2-wrapper.h @@ -52,6 +52,20 @@ typedef struct _CoglGles2WrapperShader CoglGles2WrapperShader; #define COGL_GLES2_PROJECTION_STACK_SIZE 2 #define COGL_GLES2_TEXTURE_STACK_SIZE 2 +/* Accessors for the texture unit bit mask */ +#define COGL_GLES2_TEXTURE_UNIT_IS_ENABLED(mask, unit) \ + (((mask) & (1 << ((unit) * 2))) ? TRUE : FALSE) +#define COGL_GLES2_TEXTURE_UNIT_IS_ALPHA_ONLY(mask, unit) \ + (((mask) & (1 << ((unit) * 2 + 1))) ? TRUE : FALSE) +#define COGL_GLES2_SET_BIT(mask, bit, val) \ + ((val) ? ((mask) |= (1 << (bit))) : ((mask) &= ~(1 << (bit)))) +#define COGL_GLES2_TEXTURE_UNIT_SET_ENABLED(mask, unit, val) \ + COGL_GLES2_SET_BIT ((mask), (unit) * 2, (val)) +#define COGL_GLES2_TEXTURE_UNIT_SET_ALPHA_ONLY(mask, unit, val) \ + COGL_GLES2_SET_BIT ((mask), (unit) * 2 + 1, (val)) + +#define COGL_GLES2_MAX_TEXTURE_UNITS (sizeof (guint32) * 8 / 2) + /* Dirty flags for shader uniforms */ enum { @@ -82,16 +96,15 @@ enum struct _CoglGles2WrapperAttributes { - GArray *multi_texture_coords; + GLint multi_texture_coords[COGL_GLES2_MAX_TEXTURE_UNITS]; }; struct _CoglGles2WrapperUniforms { GLint mvp_matrix_uniform; GLint modelview_matrix_uniform; - GArray *texture_matrix_uniforms; - - GArray *texture_sampler_uniforms; + GLint texture_matrix_uniforms[COGL_GLES2_MAX_TEXTURE_UNITS]; + GLint texture_sampler_uniforms[COGL_GLES2_MAX_TEXTURE_UNITS]; GLint fog_density_uniform; GLint fog_start_uniform; @@ -100,14 +113,7 @@ struct _CoglGles2WrapperUniforms GLint alpha_test_ref_uniform; - GLint texture_unit_uniform; -}; - -struct _CoglGles2WrapperTextureUnitSettings -{ - guint enabled:1; - guint alpha_only:1; - /* TODO: blending state */ + GLint texture_unit_uniform; }; /* NB: We get a copy of this for each fragment/vertex @@ -115,8 +121,7 @@ struct _CoglGles2WrapperTextureUnitSettings * fairly lean */ struct _CoglGles2WrapperSettings { - CoglGles2WrapperTextureUnitSettings *texture_units; - guint n_texture_units; + guint32 texture_units; GLint alpha_test_func; GLint fog_mode; @@ -149,10 +154,11 @@ struct _CoglGles2Wrapper GLuint modelview_stack_pos; GLfloat projection_stack[COGL_GLES2_PROJECTION_STACK_SIZE * 16]; GLuint projection_stack_pos; - GArray *texture_units; guint active_texture_unit; guint active_client_texture_unit; + CoglGles2WrapperTextureUnit texture_units[COGL_GLES2_MAX_TEXTURE_UNITS]; + /* The combined modelview and projection matrix is only updated at the last minute in glDrawArrays to avoid recalculating it for every change to the modelview matrix */