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.
This commit is contained in:
Neil Roberts 2010-11-22 18:29:50 +00:00
parent 38ad560b19
commit 60000690e1
3 changed files with 102 additions and 36 deletions

View File

@ -521,7 +521,8 @@ _cogl_pipeline_flush_color_blend_alpha_depth_state (
blend_state->blend_dst_factor_rgb)); 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 = CoglPipeline *authority =
_cogl_pipeline_get_authority (pipeline, COGL_PIPELINE_STATE_ALPHA_FUNC); _cogl_pipeline_get_authority (pipeline, COGL_PIPELINE_STATE_ALPHA_FUNC);

View File

@ -279,13 +279,14 @@ typedef enum _CoglPipelineState
COGL_PIPELINE_STATE_LIGHTING = 1L<<3, COGL_PIPELINE_STATE_LIGHTING = 1L<<3,
COGL_PIPELINE_STATE_ALPHA_FUNC = 1L<<4, COGL_PIPELINE_STATE_ALPHA_FUNC = 1L<<4,
COGL_PIPELINE_STATE_BLEND = 1L<<5, COGL_PIPELINE_STATE_ALPHA_FUNC_REFERENCE = 1L<<5,
COGL_PIPELINE_STATE_USER_SHADER = 1L<<6, COGL_PIPELINE_STATE_BLEND = 1L<<6,
COGL_PIPELINE_STATE_DEPTH = 1L<<7, COGL_PIPELINE_STATE_USER_SHADER = 1L<<7,
COGL_PIPELINE_STATE_FOG = 1L<<8, COGL_PIPELINE_STATE_DEPTH = 1L<<8,
COGL_PIPELINE_STATE_POINT_SIZE = 1L<<9, 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_ALL_SPARSE =
COGL_PIPELINE_STATE_COLOR | COGL_PIPELINE_STATE_COLOR |
@ -293,6 +294,7 @@ typedef enum _CoglPipelineState
COGL_PIPELINE_STATE_LAYERS | COGL_PIPELINE_STATE_LAYERS |
COGL_PIPELINE_STATE_LIGHTING | COGL_PIPELINE_STATE_LIGHTING |
COGL_PIPELINE_STATE_ALPHA_FUNC | COGL_PIPELINE_STATE_ALPHA_FUNC |
COGL_PIPELINE_STATE_ALPHA_FUNC_REFERENCE |
COGL_PIPELINE_STATE_BLEND | COGL_PIPELINE_STATE_BLEND |
COGL_PIPELINE_STATE_USER_SHADER | COGL_PIPELINE_STATE_USER_SHADER |
COGL_PIPELINE_STATE_DEPTH | COGL_PIPELINE_STATE_DEPTH |
@ -310,6 +312,7 @@ typedef enum _CoglPipelineState
COGL_PIPELINE_STATE_NEEDS_BIG_STATE = COGL_PIPELINE_STATE_NEEDS_BIG_STATE =
COGL_PIPELINE_STATE_LIGHTING | COGL_PIPELINE_STATE_LIGHTING |
COGL_PIPELINE_STATE_ALPHA_FUNC | COGL_PIPELINE_STATE_ALPHA_FUNC |
COGL_PIPELINE_STATE_ALPHA_FUNC_REFERENCE |
COGL_PIPELINE_STATE_BLEND | COGL_PIPELINE_STATE_BLEND |
COGL_PIPELINE_STATE_USER_SHADER | COGL_PIPELINE_STATE_USER_SHADER |
COGL_PIPELINE_STATE_DEPTH | COGL_PIPELINE_STATE_DEPTH |

View File

