Move find_arbfp_authority to cogl-pipeline.c

The code for finding the arbfp authority for a pipeline should be the
same as finding the GLSL authority. So that the code can be shared the
function has been moved to cogl-pipeline.c and renamed to
_cogl_pipeline_find_codegen_authority.
This commit is contained in:
Neil Roberts 2010-11-19 10:43:52 +00:00
parent 7379a5fc04
commit fac7338fdd
3 changed files with 147 additions and 144 deletions

View File

@ -151,149 +151,6 @@ _cogl_pipeline_backend_arbfp_get_max_texture_units (void)
return _cogl_get_max_texture_image_units (); return _cogl_get_max_texture_image_units ();
} }
typedef struct
{
int i;
CoglPipelineLayer **layers;
} AddLayersToArrayState;
static gboolean
add_layer_to_array_cb (CoglPipelineLayer *layer,
void *user_data)
{
AddLayersToArrayState *state = user_data;
state->layers[state->i++] = layer;
return TRUE;
}
static gboolean
layers_arbfp_would_differ (CoglPipelineLayer **pipeline0_layers,
CoglPipelineLayer **pipeline1_layers,
int n_layers)
{
int i;
/* The layer state that affects arbfp codegen... */
unsigned long arbfp_codegen_modifiers =
COGL_PIPELINE_LAYER_STATE_COMBINE |
COGL_PIPELINE_LAYER_STATE_UNIT;
for (i = 0; i < n_layers; i++)
{
CoglPipelineLayer *layer0 = pipeline0_layers[i];
CoglPipelineLayer *layer1 = pipeline1_layers[i];
unsigned long layer_differences;
if (layer0 == layer1)
continue;
layer_differences =
_cogl_pipeline_layer_compare_differences (layer0, layer1);
if (layer_differences & arbfp_codegen_modifiers)
{
/* When it comes to texture differences the only thing that
* affects the arbfp is the target enum... */
if (layer_differences == COGL_PIPELINE_LAYER_STATE_TEXTURE)
{
CoglHandle tex0 = _cogl_pipeline_layer_get_texture (layer0);
CoglHandle tex1 = _cogl_pipeline_layer_get_texture (layer1);
GLenum gl_target0;
GLenum gl_target1;
cogl_texture_get_gl_texture (tex0, NULL, &gl_target0);
cogl_texture_get_gl_texture (tex1, NULL, &gl_target1);
if (gl_target0 == gl_target1)
continue;
}
return TRUE;
}
}
return FALSE;
}
/* This tries to find the oldest ancestor whos state would generate
* the same arbfp program as the current pipeline. This is a simple
* mechanism for reducing the number of arbfp programs we have to
* generate.
*/
static CoglPipeline *
find_arbfp_authority (CoglPipeline *pipeline, CoglHandle user_program)
{
CoglPipeline *authority0;
CoglPipeline *authority1;
int n_layers;
CoglPipelineLayer **authority0_layers;
CoglPipelineLayer **authority1_layers;
/* XXX: we'll need to update this when we add fog support to the
* arbfp codegen */
if (user_program != COGL_INVALID_HANDLE)
return pipeline;
/* Find the first pipeline that modifies state that affects the
* arbfp codegen... */
authority0 = _cogl_pipeline_get_authority (pipeline,
COGL_PIPELINE_STATE_LAYERS);
/* Find the next ancestor after that, that also modifies state
* affecting arbfp codegen... */
if (_cogl_pipeline_get_parent (authority0))
{
authority1 =
_cogl_pipeline_get_authority (_cogl_pipeline_get_parent (authority0),
COGL_PIPELINE_STATE_LAYERS);
}
else
return authority0;
n_layers = authority0->n_layers;
for (;;)
{
AddLayersToArrayState state;
if (authority0->n_layers != authority1->n_layers)
return authority0;
authority0_layers =
g_alloca (sizeof (CoglPipelineLayer *) * n_layers);
state.i = 0;
state.layers = authority0_layers;
_cogl_pipeline_foreach_layer_internal (authority0,
add_layer_to_array_cb,
&state);
authority1_layers =
g_alloca (sizeof (CoglPipelineLayer *) * n_layers);
state.i = 0;
state.layers = authority1_layers;
_cogl_pipeline_foreach_layer_internal (authority1,
add_layer_to_array_cb,
&state);
if (layers_arbfp_would_differ (authority0_layers, authority1_layers,
n_layers))
return authority0;
/* Find the next ancestor after that, that also modifies state
* affecting arbfp codegen... */
if (!_cogl_pipeline_get_parent (authority1))
break;
authority0 = authority1;
authority1 =
_cogl_pipeline_get_authority (_cogl_pipeline_get_parent (authority1),
COGL_PIPELINE_STATE_LAYERS);
if (authority1 == authority0)
break;
}
return authority1;
}
static CoglPipelineBackendARBfpPrivate * static CoglPipelineBackendARBfpPrivate *
get_arbfp_priv (CoglPipeline *pipeline) get_arbfp_priv (CoglPipeline *pipeline)
{ {
@ -374,7 +231,7 @@ _cogl_pipeline_backend_arbfp_start (CoglPipeline *pipeline,
* arbfp-authority to maximize the chance that other pipelines can * arbfp-authority to maximize the chance that other pipelines can
* share it. * share it.
*/ */
authority = find_arbfp_authority (pipeline, user_program); authority = _cogl_pipeline_find_codegen_authority (pipeline, user_program);
authority_priv = get_arbfp_priv (authority); authority_priv = get_arbfp_priv (authority);
if (!authority_priv) if (!authority_priv)
{ {

View File

@ -956,5 +956,9 @@ _cogl_pipeline_foreach_layer_internal (CoglPipeline *pipeline,
int int
_cogl_pipeline_layer_get_unit_index (CoglPipelineLayer *layer); _cogl_pipeline_layer_get_unit_index (CoglPipelineLayer *layer);
CoglPipeline *
_cogl_pipeline_find_codegen_authority (CoglPipeline *pipeline,
CoglHandle user_program);
#endif /* __COGL_PIPELINE_PRIVATE_H */ #endif /* __COGL_PIPELINE_PRIVATE_H */

View File

@ -5595,3 +5595,145 @@ _cogl_debug_dump_pipelines_dot_file (const char *filename)
g_string_free (graph, TRUE); g_string_free (graph, TRUE);
} }
typedef struct
{
int i;
CoglPipelineLayer **layers;
} AddLayersToArrayState;
static gboolean
add_layer_to_array_cb (CoglPipelineLayer *layer,
void *user_data)
{
AddLayersToArrayState *state = user_data;
state->layers[state->i++] = layer;
return TRUE;
}
static gboolean
layers_codegen_would_differ (CoglPipelineLayer **pipeline0_layers,
CoglPipelineLayer **pipeline1_layers,
int n_layers)
{
int i;
/* The layer state that affects codegen... */
unsigned long codegen_modifiers =
COGL_PIPELINE_LAYER_STATE_COMBINE |
COGL_PIPELINE_LAYER_STATE_UNIT;
for (i = 0; i < n_layers; i++)
{
CoglPipelineLayer *layer0 = pipeline0_layers[i];
CoglPipelineLayer *layer1 = pipeline1_layers[i];
unsigned long layer_differences;
if (layer0 == layer1)
continue;
layer_differences =
_cogl_pipeline_layer_compare_differences (layer0, layer1);
if (layer_differences & codegen_modifiers)
{
/* When it comes to texture differences the only thing that
* affects the codegen is the target enum... */
if (layer_differences == COGL_PIPELINE_LAYER_STATE_TEXTURE)
{
CoglHandle tex0 = _cogl_pipeline_layer_get_texture (layer0);
CoglHandle tex1 = _cogl_pipeline_layer_get_texture (layer1);
GLenum gl_target0;
GLenum gl_target1;
cogl_texture_get_gl_texture (tex0, NULL, &gl_target0);
cogl_texture_get_gl_texture (tex1, NULL, &gl_target1);
if (gl_target0 == gl_target1)
continue;
}
return TRUE;
}
}
return FALSE;
}
/* This tries to find the oldest ancestor whos state would generate
* the same shader program as the current pipeline. This is a simple
* mechanism for reducing the number of programs we have to generate.
*/
CoglPipeline *
_cogl_pipeline_find_codegen_authority (CoglPipeline *pipeline,
CoglHandle user_program)
{
CoglPipeline *authority0;
CoglPipeline *authority1;
int n_layers;
CoglPipelineLayer **authority0_layers;
CoglPipelineLayer **authority1_layers;
/* XXX: we'll need to update this when we add fog support to the
* codegen */
if (user_program != COGL_INVALID_HANDLE)
return pipeline;
/* Find the first pipeline that modifies state that affects the
* codegen... */
authority0 = _cogl_pipeline_get_authority (pipeline,
COGL_PIPELINE_STATE_LAYERS);
/* Find the next ancestor after that, that also modifies state
* affecting codegen... */
if (_cogl_pipeline_get_parent (authority0))
{
authority1 =
_cogl_pipeline_get_authority (_cogl_pipeline_get_parent (authority0),
COGL_PIPELINE_STATE_LAYERS);
}
else
return authority0;
n_layers = authority0->n_layers;
for (;;)
{
AddLayersToArrayState state;
if (authority0->n_layers != authority1->n_layers)
return authority0;
authority0_layers =
g_alloca (sizeof (CoglPipelineLayer *) * n_layers);
state.i = 0;
state.layers = authority0_layers;
_cogl_pipeline_foreach_layer_internal (authority0,
add_layer_to_array_cb,
&state);
authority1_layers =
g_alloca (sizeof (CoglPipelineLayer *) * n_layers);
state.i = 0;
state.layers = authority1_layers;
_cogl_pipeline_foreach_layer_internal (authority1,
add_layer_to_array_cb,
&state);
if (layers_codegen_would_differ (authority0_layers, authority1_layers,
n_layers))
return authority0;
/* Find the next ancestor after that, that also modifies state
* affecting codegen... */
if (!_cogl_pipeline_get_parent (authority1))
break;
authority0 = authority1;
authority1 =
_cogl_pipeline_get_authority (_cogl_pipeline_get_parent (authority1),
COGL_PIPELINE_STATE_LAYERS);
if (authority1 == authority0)
break;
}
return authority1;
}