From 60000690e1b24174d6ced3addce16d87be9bec40 Mon Sep 17 00:00:00 2001 From: Neil Roberts Date: Mon, 22 Nov 2010 18:29:50 +0000 Subject: [PATCH] cogl: Separate out state flags for the alpha test func and ref Previously the flag to mark the differences for the alpha test function and reference value were conflated into one. However this is awkward when generating shader code to simulate the alpha testing for GLES 2 because in that case changing the function would need a different program but changing the reference value just requires updating a uniform. This patch makes the function and reference have their own state flags. --- cogl/cogl-pipeline-opengl.c | 3 +- cogl/cogl-pipeline-private.h | 25 ++++---- cogl/cogl-pipeline.c | 110 +++++++++++++++++++++++++++-------- 3 files changed, 102 insertions(+), 36 deletions(-) diff --git a/cogl/cogl-pipeline-opengl.c b/cogl/cogl-pipeline-opengl.c index 80a7ebeaa..39db8d7c4 100644 --- a/cogl/cogl-pipeline-opengl.c +++ b/cogl/cogl-pipeline-opengl.c @@ -521,7 +521,8 @@ _cogl_pipeline_flush_color_blend_alpha_depth_state ( blend_state->blend_dst_factor_rgb)); } - if (pipelines_difference & COGL_PIPELINE_STATE_ALPHA_FUNC) + if (pipelines_difference & (COGL_PIPELINE_STATE_ALPHA_FUNC | + COGL_PIPELINE_STATE_ALPHA_FUNC_REFERENCE)) { CoglPipeline *authority = _cogl_pipeline_get_authority (pipeline, COGL_PIPELINE_STATE_ALPHA_FUNC); diff --git a/cogl/cogl-pipeline-private.h b/cogl/cogl-pipeline-private.h index 333601a31..6e0788427 100644 --- a/cogl/cogl-pipeline-private.h +++ b/cogl/cogl-pipeline-private.h @@ -273,19 +273,20 @@ struct _CoglPipelineLayer * state changes... */ typedef enum _CoglPipelineState { - COGL_PIPELINE_STATE_COLOR = 1L<<0, - COGL_PIPELINE_STATE_BLEND_ENABLE = 1L<<1, - COGL_PIPELINE_STATE_LAYERS = 1L<<2, + COGL_PIPELINE_STATE_COLOR = 1L<<0, + COGL_PIPELINE_STATE_BLEND_ENABLE = 1L<<1, + COGL_PIPELINE_STATE_LAYERS = 1L<<2, - COGL_PIPELINE_STATE_LIGHTING = 1L<<3, - COGL_PIPELINE_STATE_ALPHA_FUNC = 1L<<4, - COGL_PIPELINE_STATE_BLEND = 1L<<5, - COGL_PIPELINE_STATE_USER_SHADER = 1L<<6, - COGL_PIPELINE_STATE_DEPTH = 1L<<7, - COGL_PIPELINE_STATE_FOG = 1L<<8, - COGL_PIPELINE_STATE_POINT_SIZE = 1L<<9, + COGL_PIPELINE_STATE_LIGHTING = 1L<<3, + COGL_PIPELINE_STATE_ALPHA_FUNC = 1L<<4, + COGL_PIPELINE_STATE_ALPHA_FUNC_REFERENCE = 1L<<5, + COGL_PIPELINE_STATE_BLEND = 1L<<6, + COGL_PIPELINE_STATE_USER_SHADER = 1L<<7, + COGL_PIPELINE_STATE_DEPTH = 1L<<8, + COGL_PIPELINE_STATE_FOG = 1L<<9, + COGL_PIPELINE_STATE_POINT_SIZE = 1L<<10, - COGL_PIPELINE_STATE_REAL_BLEND_ENABLE = 1L<<10, + COGL_PIPELINE_STATE_REAL_BLEND_ENABLE = 1L<<11, COGL_PIPELINE_STATE_ALL_SPARSE = COGL_PIPELINE_STATE_COLOR | @@ -293,6 +294,7 @@ typedef enum _CoglPipelineState COGL_PIPELINE_STATE_LAYERS | COGL_PIPELINE_STATE_LIGHTING | COGL_PIPELINE_STATE_ALPHA_FUNC | + COGL_PIPELINE_STATE_ALPHA_FUNC_REFERENCE | COGL_PIPELINE_STATE_BLEND | COGL_PIPELINE_STATE_USER_SHADER | COGL_PIPELINE_STATE_DEPTH | @@ -310,6 +312,7 @@ typedef enum _CoglPipelineState COGL_PIPELINE_STATE_NEEDS_BIG_STATE = COGL_PIPELINE_STATE_LIGHTING | COGL_PIPELINE_STATE_ALPHA_FUNC | + COGL_PIPELINE_STATE_ALPHA_FUNC_REFERENCE | COGL_PIPELINE_STATE_BLEND | COGL_PIPELINE_STATE_USER_SHADER | COGL_PIPELINE_STATE_DEPTH | diff --git a/cogl/cogl-pipeline.c b/cogl/cogl-pipeline.c index f38450add..712bde3ce 100644 --- a/cogl/cogl-pipeline.c +++ b/cogl/cogl-pipeline.c @@ -1010,11 +1010,12 @@ _cogl_pipeline_copy_differences (CoglPipeline *dest, } if (differences & COGL_PIPELINE_STATE_ALPHA_FUNC) - { - memcpy (&big_state->alpha_state, - &src->big_state->alpha_state, - sizeof (CoglPipelineAlphaFuncState)); - } + big_state->alpha_state.alpha_func = + src->big_state->alpha_state.alpha_func; + + if (differences & COGL_PIPELINE_STATE_ALPHA_FUNC_REFERENCE) + big_state->alpha_state.alpha_func_reference = + src->big_state->alpha_state.alpha_func_reference; if (differences & COGL_PIPELINE_STATE_BLEND) { @@ -3014,19 +3015,28 @@ _cogl_pipeline_lighting_state_equal (CoglPipeline *authority0, } static gboolean -_cogl_pipeline_alpha_state_equal (CoglPipeline *authority0, - CoglPipeline *authority1) +_cogl_pipeline_alpha_func_state_equal (CoglPipeline *authority0, + CoglPipeline *authority1) { CoglPipelineAlphaFuncState *alpha_state0 = &authority0->big_state->alpha_state; CoglPipelineAlphaFuncState *alpha_state1 = &authority1->big_state->alpha_state; - if (alpha_state0->alpha_func != alpha_state1->alpha_func || - alpha_state0->alpha_func_reference != alpha_state1->alpha_func_reference) - return FALSE; - else - return TRUE; + return alpha_state0->alpha_func == alpha_state1->alpha_func; +} + +static gboolean +_cogl_pipeline_alpha_func_reference_state_equal (CoglPipeline *authority0, + CoglPipeline *authority1) +{ + CoglPipelineAlphaFuncState *alpha_state0 = + &authority0->big_state->alpha_state; + CoglPipelineAlphaFuncState *alpha_state1 = + &authority1->big_state->alpha_state; + + return (alpha_state0->alpha_func_reference == + alpha_state1->alpha_func_reference); } static gboolean @@ -3315,7 +3325,13 @@ _cogl_pipeline_equal (CoglPipeline *pipeline0, if (!simple_property_equal (pipeline0, pipeline1, pipelines_difference, COGL_PIPELINE_STATE_ALPHA_FUNC, - _cogl_pipeline_alpha_state_equal)) + _cogl_pipeline_alpha_func_state_equal)) + goto done; + + if (!simple_property_equal (pipeline0, pipeline1, + pipelines_difference, + COGL_PIPELINE_STATE_ALPHA_FUNC_REFERENCE, + _cogl_pipeline_alpha_func_reference_state_equal)) goto done; /* We don't need to compare the detailed blending state if we know @@ -3834,10 +3850,9 @@ cogl_pipeline_set_emission (CoglPipeline *pipeline, const CoglColor *emission) handle_automatic_blend_enable (pipeline, state); } -void -cogl_pipeline_set_alpha_test_function (CoglPipeline *pipeline, - CoglPipelineAlphaFunc alpha_func, - float alpha_reference) +static void +_cogl_pipeline_set_alpha_test_function (CoglPipeline *pipeline, + CoglPipelineAlphaFunc alpha_func) { CoglPipelineState state = COGL_PIPELINE_STATE_ALPHA_FUNC; CoglPipeline *authority; @@ -3848,8 +3863,7 @@ cogl_pipeline_set_alpha_test_function (CoglPipeline *pipeline, authority = _cogl_pipeline_get_authority (pipeline, state); alpha_state = &authority->big_state->alpha_state; - if (alpha_state->alpha_func == alpha_func && - alpha_state->alpha_func_reference == alpha_reference) + if (alpha_state->alpha_func == alpha_func) return; /* - Flush journal primitives referencing the current state. @@ -3861,10 +3875,51 @@ cogl_pipeline_set_alpha_test_function (CoglPipeline *pipeline, alpha_state = &pipeline->big_state->alpha_state; alpha_state->alpha_func = alpha_func; - alpha_state->alpha_func_reference = alpha_reference; _cogl_pipeline_update_authority (pipeline, authority, state, - _cogl_pipeline_alpha_state_equal); + _cogl_pipeline_alpha_func_state_equal); +} + +static void +_cogl_pipeline_set_alpha_test_function_reference (CoglPipeline *pipeline, + float alpha_reference) +{ + CoglPipelineState state = COGL_PIPELINE_STATE_ALPHA_FUNC_REFERENCE; + CoglPipeline *authority; + CoglPipelineAlphaFuncState *alpha_state; + + g_return_if_fail (cogl_is_pipeline (pipeline)); + + authority = _cogl_pipeline_get_authority (pipeline, state); + + alpha_state = &authority->big_state->alpha_state; + if (alpha_state->alpha_func_reference == alpha_reference) + return; + + /* - Flush journal primitives referencing the current state. + * - Make sure the pipeline has no dependants so it may be modified. + * - If the pipeline isn't currently an authority for the state being + * changed, then initialize that state from the current authority. + */ + _cogl_pipeline_pre_change_notify (pipeline, state, NULL, FALSE); + + alpha_state = &pipeline->big_state->alpha_state; + alpha_state->alpha_func_reference = alpha_reference; + + _cogl_pipeline_update_authority + (pipeline, authority, state, + _cogl_pipeline_alpha_func_reference_state_equal); +} + +void +cogl_pipeline_set_alpha_test_function (CoglPipeline *pipeline, + CoglPipelineAlphaFunc alpha_func, + float alpha_reference) +{ + _cogl_pipeline_set_alpha_test_function (pipeline, alpha_func); + _cogl_pipeline_set_alpha_test_function_reference (pipeline, alpha_reference); +} + } GLenum @@ -5743,6 +5798,13 @@ _cogl_pipeline_find_codegen_authority (CoglPipeline *pipeline, int n_layers; CoglPipelineLayer **authority0_layers; CoglPipelineLayer **authority1_layers; + /* Under GLES2 the alpha func becomes part of the fragment program + so we can't share programs there */ + const int codegen_state = (COGL_PIPELINE_STATE_LAYERS +#ifdef HAVE_COGL_GLES2 + | COGL_PIPELINE_STATE_ALPHA_FUNC +#endif + ); /* XXX: we'll need to update this when we add fog support to the * codegen */ @@ -5753,7 +5815,7 @@ _cogl_pipeline_find_codegen_authority (CoglPipeline *pipeline, /* Find the first pipeline that modifies state that affects the * codegen... */ authority0 = _cogl_pipeline_get_authority (pipeline, - COGL_PIPELINE_STATE_LAYERS); + codegen_state); /* Find the next ancestor after that, that also modifies state * affecting codegen... */ @@ -5761,7 +5823,7 @@ _cogl_pipeline_find_codegen_authority (CoglPipeline *pipeline, { authority1 = _cogl_pipeline_get_authority (_cogl_pipeline_get_parent (authority0), - COGL_PIPELINE_STATE_LAYERS); + codegen_state); } else return authority0; @@ -5804,7 +5866,7 @@ _cogl_pipeline_find_codegen_authority (CoglPipeline *pipeline, authority0 = authority1; authority1 = _cogl_pipeline_get_authority (_cogl_pipeline_get_parent (authority1), - COGL_PIPELINE_STATE_LAYERS); + codegen_state); if (authority1 == authority0) break; }