pipeline: Unify how the backends store private data

Previously the fragends had a separate private data pointer which was
used by the GLSL and ARBfp fragends to store a tiny struct containing
a single pointer to the ref-counted shader state. The space for the
private data pointer is reserved in all of the pipelines for all of
the potential backends. The vertends and progends however did this
differently by directly storing the pointer to the ref counted data
using cogl_object_set_user_data. This patch unifies the different
methods so that they all use cogl_object_set_user_data and the
fragends don't bother with the separate tiny allocation for the
private data. The private data pointer array has been removed from
CoglPipeline and the corresponding fragend virtual to free the private
data has also been removed because this can instead be done with the
destroy notify from the object user data.

The variable names used have been unified so that all of the vertends
and fragends name their data struct CoglPipelineShaderState and use a
variable called shader_state to refer to it. The progend uses
CoglPipelineProgramState and a variable called program_state.

This should also fix two potential bugs. the ARBfp fragend was
apprently leaking a reference to the private state when it creates the
private data because it was adding a reference before stroring the
pointer to the newly allocated data but the ref count is already set
to 1 on creation. The other potential bug is that the free function
for CoglPipeline was only calling the free_priv virtual for the
currently used fragend of the pipeline. The design of the fragends is
meant to allow a pipeline to have multiple fragend priv datas because
a child pipeline could be attaching its fragend data to the ancestor
and its allowed to pick a different fragend.
This commit is contained in:
Neil Roberts
2011-06-30 13:39:48 +01:00
parent 221850eca9
commit d69d49fada
7 changed files with 585 additions and 716 deletions

View File