@ -1010,11 +1010,12 @@ _cogl_pipeline_copy_differences (CoglPipeline *dest,
} }
if (differences & COGL_PIPELINE_STATE_ALPHA_FUNC) if (differences & COGL_PIPELINE_STATE_ALPHA_FUNC)
{ big_state->alpha_state.alpha_func =
memcpy (&big_state->alpha_state, src->big_state->alpha_state.alpha_func;
&src->big_state->alpha_state,
sizeof (CoglPipelineAlphaFuncState)); 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) if (differences & COGL_PIPELINE_STATE_BLEND)
{ {
@ -3014,7 +3015,7 @@ _cogl_pipeline_lighting_state_equal (CoglPipeline *authority0,
} }
static gboolean static gboolean
_cogl_pipeline_alpha_state_equal (CoglPipeline *authority0, _cogl_pipeline_alpha_func_state_equal (CoglPipeline *authority0,
CoglPipeline *authority1) CoglPipeline *authority1)
{ {
CoglPipelineAlphaFuncState *alpha_state0 = CoglPipelineAlphaFuncState *alpha_state0 =
@ -3022,11 +3023,20 @@ _cogl_pipeline_alpha_state_equal (CoglPipeline *authority0,
CoglPipelineAlphaFuncState *alpha_state1 = CoglPipelineAlphaFuncState *alpha_state1 =
&authority1->big_state->alpha_state; &authority1->big_state->alpha_state;
if (alpha_state0->alpha_func != alpha_state1->alpha_func || return alpha_state0->alpha_func == alpha_state1->alpha_func;
alpha_state0->alpha_func_reference != alpha_state1->alpha_func_reference) }
return FALSE;
else static gboolean
return TRUE; _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 static gboolean
@ -3315,7 +3325,13 @@ _cogl_pipeline_equal (CoglPipeline *pipeline0,
if (!simple_property_equal (pipeline0, pipeline1, if (!simple_property_equal (pipeline0, pipeline1,
pipelines_difference, pipelines_difference,
COGL_PIPELINE_STATE_ALPHA_FUNC, 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; goto done;
/* We don't need to compare the detailed blending state if we know /* 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); handle_automatic_blend_enable (pipeline, state);
} }
void static void
cogl_pipeline_set_alpha_test_function (CoglPipeline *pipeline, _cogl_pipeline_set_alpha_test_function (CoglPipeline *pipeline,
CoglPipelineAlphaFunc alpha_func, CoglPipelineAlphaFunc alpha_func)
float alpha_reference)
{ {
CoglPipelineState state = COGL_PIPELINE_STATE_ALPHA_FUNC; CoglPipelineState state = COGL_PIPELINE_STATE_ALPHA_FUNC;
CoglPipeline *authority; CoglPipeline *authority;
@ -3848,8 +3863,7 @@ cogl_pipeline_set_alpha_test_function (CoglPipeline *pipeline,
authority = _cogl_pipeline_get_authority (pipeline, state); authority = _cogl_pipeline_get_authority (pipeline, state);
alpha_state = &authority->big_state->alpha_state; alpha_state = &authority->big_state->alpha_state;
if (alpha_state->alpha_func == alpha_func && if (alpha_state->alpha_func == alpha_func)
alpha_state->alpha_func_reference == alpha_reference)
return; return;
/* - Flush journal primitives referencing the current state. /* - 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 = &pipeline->big_state->alpha_state;
alpha_state->alpha_func = alpha_func; alpha_state->alpha_func = alpha_func;
alpha_state->alpha_func_reference = alpha_reference;
_cogl_pipeline_update_authority (pipeline, authority, state, _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 GLenum
@ -5743,6 +5798,13 @@ _cogl_pipeline_find_codegen_authority (CoglPipeline *pipeline,
int n_layers; int n_layers;
CoglPipelineLayer **authority0_layers; CoglPipelineLayer **authority0_layers;
CoglPipelineLayer **authority1_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 /* XXX: we'll need to update this when we add fog support to the
* codegen */ * codegen */
@ -5753,7 +5815,7 @@ _cogl_pipeline_find_codegen_authority (CoglPipeline *pipeline,
/* Find the first pipeline that modifies state that affects the /* Find the first pipeline that modifies state that affects the
* codegen... */ * codegen... */
authority0 = _cogl_pipeline_get_authority (pipeline, authority0 = _cogl_pipeline_get_authority (pipeline,
COGL_PIPELINE_STATE_LAYERS); codegen_state);
/* Find the next ancestor after that, that also modifies state /* Find the next ancestor after that, that also modifies state
* affecting codegen... */ * affecting codegen... */
@ -5761,7 +5823,7 @@ _cogl_pipeline_find_codegen_authority (CoglPipeline *pipeline,
{ {
authority1 = authority1 =
_cogl_pipeline_get_authority (_cogl_pipeline_get_parent (authority0), _cogl_pipeline_get_authority (_cogl_pipeline_get_parent (authority0),
COGL_PIPELINE_STATE_LAYERS); codegen_state);
} }
else else
return authority0; return authority0;
@ -5804,7 +5866,7 @@ _cogl_pipeline_find_codegen_authority (CoglPipeline *pipeline,
authority0 = authority1; authority0 = authority1;
authority1 = authority1 =
_cogl_pipeline_get_authority (_cogl_pipeline_get_parent (authority1), _cogl_pipeline_get_authority (_cogl_pipeline_get_parent (authority1),
COGL_PIPELINE_STATE_LAYERS); codegen_state);
if (authority1 == authority0) if (authority1 == authority0)
break; break;
} }