pipeline: generalize _cogl_pipeline_equal

_cogl_pipeline_equal now accepts a mask of pipeline differences and layer
differences to constrain what state will be compared. In addition a set
of flags are passed that can tweak the comparison semantics for some
state groups. For example when comparing layer textures we sometimes
only need to compare the texture target and can ignore the data itself.

In updating the code this patch also changes it so all required pipeline
authorities are resolved in one step up-front instead of resolving the
authority for each state group in turn and repeatedly having to traverse
the pipeline's ancestry. This adds two new functions
_cogl_pipeline_resolve_authorities and
_cogl_pipeline_layer_resolve_authorities to handle resolving a set of
authorities.
This commit is contained in:
Robert Bragg 2010-12-03 11:36:49 +00:00
parent 62b051951c
commit cc36e49ec5
3 changed files with 309 additions and 136 deletions

View File

@ -406,13 +406,12 @@ compare_entry_pipelines (CoglJournalEntry *entry0, CoglJournalEntry *entry1)
{
/* batch rectangles using compatible pipelines */
/* XXX: _cogl_pipeline_equal may give false negatives since it avoids
* deep comparisons as an optimization. It aims to compare enough so
* that we that we are able to batch the 90% common cases, but may not
* look at less common differences. */
if (_cogl_pipeline_equal (entry0->pipeline,
entry1->pipeline,
TRUE))
(COGL_PIPELINE_STATE_ALL &
~COGL_PIPELINE_STATE_COLOR),
COGL_PIPELINE_LAYER_STATE_ALL,
0))
return TRUE;
else
return FALSE;

View File