@ -138,14 +138,14 @@ typedef struct
CoglPipeline *last_used_for_pipeline;
UnitState *unit_state;
} CoglPipelineProgendPrivate;
} CoglPipelineProgramState;
static CoglUserDataKey glsl_priv_key;
static CoglUserDataKey program_state_key;
static CoglPipelineProgendPrivate *
get_glsl_priv (CoglPipeline *pipeline)
static CoglPipelineProgramState *
get_program_state (CoglPipeline *pipeline)
{
return cogl_object_get_user_data (COGL_OBJECT (pipeline), &glsl_priv_key);
return cogl_object_get_user_data (COGL_OBJECT (pipeline), &program_state_key);
}
#ifdef HAVE_COGL_GLES2
@ -162,96 +162,101 @@ get_glsl_priv (CoglPipeline *pipeline)
int
_cogl_pipeline_progend_glsl_get_position_attribute (CoglPipeline *pipeline)
{
CoglPipelineProgendPrivate *priv = get_glsl_priv (pipeline);
CoglPipelineProgramState *program_state = get_program_state (pipeline);
_COGL_GET_CONTEXT (ctx, -1);
g_return_val_if_fail (priv != NULL, -1);
g_return_val_if_fail (priv->program != 0, -1);
g_return_val_if_fail (program_state != NULL, -1);
g_return_val_if_fail (program_state->program != 0, -1);
if (priv->position_attribute_location == ATTRIBUTE_LOCATION_UNKNOWN)
GE_RET( priv->position_attribute_location,
ctx, glGetAttribLocation (priv->program, "cogl_position_in") );
if (program_state->position_attribute_location == ATTRIBUTE_LOCATION_UNKNOWN)
GE_RET( program_state->position_attribute_location,
ctx, glGetAttribLocation (program_state->program,
"cogl_position_in") );
return priv->position_attribute_location;
return program_state->position_attribute_location;
}
int
_cogl_pipeline_progend_glsl_get_color_attribute (CoglPipeline *pipeline)
{
CoglPipelineProgendPrivate *priv = get_glsl_priv (pipeline);
CoglPipelineProgramState *program_state = get_program_state (pipeline);
_COGL_GET_CONTEXT (ctx, -1);
g_return_val_if_fail (priv != NULL, -1);
g_return_val_if_fail (priv->program != 0, -1);
g_return_val_if_fail (program_state != NULL, -1);
g_return_val_if_fail (program_state->program != 0, -1);
if (priv->color_attribute_location == ATTRIBUTE_LOCATION_UNKNOWN)
GE_RET( priv->color_attribute_location,
ctx, glGetAttribLocation (priv->program, "cogl_color_in") );
if (program_state->color_attribute_location == ATTRIBUTE_LOCATION_UNKNOWN)
GE_RET( program_state->color_attribute_location,
ctx, glGetAttribLocation (program_state->program,
"cogl_color_in") );
return priv->color_attribute_location;
return program_state->color_attribute_location;
}
int
_cogl_pipeline_progend_glsl_get_normal_attribute (CoglPipeline *pipeline)
{
CoglPipelineProgendPrivate *priv = get_glsl_priv (pipeline);
CoglPipelineProgramState *program_state = get_program_state (pipeline);
_COGL_GET_CONTEXT (ctx, -1);
g_return_val_if_fail (priv != NULL, -1);
g_return_val_if_fail (priv->program != 0, -1);
g_return_val_if_fail (program_state != NULL, -1);
g_return_val_if_fail (program_state->program != 0, -1);
if (priv->normal_attribute_location == ATTRIBUTE_LOCATION_UNKNOWN)
GE_RET( priv->normal_attribute_location,
ctx, glGetAttribLocation (priv->program, "cogl_normal_in") );
if (program_state->normal_attribute_location == ATTRIBUTE_LOCATION_UNKNOWN)
GE_RET( program_state->normal_attribute_location,
ctx, glGetAttribLocation (program_state->program,
"cogl_normal_in") );
return priv->normal_attribute_location;
return program_state->normal_attribute_location;
}
int
_cogl_pipeline_progend_glsl_get_tex_coord_attribute (CoglPipeline *pipeline,
int unit)
{
CoglPipelineProgendPrivate *priv = get_glsl_priv (pipeline);
CoglPipelineProgramState *program_state = get_program_state (pipeline);
_COGL_GET_CONTEXT (ctx, -1);
g_return_val_if_fail (priv != NULL, -1);
g_return_val_if_fail (priv->program != 0, -1);
g_return_val_if_fail (program_state != NULL, -1);
g_return_val_if_fail (program_state->program != 0, -1);
if (unit == 0)
{
if (priv->tex_coord0_attribute_location == ATTRIBUTE_LOCATION_UNKNOWN)
GE_RET( priv->tex_coord0_attribute_location,
ctx, glGetAttribLocation (priv->program,
if (program_state->tex_coord0_attribute_location ==
ATTRIBUTE_LOCATION_UNKNOWN)
GE_RET( program_state->tex_coord0_attribute_location,
ctx, glGetAttribLocation (program_state->program,
"cogl_tex_coord0_in") );
return priv->tex_coord0_attribute_location;
return program_state->tex_coord0_attribute_location;
}
else
{
char *name = g_strdup_printf ("cogl_tex_coord%i_in", unit);
int *locations;
if (priv->tex_coord_attribute_locations == NULL)
priv->tex_coord_attribute_locations = g_array_new (FALSE, FALSE,
sizeof (int));
if (priv->tex_coord_attribute_locations->len <= unit - 1)
if (program_state->tex_coord_attribute_locations == NULL)
program_state->tex_coord_attribute_locations =
g_array_new (FALSE, FALSE, sizeof (int));
if (program_state->tex_coord_attribute_locations->len <= unit - 1)
{
int i = priv->tex_coord_attribute_locations->len;
g_array_set_size (priv->tex_coord_attribute_locations, unit);
int i = program_state->tex_coord_attribute_locations->len;
g_array_set_size (program_state->tex_coord_attribute_locations, unit);
for (; i < unit; i++)
g_array_index (priv->tex_coord_attribute_locations, int, i) =
ATTRIBUTE_LOCATION_UNKNOWN;
g_array_index (program_state->tex_coord_attribute_locations, int, i)
= ATTRIBUTE_LOCATION_UNKNOWN;
}
locations = &g_array_index (priv->tex_coord_attribute_locations, int, 0);
locations = &g_array_index (program_state->tex_coord_attribute_locations,
int, 0);
if (locations[unit - 1] == ATTRIBUTE_LOCATION_UNKNOWN)
GE_RET( locations[unit - 1],
ctx, glGetAttribLocation (priv->program, name) );
ctx, glGetAttribLocation (program_state->program, name) );
g_free (name);
@ -260,79 +265,100 @@ _cogl_pipeline_progend_glsl_get_tex_coord_attribute (CoglPipeline *pipeline,
}
static void
clear_attribute_cache (CoglPipelineProgendPrivate *priv)
clear_attribute_cache (CoglPipelineProgramState *program_state)
{
priv->position_attribute_location = ATTRIBUTE_LOCATION_UNKNOWN;
priv->color_attribute_location = ATTRIBUTE_LOCATION_UNKNOWN;
priv->normal_attribute_location = ATTRIBUTE_LOCATION_UNKNOWN;
priv->tex_coord0_attribute_location = ATTRIBUTE_LOCATION_UNKNOWN;
if (priv->tex_coord_attribute_locations)
program_state->position_attribute_location = ATTRIBUTE_LOCATION_UNKNOWN;
program_state->color_attribute_location = ATTRIBUTE_LOCATION_UNKNOWN;
program_state->normal_attribute_location = ATTRIBUTE_LOCATION_UNKNOWN;
program_state->tex_coord0_attribute_location = ATTRIBUTE_LOCATION_UNKNOWN;
if (program_state->tex_coord_attribute_locations)
{
g_array_free (priv->tex_coord_attribute_locations, TRUE);
priv->tex_coord_attribute_locations = NULL;
g_array_free (program_state->tex_coord_attribute_locations, TRUE);
program_state->tex_coord_attribute_locations = NULL;
}
}
static void
clear_flushed_matrix_stacks (CoglPipelineProgendPrivate *priv)
clear_flushed_matrix_stacks (CoglPipelineProgramState *program_state)
{
if (priv->flushed_modelview_stack)
if (program_state->flushed_modelview_stack)
{
cogl_object_unref (priv->flushed_modelview_stack);
priv->flushed_modelview_stack = NULL;
cogl_object_unref (program_state->flushed_modelview_stack);
program_state->flushed_modelview_stack = NULL;
}
if (priv->flushed_projection_stack)
if (program_state->flushed_projection_stack)
{
cogl_object_unref (priv->flushed_projection_stack);
priv->flushed_projection_stack = NULL;
cogl_object_unref (program_state->flushed_projection_stack);
program_state->flushed_projection_stack = NULL;
}
priv->flushed_modelview_is_identity = FALSE;
program_state->flushed_modelview_is_identity = FALSE;
}
#endif /* HAVE_COGL_GLES2 */
static void
destroy_glsl_priv (void *user_data)
static CoglPipelineProgramState *
program_state_new (int n_layers)
{
CoglPipelineProgendPrivate *priv = user_data;
CoglPipelineProgramState *program_state;
program_state = g_slice_new (CoglPipelineProgramState);
program_state->ref_count = 1;
program_state->program = 0;
program_state->n_tex_coord_attribs = 0;
program_state->unit_state = g_new (UnitState, n_layers);
#ifdef HAVE_COGL_GLES2
program_state->tex_coord_attribute_locations = NULL;
program_state->flushed_modelview_stack = NULL;
program_state->flushed_modelview_is_identity = FALSE;
program_state->flushed_projection_stack = NULL;
#endif
return program_state;
}
static void
destroy_program_state (void *user_data)
{
CoglPipelineProgramState *program_state = user_data;
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
if (--priv->ref_count == 0)
if (--program_state->ref_count == 0)
{
#ifdef HAVE_COGL_GLES2
if (ctx->driver == COGL_DRIVER_GLES2)
{
clear_attribute_cache (priv);
clear_flushed_matrix_stacks (priv);
clear_attribute_cache (program_state);
clear_flushed_matrix_stacks (program_state);
}
#endif
if (priv->program)
GE( ctx, glDeleteProgram (priv->program) );
if (program_state->program)
GE( ctx, glDeleteProgram (program_state->program) );
g_free (priv->unit_state);
g_free (program_state->unit_state);
g_slice_free (CoglPipelineProgendPrivate, priv);
g_slice_free (CoglPipelineProgramState, program_state);
}
}
static void
set_glsl_priv (CoglPipeline *pipeline, CoglPipelineProgendPrivate *priv)
set_program_state (CoglPipeline *pipeline,
CoglPipelineProgramState *program_state)
{
cogl_object_set_user_data (COGL_OBJECT (pipeline),
&glsl_priv_key,
priv,
destroy_glsl_priv);
&program_state_key,
program_state,
destroy_program_state);
}
static void
dirty_glsl_program_state (CoglPipeline *pipeline)
dirty_program_state (CoglPipeline *pipeline)
{
cogl_object_set_user_data (COGL_OBJECT (pipeline),
&glsl_priv_key,
&program_state_key,
NULL,
destroy_glsl_priv);
NULL);
}
static void
@ -371,7 +397,7 @@ typedef struct
int unit;
GLuint gl_program;
gboolean update_all;
CoglPipelineProgendPrivate *priv;
CoglPipelineProgramState *program_state;
} UpdateUniformsState;
static gboolean
@ -380,8 +406,8 @@ get_uniform_cb (CoglPipeline *pipeline,
void *user_data)
{
UpdateUniformsState *state = user_data;
CoglPipelineProgendPrivate *priv = state->priv;
UnitState *unit_state = &priv->unit_state[state->unit];
CoglPipelineProgramState *program_state = state->program_state;
UnitState *unit_state = &program_state->unit_state[state->unit];
GLint uniform_location;
_COGL_GET_CONTEXT (ctx, FALSE);
@ -439,8 +465,8 @@ update_constants_cb (CoglPipeline *pipeline,
void *user_data)
{
UpdateUniformsState *state = user_data;
CoglPipelineProgendPrivate *priv = state->priv;
UnitState *unit_state = &priv->unit_state[state->unit++];
CoglPipelineProgramState *program_state = state->program_state;
UnitState *unit_state = &program_state->unit_state[state->unit++];
_COGL_GET_CONTEXT (ctx, FALSE);
@ -482,21 +508,22 @@ update_constants_cb (CoglPipeline *pipeline,
static void
update_builtin_uniforms (CoglPipeline *pipeline,
GLuint gl_program,
CoglPipelineProgendPrivate *priv)
CoglPipelineProgramState *program_state)
{
int i;
if (priv->dirty_builtin_uniforms == 0)
if (program_state->dirty_builtin_uniforms == 0)
return;
for (i = 0; i < G_N_ELEMENTS (builtin_uniforms); i++)
if ((priv->dirty_builtin_uniforms & (1 << i)) &&
priv->builtin_uniform_locations[i] != -1)
if ((program_state->dirty_builtin_uniforms & (1 << i)) &&
program_state->builtin_uniform_locations[i] != -1)
builtin_uniforms[i].update_func (pipeline,
priv->builtin_uniform_locations[i],
program_state
->builtin_uniform_locations[i],
builtin_uniforms[i].getter_func);
priv->dirty_builtin_uniforms = 0;
program_state->dirty_builtin_uniforms = 0;
}
#endif /* HAVE_COGL_GLES2 */
@ -506,7 +533,7 @@ _cogl_pipeline_progend_glsl_end (CoglPipeline *pipeline,
unsigned long pipelines_difference,
int n_tex_coord_attribs)
{
CoglPipelineProgendPrivate *priv;
CoglPipelineProgramState *program_state;
GLuint gl_program;
gboolean program_changed = FALSE;
UpdateUniformsState state;
@ -520,11 +547,11 @@ _cogl_pipeline_progend_glsl_end (CoglPipeline *pipeline,
pipeline->vertend != COGL_PIPELINE_VERTEND_GLSL)
return;
priv = get_glsl_priv (pipeline);
program_state = get_program_state (pipeline);
user_program = cogl_pipeline_get_user_program (pipeline);
if (priv == NULL)
if (program_state == NULL)
{
CoglPipeline *authority;
@ -539,29 +566,19 @@ _cogl_pipeline_progend_glsl_end (CoglPipeline *pipeline,
_cogl_pipeline_get_layer_state_for_fragment_codegen (ctx) |
COGL_PIPELINE_LAYER_STATE_AFFECTS_VERTEX_CODEGEN);
priv = get_glsl_priv (authority);
program_state = get_program_state (authority);
if (priv == NULL)
if (program_state == NULL)
{
priv = g_slice_new (CoglPipelineProgendPrivate);
priv->ref_count = 1;
priv->program = 0;
priv->n_tex_coord_attribs = 0;
priv->unit_state = g_new (UnitState,
cogl_pipeline_get_n_layers (pipeline));
#ifdef HAVE_COGL_GLES2
priv->tex_coord_attribute_locations = NULL;
priv->flushed_modelview_stack = NULL;
priv->flushed_modelview_is_identity = FALSE;
priv->flushed_projection_stack = NULL;
#endif
set_glsl_priv (authority, priv);
program_state
= program_state_new (cogl_pipeline_get_n_layers (pipeline));
set_program_state (authority, program_state);
}
if (authority != pipeline)
{
priv->ref_count++;
set_glsl_priv (pipeline, priv);
program_state->ref_count++;
set_program_state (pipeline, program_state);
}
}
@ -571,26 +588,26 @@ _cogl_pipeline_progend_glsl_end (CoglPipeline *pipeline,
* Also if the number of texture coordinate attributes in use has
* increased, then delete the program so we can prepend a new
* _cogl_tex_coord[] varying array declaration. */
if (priv->program && user_program &&
(user_program->age != priv->user_program_age ||
n_tex_coord_attribs > priv->n_tex_coord_attribs))
if (program_state->program && user_program &&
(user_program->age != program_state->user_program_age ||
n_tex_coord_attribs > program_state->n_tex_coord_attribs))
{
GE( ctx, glDeleteProgram (priv->program) );
priv->program = 0;
GE( ctx, glDeleteProgram (program_state->program) );
program_state->program = 0;
}
if (priv->program == 0)
if (program_state->program == 0)
{
GLuint backend_shader;
GSList *l;
GE_RET( priv->program, ctx, glCreateProgram () );
GE_RET( program_state->program, ctx, glCreateProgram () );
/* Attach all of the shader from the user program */
if (user_program)
{
if (priv->n_tex_coord_attribs > n_tex_coord_attribs)
n_tex_coord_attribs = priv->n_tex_coord_attribs;
if (program_state->n_tex_coord_attribs > n_tex_coord_attribs)
n_tex_coord_attribs = program_state->n_tex_coord_attribs;
#ifdef HAVE_COGL_GLES2
/* Find the largest count of texture coordinate attributes
@ -614,29 +631,29 @@ _cogl_pipeline_progend_glsl_end (CoglPipeline *pipeline,
g_assert (shader->language == COGL_SHADER_LANGUAGE_GLSL);
GE( ctx, glAttachShader (priv->program,
GE( ctx, glAttachShader (program_state->program,
shader->gl_handle) );
}
priv->user_program_age = user_program->age;
program_state->user_program_age = user_program->age;
}
/* Attach any shaders from the GLSL backends */
if (pipeline->fragend == COGL_PIPELINE_FRAGEND_GLSL &&
(backend_shader = _cogl_pipeline_fragend_glsl_get_shader (pipeline)))
GE( ctx, glAttachShader (priv->program, backend_shader) );
GE( ctx, glAttachShader (program_state->program, backend_shader) );
if (pipeline->vertend == COGL_PIPELINE_VERTEND_GLSL &&
(backend_shader = _cogl_pipeline_vertend_glsl_get_shader (pipeline)))
GE( ctx, glAttachShader (priv->program, backend_shader) );
GE( ctx, glAttachShader (program_state->program, backend_shader) );
link_program (priv->program);
link_program (program_state->program);
program_changed = TRUE;
priv->n_tex_coord_attribs = n_tex_coord_attribs;
program_state->n_tex_coord_attribs = n_tex_coord_attribs;
}
gl_program = priv->program;
gl_program = program_state->program;
if (pipeline->fragend == COGL_PIPELINE_FRAGEND_GLSL)
_cogl_use_fragment_program (gl_program, COGL_PIPELINE_PROGRAM_TYPE_GLSL);
@ -645,7 +662,7 @@ _cogl_pipeline_progend_glsl_end (CoglPipeline *pipeline,
state.unit = 0;
state.gl_program = gl_program;
state.priv = priv;
state.program_state = program_state;
if (program_changed)
cogl_pipeline_foreach_layer (pipeline,
@ -654,7 +671,7 @@ _cogl_pipeline_progend_glsl_end (CoglPipeline *pipeline,
state.unit = 0;
state.update_all = (program_changed ||
priv->last_used_for_pipeline != pipeline);
program_state->last_used_for_pipeline != pipeline);
cogl_pipeline_foreach_layer (pipeline,
update_constants_cb,
@ -667,33 +684,31 @@ _cogl_pipeline_progend_glsl_end (CoglPipeline *pipeline,
{
int i;
clear_attribute_cache (priv);
clear_flushed_matrix_stacks (priv);
clear_attribute_cache (program_state);
clear_flushed_matrix_stacks (program_state);
for (i = 0; i < G_N_ELEMENTS (builtin_uniforms); i++)
GE_RET( priv->builtin_uniform_locations[i],
ctx,
GE_RET( program_state->builtin_uniform_locations[i], ctx,
glGetUniformLocation (gl_program,
builtin_uniforms[i].uniform_name) );
GE_RET( priv->modelview_uniform,
ctx, glGetUniformLocation (gl_program,
"cogl_modelview_matrix") );
GE_RET( program_state->modelview_uniform, ctx,
glGetUniformLocation (gl_program,
"cogl_modelview_matrix") );
GE_RET( priv->projection_uniform,
ctx, glGetUniformLocation (gl_program,
"cogl_projection_matrix") );
GE_RET( program_state->projection_uniform, ctx,
glGetUniformLocation (gl_program,
"cogl_projection_matrix") );
GE_RET( priv->mvp_uniform,
ctx,
GE_RET( program_state->mvp_uniform, ctx,
glGetUniformLocation (gl_program,
"cogl_modelview_projection_matrix") );
}
if (program_changed ||
priv->last_used_for_pipeline != pipeline)
priv->dirty_builtin_uniforms = ~(unsigned long) 0;
program_state->last_used_for_pipeline != pipeline)
program_state->dirty_builtin_uniforms = ~(unsigned long) 0;
update_builtin_uniforms (pipeline, gl_program, priv);
update_builtin_uniforms (pipeline, gl_program, program_state);
}
#endif
@ -704,7 +719,7 @@ _cogl_pipeline_progend_glsl_end (CoglPipeline *pipeline,
/* We need to track the last pipeline that the program was used with
* so know if we need to update all of the uniforms */
priv->last_used_for_pipeline = pipeline;
program_state->last_used_for_pipeline = pipeline;
}
static void
@ -715,7 +730,8 @@ _cogl_pipeline_progend_glsl_pre_change_notify (CoglPipeline *pipeline,
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
if ((change & _cogl_pipeline_get_state_for_fragment_codegen (ctx)))
dirty_glsl_program_state (pipeline);
dirty_program_state (pipeline);
#ifdef HAVE_COGL_GLES2
else if (ctx->driver == COGL_DRIVER_GLES2)
{
@ -724,9 +740,10 @@ _cogl_pipeline_progend_glsl_pre_change_notify (CoglPipeline *pipeline,
for (i = 0; i < G_N_ELEMENTS (builtin_uniforms); i++)
if ((change & builtin_uniforms[i].change))
{
CoglPipelineProgendPrivate *priv = get_glsl_priv (pipeline);
if (priv)
priv->dirty_builtin_uniforms |= 1 << i;
CoglPipelineProgramState *program_state
= get_program_state (pipeline);
if (program_state)
program_state->dirty_builtin_uniforms |= 1 << i;
return;
}
}
@ -751,27 +768,27 @@ _cogl_pipeline_progend_glsl_layer_pre_change_notify (
if ((change & _cogl_pipeline_get_state_for_fragment_codegen (ctx)))
{
dirty_glsl_program_state (owner);
dirty_program_state (owner);
return;
}
if (change & COGL_PIPELINE_LAYER_STATE_COMBINE_CONSTANT)
{
CoglPipelineProgendPrivate *priv = get_glsl_priv (owner);
if (priv)
CoglPipelineProgramState *program_state = get_program_state (owner);
if (program_state)
{
int unit_index = _cogl_pipeline_layer_get_unit_index (layer);
priv->unit_state[unit_index].dirty_combine_constant = TRUE;
program_state->unit_state[unit_index].dirty_combine_constant = TRUE;
}
}
if (change & COGL_PIPELINE_LAYER_STATE_USER_MATRIX)
{
CoglPipelineProgendPrivate *priv = get_glsl_priv (owner);
if (priv)
CoglPipelineProgramState *program_state = get_program_state (owner);
if (program_state)
{
int unit_index = _cogl_pipeline_layer_get_unit_index (layer);
priv->unit_state[unit_index].dirty_texture_matrix = TRUE;
program_state->unit_state[unit_index].dirty_texture_matrix = TRUE;
}
}
}
@ -783,11 +800,11 @@ flush_modelview_cb (gboolean is_identity,
const CoglMatrix *matrix,
void *user_data)
{
CoglPipelineProgendPrivate *priv = user_data;
CoglPipelineProgramState *program_state = user_data;
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
GE( ctx, glUniformMatrix4fv (priv->modelview_uniform, 1, FALSE,
GE( ctx, glUniformMatrix4fv (program_state->modelview_uniform, 1, FALSE,
cogl_matrix_get_array (matrix)) );
}
@ -796,17 +813,17 @@ flush_projection_cb (gboolean is_identity,
const CoglMatrix *matrix,
void *user_data)
{
CoglPipelineProgendPrivate *priv = user_data;
CoglPipelineProgramState *program_state = user_data;
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
GE( ctx, glUniformMatrix4fv (priv->projection_uniform, 1, FALSE,
GE( ctx, glUniformMatrix4fv (program_state->projection_uniform, 1, FALSE,
cogl_matrix_get_array (matrix)) );
}
typedef struct
{
CoglPipelineProgendPrivate *priv;
CoglPipelineProgramState *program_state;
const CoglMatrix *projection_matrix;
} FlushCombinedData;
@ -825,7 +842,8 @@ flush_combined_step_two_cb (gboolean is_identity,
if (is_identity)
{
const float *array = cogl_matrix_get_array (data->projection_matrix);
GE( ctx, glUniformMatrix4fv (data->priv->mvp_uniform, 1, FALSE, array ) );
GE( ctx, glUniformMatrix4fv (data->program_state->mvp_uniform,
1, FALSE, array ) );
}
else
{
@ -833,7 +851,7 @@ flush_combined_step_two_cb (gboolean is_identity,
data->projection_matrix,
matrix);
GE( ctx, glUniformMatrix4fv (data->priv->mvp_uniform, 1, FALSE,
GE( ctx, glUniformMatrix4fv (data->program_state->mvp_uniform, 1, FALSE,
cogl_matrix_get_array (&mvp_matrix)) );
}
}
@ -847,7 +865,7 @@ flush_combined_step_one_cb (gboolean is_identity,
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
data.priv = user_data;
data.program_state = user_data;
data.projection_matrix = matrix;
_cogl_matrix_stack_prepare_for_flush (ctx->flushed_modelview_stack,
@ -859,7 +877,7 @@ flush_combined_step_one_cb (gboolean is_identity,
static void
_cogl_pipeline_progend_glsl_pre_paint (CoglPipeline *pipeline)
{
CoglPipelineProgendPrivate *priv = get_glsl_priv (pipeline);
CoglPipelineProgramState *program_state = get_program_state (pipeline);
gboolean modelview_changed;
gboolean projection_changed;
@ -872,7 +890,7 @@ _cogl_pipeline_progend_glsl_pre_paint (CoglPipeline *pipeline)
vertend, but this is a requirement on GLES2 anyway */
g_return_if_fail (pipeline->vertend == COGL_PIPELINE_VERTEND_GLSL);
priv = get_glsl_priv (pipeline);
program_state = get_program_state (pipeline);
/* An initial pipeline is flushed while creating the context. At
this point there are no matrices flushed so we can't do
@ -885,59 +903,62 @@ _cogl_pipeline_progend_glsl_pre_paint (CoglPipeline *pipeline)
the identity matrix so it makes sense to optimise this case by
specifically checking whether we already have the identity matrix
which will catch a lot of common cases of redundant flushing */
if (priv->flushed_modelview_is_identity &&
if (program_state->flushed_modelview_is_identity &&
_cogl_matrix_stack_has_identity_flag (ctx->flushed_modelview_stack))
modelview_changed = FALSE;
else
modelview_changed =
priv->flushed_modelview_stack != ctx->flushed_modelview_stack ||
priv->flushed_modelview_stack_age !=
_cogl_matrix_stack_get_age (priv->flushed_modelview_stack);
program_state->flushed_modelview_stack != ctx->flushed_modelview_stack ||
program_state->flushed_modelview_stack_age !=
_cogl_matrix_stack_get_age (program_state->flushed_modelview_stack);
projection_changed =
priv->flushed_projection_stack != ctx->flushed_projection_stack ||
priv->flushed_projection_stack_age !=
_cogl_matrix_stack_get_age (priv->flushed_projection_stack);
program_state->flushed_projection_stack != ctx->flushed_projection_stack ||
program_state->flushed_projection_stack_age !=
_cogl_matrix_stack_get_age (program_state->flushed_projection_stack);
if (modelview_changed)
{
cogl_object_ref (ctx->flushed_modelview_stack);
if (priv->flushed_modelview_stack)
cogl_object_unref (priv->flushed_modelview_stack);
priv->flushed_modelview_stack = ctx->flushed_modelview_stack;
priv->flushed_modelview_stack_age =
if (program_state->flushed_modelview_stack)
cogl_object_unref (program_state->flushed_modelview_stack);
program_state->flushed_modelview_stack = ctx->flushed_modelview_stack;
program_state->flushed_modelview_stack_age =
_cogl_matrix_stack_get_age (ctx->flushed_modelview_stack);
priv->flushed_modelview_is_identity =
program_state->flushed_modelview_is_identity =
_cogl_matrix_stack_has_identity_flag (ctx->flushed_modelview_stack);
if (priv->modelview_uniform != -1)
_cogl_matrix_stack_prepare_for_flush (priv->flushed_modelview_stack,
if (program_state->modelview_uniform != -1)
_cogl_matrix_stack_prepare_for_flush (program_state
->flushed_modelview_stack,
COGL_MATRIX_MODELVIEW,
flush_modelview_cb,
priv);
program_state);
}
if (projection_changed)
{
cogl_object_ref (ctx->flushed_projection_stack);
if (priv->flushed_projection_stack)
cogl_object_unref (priv->flushed_projection_stack);
priv->flushed_projection_stack = ctx->flushed_projection_stack;
priv->flushed_projection_stack_age =
if (program_state->flushed_projection_stack)
cogl_object_unref (program_state->flushed_projection_stack);
program_state->flushed_projection_stack = ctx->flushed_projection_stack;
program_state->flushed_projection_stack_age =
_cogl_matrix_stack_get_age (ctx->flushed_projection_stack);
if (priv->projection_uniform != -1)
_cogl_matrix_stack_prepare_for_flush (priv->flushed_projection_stack,
if (program_state->projection_uniform != -1)
_cogl_matrix_stack_prepare_for_flush (program_state
->flushed_projection_stack,
COGL_MATRIX_PROJECTION,
flush_projection_cb,
priv);
program_state);
}
if (priv->mvp_uniform != -1 && (modelview_changed || projection_changed))
if (program_state->mvp_uniform != -1 &&
(modelview_changed || projection_changed))
_cogl_matrix_stack_prepare_for_flush (ctx->flushed_projection_stack,
COGL_MATRIX_PROJECTION,
flush_combined_step_one_cb,
priv);
program_state);
}
static void