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:
parent
8e899985c6
commit
2c9cd76baa
@ -406,13 +406,12 @@ compare_entry_pipelines (CoglJournalEntry *entry0, CoglJournalEntry *entry1)
|
|||||||
{
|
{
|
||||||
/* batch rectangles using compatible pipelines */
|
/* 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,
|
if (_cogl_pipeline_equal (entry0->pipeline,
|
||||||
entry1->pipeline,
|
entry1->pipeline,
|
||||||
TRUE))
|
(COGL_PIPELINE_STATE_ALL &
|
||||||
|
~COGL_PIPELINE_STATE_COLOR),
|
||||||
|
COGL_PIPELINE_LAYER_STATE_ALL,
|
||||||
|
0))
|
||||||
return TRUE;
|
return TRUE;
|
||||||
else
|
else
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
@ -71,30 +71,55 @@ typedef struct _CoglPipelineLayer CoglPipelineLayer;
|
|||||||
#define COGL_PIPELINE_BACKEND_DEFAULT 0
|
#define COGL_PIPELINE_BACKEND_DEFAULT 0
|
||||||
#define COGL_PIPELINE_BACKEND_UNDEFINED 3
|
#define COGL_PIPELINE_BACKEND_UNDEFINED 3
|
||||||
|
|
||||||
|
/* XXX: should I rename these as
|
||||||
|
* COGL_PIPELINE_LAYER_STATE_INDEX_XYZ... ?
|
||||||
|
*/
|
||||||
typedef enum
|
typedef enum
|
||||||
{
|
{
|
||||||
COGL_PIPELINE_LAYER_STATE_UNIT = 1L<<0,
|
/* sparse state */
|
||||||
COGL_PIPELINE_LAYER_STATE_TEXTURE = 1L<<1,
|
COGL_PIPELINE_LAYER_STATE_UNIT_INDEX,
|
||||||
COGL_PIPELINE_LAYER_STATE_FILTERS = 1L<<2,
|
COGL_PIPELINE_LAYER_STATE_TEXTURE_INDEX,
|
||||||
COGL_PIPELINE_LAYER_STATE_WRAP_MODES = 1L<<3,
|
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,
|
/* note: layers don't currently have any non-sparse state */
|
||||||
COGL_PIPELINE_LAYER_STATE_COMBINE_CONSTANT = 1L<<5,
|
|
||||||
COGL_PIPELINE_LAYER_STATE_USER_MATRIX = 1L<<6,
|
|
||||||
|
|
||||||
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_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_ALL_SPARSE =
|
||||||
COGL_PIPELINE_LAYER_STATE_UNIT |
|
(1L<<COGL_PIPELINE_LAYER_STATE_COUNT) - 1,
|
||||||
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,
|
|
||||||
|
|
||||||
COGL_PIPELINE_LAYER_STATE_NEEDS_BIG_STATE =
|
COGL_PIPELINE_LAYER_STATE_NEEDS_BIG_STATE =
|
||||||
COGL_PIPELINE_LAYER_STATE_COMBINE |
|
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
|
/* Used in pipeline->differences masks and for notifying pipeline
|
||||||
* state changes... */
|
* state changes... */
|
||||||
typedef enum _CoglPipelineState
|
typedef enum _CoglPipelineState
|
||||||
{
|
{
|
||||||
COGL_PIPELINE_STATE_COLOR = 1L<<0,
|
COGL_PIPELINE_STATE_COLOR =
|
||||||
COGL_PIPELINE_STATE_BLEND_ENABLE = 1L<<1,
|
1L<<COGL_PIPELINE_STATE_COLOR_INDEX,
|
||||||
COGL_PIPELINE_STATE_LAYERS = 1L<<2,
|
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_LIGHTING =
|
||||||
COGL_PIPELINE_STATE_ALPHA_FUNC = 1L<<4,
|
1L<<COGL_PIPELINE_STATE_LIGHTING_INDEX,
|
||||||
COGL_PIPELINE_STATE_ALPHA_FUNC_REFERENCE = 1L<<5,
|
COGL_PIPELINE_STATE_ALPHA_FUNC =
|
||||||
COGL_PIPELINE_STATE_BLEND = 1L<<6,
|
1L<<COGL_PIPELINE_STATE_ALPHA_FUNC_INDEX,
|
||||||
COGL_PIPELINE_STATE_USER_SHADER = 1L<<7,
|
COGL_PIPELINE_STATE_ALPHA_FUNC_REFERENCE =
|
||||||
COGL_PIPELINE_STATE_DEPTH = 1L<<8,
|
1L<<COGL_PIPELINE_STATE_ALPHA_FUNC_REFERENCE_INDEX,
|
||||||
COGL_PIPELINE_STATE_FOG = 1L<<9,
|
COGL_PIPELINE_STATE_BLEND =
|
||||||
COGL_PIPELINE_STATE_POINT_SIZE = 1L<<10,
|
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_ALL_SPARSE =
|
||||||
COGL_PIPELINE_STATE_COLOR |
|
(COGL_PIPELINE_STATE_ALL
|
||||||
COGL_PIPELINE_STATE_BLEND_ENABLE |
|
& ~COGL_PIPELINE_STATE_REAL_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_AFFECTS_BLENDING =
|
COGL_PIPELINE_STATE_AFFECTS_BLENDING =
|
||||||
COGL_PIPELINE_STATE_COLOR |
|
COGL_PIPELINE_STATE_COLOR |
|
||||||
@ -834,10 +890,23 @@ unsigned long
|
|||||||
_cogl_pipeline_compare_differences (CoglPipeline *pipeline0,
|
_cogl_pipeline_compare_differences (CoglPipeline *pipeline0,
|
||||||
CoglPipeline *pipeline1);
|
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
|
gboolean
|
||||||
_cogl_pipeline_equal (CoglPipeline *pipeline0,
|
_cogl_pipeline_equal (CoglPipeline *pipeline0,
|
||||||
CoglPipeline *pipeline1,
|
CoglPipeline *pipeline1,
|
||||||
gboolean skip_gl_color);
|
unsigned long differences,
|
||||||
|
unsigned long layer_differences,
|
||||||
|
CoglPipelineEvalFlags flags);
|
||||||
|
|
||||||
CoglPipeline *
|
CoglPipeline *
|
||||||
_cogl_pipeline_journal_ref (CoglPipeline *pipeline);
|
_cogl_pipeline_journal_ref (CoglPipeline *pipeline);
|
||||||
|
@ -2708,7 +2708,8 @@ _cogl_pipeline_apply_overrides (CoglPipeline *pipeline,
|
|||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
_cogl_pipeline_layer_texture_equal (CoglPipelineLayer *authority0,
|
_cogl_pipeline_layer_texture_equal (CoglPipelineLayer *authority0,
|
||||||
CoglPipelineLayer *authority1)
|
CoglPipelineLayer *authority1,
|
||||||
|
CoglPipelineEvalFlags flags)
|
||||||
{
|
{
|
||||||
GLuint gl_handle0, gl_handle1;
|
GLuint gl_handle0, gl_handle1;
|
||||||
GLenum gl_target0, gl_target1;
|
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 (authority0->texture, &gl_handle0, &gl_target0);
|
||||||
cogl_texture_get_gl_texture (authority1->texture, &gl_handle1, &gl_target1);
|
cogl_texture_get_gl_texture (authority1->texture, &gl_handle1, &gl_target1);
|
||||||
|
|
||||||
return (gl_handle0 == gl_handle1 &&
|
if (flags & COGL_PIPELINE_EVAL_FLAG_IGNORE_TEXTURE_DATA)
|
||||||
gl_target0 == gl_target1);
|
return (gl_target0 == gl_target1);
|
||||||
|
else
|
||||||
|
return (gl_handle0 == gl_handle1 && gl_target0 == gl_target1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Determine the mask of differences between two layers.
|
/* Determine the mask of differences between two layers.
|
||||||
@ -2915,24 +2918,58 @@ typedef gboolean
|
|||||||
CoglPipelineLayer *authority1);
|
CoglPipelineLayer *authority1);
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
layer_state_equal (CoglPipelineLayerState state,
|
layer_state_equal (CoglPipelineLayerStateIndex state_index,
|
||||||
CoglPipelineLayer *layer0,
|
CoglPipelineLayer **authorities0,
|
||||||
CoglPipelineLayer *layer1,
|
CoglPipelineLayer **authorities1,
|
||||||
CoglPipelineLayerStateComparitor comparitor)
|
CoglPipelineLayerStateComparitor comparitor)
|
||||||
{
|
{
|
||||||
CoglPipelineLayer *authority0 =
|
return comparitor (authorities0[state_index], authorities1[state_index]);
|
||||||
_cogl_pipeline_layer_get_authority (layer0, state);
|
}
|
||||||
CoglPipelineLayer *authority1 =
|
|
||||||
_cogl_pipeline_layer_get_authority (layer1, state);
|
|
||||||
|
|
||||||
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
|
static gboolean
|
||||||
_cogl_pipeline_layer_equal (CoglPipelineLayer *layer0,
|
_cogl_pipeline_layer_equal (CoglPipelineLayer *layer0,
|
||||||
CoglPipelineLayer *layer1)
|
CoglPipelineLayer *layer1,
|
||||||
|
unsigned long differences_mask,
|
||||||
|
CoglPipelineEvalFlags flags)
|
||||||
{
|
{
|
||||||
unsigned long layers_difference;
|
unsigned long layers_difference;
|
||||||
|
CoglPipelineLayer *authorities0[COGL_PIPELINE_LAYER_STATE_SPARSE_COUNT];
|
||||||
|
CoglPipelineLayer *authorities1[COGL_PIPELINE_LAYER_STATE_SPARSE_COUNT];
|
||||||
|
|
||||||
if (layer0 == layer1)
|
if (layer0 == layer1)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
@ -2940,45 +2977,59 @@ _cogl_pipeline_layer_equal (CoglPipelineLayer *layer0,
|
|||||||
layers_difference =
|
layers_difference =
|
||||||
_cogl_pipeline_layer_compare_differences (layer0, layer1);
|
_cogl_pipeline_layer_compare_differences (layer0, layer1);
|
||||||
|
|
||||||
if (layers_difference & COGL_PIPELINE_LAYER_STATE_TEXTURE &&
|
/* Only compare the sparse state groups requested by the caller... */
|
||||||
!layer_state_equal (COGL_PIPELINE_LAYER_STATE_TEXTURE,
|
layers_difference &= differences_mask;
|
||||||
layer0, layer1,
|
|
||||||
_cogl_pipeline_layer_texture_equal))
|
_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;
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
if (layers_difference & COGL_PIPELINE_LAYER_STATE_COMBINE &&
|
if (layers_difference & COGL_PIPELINE_LAYER_STATE_COMBINE &&
|
||||||
!layer_state_equal (COGL_PIPELINE_LAYER_STATE_COMBINE,
|
!layer_state_equal (COGL_PIPELINE_LAYER_STATE_COMBINE_INDEX,
|
||||||
layer0, layer1,
|
authorities0, authorities1,
|
||||||
_cogl_pipeline_layer_combine_state_equal))
|
_cogl_pipeline_layer_combine_state_equal))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
if (layers_difference & COGL_PIPELINE_LAYER_STATE_COMBINE_CONSTANT &&
|
if (layers_difference & COGL_PIPELINE_LAYER_STATE_COMBINE_CONSTANT &&
|
||||||
!layer_state_equal (COGL_PIPELINE_LAYER_STATE_COMBINE_CONSTANT,
|
!layer_state_equal (COGL_PIPELINE_LAYER_STATE_COMBINE_CONSTANT_INDEX,
|
||||||
layer0, layer1,
|
authorities0, authorities1,
|
||||||
_cogl_pipeline_layer_combine_constant_equal))
|
_cogl_pipeline_layer_combine_constant_equal))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
if (layers_difference & COGL_PIPELINE_LAYER_STATE_FILTERS &&
|
if (layers_difference & COGL_PIPELINE_LAYER_STATE_FILTERS &&
|
||||||
!layer_state_equal (COGL_PIPELINE_LAYER_STATE_FILTERS,
|
!layer_state_equal (COGL_PIPELINE_LAYER_STATE_FILTERS_INDEX,
|
||||||
layer0, layer1,
|
authorities0, authorities1,
|
||||||
_cogl_pipeline_layer_filters_equal))
|
_cogl_pipeline_layer_filters_equal))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
if (layers_difference & COGL_PIPELINE_LAYER_STATE_WRAP_MODES &&
|
if (layers_difference & COGL_PIPELINE_LAYER_STATE_WRAP_MODES &&
|
||||||
!layer_state_equal (COGL_PIPELINE_LAYER_STATE_WRAP_MODES,
|
!layer_state_equal (COGL_PIPELINE_LAYER_STATE_WRAP_MODES_INDEX,
|
||||||
layer0, layer1,
|
authorities0, authorities1,
|
||||||
_cogl_pipeline_layer_wrap_modes_equal))
|
_cogl_pipeline_layer_wrap_modes_equal))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
if (layers_difference & COGL_PIPELINE_LAYER_STATE_USER_MATRIX &&
|
if (layers_difference & COGL_PIPELINE_LAYER_STATE_USER_MATRIX &&
|
||||||
!layer_state_equal (COGL_PIPELINE_LAYER_STATE_USER_MATRIX,
|
!layer_state_equal (COGL_PIPELINE_LAYER_STATE_USER_MATRIX_INDEX,
|
||||||
layer0, layer1,
|
authorities0, authorities1,
|
||||||
_cogl_pipeline_layer_user_matrix_equal))
|
_cogl_pipeline_layer_user_matrix_equal))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
if (layers_difference & COGL_PIPELINE_LAYER_STATE_POINT_SPRITE_COORDS &&
|
if (layers_difference & COGL_PIPELINE_LAYER_STATE_POINT_SPRITE_COORDS &&
|
||||||
!layer_state_equal (COGL_PIPELINE_LAYER_STATE_POINT_SPRITE_COORDS,
|
!layer_state_equal (COGL_PIPELINE_LAYER_STATE_POINT_SPRITE_COORDS_INDEX,
|
||||||
layer0, layer1,
|
authorities0, authorities1,
|
||||||
_cogl_pipeline_layer_point_sprite_coords_equal))
|
_cogl_pipeline_layer_point_sprite_coords_equal))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
@ -3065,9 +3116,15 @@ _cogl_pipeline_blend_state_equal (CoglPipeline *authority0,
|
|||||||
blend_state1->blend_dst_factor_rgb)
|
blend_state1->blend_dst_factor_rgb)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
#ifndef HAVE_COGL_GLES
|
#ifndef HAVE_COGL_GLES
|
||||||
|
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,
|
if (!cogl_color_equal (&blend_state0->blend_constant,
|
||||||
&blend_state1->blend_constant))
|
&blend_state1->blend_constant))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
@ -3121,7 +3178,9 @@ _cogl_pipeline_user_shader_equal (CoglPipeline *authority0,
|
|||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
_cogl_pipeline_layers_equal (CoglPipeline *authority0,
|
_cogl_pipeline_layers_equal (CoglPipeline *authority0,
|
||||||
CoglPipeline *authority1)
|
CoglPipeline *authority1,
|
||||||
|
unsigned long differences,
|
||||||
|
CoglPipelineEvalFlags flags)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
@ -3134,7 +3193,9 @@ _cogl_pipeline_layers_equal (CoglPipeline *authority0,
|
|||||||
for (i = 0; i < authority0->n_layers; i++)
|
for (i = 0; i < authority0->n_layers; i++)
|
||||||
{
|
{
|
||||||
if (!_cogl_pipeline_layer_equal (authority0->layers_cache[i],
|
if (!_cogl_pipeline_layer_equal (authority0->layers_cache[i],
|
||||||
authority1->layers_cache[i]))
|
authority1->layers_cache[i],
|
||||||
|
differences,
|
||||||
|
flags))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
return TRUE;
|
return TRUE;
|
||||||
@ -3229,21 +3290,55 @@ _cogl_pipeline_compare_differences (CoglPipeline *pipeline0,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
simple_property_equal (CoglPipeline *pipeline0,
|
simple_property_equal (CoglPipeline **authorities0,
|
||||||
CoglPipeline *pipeline1,
|
CoglPipeline **authorities1,
|
||||||
unsigned long pipelines_difference,
|
unsigned long pipelines_difference,
|
||||||
CoglPipelineState state,
|
CoglPipelineStateIndex state_index,
|
||||||
CoglPipelineStateComparitor comparitor)
|
CoglPipelineStateComparitor comparitor)
|
||||||
{
|
{
|
||||||
if (pipelines_difference & state)
|
if (pipelines_difference & (1L<<state_index))
|
||||||
{
|
{
|
||||||
if (!comparitor (_cogl_pipeline_get_authority (pipeline0, state),
|
if (!comparitor (authorities0[state_index], authorities1[state_index]))
|
||||||
_cogl_pipeline_get_authority (pipeline1, state)))
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
return TRUE;
|
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:
|
/* Comparison of two arbitrary pipelines is done by:
|
||||||
* 1) walking up the parents of each pipeline until a common
|
* 1) walking up the parents of each pipeline until a common
|
||||||
* ancestor is found, and at each step ORing together the
|
* 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
|
* 2) using the final difference mask to determine which state
|
||||||
* groups to compare.
|
* groups to compare.
|
||||||
*
|
*
|
||||||
* This is used by the Cogl journal to compare pipelines so that it
|
* This is used, for example, by the Cogl journal to compare pipelines so that
|
||||||
* can split up geometry that needs different OpenGL state.
|
* it can split up geometry that needs different OpenGL state.
|
||||||
*
|
*
|
||||||
* It is acceptable to have false negatives - although they will result
|
* XXX: When comparing texture layers, _cogl_pipeline_equal will actually
|
||||||
* in redundant OpenGL calls that try and update the state.
|
* 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
|
||||||
* When comparing texture layers, _cogl_pipeline_equal will actually
|
* the same texture. This is useful for comparing pipelines in the journal but
|
||||||
* compare the underlying GL texture handle that the Cogl texture uses
|
* it means that _cogl_pipeline_equal doesn't strictly compare whether the
|
||||||
* so that atlas textures and sub textures will be considered equal if
|
* pipelines are the same. If we needed those semantics we could perhaps add
|
||||||
* they point to the same texture. This is useful for comparing
|
* another function or some flags to control the behaviour.
|
||||||
* 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.
|
|
||||||
*/
|
*/
|
||||||
gboolean
|
gboolean
|
||||||
_cogl_pipeline_equal (CoglPipeline *pipeline0,
|
_cogl_pipeline_equal (CoglPipeline *pipeline0,
|
||||||
CoglPipeline *pipeline1,
|
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;
|
gboolean ret;
|
||||||
|
|
||||||
COGL_STATIC_TIMER (pipeline_equal_timer,
|
COGL_STATIC_TIMER (pipeline_equal_timer,
|
||||||
"Mainloop", /* parent */
|
"Mainloop", /* parent */
|
||||||
"_cogl_pipeline_equal",
|
"_cogl_pipeline_equal",
|
||||||
@ -3294,7 +3388,8 @@ _cogl_pipeline_equal (CoglPipeline *pipeline0,
|
|||||||
|
|
||||||
/* First check non-sparse properties */
|
/* 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;
|
goto done;
|
||||||
|
|
||||||
/* Then check sparse properties */
|
/* Then check sparse properties */
|
||||||
@ -3302,34 +3397,43 @@ _cogl_pipeline_equal (CoglPipeline *pipeline0,
|
|||||||
pipelines_difference =
|
pipelines_difference =
|
||||||
_cogl_pipeline_compare_differences (pipeline0, pipeline1);
|
_cogl_pipeline_compare_differences (pipeline0, pipeline1);
|
||||||
|
|
||||||
if (pipelines_difference & COGL_PIPELINE_STATE_COLOR &&
|
/* Only compare the sparse state groups requested by the caller... */
|
||||||
!skip_gl_color)
|
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 = authorities0[COGL_PIPELINE_STATE_COLOR_INDEX];
|
||||||
CoglPipeline *authority0 =
|
CoglPipeline *authority1 = authorities1[COGL_PIPELINE_STATE_COLOR_INDEX];
|
||||||
_cogl_pipeline_get_authority (pipeline0, state);
|
|
||||||
CoglPipeline *authority1 =
|
|
||||||
_cogl_pipeline_get_authority (pipeline1, state);
|
|
||||||
|
|
||||||
if (!cogl_color_equal (&authority0->color, &authority1->color))
|
if (!cogl_color_equal (&authority0->color, &authority1->color))
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!simple_property_equal (pipeline0, pipeline1,
|
if (!simple_property_equal (authorities0, authorities1,
|
||||||
pipelines_difference,
|
pipelines_difference,
|
||||||
COGL_PIPELINE_STATE_LIGHTING,
|
COGL_PIPELINE_STATE_LIGHTING_INDEX,
|
||||||
_cogl_pipeline_lighting_state_equal))
|
_cogl_pipeline_lighting_state_equal))
|
||||||
goto done;
|
goto done;
|
||||||
|
|
||||||
if (!simple_property_equal (pipeline0, pipeline1,
|
if (!simple_property_equal (authorities0, authorities1,
|
||||||
pipelines_difference,
|
pipelines_difference,
|
||||||
COGL_PIPELINE_STATE_ALPHA_FUNC,
|
COGL_PIPELINE_STATE_ALPHA_FUNC_INDEX,
|
||||||
_cogl_pipeline_alpha_func_state_equal))
|
_cogl_pipeline_alpha_func_state_equal))
|
||||||
goto done;
|
goto done;
|
||||||
|
|
||||||
if (!simple_property_equal (pipeline0, pipeline1,
|
if (!simple_property_equal (authorities0, authorities1,
|
||||||
pipelines_difference,
|
pipelines_difference,
|
||||||
COGL_PIPELINE_STATE_ALPHA_FUNC_REFERENCE,
|
COGL_PIPELINE_STATE_ALPHA_FUNC_REFERENCE_INDEX,
|
||||||
_cogl_pipeline_alpha_func_reference_state_equal))
|
_cogl_pipeline_alpha_func_reference_state_equal))
|
||||||
goto done;
|
goto done;
|
||||||
|
|
||||||
@ -3338,11 +3442,8 @@ _cogl_pipeline_equal (CoglPipeline *pipeline0,
|
|||||||
if (pipeline0->real_blend_enable &&
|
if (pipeline0->real_blend_enable &&
|
||||||
pipelines_difference & COGL_PIPELINE_STATE_BLEND)
|
pipelines_difference & COGL_PIPELINE_STATE_BLEND)
|
||||||
{
|
{
|
||||||
CoglPipelineState state = COGL_PIPELINE_STATE_BLEND;
|
CoglPipeline *authority0 = authorities0[COGL_PIPELINE_STATE_BLEND_INDEX];
|
||||||
CoglPipeline *authority0 =
|
CoglPipeline *authority1 = authorities1[COGL_PIPELINE_STATE_BLEND_INDEX];
|
||||||
_cogl_pipeline_get_authority (pipeline0, state);
|
|
||||||
CoglPipeline *authority1 =
|
|
||||||
_cogl_pipeline_get_authority (pipeline1, state);
|
|
||||||
|
|
||||||
if (!_cogl_pipeline_blend_state_equal (authority0, authority1))
|
if (!_cogl_pipeline_blend_state_equal (authority0, authority1))
|
||||||
goto done;
|
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
|
/* XXX: we don't need to compare the BLEND_ENABLE state because it's
|
||||||
* already reflected in ->real_blend_enable */
|
* already reflected in ->real_blend_enable */
|
||||||
#if 0
|
#if 0
|
||||||
if (!simple_property_equal (pipeline0, pipeline1,
|
if (!simple_property_equal (authorities0, authorities1,
|
||||||
pipelines_difference,
|
pipelines_difference,
|
||||||
COGL_PIPELINE_STATE_BLEND,
|
COGL_PIPELINE_STATE_BLEND_INDEX,
|
||||||
_cogl_pipeline_blend_enable_equal))
|
_cogl_pipeline_blend_enable_equal))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (!simple_property_equal (pipeline0, pipeline1,
|
if (!simple_property_equal (authorities0, authorities1,
|
||||||
pipelines_difference,
|
pipelines_difference,
|
||||||
COGL_PIPELINE_STATE_DEPTH,
|
COGL_PIPELINE_STATE_DEPTH_INDEX,
|
||||||
_cogl_pipeline_depth_state_equal))
|
_cogl_pipeline_depth_state_equal))
|
||||||
goto done;
|
goto done;
|
||||||
|
|
||||||
if (!simple_property_equal (pipeline0, pipeline1,
|
if (!simple_property_equal (authorities0, authorities1,
|
||||||
pipelines_difference,
|
pipelines_difference,
|
||||||
COGL_PIPELINE_STATE_FOG,
|
COGL_PIPELINE_STATE_FOG_INDEX,
|
||||||
_cogl_pipeline_fog_state_equal))
|
_cogl_pipeline_fog_state_equal))
|
||||||
goto done;
|
goto done;
|
||||||
|
|
||||||
if (!simple_property_equal (pipeline0, pipeline1,
|
if (!simple_property_equal (authorities0, authorities1,
|
||||||
pipelines_difference,
|
pipelines_difference,
|
||||||
COGL_PIPELINE_STATE_POINT_SIZE,
|
COGL_PIPELINE_STATE_POINT_SIZE_INDEX,
|
||||||
_cogl_pipeline_point_size_equal))
|
_cogl_pipeline_point_size_equal))
|
||||||
goto done;
|
goto done;
|
||||||
|
|
||||||
if (!simple_property_equal (pipeline0, pipeline1,
|
if (!simple_property_equal (authorities0, authorities1,
|
||||||
pipelines_difference,
|
pipelines_difference,
|
||||||
COGL_PIPELINE_STATE_USER_SHADER,
|
COGL_PIPELINE_STATE_USER_SHADER_INDEX,
|
||||||
_cogl_pipeline_user_shader_equal))
|
_cogl_pipeline_user_shader_equal))
|
||||||
goto done;
|
goto done;
|
||||||
|
|
||||||
if (!simple_property_equal (pipeline0, pipeline1,
|
if (pipelines_difference & COGL_PIPELINE_STATE_LAYERS)
|
||||||
pipelines_difference,
|
{
|
||||||
COGL_PIPELINE_STATE_LAYERS,
|
CoglPipelineStateIndex state_index = COGL_PIPELINE_STATE_LAYERS_INDEX;
|
||||||
_cogl_pipeline_layers_equal))
|
if (!_cogl_pipeline_layers_equal (authorities0[state_index],
|
||||||
|
authorities1[state_index],
|
||||||
|
layer_differences,
|
||||||
|
flags))
|
||||||
goto done;
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
ret = TRUE;
|
ret = TRUE;
|
||||||
done:
|
done:
|
||||||
|
Loading…
Reference in New Issue
Block a user