@ -71,30 +71,55 @@ typedef struct _CoglPipelineLayer CoglPipelineLayer;
#define COGL_PIPELINE_BACKEND_DEFAULT 0
#define COGL_PIPELINE_BACKEND_UNDEFINED 3
/* XXX: should I rename these as
* COGL_PIPELINE_LAYER_STATE_INDEX_XYZ... ?
*/
typedef enum
{
COGL_PIPELINE_LAYER_STATE_UNIT = 1L<<0,
COGL_PIPELINE_LAYER_STATE_TEXTURE = 1L<<1,
COGL_PIPELINE_LAYER_STATE_FILTERS = 1L<<2,
COGL_PIPELINE_LAYER_STATE_WRAP_MODES = 1L<<3,
/* sparse state */
COGL_PIPELINE_LAYER_STATE_UNIT_INDEX,
COGL_PIPELINE_LAYER_STATE_TEXTURE_INDEX,
COGL_PIPELINE_LAYER_STATE_FILTERS_INDEX,
COGL_PIPELINE_LAYER_STATE_WRAP_MODES_INDEX,
COGL_PIPELINE_LAYER_STATE_COMBINE_INDEX,
COGL_PIPELINE_LAYER_STATE_COMBINE_CONSTANT_INDEX,
COGL_PIPELINE_LAYER_STATE_USER_MATRIX_INDEX,
COGL_PIPELINE_LAYER_STATE_POINT_SPRITE_COORDS_INDEX,
COGL_PIPELINE_LAYER_STATE_COMBINE = 1L<<4,
COGL_PIPELINE_LAYER_STATE_COMBINE_CONSTANT = 1L<<5,
COGL_PIPELINE_LAYER_STATE_USER_MATRIX = 1L<<6,
/* note: layers don't currently have any non-sparse state */
COGL_PIPELINE_LAYER_STATE_POINT_SPRITE_COORDS = 1L<<7,
COGL_PIPELINE_LAYER_STATE_SPARSE_COUNT,
COGL_PIPELINE_LAYER_STATE_COUNT = COGL_PIPELINE_LAYER_STATE_SPARSE_COUNT
} CoglPipelineLayerStateIndex;
typedef enum
{
COGL_PIPELINE_LAYER_STATE_UNIT =
1L<<COGL_PIPELINE_LAYER_STATE_UNIT_INDEX,
COGL_PIPELINE_LAYER_STATE_TEXTURE =
1L<<COGL_PIPELINE_LAYER_STATE_TEXTURE_INDEX,
COGL_PIPELINE_LAYER_STATE_FILTERS =
1L<<COGL_PIPELINE_LAYER_STATE_FILTERS_INDEX,
COGL_PIPELINE_LAYER_STATE_WRAP_MODES =
1L<<COGL_PIPELINE_LAYER_STATE_WRAP_MODES_INDEX,
COGL_PIPELINE_LAYER_STATE_COMBINE =
1L<<COGL_PIPELINE_LAYER_STATE_COMBINE_INDEX,
COGL_PIPELINE_LAYER_STATE_COMBINE_CONSTANT =
1L<<COGL_PIPELINE_LAYER_STATE_COMBINE_CONSTANT_INDEX,
COGL_PIPELINE_LAYER_STATE_USER_MATRIX =
1L<<COGL_PIPELINE_LAYER_STATE_USER_MATRIX_INDEX,
COGL_PIPELINE_LAYER_STATE_POINT_SPRITE_COORDS =
1L<<COGL_PIPELINE_LAYER_STATE_POINT_SPRITE_COORDS_INDEX,
/* COGL_PIPELINE_LAYER_STATE_TEXTURE_INTERN = 1L<<8, */
COGL_PIPELINE_LAYER_STATE_ALL =
(1L<<COGL_PIPELINE_LAYER_STATE_COUNT) - 1,
COGL_PIPELINE_LAYER_STATE_ALL_SPARSE =
COGL_PIPELINE_LAYER_STATE_UNIT |
COGL_PIPELINE_LAYER_STATE_TEXTURE |
COGL_PIPELINE_LAYER_STATE_FILTERS |
COGL_PIPELINE_LAYER_STATE_WRAP_MODES |
COGL_PIPELINE_LAYER_STATE_COMBINE |
COGL_PIPELINE_LAYER_STATE_COMBINE_CONSTANT |
COGL_PIPELINE_LAYER_STATE_USER_MATRIX |
COGL_PIPELINE_LAYER_STATE_POINT_SPRITE_COORDS,
(1L<<COGL_PIPELINE_LAYER_STATE_COUNT) - 1,
COGL_PIPELINE_LAYER_STATE_NEEDS_BIG_STATE =
COGL_PIPELINE_LAYER_STATE_COMBINE |
@ -259,37 +284,68 @@ struct _CoglPipelineLayer
};
/* XXX: should I rename these as
* COGL_PIPELINE_STATE_INDEX_XYZ... ?
*/
typedef enum
{
/* sparse state */
COGL_PIPELINE_STATE_COLOR_INDEX,
COGL_PIPELINE_STATE_BLEND_ENABLE_INDEX,
COGL_PIPELINE_STATE_LAYERS_INDEX,
COGL_PIPELINE_STATE_LIGHTING_INDEX,
COGL_PIPELINE_STATE_ALPHA_FUNC_INDEX,
COGL_PIPELINE_STATE_ALPHA_FUNC_REFERENCE_INDEX,
COGL_PIPELINE_STATE_BLEND_INDEX,
COGL_PIPELINE_STATE_USER_SHADER_INDEX,
COGL_PIPELINE_STATE_DEPTH_INDEX,
COGL_PIPELINE_STATE_FOG_INDEX,
COGL_PIPELINE_STATE_POINT_SIZE_INDEX,
/* non-sparse */
COGL_PIPELINE_STATE_REAL_BLEND_ENABLE_INDEX,
COGL_PIPELINE_STATE_COUNT,
COGL_PIPELINE_STATE_SPARSE_COUNT = COGL_PIPELINE_STATE_COUNT - 1,
} CoglPipelineStateIndex;
/* Used in pipeline->differences masks and for notifying pipeline
* 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<<COGL_PIPELINE_STATE_COLOR_INDEX,
COGL_PIPELINE_STATE_BLEND_ENABLE =
1L<<COGL_PIPELINE_STATE_BLEND_ENABLE_INDEX,
COGL_PIPELINE_STATE_LAYERS =
1L<<COGL_PIPELINE_STATE_LAYERS_INDEX,
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_LIGHTING =
1L<<COGL_PIPELINE_STATE_LIGHTING_INDEX,
COGL_PIPELINE_STATE_ALPHA_FUNC =
1L<<COGL_PIPELINE_STATE_ALPHA_FUNC_INDEX,
COGL_PIPELINE_STATE_ALPHA_FUNC_REFERENCE =
1L<<COGL_PIPELINE_STATE_ALPHA_FUNC_REFERENCE_INDEX,
COGL_PIPELINE_STATE_BLEND =
1L<<COGL_PIPELINE_STATE_BLEND_INDEX,
COGL_PIPELINE_STATE_USER_SHADER =
1L<<COGL_PIPELINE_STATE_USER_SHADER_INDEX,
COGL_PIPELINE_STATE_DEPTH =
1L<<COGL_PIPELINE_STATE_DEPTH_INDEX,
COGL_PIPELINE_STATE_FOG =
1L<<COGL_PIPELINE_STATE_FOG_INDEX,
COGL_PIPELINE_STATE_POINT_SIZE =
1L<<COGL_PIPELINE_STATE_POINT_SIZE_INDEX,
COGL_PIPELINE_STATE_REAL_BLEND_ENABLE = 1L<<11,
COGL_PIPELINE_STATE_REAL_BLEND_ENABLE =
1L<<COGL_PIPELINE_STATE_REAL_BLEND_ENABLE_INDEX,
COGL_PIPELINE_STATE_ALL =
((1L<<COGL_PIPELINE_STATE_COUNT) - 1),
COGL_PIPELINE_STATE_ALL_SPARSE =
COGL_PIPELINE_STATE_COLOR |
COGL_PIPELINE_STATE_BLEND_ENABLE |
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 |
COGL_PIPELINE_STATE_FOG |
COGL_PIPELINE_STATE_POINT_SIZE,
(COGL_PIPELINE_STATE_ALL
& ~COGL_PIPELINE_STATE_REAL_BLEND_ENABLE),
COGL_PIPELINE_STATE_AFFECTS_BLENDING =
COGL_PIPELINE_STATE_COLOR |
@ -834,10 +890,23 @@ unsigned long
_cogl_pipeline_compare_differences (CoglPipeline *pipeline0,
CoglPipeline *pipeline1);
/* Sometimes when evaluating pipelines, either during comparisons or
* if calculating a hash value we need to tweak the evaluation
* semantics */
typedef enum _CoglPipelineEvalFlags
{
/* When evaluating a pipeline-layer with associated textures then
* evaluate the texture target, but don't consider the texture data
* itself. */
COGL_PIPELINE_EVAL_FLAG_IGNORE_TEXTURE_DATA = 1L<<0
} CoglPipelineEvalFlags;
gboolean
_cogl_pipeline_equal (CoglPipeline *pipeline0,
CoglPipeline *pipeline1,
gboolean skip_gl_color);
unsigned long differences,
unsigned long layer_differences,
CoglPipelineEvalFlags flags);
CoglPipeline *
_cogl_pipeline_journal_ref (CoglPipeline *pipeline);

