[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;
|
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
|
void
|
||||||
cogl_gles2_wrapper_init (CoglGles2Wrapper *wrapper)
|
cogl_gles2_wrapper_init (CoglGles2Wrapper *wrapper)
|
||||||
{
|
{
|
||||||
@ -120,9 +154,6 @@ cogl_gles2_wrapper_init (CoglGles2Wrapper *wrapper)
|
|||||||
cogl_wrap_glMatrixMode (GL_MODELVIEW);
|
cogl_wrap_glMatrixMode (GL_MODELVIEW);
|
||||||
cogl_wrap_glLoadIdentity ();
|
cogl_wrap_glLoadIdentity ();
|
||||||
|
|
||||||
wrapper->texture_units =
|
|
||||||
g_array_new (FALSE, FALSE, sizeof (CoglGles2WrapperTextureUnit *));
|
|
||||||
|
|
||||||
/* The gl*ActiveTexture wrappers will initialise the texture
|
/* The gl*ActiveTexture wrappers will initialise the texture
|
||||||
* stack for the texture unit when it's first activated */
|
* stack for the texture unit when it's first activated */
|
||||||
cogl_wrap_glActiveTexture (GL_TEXTURE0);
|
cogl_wrap_glActiveTexture (GL_TEXTURE0);
|
||||||
@ -139,6 +170,8 @@ cogl_gles2_wrapper_init (CoglGles2Wrapper *wrapper)
|
|||||||
/* Initialize alpha testing */
|
/* Initialize alpha testing */
|
||||||
cogl_wrap_glDisable (GL_ALPHA_TEST);
|
cogl_wrap_glDisable (GL_ALPHA_TEST);
|
||||||
cogl_wrap_glAlphaFunc (GL_ALWAYS, 0.0f);
|
cogl_wrap_glAlphaFunc (GL_ALWAYS, 0.0f);
|
||||||
|
|
||||||
|
initialize_texture_units (wrapper);
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
@ -147,17 +180,11 @@ cogl_gles2_settings_equal (const CoglGles2WrapperSettings *a,
|
|||||||
gboolean vertex_tests,
|
gboolean vertex_tests,
|
||||||
gboolean fragment_tests)
|
gboolean fragment_tests)
|
||||||
{
|
{
|
||||||
|
if (a->texture_units != b->texture_units)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
if (fragment_tests)
|
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)
|
if (a->alpha_test_enabled != b->alpha_test_enabled)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
if (a->alpha_test_enabled && a->alpha_test_func != b->alpha_test_func)
|
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;
|
CoglGles2WrapperShader *shader;
|
||||||
GSList *node;
|
GSList *node;
|
||||||
int i;
|
int i;
|
||||||
|
int n_texture_units = 0;
|
||||||
|
|
||||||
_COGL_GET_GLES2_WRAPPER (w, NULL);
|
_COGL_GET_GLES2_WRAPPER (w, NULL);
|
||||||
|
|
||||||
@ -195,43 +223,47 @@ cogl_gles2_get_vertex_shader (const CoglGles2WrapperSettings *settings)
|
|||||||
/* Otherwise create a new shader */
|
/* Otherwise create a new shader */
|
||||||
shader_source = g_string_new (cogl_fixed_vertex_shader_per_vertex_attribs);
|
shader_source = g_string_new (cogl_fixed_vertex_shader_per_vertex_attribs);
|
||||||
|
|
||||||
for (i = 0; i < settings->n_texture_units; i++)
|
for (i = 0; i < COGL_GLES2_MAX_TEXTURE_UNITS; i++)
|
||||||
{
|
if (COGL_GLES2_TEXTURE_UNIT_IS_ENABLED (settings->texture_units, i))
|
||||||
if (!settings->texture_units[i].enabled)
|
|
||||||
continue;
|
|
||||||
g_string_append_printf (shader_source,
|
g_string_append_printf (shader_source,
|
||||||
"attribute vec4 multi_tex_coord_attrib%d;\n",
|
"attribute vec4 multi_tex_coord_attrib%d;\n",
|
||||||
i);
|
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 (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 (shader_source, cogl_fixed_vertex_shader_output_variables);
|
||||||
g_string_append_printf (shader_source,
|
|
||||||
"varying vec2 tex_coord[%d];",
|
if (n_texture_units > 0)
|
||||||
settings->n_texture_units);
|
{
|
||||||
|
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_fogging_options);
|
||||||
g_string_append (shader_source, cogl_fixed_vertex_shader_main_start);
|
g_string_append (shader_source, cogl_fixed_vertex_shader_main_start);
|
||||||
|
|
||||||
for (i = 0; i < settings->n_texture_units; i++)
|
for (i = 0; i < COGL_GLES2_MAX_TEXTURE_UNITS; i++)
|
||||||
{
|
if (COGL_GLES2_TEXTURE_UNIT_IS_ENABLED (settings->texture_units, i))
|
||||||
if (!settings->texture_units[i].enabled)
|
{
|
||||||
continue;
|
g_string_append_printf (shader_source,
|
||||||
|
"transformed_tex_coord = "
|
||||||
g_string_append_printf (shader_source,
|
"texture_matrix[%d] "
|
||||||
"transformed_tex_coord = "
|
" * multi_tex_coord_attrib%d;\n",
|
||||||
"texture_matrix[%d] "
|
i, i);
|
||||||
" * multi_tex_coord_attrib%d;\n",
|
g_string_append_printf (shader_source,
|
||||||
i, i);
|
"tex_coord[%d] = transformed_tex_coord.st "
|
||||||
g_string_append_printf (shader_source,
|
" / transformed_tex_coord.q;\n",
|
||||||
"tex_coord[%d] = transformed_tex_coord.st "
|
i);
|
||||||
" / transformed_tex_coord.q;\n",
|
}
|
||||||
i);
|
|
||||||
}
|
|
||||||
|
|
||||||
g_string_append (shader_source, cogl_fixed_vertex_shader_frag_color_start);
|
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;
|
CoglGles2WrapperShader *shader;
|
||||||
GSList *node;
|
GSList *node;
|
||||||
int i;
|
int i;
|
||||||
|
int n_texture_units = 0;
|
||||||
|
|
||||||
_COGL_GET_GLES2_WRAPPER (w, NULL);
|
_COGL_GET_GLES2_WRAPPER (w, NULL);
|
||||||
|
|
||||||
@ -299,15 +332,24 @@ cogl_gles2_get_fragment_shader (const CoglGles2WrapperSettings *settings)
|
|||||||
/* Otherwise create a new shader */
|
/* Otherwise create a new shader */
|
||||||
shader_source = g_string_new (cogl_fixed_fragment_shader_variables_start);
|
shader_source = g_string_new (cogl_fixed_fragment_shader_variables_start);
|
||||||
|
|
||||||
g_string_append (shader_source, cogl_fixed_fragment_shader_inputs);
|
/* Find the biggest enabled texture unit index */
|
||||||
g_string_append_printf (shader_source,
|
for (i = 0; i < COGL_GLES2_MAX_TEXTURE_UNITS; i++)
|
||||||
"varying vec2 tex_coord[%d];\n",
|
if (COGL_GLES2_TEXTURE_UNIT_IS_ENABLED (settings->texture_units, i))
|
||||||
settings->n_texture_units);
|
n_texture_units = i + 1;
|
||||||
|
|
||||||
g_string_append (shader_source, cogl_fixed_fragment_shader_texturing_options);
|
g_string_append (shader_source, cogl_fixed_fragment_shader_inputs);
|
||||||
g_string_append_printf (shader_source,
|
|
||||||
"uniform sampler2D texture_unit[%d];\n",
|
if (n_texture_units > 0)
|
||||||
settings->n_texture_units);
|
{
|
||||||
|
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);
|
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
|
/* This pointless extra variable is needed to work around an
|
||||||
apparent bug in the PowerVR drivers. Without it the alpha
|
apparent bug in the PowerVR drivers. Without it the alpha
|
||||||
blending seems to stop working */
|
blending seems to stop working */
|
||||||
/* g_string_append (shader_source, "gl_FragColor = frag_color;\n");
|
|
||||||
*/
|
|
||||||
g_string_append (shader_source,
|
g_string_append (shader_source,
|
||||||
"vec4 frag_color_copy = frag_color;\n");
|
"vec4 frag_color_copy = frag_color;\n");
|
||||||
g_string_append (shader_source, "gl_FragColor = frag_color;\n");
|
g_string_append (shader_source, "gl_FragColor = frag_color;\n");
|
||||||
|
|
||||||
for (i = 0; i < settings->n_texture_units; i++)
|
for (i = 0; i < n_texture_units; i++)
|
||||||
{
|
if (COGL_GLES2_TEXTURE_UNIT_IS_ENABLED (settings->texture_units, i))
|
||||||
if (settings->texture_units[i].alpha_only)
|
{
|
||||||
{
|
if (COGL_GLES2_TEXTURE_UNIT_IS_ALPHA_ONLY (settings->texture_units, i))
|
||||||
/* If the texture only has an alpha channel (eg, with the textures
|
/* If the texture only has an alpha channel (eg, with the textures
|
||||||
from the pango renderer) then the RGB components will be
|
from the pango renderer) then the RGB components will be
|
||||||
black. We want to use the RGB from the current color in that
|
black. We want to use the RGB from the current color in that
|
||||||
case */
|
case */
|
||||||
g_string_append_printf (
|
g_string_append_printf (shader_source,
|
||||||
shader_source,
|
"gl_FragColor.a *= "
|
||||||
"gl_FragColor.a *= "
|
"texture2D (texture_unit[%d], "
|
||||||
"texture2D (texture_unit[%d], tex_coord[%d]).a;\n",
|
"tex_coord[%d]).a;\n",
|
||||||
i, i);
|
i, i);
|
||||||
}
|
else
|
||||||
else
|
g_string_append_printf (shader_source,
|
||||||
{
|
"gl_FragColor *= "
|
||||||
g_string_append_printf (
|
"texture2D (texture_unit[%d], "
|
||||||
shader_source,
|
"tex_coord[%d]);\n",
|
||||||
"gl_FragColor *= "
|
i, i);
|
||||||
"texture2D (texture_unit[%d], tex_coord[%d]);\n",
|
}
|
||||||
i, i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (i == 0)
|
|
||||||
g_string_append (shader_source, "gl_FragColor = frag_color;\n");
|
|
||||||
|
|
||||||
if (settings->fog_enabled)
|
if (settings->fog_enabled)
|
||||||
g_string_append (shader_source, cogl_fixed_fragment_shader_fog);
|
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
|
uniforms->modelview_matrix_uniform
|
||||||
= glGetUniformLocation (program, "modelview_matrix");
|
= glGetUniformLocation (program, "modelview_matrix");
|
||||||
|
|
||||||
uniforms->texture_matrix_uniforms =
|
for (i = 0; i < COGL_GLES2_MAX_TEXTURE_UNITS; i++)
|
||||||
g_array_new (FALSE, FALSE, sizeof (GLint));
|
if (COGL_GLES2_TEXTURE_UNIT_IS_ENABLED (settings->texture_units, i))
|
||||||
uniforms->texture_sampler_uniforms =
|
{
|
||||||
g_array_new (FALSE, FALSE, sizeof (GLint));
|
char *matrix_var_name = g_strdup_printf ("texture_matrix[%d]", i);
|
||||||
attribs->multi_texture_coords =
|
char *sampler_var_name = g_strdup_printf ("texture_unit[%d]", i);
|
||||||
g_array_new (FALSE, FALSE, sizeof (GLint));
|
char *tex_coord_var_name =
|
||||||
for (i = 0; i < settings->n_texture_units; i++)
|
g_strdup_printf ("multi_tex_coord_attrib%d", 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;
|
|
||||||
|
|
||||||
location = glGetUniformLocation (program, matrix_var_name);
|
uniforms->texture_matrix_uniforms[i]
|
||||||
g_array_append_val (uniforms->texture_matrix_uniforms, location);
|
= glGetUniformLocation (program, matrix_var_name);
|
||||||
location = glGetUniformLocation (program, sampler_var_name);
|
uniforms->texture_sampler_uniforms[i]
|
||||||
g_array_append_val (uniforms->texture_sampler_uniforms, location);
|
= glGetUniformLocation (program, sampler_var_name);
|
||||||
location = glGetAttribLocation (program, tex_coord_var_name);
|
attribs->multi_texture_coords[i]
|
||||||
g_array_append_val (attribs->multi_texture_coords, location);
|
= glGetAttribLocation (program, tex_coord_var_name);
|
||||||
|
|
||||||
g_free (tex_coord_var_name);
|
g_free (tex_coord_var_name);
|
||||||
g_free (sampler_var_name);
|
g_free (sampler_var_name);
|
||||||
g_free (matrix_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
|
uniforms->fog_density_uniform
|
||||||
= glGetUniformLocation (program, "fog_density");
|
= glGetUniformLocation (program, "fog_density");
|
||||||
@ -633,9 +668,7 @@ cogl_gles2_wrapper_update_matrix (CoglGles2Wrapper *wrapper, GLenum matrix_num)
|
|||||||
|
|
||||||
case GL_TEXTURE:
|
case GL_TEXTURE:
|
||||||
wrapper->dirty_uniforms |= COGL_GLES2_DIRTY_TEXTURE_MATRICES;
|
wrapper->dirty_uniforms |= COGL_GLES2_DIRTY_TEXTURE_MATRICES;
|
||||||
texture_unit = g_array_index (wrapper->texture_units,
|
texture_unit = wrapper->texture_units + wrapper->active_texture_unit;
|
||||||
CoglGles2WrapperTextureUnit *,
|
|
||||||
wrapper->active_texture_unit);
|
|
||||||
texture_unit->dirty_matrix = 1;
|
texture_unit->dirty_matrix = 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -671,9 +704,7 @@ cogl_wrap_glPushMatrix ()
|
|||||||
case GL_TEXTURE:
|
case GL_TEXTURE:
|
||||||
{
|
{
|
||||||
CoglGles2WrapperTextureUnit *texture_unit;
|
CoglGles2WrapperTextureUnit *texture_unit;
|
||||||
texture_unit = g_array_index (w->texture_units,
|
texture_unit = w->texture_units + w->active_texture_unit;
|
||||||
CoglGles2WrapperTextureUnit *,
|
|
||||||
w->active_texture_unit);
|
|
||||||
src = texture_unit->texture_stack
|
src = texture_unit->texture_stack
|
||||||
+ texture_unit->texture_stack_pos * 16;
|
+ texture_unit->texture_stack_pos * 16;
|
||||||
texture_unit->texture_stack_pos = (texture_unit->texture_stack_pos + 1)
|
texture_unit->texture_stack_pos = (texture_unit->texture_stack_pos + 1)
|
||||||
@ -709,9 +740,7 @@ cogl_wrap_glPopMatrix ()
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case GL_TEXTURE:
|
case GL_TEXTURE:
|
||||||
texture_unit = g_array_index (w->texture_units,
|
texture_unit = w->texture_units + w->active_texture_unit;
|
||||||
CoglGles2WrapperTextureUnit *,
|
|
||||||
w->active_texture_unit);
|
|
||||||
texture_unit->texture_stack_pos = (texture_unit->texture_stack_pos - 1)
|
texture_unit->texture_stack_pos = (texture_unit->texture_stack_pos - 1)
|
||||||
& (COGL_GLES2_TEXTURE_STACK_SIZE - 1);
|
& (COGL_GLES2_TEXTURE_STACK_SIZE - 1);
|
||||||
break;
|
break;
|
||||||
@ -744,10 +773,7 @@ cogl_gles2_get_matrix_stack_top (CoglGles2Wrapper *wrapper)
|
|||||||
return wrapper->projection_stack + wrapper->projection_stack_pos * 16;
|
return wrapper->projection_stack + wrapper->projection_stack_pos * 16;
|
||||||
|
|
||||||
case GL_TEXTURE:
|
case GL_TEXTURE:
|
||||||
|
texture_unit = wrapper->texture_units + wrapper->active_texture_unit;
|
||||||
texture_unit = g_array_index (wrapper->texture_units,
|
|
||||||
CoglGles2WrapperTextureUnit *,
|
|
||||||
wrapper->active_texture_unit);
|
|
||||||
return texture_unit->texture_stack
|
return texture_unit->texture_stack
|
||||||
+ texture_unit->texture_stack_pos * 16;
|
+ 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;
|
active_unit = w->active_client_texture_unit;
|
||||||
|
|
||||||
texture_unit = g_array_index (w->texture_units,
|
texture_unit = w->texture_units + active_unit;
|
||||||
CoglGles2WrapperTextureUnit *,
|
|
||||||
active_unit);
|
|
||||||
texture_unit->texture_coords_size = size;
|
texture_unit->texture_coords_size = size;
|
||||||
texture_unit->texture_coords_type = type;
|
texture_unit->texture_coords_type = type;
|
||||||
texture_unit->texture_coords_stride = stride;
|
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 */
|
/* 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;
|
CoglGles2WrapperTextureUnit *texture_unit;
|
||||||
GLint uniform =
|
GLint uniform = program->uniforms.texture_matrix_uniforms[i];
|
||||||
g_array_index (program->uniforms.texture_matrix_uniforms,
|
|
||||||
GLint, i);
|
|
||||||
|
|
||||||
texture_unit = g_array_index (w->texture_units,
|
texture_unit = w->texture_units + i;
|
||||||
CoglGles2WrapperTextureUnit *,
|
|
||||||
i);
|
|
||||||
if (uniform != -1)
|
if (uniform != -1)
|
||||||
glUniformMatrix4fv (uniform, 1, GL_FALSE,
|
glUniformMatrix4fv (uniform, 1, GL_FALSE,
|
||||||
texture_unit->texture_stack
|
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 */
|
/* 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 =
|
GLint uniform = program->uniforms.texture_sampler_uniforms[i];
|
||||||
g_array_index (program->uniforms.texture_sampler_uniforms,
|
|
||||||
GLint, i);
|
|
||||||
|
|
||||||
if (uniform != -1)
|
if (uniform != -1)
|
||||||
glUniform1i (uniform, i);
|
glUniform1i (uniform, i);
|
||||||
@ -1194,33 +1212,27 @@ cogl_wrap_prepare_for_draw (void)
|
|||||||
int i;
|
int i;
|
||||||
|
|
||||||
/* TODO - coverage test */
|
/* TODO - coverage test */
|
||||||
for (i = 0; i < w->settings.n_texture_units; i++)
|
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;
|
GLint tex_coord_var_index;
|
||||||
|
CoglGles2WrapperTextureUnit *texture_unit;
|
||||||
|
|
||||||
if (!w->settings.texture_units[i].enabled)
|
texture_unit = w->texture_units + w->active_texture_unit;
|
||||||
continue;
|
if (!texture_unit->texture_coords_enabled)
|
||||||
|
continue;
|
||||||
|
|
||||||
texture_unit = g_array_index (w->texture_units,
|
/* TODO - we should probably have a per unit dirty flag too */
|
||||||
CoglGles2WrapperTextureUnit *,
|
|
||||||
w->active_texture_unit);
|
|
||||||
if (!texture_unit->texture_coords_enabled)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
/* TODO - we should probably have a per unit dirty flag too */
|
/* TODO - coverage test */
|
||||||
|
tex_coord_var_index = program->attributes.multi_texture_coords[i];
|
||||||
/* TODO - coverage test */
|
glVertexAttribPointer (tex_coord_var_index,
|
||||||
tex_coord_var_index =
|
texture_unit->texture_coords_size,
|
||||||
g_array_index (program->attributes.multi_texture_coords,
|
texture_unit->texture_coords_type,
|
||||||
GLint, i);
|
GL_FALSE,
|
||||||
glVertexAttribPointer (tex_coord_var_index,
|
texture_unit->texture_coords_stride,
|
||||||
texture_unit->texture_coords_size,
|
texture_unit->texture_coords_pointer);
|
||||||
texture_unit->texture_coords_type,
|
}
|
||||||
GL_FALSE,
|
|
||||||
texture_unit->texture_coords_stride,
|
|
||||||
texture_unit->texture_coords_pointer);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (w->dirty_vertex_attrib_enables)
|
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 */
|
/* 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 =
|
CoglGles2WrapperTextureUnit *texture_unit
|
||||||
g_array_index (w->texture_units,
|
= w->texture_units + w->active_texture_unit;
|
||||||
CoglGles2WrapperTextureUnit *,
|
GLint attrib = program->attributes.multi_texture_coords[i];
|
||||||
w->active_texture_unit);
|
|
||||||
if (texture_unit->texture_coords_enabled)
|
if (attrib != -1)
|
||||||
glEnableVertexAttribArray (
|
{
|
||||||
g_array_index (program->attributes.multi_texture_coords,
|
if (texture_unit->texture_coords_enabled)
|
||||||
GLint, i));
|
glEnableVertexAttribArray (attrib);
|
||||||
else
|
else
|
||||||
glDisableVertexAttribArray (
|
glDisableVertexAttribArray (attrib);
|
||||||
g_array_index (program->attributes.multi_texture_coords,
|
}
|
||||||
GLint, i));
|
|
||||||
w->dirty_vertex_attrib_enables = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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
|
/* We need to keep track of whether the texture is alpha-only
|
||||||
because the emulation of GL_MODULATE needs to work differently in
|
because the emulation of GL_MODULATE needs to work differently in
|
||||||
that case */
|
that case */
|
||||||
_COGL_GLES2_CHANGE_SETTING (
|
if (COGL_GLES2_TEXTURE_UNIT_IS_ALPHA_ONLY (w->settings.texture_units,
|
||||||
w, texture_units[w->active_texture_unit].alpha_only,
|
w->active_texture_unit)
|
||||||
internal_format == GL_ALPHA);
|
!= (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
|
void
|
||||||
@ -1292,66 +1309,14 @@ cogl_wrap_glTexEnvi (GLenum target, GLenum pname, GLfloat param)
|
|||||||
nothing needs to be done here. */
|
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
|
void
|
||||||
cogl_wrap_glClientActiveTexture (GLenum texture)
|
cogl_wrap_glClientActiveTexture (GLenum texture)
|
||||||
{
|
{
|
||||||
int texture_unit_index = texture - GL_TEXTURE0;
|
int texture_unit_index = texture - GL_TEXTURE0;
|
||||||
_COGL_GET_GLES2_WRAPPER (w, NO_RETVAL);
|
_COGL_GET_GLES2_WRAPPER (w, NO_RETVAL);
|
||||||
|
|
||||||
w->active_client_texture_unit = texture_unit_index;
|
if (texture_unit_index < COGL_GLES2_MAX_TEXTURE_UNITS)
|
||||||
|
w->active_client_texture_unit = texture_unit_index;
|
||||||
realize_texture_units (w, texture_unit_index);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -1360,9 +1325,8 @@ cogl_wrap_glActiveTexture (GLenum texture)
|
|||||||
int texture_unit_index = texture - GL_TEXTURE0;
|
int texture_unit_index = texture - GL_TEXTURE0;
|
||||||
_COGL_GET_GLES2_WRAPPER (w, NO_RETVAL);
|
_COGL_GET_GLES2_WRAPPER (w, NO_RETVAL);
|
||||||
|
|
||||||
w->active_texture_unit = texture_unit_index;
|
if (texture_unit_index < COGL_GLES2_MAX_TEXTURE_UNITS)
|
||||||
|
w->active_texture_unit = texture_unit_index;
|
||||||
realize_texture_units (w, texture_unit_index);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -1373,8 +1337,14 @@ cogl_wrap_glEnable (GLenum cap)
|
|||||||
switch (cap)
|
switch (cap)
|
||||||
{
|
{
|
||||||
case GL_TEXTURE_2D:
|
case GL_TEXTURE_2D:
|
||||||
_COGL_GLES2_CHANGE_SETTING (
|
if (!COGL_GLES2_TEXTURE_UNIT_IS_ENABLED (w->settings.texture_units,
|
||||||
w, texture_units[w->active_texture_unit].enabled, TRUE);
|
w->active_texture_unit))
|
||||||
|
{
|
||||||
|
COGL_GLES2_TEXTURE_UNIT_SET_ENABLED (w->settings.texture_units,
|
||||||
|
w->active_texture_unit,
|
||||||
|
TRUE);
|
||||||
|
w->settings_dirty = TRUE;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case GL_FOG:
|
case GL_FOG:
|
||||||
@ -1398,8 +1368,14 @@ cogl_wrap_glDisable (GLenum cap)
|
|||||||
switch (cap)
|
switch (cap)
|
||||||
{
|
{
|
||||||
case GL_TEXTURE_2D:
|
case GL_TEXTURE_2D:
|
||||||
_COGL_GLES2_CHANGE_SETTING (
|
if (COGL_GLES2_TEXTURE_UNIT_IS_ENABLED (w->settings.texture_units,
|
||||||
w, texture_units[w->active_texture_unit].enabled, FALSE);
|
w->active_texture_unit))
|
||||||
|
{
|
||||||
|
COGL_GLES2_TEXTURE_UNIT_SET_ENABLED (w->settings.texture_units,
|
||||||
|
w->active_texture_unit,
|
||||||
|
FALSE);
|
||||||
|
w->settings_dirty = TRUE;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case GL_FOG:
|
case GL_FOG:
|
||||||
@ -1429,9 +1405,7 @@ cogl_wrap_glEnableClientState (GLenum array)
|
|||||||
case GL_TEXTURE_COORD_ARRAY:
|
case GL_TEXTURE_COORD_ARRAY:
|
||||||
/* TODO - review if this should be in w->settings? */
|
/* TODO - review if this should be in w->settings? */
|
||||||
|
|
||||||
texture_unit = g_array_index (w->texture_units,
|
texture_unit = w->texture_units + w->active_texture_unit;
|
||||||
CoglGles2WrapperTextureUnit *,
|
|
||||||
w->active_texture_unit);
|
|
||||||
if (texture_unit->texture_coords_enabled != 1)
|
if (texture_unit->texture_coords_enabled != 1)
|
||||||
{
|
{
|
||||||
texture_unit->texture_coords_enabled = 1;
|
texture_unit->texture_coords_enabled = 1;
|
||||||
@ -1461,9 +1435,7 @@ cogl_wrap_glDisableClientState (GLenum array)
|
|||||||
break;
|
break;
|
||||||
case GL_TEXTURE_COORD_ARRAY:
|
case GL_TEXTURE_COORD_ARRAY:
|
||||||
|
|
||||||
texture_unit = g_array_index (w->texture_units,
|
texture_unit = w->texture_units + w->active_texture_unit;
|
||||||
CoglGles2WrapperTextureUnit *,
|
|
||||||
w->active_texture_unit);
|
|
||||||
/* TODO - review if this should be in w->settings? */
|
/* TODO - review if this should be in w->settings? */
|
||||||
if (texture_unit->texture_coords_enabled != 0)
|
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_PROJECTION_STACK_SIZE 2
|
||||||
#define COGL_GLES2_TEXTURE_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 */
|
/* Dirty flags for shader uniforms */
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
@ -82,16 +96,15 @@ enum
|
|||||||
|
|
||||||
struct _CoglGles2WrapperAttributes
|
struct _CoglGles2WrapperAttributes
|
||||||
{
|
{
|
||||||
GArray *multi_texture_coords;
|
GLint multi_texture_coords[COGL_GLES2_MAX_TEXTURE_UNITS];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _CoglGles2WrapperUniforms
|
struct _CoglGles2WrapperUniforms
|
||||||
{
|
{
|
||||||
GLint mvp_matrix_uniform;
|
GLint mvp_matrix_uniform;
|
||||||
GLint modelview_matrix_uniform;
|
GLint modelview_matrix_uniform;
|
||||||
GArray *texture_matrix_uniforms;
|
GLint texture_matrix_uniforms[COGL_GLES2_MAX_TEXTURE_UNITS];
|
||||||
|
GLint texture_sampler_uniforms[COGL_GLES2_MAX_TEXTURE_UNITS];
|
||||||
GArray *texture_sampler_uniforms;
|
|
||||||
|
|
||||||
GLint fog_density_uniform;
|
GLint fog_density_uniform;
|
||||||
GLint fog_start_uniform;
|
GLint fog_start_uniform;
|
||||||
@ -100,14 +113,7 @@ struct _CoglGles2WrapperUniforms
|
|||||||
|
|
||||||
GLint alpha_test_ref_uniform;
|
GLint alpha_test_ref_uniform;
|
||||||
|
|
||||||
GLint texture_unit_uniform;
|
GLint texture_unit_uniform;
|
||||||
};
|
|
||||||
|
|
||||||
struct _CoglGles2WrapperTextureUnitSettings
|
|
||||||
{
|
|
||||||
guint enabled:1;
|
|
||||||
guint alpha_only:1;
|
|
||||||
/* TODO: blending state */
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/* NB: We get a copy of this for each fragment/vertex
|
/* NB: We get a copy of this for each fragment/vertex
|
||||||
@ -115,8 +121,7 @@ struct _CoglGles2WrapperTextureUnitSettings
|
|||||||
* fairly lean */
|
* fairly lean */
|
||||||
struct _CoglGles2WrapperSettings
|
struct _CoglGles2WrapperSettings
|
||||||
{
|
{
|
||||||
CoglGles2WrapperTextureUnitSettings *texture_units;
|
guint32 texture_units;
|
||||||
guint n_texture_units;
|
|
||||||
|
|
||||||
GLint alpha_test_func;
|
GLint alpha_test_func;
|
||||||
GLint fog_mode;
|
GLint fog_mode;
|
||||||
@ -149,10 +154,11 @@ struct _CoglGles2Wrapper
|
|||||||
GLuint modelview_stack_pos;
|
GLuint modelview_stack_pos;
|
||||||
GLfloat projection_stack[COGL_GLES2_PROJECTION_STACK_SIZE * 16];
|
GLfloat projection_stack[COGL_GLES2_PROJECTION_STACK_SIZE * 16];
|
||||||
GLuint projection_stack_pos;
|
GLuint projection_stack_pos;
|
||||||
GArray *texture_units;
|
|
||||||
guint active_texture_unit;
|
guint active_texture_unit;
|
||||||
guint active_client_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 combined modelview and projection matrix is only updated at
|
||||||
the last minute in glDrawArrays to avoid recalculating it for
|
the last minute in glDrawArrays to avoid recalculating it for
|
||||||
every change to the modelview matrix */
|
every change to the modelview matrix */
|
||||||
|
Loading…
Reference in New Issue
Block a user