mirror of
https://github.com/brl/mutter.git
synced 2024-11-27 02:20:43 -05:00
[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.
This commit is contained in:
parent
21aa09748c
commit
b0df99fbad
@ -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)
|
||||
{
|
||||
|
@ -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 */
|
||||
|
Loading…
Reference in New Issue
Block a user