View File

@ -2708,7 +2708,8 @@ _cogl_pipeline_apply_overrides (CoglPipeline *pipeline,
static gboolean
_cogl_pipeline_layer_texture_equal (CoglPipelineLayer *authority0,
CoglPipelineLayer *authority1)
CoglPipelineLayer *authority1,
CoglPipelineEvalFlags flags)
{
GLuint gl_handle0, gl_handle1;
GLenum gl_target0, gl_target1;
@ -2716,8 +2717,10 @@ _cogl_pipeline_layer_texture_equal (CoglPipelineLayer *authority0,
cogl_texture_get_gl_texture (authority0->texture, &gl_handle0, &gl_target0);
cogl_texture_get_gl_texture (authority1->texture, &gl_handle1, &gl_target1);
return (gl_handle0 == gl_handle1 &&
gl_target0 == gl_target1);
if (flags & COGL_PIPELINE_EVAL_FLAG_IGNORE_TEXTURE_DATA)
return (gl_target0 == gl_target1);
else
return (gl_handle0 == gl_handle1 && gl_target0 == gl_target1);
}
/* Determine the mask of differences between two layers.
@ -2915,24 +2918,58 @@ typedef gboolean
CoglPipelineLayer *authority1);
static gboolean
layer_state_equal (CoglPipelineLayerState state,
CoglPipelineLayer *layer0,
CoglPipelineLayer *layer1,
layer_state_equal (CoglPipelineLayerStateIndex state_index,
CoglPipelineLayer **authorities0,
CoglPipelineLayer **authorities1,
CoglPipelineLayerStateComparitor comparitor)
{
CoglPipelineLayer *authority0 =
_cogl_pipeline_layer_get_authority (layer0, state);
CoglPipelineLayer *authority1 =
_cogl_pipeline_layer_get_authority (layer1, state);
return comparitor (authorities0[state_index], authorities1[state_index]);
}
return comparitor (authority0, authority1);
static void
_cogl_pipeline_layer_resolve_authorities (CoglPipelineLayer *layer,
unsigned long differences,
CoglPipelineLayer **authorities)
{
unsigned long remaining = differences;
CoglPipelineLayer *authority = layer;
do
{
unsigned long found = authority->differences & remaining;
int i;
if (found == 0)
continue;
for (i = 0; True; i++)
{
unsigned long state = (1L<<i);
if (state & found)
authorities[i] = authority;
else if (state > found)
break;
}
remaining &= ~found;
if (remaining == 0)
return;
}
while ((authority = _cogl_pipeline_layer_get_parent (authority)));
g_assert (remaining == 0);
}
static gboolean
_cogl_pipeline_layer_equal (CoglPipelineLayer *layer0,
CoglPipelineLayer *layer1)
CoglPipelineLayer *layer1,
unsigned long differences_mask,
CoglPipelineEvalFlags flags)
{
unsigned long layers_difference;
CoglPipelineLayer *authorities0[COGL_PIPELINE_LAYER_STATE_SPARSE_COUNT];
CoglPipelineLayer *authorities1[COGL_PIPELINE_LAYER_STATE_SPARSE_COUNT];
if (layer0 == layer1)
return TRUE;
@ -2940,45 +2977,59 @@ _cogl_pipeline_layer_equal (CoglPipelineLayer *layer0,
layers_difference =
_cogl_pipeline_layer_compare_differences (layer0, layer1);
if (layers_difference & COGL_PIPELINE_LAYER_STATE_TEXTURE &&
!layer_state_equal (COGL_PIPELINE_LAYER_STATE_TEXTURE,
layer0, layer1,
_cogl_pipeline_layer_texture_equal))
return FALSE;
/* Only compare the sparse state groups requested by the caller... */
layers_difference &= differences_mask;
_cogl_pipeline_layer_resolve_authorities (layer0,
layers_difference,
authorities0);
_cogl_pipeline_layer_resolve_authorities (layer1,
layers_difference,
authorities1);
if (layers_difference & COGL_PIPELINE_LAYER_STATE_TEXTURE)
{
CoglPipelineLayerStateIndex state_index =
COGL_PIPELINE_LAYER_STATE_TEXTURE_INDEX;
if (!_cogl_pipeline_layer_texture_equal (authorities0[state_index],
authorities1[state_index],
flags))
return FALSE;
}
if (layers_difference & COGL_PIPELINE_LAYER_STATE_COMBINE &&
!layer_state_equal (COGL_PIPELINE_LAYER_STATE_COMBINE,
layer0, layer1,
!layer_state_equal (COGL_PIPELINE_LAYER_STATE_COMBINE_INDEX,
authorities0, authorities1,
_cogl_pipeline_layer_combine_state_equal))
return FALSE;
if (layers_difference & COGL_PIPELINE_LAYER_STATE_COMBINE_CONSTANT &&
!layer_state_equal (COGL_PIPELINE_LAYER_STATE_COMBINE_CONSTANT,
layer0, layer1,
!layer_state_equal (COGL_PIPELINE_LAYER_STATE_COMBINE_CONSTANT_INDEX,
authorities0, authorities1,
_cogl_pipeline_layer_combine_constant_equal))
return FALSE;
if (layers_difference & COGL_PIPELINE_LAYER_STATE_FILTERS &&
!layer_state_equal (COGL_PIPELINE_LAYER_STATE_FILTERS,
layer0, layer1,
!layer_state_equal (COGL_PIPELINE_LAYER_STATE_FILTERS_INDEX,
authorities0, authorities1,
_cogl_pipeline_layer_filters_equal))
return FALSE;
if (layers_difference & COGL_PIPELINE_LAYER_STATE_WRAP_MODES &&
!layer_state_equal (COGL_PIPELINE_LAYER_STATE_WRAP_MODES,
layer0, layer1,
!layer_state_equal (COGL_PIPELINE_LAYER_STATE_WRAP_MODES_INDEX,
authorities0, authorities1,
_cogl_pipeline_layer_wrap_modes_equal))
return FALSE;
if (layers_difference & COGL_PIPELINE_LAYER_STATE_USER_MATRIX &&
!layer_state_equal (COGL_PIPELINE_LAYER_STATE_USER_MATRIX,
layer0, layer1,
!layer_state_equal (COGL_PIPELINE_LAYER_STATE_USER_MATRIX_INDEX,
authorities0, authorities1,
_cogl_pipeline_layer_user_matrix_equal))
return FALSE;
if (layers_difference & COGL_PIPELINE_LAYER_STATE_POINT_SPRITE_COORDS &&
!layer_state_equal (COGL_PIPELINE_LAYER_STATE_POINT_SPRITE_COORDS,
layer0, layer1,
!layer_state_equal (COGL_PIPELINE_LAYER_STATE_POINT_SPRITE_COORDS_INDEX,
authorities0, authorities1,
_cogl_pipeline_layer_point_sprite_coords_equal))
return FALSE;
@ -3065,9 +3116,15 @@ _cogl_pipeline_blend_state_equal (CoglPipeline *authority0,
blend_state1->blend_dst_factor_rgb)
return FALSE;
#ifndef HAVE_COGL_GLES
if (!cogl_color_equal (&blend_state0->blend_constant,
&blend_state1->blend_constant))
return FALSE;
if (blend_state0->blend_src_factor_rgb == GL_ONE_MINUS_CONSTANT_COLOR ||
blend_state0->blend_src_factor_rgb == GL_CONSTANT_COLOR ||
blend_state0->blend_dst_factor_rgb == GL_ONE_MINUS_CONSTANT_COLOR ||
blend_state0->blend_dst_factor_rgb == GL_CONSTANT_COLOR)
{
if (!cogl_color_equal (&blend_state0->blend_constant,
&blend_state1->blend_constant))
return FALSE;
}
#endif
return TRUE;
@ -3121,7 +3178,9 @@ _cogl_pipeline_user_shader_equal (CoglPipeline *authority0,
static gboolean
_cogl_pipeline_layers_equal (CoglPipeline *authority0,
CoglPipeline *authority1)
CoglPipeline *authority1,
unsigned long differences,
CoglPipelineEvalFlags flags)
{
int i;
@ -3134,7 +3193,9 @@ _cogl_pipeline_layers_equal (CoglPipeline *authority0,
for (i = 0; i < authority0->n_layers; i++)
{
if (!_cogl_pipeline_layer_equal (authority0->layers_cache[i],
authority1->layers_cache[i]))
authority1->layers_cache[i],
differences,
flags))
return FALSE;
}
return TRUE;
@ -3229,21 +3290,55 @@ _cogl_pipeline_compare_differences (CoglPipeline *pipeline0,
}
static gboolean
simple_property_equal (CoglPipeline *pipeline0,
CoglPipeline *pipeline1,
simple_property_equal (CoglPipeline **authorities0,
CoglPipeline **authorities1,
unsigned long pipelines_difference,
CoglPipelineState state,
CoglPipelineStateIndex state_index,
CoglPipelineStateComparitor comparitor)
{
if (pipelines_difference & state)
if (pipelines_difference & (1L<<state_index))
{
if (!comparitor (_cogl_pipeline_get_authority (pipeline0, state),
_cogl_pipeline_get_authority (pipeline1, state)))
if (!comparitor (authorities0[state_index], authorities1[state_index]))
return FALSE;
}
return TRUE;
}
static void
_cogl_pipeline_resolve_authorities (CoglPipeline *pipeline,
unsigned long differences,
CoglPipeline **authorities)
{
unsigned long remaining = differences;
CoglPipeline *authority = pipeline;
do
{
unsigned long found = authority->differences & remaining;
int i;
if (found == 0)
continue;
for (i = 0; True; i++)
{
unsigned long state = (1L<<i);
if (state & found)
authorities[i] = authority;
else if (state > found)
break;
}
remaining &= ~found;
if (remaining == 0)
return;
}
while ((authority = _cogl_pipeline_get_parent (authority)));
g_assert (remaining == 0);
}
/* Comparison of two arbitrary pipelines is done by:
* 1) walking up the parents of each pipeline until a common
* ancestor is found, and at each step ORing together the
@ -3252,30 +3347,29 @@ simple_property_equal (CoglPipeline *pipeline0,
* 2) using the final difference mask to determine which state
* groups to compare.
*
* This is used by the Cogl journal to compare pipelines so that it
* can split up geometry that needs different OpenGL state.
* This is used, for example, by the Cogl journal to compare pipelines so that
* it can split up geometry that needs different OpenGL state.
*
* It is acceptable to have false negatives - although they will result
* in redundant OpenGL calls that try and update the state.
*
* When comparing texture layers, _cogl_pipeline_equal will actually
* compare the underlying GL texture handle that the Cogl texture uses
* so that atlas textures and sub textures will be considered equal if
* they point to the same texture. This is useful for comparing
* pipelines in the journal but it means that _cogl_pipeline_equal
* doesn't strictly compare whether the pipelines are the same. If we
* needed those semantics we could perhaps add another function or
* some flags to control the behaviour.
*
* False positives aren't allowed.
* XXX: When comparing texture layers, _cogl_pipeline_equal will actually
* compare the underlying GL texture handle that the Cogl texture uses so that
* atlas textures and sub textures will be considered equal if they point to
* the same texture. This is useful for comparing pipelines in the journal but
* it means that _cogl_pipeline_equal doesn't strictly compare whether the
* pipelines are the same. If we needed those semantics we could perhaps add
* another function or some flags to control the behaviour.
*/
gboolean
_cogl_pipeline_equal (CoglPipeline *pipeline0,
CoglPipeline *pipeline1,
gboolean skip_gl_color)
unsigned long differences,
unsigned long layer_differences,
CoglPipelineEvalFlags flags)
{
unsigned long pipelines_difference;
unsigned long pipelines_difference;
CoglPipeline *authorities0[COGL_PIPELINE_STATE_SPARSE_COUNT];
CoglPipeline *authorities1[COGL_PIPELINE_STATE_SPARSE_COUNT];
gboolean ret;
COGL_STATIC_TIMER (pipeline_equal_timer,
"Mainloop", /* parent */
"_cogl_pipeline_equal",
@ -3294,7 +3388,8 @@ _cogl_pipeline_equal (CoglPipeline *pipeline0,
/* First check non-sparse properties */
if (pipeline0->real_blend_enable != pipeline1->real_blend_enable)
if (differences & COGL_PIPELINE_STATE_REAL_BLEND_ENABLE &&
pipeline0->real_blend_enable != pipeline1->real_blend_enable)
goto done;
/* Then check sparse properties */
@ -3302,34 +3397,43 @@ _cogl_pipeline_equal (CoglPipeline *pipeline0,
pipelines_difference =
_cogl_pipeline_compare_differences (pipeline0, pipeline1);
if (pipelines_difference & COGL_PIPELINE_STATE_COLOR &&
!skip_gl_color)
/* Only compare the sparse state groups requested by the caller... */
pipelines_difference &= differences;
_cogl_pipeline_resolve_authorities (pipeline0,
pipelines_difference,
authorities0);
_cogl_pipeline_resolve_authorities (pipeline1,
pipelines_difference,
authorities1);
/* FIXME: we should resolve all the required authorities up front since
* that should reduce some repeat ancestor traversals. */
if (pipelines_difference & COGL_PIPELINE_STATE_COLOR)
{
CoglPipelineState state = COGL_PIPELINE_STATE_COLOR;
CoglPipeline *authority0 =
_cogl_pipeline_get_authority (pipeline0, state);
CoglPipeline *authority1 =
_cogl_pipeline_get_authority (pipeline1, state);
CoglPipeline *authority0 = authorities0[COGL_PIPELINE_STATE_COLOR_INDEX];
CoglPipeline *authority1 = authorities1[COGL_PIPELINE_STATE_COLOR_INDEX];
if (!cogl_color_equal (&authority0->color, &authority1->color))
goto done;
}
if (!simple_property_equal (pipeline0, pipeline1,
if (!simple_property_equal (authorities0, authorities1,
pipelines_difference,
COGL_PIPELINE_STATE_LIGHTING,
COGL_PIPELINE_STATE_LIGHTING_INDEX,
_cogl_pipeline_lighting_state_equal))
goto done;
if (!simple_property_equal (pipeline0, pipeline1,
if (!simple_property_equal (authorities0, authorities1,
pipelines_difference,
COGL_PIPELINE_STATE_ALPHA_FUNC,
COGL_PIPELINE_STATE_ALPHA_FUNC_INDEX,
_cogl_pipeline_alpha_func_state_equal))
goto done;
if (!simple_property_equal (pipeline0, pipeline1,
if (!simple_property_equal (authorities0, authorities1,
pipelines_difference,
COGL_PIPELINE_STATE_ALPHA_FUNC_REFERENCE,
COGL_PIPELINE_STATE_ALPHA_FUNC_REFERENCE_INDEX,
_cogl_pipeline_alpha_func_reference_state_equal))
goto done;
@ -3338,11 +3442,8 @@ _cogl_pipeline_equal (CoglPipeline *pipeline0,
if (pipeline0->real_blend_enable &&
pipelines_difference & COGL_PIPELINE_STATE_BLEND)
{
CoglPipelineState state = COGL_PIPELINE_STATE_BLEND;
CoglPipeline *authority0 =
_cogl_pipeline_get_authority (pipeline0, state);
CoglPipeline *authority1 =
_cogl_pipeline_get_authority (pipeline1, state);
CoglPipeline *authority0 = authorities0[COGL_PIPELINE_STATE_BLEND_INDEX];
CoglPipeline *authority1 = authorities1[COGL_PIPELINE_STATE_BLEND_INDEX];
if (!_cogl_pipeline_blend_state_equal (authority0, authority1))
goto done;
@ -3351,42 +3452,46 @@ _cogl_pipeline_equal (CoglPipeline *pipeline0,
/* XXX: we don't need to compare the BLEND_ENABLE state because it's
* already reflected in ->real_blend_enable */
#if 0
if (!simple_property_equal (pipeline0, pipeline1,
if (!simple_property_equal (authorities0, authorities1,
pipelines_difference,
COGL_PIPELINE_STATE_BLEND,
COGL_PIPELINE_STATE_BLEND_INDEX,
_cogl_pipeline_blend_enable_equal))
return FALSE;
#endif
if (!simple_property_equal (pipeline0, pipeline1,
if (!simple_property_equal (authorities0, authorities1,
pipelines_difference,
COGL_PIPELINE_STATE_DEPTH,
COGL_PIPELINE_STATE_DEPTH_INDEX,
_cogl_pipeline_depth_state_equal))
goto done;
if (!simple_property_equal (pipeline0, pipeline1,
if (!simple_property_equal (authorities0, authorities1,
pipelines_difference,
COGL_PIPELINE_STATE_FOG,
COGL_PIPELINE_STATE_FOG_INDEX,
_cogl_pipeline_fog_state_equal))
goto done;
if (!simple_property_equal (pipeline0, pipeline1,
if (!simple_property_equal (authorities0, authorities1,
pipelines_difference,
COGL_PIPELINE_STATE_POINT_SIZE,
COGL_PIPELINE_STATE_POINT_SIZE_INDEX,
_cogl_pipeline_point_size_equal))
goto done;
if (!simple_property_equal (pipeline0, pipeline1,
if (!simple_property_equal (authorities0, authorities1,
pipelines_difference,
COGL_PIPELINE_STATE_USER_SHADER,
COGL_PIPELINE_STATE_USER_SHADER_INDEX,
_cogl_pipeline_user_shader_equal))
goto done;
if (!simple_property_equal (pipeline0, pipeline1,
pipelines_difference,
COGL_PIPELINE_STATE_LAYERS,
_cogl_pipeline_layers_equal))
goto done;
if (pipelines_difference & COGL_PIPELINE_STATE_LAYERS)
{
CoglPipelineStateIndex state_index = COGL_PIPELINE_STATE_LAYERS_INDEX;
if (!_cogl_pipeline_layers_equal (authorities0[state_index],
authorities1[state_index],
layer_differences,
flags))
goto done;
}
ret = TRUE;
done: