From fac7338fdd2a9008f6f3fd1ab18273f95172b499 Mon Sep 17 00:00:00 2001 From: Neil Roberts Date: Fri, 19 Nov 2010 10:43:52 +0000 Subject: [PATCH] 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. --- cogl/cogl-pipeline-arbfp.c | 145 +---------------------------------- cogl/cogl-pipeline-private.h | 4 + cogl/cogl-pipeline.c | 142 ++++++++++++++++++++++++++++++++++ 3 files changed, 147 insertions(+), 144 deletions(-) diff --git a/cogl/cogl-pipeline-arbfp.c b/cogl/cogl-pipeline-arbfp.c index fb2c72ac6..b6b74917d 100644 --- a/cogl/cogl-pipeline-arbfp.c +++ b/cogl/cogl-pipeline-arbfp.c @@ -151,149 +151,6 @@ _cogl_pipeline_backend_arbfp_get_max_texture_units (void) 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 * 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 * share it. */ - authority = find_arbfp_authority (pipeline, user_program); + authority = _cogl_pipeline_find_codegen_authority (pipeline, user_program); authority_priv = get_arbfp_priv (authority); if (!authority_priv) { diff --git a/cogl/cogl-pipeline-private.h b/cogl/cogl-pipeline-private.h index 9a8e5f9fc..c155ca3bf 100644 --- a/cogl/cogl-pipeline-private.h +++ b/cogl/cogl-pipeline-private.h @@ -956,5 +956,9 @@ _cogl_pipeline_foreach_layer_internal (CoglPipeline *pipeline, int _cogl_pipeline_layer_get_unit_index (CoglPipelineLayer *layer); +CoglPipeline * +_cogl_pipeline_find_codegen_authority (CoglPipeline *pipeline, + CoglHandle user_program); + #endif /* __COGL_PIPELINE_PRIVATE_H */ diff --git a/cogl/cogl-pipeline.c b/cogl/cogl-pipeline.c index 149a4a67f..7d887d0b1 100644 --- a/cogl/cogl-pipeline.c +++ b/cogl/cogl-pipeline.c @@ -5595,3 +5595,145 @@ _cogl_debug_dump_pipelines_dot_file (const char *filename) 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; +}