mirror of
https://github.com/brl/mutter.git
synced 2024-12-23 19:42:05 +00:00
pipeline: differentiate texture target and data state
There are several places where we need to compare the texture state of a pipeline and sometimes we need to take into consideration if the underlying texture has changed but other times we may only care to know if the texture target has changed. For example the fragends typically generate programs that they want to share with all pipelines with equivalent fragment processing state, and in this case when comparing pipelines we only care about the texture targets since changes to the underlying texture won't affect the programs generated. Prior to this we had tried to handle this by passing around some special flags to various functions that evaluate pipeline state to say when we do/don't care about the texture data, but this wasn't working in all cases and was more awkward to manage than the new approach. Now we simply have two state bits: COGL_PIPELINE_LAYER_STATE_TEXTURE_TARGET and COGL_PIPELINE_LAYER_STATE_TEXTURE_DATA and CoglPipelineLayer has an additional target member. Since all the appropriate code takes masks of these state bits to determine what to evaluate we don't need any extra magic flags.
This commit is contained in:
parent
8ab68d26a5
commit
88a085fdd8
@ -240,8 +240,7 @@ _cogl_pipeline_fragend_arbfp_start (CoglPipeline *pipeline,
|
|||||||
(pipeline,
|
(pipeline,
|
||||||
COGL_PIPELINE_STATE_AFFECTS_FRAGMENT_CODEGEN &
|
COGL_PIPELINE_STATE_AFFECTS_FRAGMENT_CODEGEN &
|
||||||
~COGL_PIPELINE_STATE_LAYERS,
|
~COGL_PIPELINE_STATE_LAYERS,
|
||||||
COGL_PIPELINE_LAYER_STATE_AFFECTS_FRAGMENT_CODEGEN,
|
COGL_PIPELINE_LAYER_STATE_AFFECTS_FRAGMENT_CODEGEN);
|
||||||
COGL_PIPELINE_FIND_EQUIVALENT_COMPARE_TEXTURE_TARGET);
|
|
||||||
authority_priv = get_arbfp_priv (authority);
|
authority_priv = get_arbfp_priv (authority);
|
||||||
if (authority_priv &&
|
if (authority_priv &&
|
||||||
authority_priv->arbfp_program_state)
|
authority_priv->arbfp_program_state)
|
||||||
@ -336,11 +335,10 @@ _cogl_pipeline_fragend_arbfp_hash (const void *data)
|
|||||||
COGL_PIPELINE_STATE_AFFECTS_FRAGMENT_CODEGEN;
|
COGL_PIPELINE_STATE_AFFECTS_FRAGMENT_CODEGEN;
|
||||||
unsigned long layer_fragment_state =
|
unsigned long layer_fragment_state =
|
||||||
COGL_PIPELINE_LAYER_STATE_AFFECTS_FRAGMENT_CODEGEN;
|
COGL_PIPELINE_LAYER_STATE_AFFECTS_FRAGMENT_CODEGEN;
|
||||||
CoglPipelineEvalFlags flags = COGL_PIPELINE_EVAL_FLAG_IGNORE_TEXTURE_DATA;
|
|
||||||
|
|
||||||
return _cogl_pipeline_hash ((CoglPipeline *)data,
|
return _cogl_pipeline_hash ((CoglPipeline *)data,
|
||||||
fragment_state, layer_fragment_state,
|
fragment_state, layer_fragment_state,
|
||||||
flags);
|
0);
|
||||||
}
|
}
|
||||||
|
|
||||||
gboolean
|
gboolean
|
||||||
@ -350,11 +348,10 @@ _cogl_pipeline_fragend_arbfp_equal (const void *a, const void *b)
|
|||||||
COGL_PIPELINE_STATE_AFFECTS_FRAGMENT_CODEGEN;
|
COGL_PIPELINE_STATE_AFFECTS_FRAGMENT_CODEGEN;
|
||||||
unsigned long layer_fragment_state =
|
unsigned long layer_fragment_state =
|
||||||
COGL_PIPELINE_LAYER_STATE_AFFECTS_FRAGMENT_CODEGEN;
|
COGL_PIPELINE_LAYER_STATE_AFFECTS_FRAGMENT_CODEGEN;
|
||||||
CoglPipelineEvalFlags flags = COGL_PIPELINE_EVAL_FLAG_IGNORE_TEXTURE_DATA;
|
|
||||||
|
|
||||||
return _cogl_pipeline_equal ((CoglPipeline *)a, (CoglPipeline *)b,
|
return _cogl_pipeline_equal ((CoglPipeline *)a, (CoglPipeline *)b,
|
||||||
fragment_state, layer_fragment_state,
|
fragment_state, layer_fragment_state,
|
||||||
flags);
|
0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char *
|
static const char *
|
||||||
|
@ -139,22 +139,19 @@ _cogl_pipeline_fragend_fixed_add_layer (CoglPipeline *pipeline,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Handle enabling or disabling the right texture target */
|
/* Handle enabling or disabling the right texture target */
|
||||||
if (layers_difference & COGL_PIPELINE_LAYER_STATE_TEXTURE)
|
if (layers_difference & COGL_PIPELINE_LAYER_STATE_TEXTURE_TARGET)
|
||||||
{
|
{
|
||||||
CoglPipelineLayer *authority =
|
CoglPipelineLayer *tex_authority =
|
||||||
_cogl_pipeline_layer_get_authority (layer,
|
_cogl_pipeline_layer_get_authority (layer,
|
||||||
COGL_PIPELINE_LAYER_STATE_TEXTURE);
|
COGL_PIPELINE_LAYER_STATE_TEXTURE_DATA);
|
||||||
CoglHandle texture;
|
CoglPipelineLayer *target_authority =
|
||||||
GLuint gl_texture;
|
_cogl_pipeline_layer_get_authority (layer,
|
||||||
GLenum gl_target;
|
COGL_PIPELINE_LAYER_STATE_TEXTURE_TARGET);
|
||||||
|
/* XXX: currently layers with no associated texture fallback to
|
||||||
texture = (authority->texture == COGL_INVALID_HANDLE ?
|
* using ctx->default_gl_texture_2d_tex so they have a texture
|
||||||
ctx->default_gl_texture_2d_tex :
|
* target of GL_TEXTURE_2D */
|
||||||
authority->texture);
|
GLenum gl_target =
|
||||||
|
tex_authority->texture ? target_authority->target : GL_TEXTURE_2D;
|
||||||
cogl_texture_get_gl_texture (texture,
|
|
||||||
&gl_texture,
|
|
||||||
&gl_target);
|
|
||||||
|
|
||||||
_cogl_set_active_texture_unit (unit_index);
|
_cogl_set_active_texture_unit (unit_index);
|
||||||
|
|
||||||
|
@ -240,8 +240,7 @@ _cogl_pipeline_fragend_glsl_start (CoglPipeline *pipeline,
|
|||||||
(pipeline,
|
(pipeline,
|
||||||
COGL_PIPELINE_STATE_AFFECTS_FRAGMENT_CODEGEN &
|
COGL_PIPELINE_STATE_AFFECTS_FRAGMENT_CODEGEN &
|
||||||
~COGL_PIPELINE_STATE_LAYERS,
|
~COGL_PIPELINE_STATE_LAYERS,
|
||||||
COGL_PIPELINE_LAYER_STATE_AFFECTS_FRAGMENT_CODEGEN,
|
COGL_PIPELINE_LAYER_STATE_AFFECTS_FRAGMENT_CODEGEN);
|
||||||
COGL_PIPELINE_FIND_EQUIVALENT_COMPARE_TEXTURE_TARGET);
|
|
||||||
|
|
||||||
authority_priv = get_glsl_priv (authority);
|
authority_priv = get_glsl_priv (authority);
|
||||||
if (!authority_priv)
|
if (!authority_priv)
|
||||||
|
@ -674,11 +674,11 @@ flush_layers_common_gl_state_cb (CoglPipelineLayer *layer, void *user_data)
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (layers_difference & COGL_PIPELINE_LAYER_STATE_TEXTURE)
|
if (layers_difference & COGL_PIPELINE_LAYER_STATE_TEXTURE_DATA)
|
||||||
{
|
{
|
||||||
|
unsigned long state = COGL_PIPELINE_LAYER_STATE_TEXTURE_DATA;
|
||||||
CoglPipelineLayer *authority =
|
CoglPipelineLayer *authority =
|
||||||
_cogl_pipeline_layer_get_authority (layer,
|
_cogl_pipeline_layer_get_authority (layer, state);
|
||||||
COGL_PIPELINE_LAYER_STATE_TEXTURE);
|
|
||||||
CoglHandle texture;
|
CoglHandle texture;
|
||||||
GLuint gl_texture;
|
GLuint gl_texture;
|
||||||
GLenum gl_target;
|
GLenum gl_target;
|
||||||
@ -909,7 +909,8 @@ compare_layer_differences_cb (CoglPipelineLayer *layer, void *user_data)
|
|||||||
* then we force an update of the texture state...
|
* then we force an update of the texture state...
|
||||||
*/
|
*/
|
||||||
if (unit->texture_storage_changed)
|
if (unit->texture_storage_changed)
|
||||||
state->layer_differences[state->i] |= COGL_PIPELINE_LAYER_STATE_TEXTURE;
|
state->layer_differences[state->i] |=
|
||||||
|
COGL_PIPELINE_LAYER_STATE_TEXTURE_DATA;
|
||||||
|
|
||||||
state->i++;
|
state->i++;
|
||||||
|
|
||||||
|
@ -116,7 +116,8 @@ typedef enum
|
|||||||
{
|
{
|
||||||
/* sparse state */
|
/* sparse state */
|
||||||
COGL_PIPELINE_LAYER_STATE_UNIT_INDEX,
|
COGL_PIPELINE_LAYER_STATE_UNIT_INDEX,
|
||||||
COGL_PIPELINE_LAYER_STATE_TEXTURE_INDEX,
|
COGL_PIPELINE_LAYER_STATE_TEXTURE_TARGET_INDEX,
|
||||||
|
COGL_PIPELINE_LAYER_STATE_TEXTURE_DATA_INDEX,
|
||||||
COGL_PIPELINE_LAYER_STATE_FILTERS_INDEX,
|
COGL_PIPELINE_LAYER_STATE_FILTERS_INDEX,
|
||||||
COGL_PIPELINE_LAYER_STATE_WRAP_MODES_INDEX,
|
COGL_PIPELINE_LAYER_STATE_WRAP_MODES_INDEX,
|
||||||
COGL_PIPELINE_LAYER_STATE_COMBINE_INDEX,
|
COGL_PIPELINE_LAYER_STATE_COMBINE_INDEX,
|
||||||
@ -141,8 +142,10 @@ typedef enum
|
|||||||
{
|
{
|
||||||
COGL_PIPELINE_LAYER_STATE_UNIT =
|
COGL_PIPELINE_LAYER_STATE_UNIT =
|
||||||
1L<<COGL_PIPELINE_LAYER_STATE_UNIT_INDEX,
|
1L<<COGL_PIPELINE_LAYER_STATE_UNIT_INDEX,
|
||||||
COGL_PIPELINE_LAYER_STATE_TEXTURE =
|
COGL_PIPELINE_LAYER_STATE_TEXTURE_TARGET =
|
||||||
1L<<COGL_PIPELINE_LAYER_STATE_TEXTURE_INDEX,
|
1L<<COGL_PIPELINE_LAYER_STATE_TEXTURE_TARGET_INDEX,
|
||||||
|
COGL_PIPELINE_LAYER_STATE_TEXTURE_DATA =
|
||||||
|
1L<<COGL_PIPELINE_LAYER_STATE_TEXTURE_DATA_INDEX,
|
||||||
COGL_PIPELINE_LAYER_STATE_FILTERS =
|
COGL_PIPELINE_LAYER_STATE_FILTERS =
|
||||||
1L<<COGL_PIPELINE_LAYER_STATE_FILTERS_INDEX,
|
1L<<COGL_PIPELINE_LAYER_STATE_FILTERS_INDEX,
|
||||||
COGL_PIPELINE_LAYER_STATE_WRAP_MODES =
|
COGL_PIPELINE_LAYER_STATE_WRAP_MODES =
|
||||||
@ -190,13 +193,13 @@ typedef enum
|
|||||||
* when point sprite coords are enabled */
|
* when point sprite coords are enabled */
|
||||||
#define COGL_PIPELINE_LAYER_STATE_AFFECTS_FRAGMENT_CODEGEN \
|
#define COGL_PIPELINE_LAYER_STATE_AFFECTS_FRAGMENT_CODEGEN \
|
||||||
(COGL_PIPELINE_LAYER_STATE_COMBINE | \
|
(COGL_PIPELINE_LAYER_STATE_COMBINE | \
|
||||||
COGL_PIPELINE_LAYER_STATE_TEXTURE | \
|
COGL_PIPELINE_LAYER_STATE_TEXTURE_TARGET | \
|
||||||
COGL_PIPELINE_LAYER_STATE_POINT_SPRITE_COORDS | \
|
COGL_PIPELINE_LAYER_STATE_POINT_SPRITE_COORDS | \
|
||||||
COGL_PIPELINE_LAYER_STATE_UNIT)
|
COGL_PIPELINE_LAYER_STATE_UNIT)
|
||||||
#else
|
#else
|
||||||
#define COGL_PIPELINE_LAYER_STATE_AFFECTS_FRAGMENT_CODEGEN \
|
#define COGL_PIPELINE_LAYER_STATE_AFFECTS_FRAGMENT_CODEGEN \
|
||||||
(COGL_PIPELINE_LAYER_STATE_COMBINE | \
|
(COGL_PIPELINE_LAYER_STATE_COMBINE | \
|
||||||
COGL_PIPELINE_LAYER_STATE_TEXTURE | \
|
COGL_PIPELINE_LAYER_STATE_TEXTURE_TARGET | \
|
||||||
COGL_PIPELINE_LAYER_STATE_UNIT)
|
COGL_PIPELINE_LAYER_STATE_UNIT)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -370,6 +373,7 @@ struct _CoglPipelineLayer
|
|||||||
/* The texture for this layer, or COGL_INVALID_HANDLE for an empty
|
/* The texture for this layer, or COGL_INVALID_HANDLE for an empty
|
||||||
* layer */
|
* layer */
|
||||||
CoglHandle texture;
|
CoglHandle texture;
|
||||||
|
GLenum target;
|
||||||
|
|
||||||
CoglPipelineFilter mag_filter;
|
CoglPipelineFilter mag_filter;
|
||||||
CoglPipelineFilter min_filter;
|
CoglPipelineFilter min_filter;
|
||||||
@ -600,12 +604,6 @@ typedef struct
|
|||||||
CoglPipelineLayer *layer;
|
CoglPipelineLayer *layer;
|
||||||
} CoglPipelineLayerCacheEntry;
|
} CoglPipelineLayerCacheEntry;
|
||||||
|
|
||||||
/* Flags used for _cogl_pipeline_find_equivalent_parent */
|
|
||||||
typedef enum
|
|
||||||
{
|
|
||||||
COGL_PIPELINE_FIND_EQUIVALENT_COMPARE_TEXTURE_TARGET = 1L<<0
|
|
||||||
} CoglPipelineFindEquivalentFlags;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* CoglPipelineDestroyCallback
|
* CoglPipelineDestroyCallback
|
||||||
* @pipeline: The #CoglPipeline that has been destroyed
|
* @pipeline: The #CoglPipeline that has been destroyed
|
||||||
@ -1092,10 +1090,7 @@ _cogl_pipeline_compare_differences (CoglPipeline *pipeline0,
|
|||||||
* semantics */
|
* semantics */
|
||||||
typedef enum _CoglPipelineEvalFlags
|
typedef enum _CoglPipelineEvalFlags
|
||||||
{
|
{
|
||||||
/* When evaluating a pipeline-layer with associated textures then
|
COGL_PIPELINE_EVAL_FLAG_NONE = 0
|
||||||
* evaluate the texture target, but don't consider the texture data
|
|
||||||
* itself. */
|
|
||||||
COGL_PIPELINE_EVAL_FLAG_IGNORE_TEXTURE_DATA = 1L<<0
|
|
||||||
} CoglPipelineEvalFlags;
|
} CoglPipelineEvalFlags;
|
||||||
|
|
||||||
gboolean
|
gboolean
|
||||||
@ -1160,8 +1155,7 @@ _cogl_pipeline_get_authority (CoglPipeline *pipeline,
|
|||||||
CoglPipeline *
|
CoglPipeline *
|
||||||
_cogl_pipeline_find_equivalent_parent (CoglPipeline *pipeline,
|
_cogl_pipeline_find_equivalent_parent (CoglPipeline *pipeline,
|
||||||
CoglPipelineState pipeline_state,
|
CoglPipelineState pipeline_state,
|
||||||
CoglPipelineLayerState layer_state,
|
CoglPipelineLayerState layer_state);
|
||||||
CoglPipelineFindEquivalentFlags flags);
|
|
||||||
|
|
||||||
CoglHandle
|
CoglHandle
|
||||||
_cogl_pipeline_get_layer_texture (CoglPipeline *pipeline,
|
_cogl_pipeline_get_layer_texture (CoglPipeline *pipeline,
|
||||||
|
@ -525,8 +525,7 @@ _cogl_pipeline_progend_glsl_end (CoglPipeline *pipeline,
|
|||||||
COGL_PIPELINE_STATE_AFFECTS_FRAGMENT_CODEGEN) &
|
COGL_PIPELINE_STATE_AFFECTS_FRAGMENT_CODEGEN) &
|
||||||
~COGL_PIPELINE_STATE_LAYERS,
|
~COGL_PIPELINE_STATE_LAYERS,
|
||||||
COGL_PIPELINE_LAYER_STATE_AFFECTS_FRAGMENT_CODEGEN |
|
COGL_PIPELINE_LAYER_STATE_AFFECTS_FRAGMENT_CODEGEN |
|
||||||
COGL_PIPELINE_LAYER_STATE_AFFECTS_VERTEX_CODEGEN,
|
COGL_PIPELINE_LAYER_STATE_AFFECTS_VERTEX_CODEGEN);
|
||||||
COGL_PIPELINE_FIND_EQUIVALENT_COMPARE_TEXTURE_TARGET);
|
|
||||||
|
|
||||||
priv = get_glsl_priv (authority);
|
priv = get_glsl_priv (authority);
|
||||||
|
|
||||||
|
@ -157,8 +157,7 @@ _cogl_pipeline_vertend_glsl_start (CoglPipeline *pipeline,
|
|||||||
(pipeline,
|
(pipeline,
|
||||||
COGL_PIPELINE_STATE_AFFECTS_VERTEX_CODEGEN &
|
COGL_PIPELINE_STATE_AFFECTS_VERTEX_CODEGEN &
|
||||||
~COGL_PIPELINE_STATE_LAYERS,
|
~COGL_PIPELINE_STATE_LAYERS,
|
||||||
COGL_PIPELINE_LAYER_STATE_AFFECTS_VERTEX_CODEGEN,
|
COGL_PIPELINE_LAYER_STATE_AFFECTS_VERTEX_CODEGEN);
|
||||||
0);
|
|
||||||
|
|
||||||
priv = get_glsl_priv (authority);
|
priv = get_glsl_priv (authority);
|
||||||
|
|
||||||
|
@ -799,7 +799,7 @@ layer_has_alpha_cb (CoglPipelineLayer *layer, void *data)
|
|||||||
*/
|
*/
|
||||||
tex_authority =
|
tex_authority =
|
||||||
_cogl_pipeline_layer_get_authority (layer,
|
_cogl_pipeline_layer_get_authority (layer,
|
||||||
COGL_PIPELINE_LAYER_STATE_TEXTURE);
|
COGL_PIPELINE_LAYER_STATE_TEXTURE_DATA);
|
||||||
if (tex_authority->texture &&
|
if (tex_authority->texture &&
|
||||||
cogl_texture_get_format (tex_authority->texture) & COGL_A_BIT)
|
cogl_texture_get_format (tex_authority->texture) & COGL_A_BIT)
|
||||||
{
|
{
|
||||||
@ -1716,7 +1716,8 @@ _cogl_pipeline_layer_init_multi_property_sparse_state (
|
|||||||
/* XXX: avoid using a default: label so we get a warning if we
|
/* XXX: avoid using a default: label so we get a warning if we
|
||||||
* don't explicitly handle a newly defined state-group here. */
|
* don't explicitly handle a newly defined state-group here. */
|
||||||
case COGL_PIPELINE_LAYER_STATE_UNIT:
|
case COGL_PIPELINE_LAYER_STATE_UNIT:
|
||||||
case COGL_PIPELINE_LAYER_STATE_TEXTURE:
|
case COGL_PIPELINE_LAYER_STATE_TEXTURE_TARGET:
|
||||||
|
case COGL_PIPELINE_LAYER_STATE_TEXTURE_DATA:
|
||||||
case COGL_PIPELINE_LAYER_STATE_POINT_SPRITE_COORDS:
|
case COGL_PIPELINE_LAYER_STATE_POINT_SPRITE_COORDS:
|
||||||
case COGL_PIPELINE_LAYER_STATE_USER_MATRIX:
|
case COGL_PIPELINE_LAYER_STATE_USER_MATRIX:
|
||||||
case COGL_PIPELINE_LAYER_STATE_COMBINE_CONSTANT:
|
case COGL_PIPELINE_LAYER_STATE_COMBINE_CONSTANT:
|
||||||
@ -2153,7 +2154,7 @@ _cogl_pipeline_layer_get_texture_real (CoglPipelineLayer *layer)
|
|||||||
{
|
{
|
||||||
CoglPipelineLayer *authority =
|
CoglPipelineLayer *authority =
|
||||||
_cogl_pipeline_layer_get_authority (layer,
|
_cogl_pipeline_layer_get_authority (layer,
|
||||||
COGL_PIPELINE_LAYER_STATE_TEXTURE);
|
COGL_PIPELINE_LAYER_STATE_TEXTURE_DATA);
|
||||||
|
|
||||||
return authority->texture;
|
return authority->texture;
|
||||||
}
|
}
|
||||||
@ -2242,12 +2243,83 @@ _cogl_pipeline_prune_empty_layer_difference (CoglPipeline *layers_authority,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
static void
|
||||||
cogl_pipeline_set_layer_texture (CoglPipeline *pipeline,
|
_cogl_pipeline_set_layer_texture_target (CoglPipeline *pipeline,
|
||||||
int layer_index,
|
int layer_index,
|
||||||
CoglHandle texture)
|
GLenum target)
|
||||||
{
|
{
|
||||||
CoglPipelineLayerState change = COGL_PIPELINE_LAYER_STATE_TEXTURE;
|
CoglPipelineLayerState change = COGL_PIPELINE_LAYER_STATE_TEXTURE_TARGET;
|
||||||
|
CoglPipelineLayer *layer;
|
||||||
|
CoglPipelineLayer *authority;
|
||||||
|
CoglPipelineLayer *new;
|
||||||
|
|
||||||
|
/* Note: this will ensure that the layer exists, creating one if it
|
||||||
|
* doesn't already.
|
||||||
|
*
|
||||||
|
* Note: If the layer already existed it's possibly owned by another
|
||||||
|
* pipeline. If the layer is created then it will be owned by
|
||||||
|
* pipeline. */
|
||||||
|
layer = _cogl_pipeline_get_layer (pipeline, layer_index);
|
||||||
|
|
||||||
|
/* Now find the ancestor of the layer that is the authority for the
|
||||||
|
* state we want to change */
|
||||||
|
authority = _cogl_pipeline_layer_get_authority (layer, change);
|
||||||
|
|
||||||
|
if (target == authority->target)
|
||||||
|
return;
|
||||||
|
|
||||||
|
new = _cogl_pipeline_layer_pre_change_notify (pipeline, layer, change);
|
||||||
|
if (new != layer)
|
||||||
|
layer = new;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* If the original layer we found is currently the authority on
|
||||||
|
* the state we are changing see if we can revert to one of our
|
||||||
|
* ancestors being the authority. */
|
||||||
|
if (layer == authority &&
|
||||||
|
_cogl_pipeline_layer_get_parent (authority) != NULL)
|
||||||
|
{
|
||||||
|
CoglPipelineLayer *parent =
|
||||||
|
_cogl_pipeline_layer_get_parent (authority);
|
||||||
|
CoglPipelineLayer *old_authority =
|
||||||
|
_cogl_pipeline_layer_get_authority (parent, change);
|
||||||
|
|
||||||
|
if (old_authority->target == target)
|
||||||
|
{
|
||||||
|
layer->differences &= ~change;
|
||||||
|
|
||||||
|
g_assert (layer->owner == pipeline);
|
||||||
|
if (layer->differences == 0)
|
||||||
|
_cogl_pipeline_prune_empty_layer_difference (pipeline,
|
||||||
|
layer);
|
||||||
|
goto changed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
layer->target = target;
|
||||||
|
|
||||||
|
/* If we weren't previously the authority on this state then we need
|
||||||
|
* to extended our differences mask and so it's possible that some
|
||||||
|
* of our ancestry will now become redundant, so we aim to reparent
|
||||||
|
* ourselves if that's true... */
|
||||||
|
if (layer != authority)
|
||||||
|
{
|
||||||
|
layer->differences |= change;
|
||||||
|
_cogl_pipeline_layer_prune_redundant_ancestry (layer);
|
||||||
|
}
|
||||||
|
|
||||||
|
changed:
|
||||||
|
|
||||||
|
handle_automatic_blend_enable (pipeline, COGL_PIPELINE_STATE_LAYERS);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_cogl_pipeline_set_layer_texture_data (CoglPipeline *pipeline,
|
||||||
|
int layer_index,
|
||||||
|
CoglHandle texture)
|
||||||
|
{
|
||||||
|
CoglPipelineLayerState change = COGL_PIPELINE_LAYER_STATE_TEXTURE_DATA;
|
||||||
CoglPipelineLayer *layer;
|
CoglPipelineLayer *layer;
|
||||||
CoglPipelineLayer *authority;
|
CoglPipelineLayer *authority;
|
||||||
CoglPipelineLayer *new;
|
CoglPipelineLayer *new;
|
||||||
@ -2321,6 +2393,48 @@ changed:
|
|||||||
handle_automatic_blend_enable (pipeline, COGL_PIPELINE_STATE_LAYERS);
|
handle_automatic_blend_enable (pipeline, COGL_PIPELINE_STATE_LAYERS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* A convenience for querying the target of a given texture that
|
||||||
|
* notably returns 0 for NULL textures - so we can say that a layer
|
||||||
|
* with no associated CoglTexture will have a texture target of 0.
|
||||||
|
*/
|
||||||
|
static GLenum
|
||||||
|
get_texture_target (CoglHandle texture)
|
||||||
|
{
|
||||||
|
GLuint ignore_handle;
|
||||||
|
GLenum gl_target;
|
||||||
|
|
||||||
|
if (texture)
|
||||||
|
cogl_texture_get_gl_texture (texture, &ignore_handle, &gl_target);
|
||||||
|
else
|
||||||
|
return 0;/* XXX: An invalid GL target enum */
|
||||||
|
|
||||||
|
return gl_target;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
cogl_pipeline_set_layer_texture (CoglPipeline *pipeline,
|
||||||
|
int layer_index,
|
||||||
|
CoglHandle texture)
|
||||||
|
{
|
||||||
|
/* For the convenience of fragend code we separate texture state
|
||||||
|
* into the "target" and the "data", and setting a layer texture
|
||||||
|
* updates both of these properties.
|
||||||
|
*
|
||||||
|
* One example for why this is helpful is that the fragends may
|
||||||
|
* cache programs they generate and want to re-use those programs
|
||||||
|
* with all pipelines having equivalent fragment processing state.
|
||||||
|
* For the sake of determining if pipelines have equivalent fragment
|
||||||
|
* processing state we don't need to compare that the same
|
||||||
|
* underlying texture objects are referenced by the pipelines but we
|
||||||
|
* do need to see if they use the same texture targets. Making this
|
||||||
|
* distinction is much simpler if they are in different state
|
||||||
|
* groups.
|
||||||
|
*/
|
||||||
|
_cogl_pipeline_set_layer_texture_target (pipeline, layer_index,
|
||||||
|
get_texture_target (texture));
|
||||||
|
_cogl_pipeline_set_layer_texture_data (pipeline, layer_index, texture);
|
||||||
|
}
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
@ -2897,20 +3011,24 @@ _cogl_pipeline_apply_overrides (CoglPipeline *pipeline,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
_cogl_pipeline_layer_texture_equal (CoglPipelineLayer *authority0,
|
_cogl_pipeline_layer_texture_target_equal (CoglPipelineLayer *authority0,
|
||||||
CoglPipelineLayer *authority1,
|
CoglPipelineLayer *authority1,
|
||||||
CoglPipelineEvalFlags flags)
|
CoglPipelineEvalFlags flags)
|
||||||
|
{
|
||||||
|
return authority0->target == authority1->target;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
_cogl_pipeline_layer_texture_data_equal (CoglPipelineLayer *authority0,
|
||||||
|
CoglPipelineLayer *authority1,
|
||||||
|
CoglPipelineEvalFlags flags)
|
||||||
{
|
{
|
||||||
GLuint gl_handle0, gl_handle1;
|
GLuint gl_handle0, gl_handle1;
|
||||||
GLenum gl_target0, gl_target1;
|
|
||||||
|
|
||||||
cogl_texture_get_gl_texture (authority0->texture, &gl_handle0, &gl_target0);
|
cogl_texture_get_gl_texture (authority0->texture, &gl_handle0, NULL);
|
||||||
cogl_texture_get_gl_texture (authority1->texture, &gl_handle1, &gl_target1);
|
cogl_texture_get_gl_texture (authority1->texture, &gl_handle1, NULL);
|
||||||
|
|
||||||
if (flags & COGL_PIPELINE_EVAL_FLAG_IGNORE_TEXTURE_DATA)
|
return gl_handle0 == gl_handle1;
|
||||||
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.
|
||||||
@ -3177,13 +3295,23 @@ _cogl_pipeline_layer_equal (CoglPipelineLayer *layer0,
|
|||||||
layers_difference,
|
layers_difference,
|
||||||
authorities1);
|
authorities1);
|
||||||
|
|
||||||
if (layers_difference & COGL_PIPELINE_LAYER_STATE_TEXTURE)
|
if (layers_difference & COGL_PIPELINE_LAYER_STATE_TEXTURE_TARGET)
|
||||||
{
|
{
|
||||||
CoglPipelineLayerStateIndex state_index =
|
CoglPipelineLayerStateIndex state_index =
|
||||||
COGL_PIPELINE_LAYER_STATE_TEXTURE_INDEX;
|
COGL_PIPELINE_LAYER_STATE_TEXTURE_TARGET_INDEX;
|
||||||
if (!_cogl_pipeline_layer_texture_equal (authorities0[state_index],
|
if (!_cogl_pipeline_layer_texture_target_equal (authorities0[state_index],
|
||||||
authorities1[state_index],
|
authorities1[state_index],
|
||||||
flags))
|
flags))
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (layers_difference & COGL_PIPELINE_LAYER_STATE_TEXTURE_DATA)
|
||||||
|
{
|
||||||
|
CoglPipelineLayerStateIndex state_index =
|
||||||
|
COGL_PIPELINE_LAYER_STATE_TEXTURE_DATA_INDEX;
|
||||||
|
if (!_cogl_pipeline_layer_texture_data_equal (authorities0[state_index],
|
||||||
|
authorities1[state_index],
|
||||||
|
flags))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4794,7 +4922,7 @@ _cogl_pipeline_layer_free (CoglPipelineLayer *layer)
|
|||||||
{
|
{
|
||||||
_cogl_pipeline_layer_unparent (COGL_PIPELINE_NODE (layer));
|
_cogl_pipeline_layer_unparent (COGL_PIPELINE_NODE (layer));
|
||||||
|
|
||||||
if (layer->differences & COGL_PIPELINE_LAYER_STATE_TEXTURE &&
|
if (layer->differences & COGL_PIPELINE_LAYER_STATE_TEXTURE_DATA &&
|
||||||
layer->texture != COGL_INVALID_HANDLE)
|
layer->texture != COGL_INVALID_HANDLE)
|
||||||
cogl_handle_unref (layer->texture);
|
cogl_handle_unref (layer->texture);
|
||||||
|
|
||||||
@ -4851,6 +4979,7 @@ _cogl_pipeline_init_default_layers (void)
|
|||||||
layer->unit_index = 0;
|
layer->unit_index = 0;
|
||||||
|
|
||||||
layer->texture = COGL_INVALID_HANDLE;
|
layer->texture = COGL_INVALID_HANDLE;
|
||||||
|
layer->target = 0;
|
||||||
|
|
||||||
layer->mag_filter = COGL_PIPELINE_FILTER_LINEAR;
|
layer->mag_filter = COGL_PIPELINE_FILTER_LINEAR;
|
||||||
layer->min_filter = COGL_PIPELINE_FILTER_LINEAR;
|
layer->min_filter = COGL_PIPELINE_FILTER_LINEAR;
|
||||||
@ -5511,7 +5640,7 @@ _cogl_pipeline_layer_pre_paint (CoglPipelineLayer *layer)
|
|||||||
|
|
||||||
texture_authority =
|
texture_authority =
|
||||||
_cogl_pipeline_layer_get_authority (layer,
|
_cogl_pipeline_layer_get_authority (layer,
|
||||||
COGL_PIPELINE_LAYER_STATE_TEXTURE);
|
COGL_PIPELINE_LAYER_STATE_TEXTURE_DATA);
|
||||||
|
|
||||||
if (texture_authority->texture != COGL_INVALID_HANDLE)
|
if (texture_authority->texture != COGL_INVALID_HANDLE)
|
||||||
{
|
{
|
||||||
@ -5750,22 +5879,27 @@ _cogl_pipeline_layer_hash_unit_state (CoglPipelineLayer *authority,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
_cogl_pipeline_layer_hash_texture_state (CoglPipelineLayer *authority,
|
_cogl_pipeline_layer_hash_texture_target_state (CoglPipelineLayer *authority,
|
||||||
CoglPipelineLayer **authorities,
|
CoglPipelineLayer **authorities,
|
||||||
HashState *state)
|
HashState *state)
|
||||||
|
{
|
||||||
|
GLenum gl_target = authority->target;
|
||||||
|
|
||||||
|
state->hash =
|
||||||
|
_cogl_util_one_at_a_time_hash (state->hash, &gl_target, sizeof (gl_target));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_cogl_pipeline_layer_hash_texture_data_state (CoglPipelineLayer *authority,
|
||||||
|
CoglPipelineLayer **authorities,
|
||||||
|
HashState *state)
|
||||||
{
|
{
|
||||||
GLuint gl_handle;
|
GLuint gl_handle;
|
||||||
GLenum gl_target;
|
|
||||||
unsigned long hash = state->hash;
|
|
||||||
|
|
||||||
cogl_texture_get_gl_texture (authority->texture, &gl_handle, &gl_target);
|
cogl_texture_get_gl_texture (authority->texture, &gl_handle, NULL);
|
||||||
|
|
||||||
hash = _cogl_util_one_at_a_time_hash (hash, &gl_target, sizeof (gl_target));
|
state->hash =
|
||||||
|
_cogl_util_one_at_a_time_hash (state->hash, &gl_handle, sizeof (gl_handle));
|
||||||
if (!(state->flags & COGL_PIPELINE_EVAL_FLAG_IGNORE_TEXTURE_DATA))
|
|
||||||
hash = _cogl_util_one_at_a_time_hash (hash, &gl_handle, sizeof (gl_handle));
|
|
||||||
|
|
||||||
state->hash = hash;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -5922,8 +6056,10 @@ _cogl_pipeline_init_layer_state_hash_functions (void)
|
|||||||
CoglPipelineLayerStateIndex _index;
|
CoglPipelineLayerStateIndex _index;
|
||||||
layer_state_hash_functions[COGL_PIPELINE_LAYER_STATE_UNIT_INDEX] =
|
layer_state_hash_functions[COGL_PIPELINE_LAYER_STATE_UNIT_INDEX] =
|
||||||
_cogl_pipeline_layer_hash_unit_state;
|
_cogl_pipeline_layer_hash_unit_state;
|
||||||
layer_state_hash_functions[COGL_PIPELINE_LAYER_STATE_TEXTURE_INDEX] =
|
layer_state_hash_functions[COGL_PIPELINE_LAYER_STATE_TEXTURE_TARGET_INDEX] =
|
||||||
_cogl_pipeline_layer_hash_texture_state;
|
_cogl_pipeline_layer_hash_texture_target_state;
|
||||||
|
layer_state_hash_functions[COGL_PIPELINE_LAYER_STATE_TEXTURE_DATA_INDEX] =
|
||||||
|
_cogl_pipeline_layer_hash_texture_data_state;
|
||||||
layer_state_hash_functions[COGL_PIPELINE_LAYER_STATE_FILTERS_INDEX] =
|
layer_state_hash_functions[COGL_PIPELINE_LAYER_STATE_FILTERS_INDEX] =
|
||||||
_cogl_pipeline_layer_hash_filters_state;
|
_cogl_pipeline_layer_hash_filters_state;
|
||||||
layer_state_hash_functions[COGL_PIPELINE_LAYER_STATE_WRAP_MODES_INDEX] =
|
layer_state_hash_functions[COGL_PIPELINE_LAYER_STATE_WRAP_MODES_INDEX] =
|
||||||
@ -5939,7 +6075,7 @@ _cogl_pipeline_init_layer_state_hash_functions (void)
|
|||||||
_cogl_pipeline_layer_hash_point_sprite_state;
|
_cogl_pipeline_layer_hash_point_sprite_state;
|
||||||
|
|
||||||
/* So we get a big error if we forget to update this code! */
|
/* So we get a big error if we forget to update this code! */
|
||||||
g_assert (COGL_PIPELINE_LAYER_STATE_SPARSE_COUNT == 8);
|
g_assert (COGL_PIPELINE_LAYER_STATE_SPARSE_COUNT == 9);
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
@ -6300,7 +6436,7 @@ dump_layer_cb (CoglPipelineNode *node, void *user_data)
|
|||||||
layer->unit_index);
|
layer->unit_index);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (layer->differences & COGL_PIPELINE_LAYER_STATE_TEXTURE)
|
if (layer->differences & COGL_PIPELINE_LAYER_STATE_TEXTURE_DATA)
|
||||||
{
|
{
|
||||||
changes = TRUE;
|
changes = TRUE;
|
||||||
g_string_append_printf (changes_label,
|
g_string_append_printf (changes_label,
|
||||||
@ -6585,43 +6721,6 @@ _cogl_pipeline_need_texture_combine_separate
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
|
||||||
layers_differ_for_find_equivalent (CoglPipelineLayerState layer_state,
|
|
||||||
CoglPipelineFindEquivalentFlags flags,
|
|
||||||
CoglPipelineLayer *layer0,
|
|
||||||
CoglPipelineLayer *layer1)
|
|
||||||
{
|
|
||||||
unsigned long layer_differences;
|
|
||||||
|
|
||||||
if (layer0 == layer1)
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
layer_differences =
|
|
||||||
_cogl_pipeline_layer_compare_differences (layer0, layer1);
|
|
||||||
|
|
||||||
if (layer_differences & layer_state)
|
|
||||||
return TRUE;
|
|
||||||
|
|
||||||
/* When generating a shader we need to detect when the texture
|
|
||||||
target changes but we don't care if the texture object
|
|
||||||
changes so we have a flag to handle this special case */
|
|
||||||
if ((flags & COGL_PIPELINE_FIND_EQUIVALENT_COMPARE_TEXTURE_TARGET) &&
|
|
||||||
(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)
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* This tries to find the oldest ancestor whose pipeline and layer
|
/* This tries to find the oldest ancestor whose pipeline and layer
|
||||||
state matches the given flags. This is mostly used to detect code
|
state matches the given flags. This is mostly used to detect code
|
||||||
gen authorities so that we can reduce the numer of programs
|
gen authorities so that we can reduce the numer of programs
|
||||||
@ -6629,8 +6728,7 @@ layers_differ_for_find_equivalent (CoglPipelineLayerState layer_state,
|
|||||||
CoglPipeline *
|
CoglPipeline *
|
||||||
_cogl_pipeline_find_equivalent_parent (CoglPipeline *pipeline,
|
_cogl_pipeline_find_equivalent_parent (CoglPipeline *pipeline,
|
||||||
CoglPipelineState pipeline_state,
|
CoglPipelineState pipeline_state,
|
||||||
CoglPipelineLayerState layer_state,
|
CoglPipelineLayerState layer_state)
|
||||||
CoglPipelineFindEquivalentFlags flags)
|
|
||||||
{
|
{
|
||||||
CoglPipeline *authority0;
|
CoglPipeline *authority0;
|
||||||
CoglPipeline *authority1;
|
CoglPipeline *authority1;
|
||||||
@ -6690,10 +6788,19 @@ _cogl_pipeline_find_equivalent_parent (CoglPipeline *pipeline,
|
|||||||
&state);
|
&state);
|
||||||
|
|
||||||
for (i = 0; i < n_layers; i++)
|
for (i = 0; i < n_layers; i++)
|
||||||
if (layers_differ_for_find_equivalent (layer_state, flags,
|
{
|
||||||
authority0_layers[i],
|
unsigned long layer_differences;
|
||||||
authority1_layers[i]))
|
|
||||||
return authority0;
|
if (authority0_layers[i] == authority1_layers[i])
|
||||||
|
continue;
|
||||||
|
|
||||||
|
layer_differences =
|
||||||
|
_cogl_pipeline_layer_compare_differences (authority0_layers[i],
|
||||||
|
authority1_layers[i]);
|
||||||
|
|
||||||
|
if (layer_differences & layer_state)
|
||||||
|
return authority0;
|
||||||
|
}
|
||||||
|
|
||||||
/* Find the next ancestor after that, that also modifies state
|
/* Find the next ancestor after that, that also modifies state
|
||||||
* affecting codegen... */
|
* affecting codegen... */
|
||||||
|
Loading…
Reference in New Issue
Block a user