mirror of
https://github.com/brl/mutter.git
synced 2024-11-26 18:11:05 -05:00
cogl-pipeline: Make find codegen authority more general
The pipeline function _cogl_pipeline_find_codegen_authority has been renamed to _cogl_pipeline_find_equivalent_parent and it now takes a set of flags for the pipeline and layer state that affects the authority. This is needed so that we can reuse the same code in the vertend and progends.
This commit is contained in:
parent
a1996706a2
commit
31f0eb4f71
@ -72,30 +72,6 @@
|
||||
#define GL_TEXTURE_3D 0x806F
|
||||
#endif
|
||||
|
||||
/* When we add new pipeline or layer state groups we need to be careful to
|
||||
* update backends to understand if that new state is associated with vertex,
|
||||
* fragment or other processing. The idea here is to attribute which groups
|
||||
* affect fragment processing and more specifically which contribute to arbfp
|
||||
* code generation.
|
||||
*/
|
||||
|
||||
#define COGL_PIPELINE_FRAGEND_ARBFP_FRAGMENT_STATE_MASK \
|
||||
(COGL_PIPELINE_STATE_LAYERS | \
|
||||
COGL_PIPELINE_STATE_USER_SHADER)
|
||||
|
||||
#define COGL_PIPELINE_FRAGEND_ARBFP_FRAGMENT_PROGRAM_STATE_MASK \
|
||||
COGL_PIPELINE_FRAGEND_ARBFP_FRAGMENT_STATE_MASK
|
||||
|
||||
#define COGL_PIPELINE_FRAGEND_ARBFP_LAYER_FRAGMENT_STATE_MASK \
|
||||
COGL_PIPELINE_LAYER_STATE_ALL
|
||||
|
||||
#define COGL_PIPELINE_FRAGEND_ARBFP_LAYER_FRAGMENT_PROGRAM_STATE_MASK \
|
||||
(COGL_PIPELINE_FRAGEND_ARBFP_LAYER_FRAGMENT_STATE_MASK & \
|
||||
~(COGL_PIPELINE_LAYER_STATE_COMBINE_CONSTANT | \
|
||||
COGL_PIPELINE_LAYER_STATE_FILTERS | \
|
||||
COGL_PIPELINE_LAYER_STATE_WRAP_MODES | \
|
||||
COGL_PIPELINE_LAYER_STATE_USER_MATRIX))
|
||||
|
||||
typedef struct _UnitState
|
||||
{
|
||||
int constant_id; /* The program.local[] index */
|
||||
@ -254,7 +230,12 @@ _cogl_pipeline_fragend_arbfp_start (CoglPipeline *pipeline,
|
||||
* arbfp-authority to maximize the chance that other pipelines can
|
||||
* share it.
|
||||
*/
|
||||
authority = _cogl_pipeline_find_codegen_authority (pipeline, user_program);
|
||||
authority = _cogl_pipeline_find_equivalent_parent
|
||||
(pipeline,
|
||||
COGL_PIPELINE_STATE_AFFECTS_FRAGMENT_CODEGEN &
|
||||
~COGL_PIPELINE_STATE_LAYERS,
|
||||
COGL_PIPELINE_LAYER_STATE_AFFECTS_FRAGMENT_CODEGEN,
|
||||
COGL_PIPELINE_FIND_EQUIVALENT_COMPARE_TEXTURE_TARGET);
|
||||
authority_priv = get_arbfp_priv (authority);
|
||||
if (authority_priv &&
|
||||
authority_priv->arbfp_program_state)
|
||||
@ -346,9 +327,9 @@ unsigned int
|
||||
_cogl_pipeline_fragend_arbfp_hash (const void *data)
|
||||
{
|
||||
unsigned long fragment_state =
|
||||
COGL_PIPELINE_FRAGEND_ARBFP_FRAGMENT_PROGRAM_STATE_MASK;
|
||||
COGL_PIPELINE_STATE_AFFECTS_FRAGMENT_CODEGEN;
|
||||
unsigned long layer_fragment_state =
|
||||
COGL_PIPELINE_FRAGEND_ARBFP_LAYER_FRAGMENT_PROGRAM_STATE_MASK;
|
||||
COGL_PIPELINE_LAYER_STATE_AFFECTS_FRAGMENT_CODEGEN;
|
||||
CoglPipelineEvalFlags flags = COGL_PIPELINE_EVAL_FLAG_IGNORE_TEXTURE_DATA;
|
||||
|
||||
return _cogl_pipeline_hash ((CoglPipeline *)data,
|
||||
@ -360,9 +341,9 @@ gboolean
|
||||
_cogl_pipeline_fragend_arbfp_equal (const void *a, const void *b)
|
||||
{
|
||||
unsigned long fragment_state =
|
||||
COGL_PIPELINE_FRAGEND_ARBFP_FRAGMENT_PROGRAM_STATE_MASK;
|
||||
COGL_PIPELINE_STATE_AFFECTS_FRAGMENT_CODEGEN;
|
||||
unsigned long layer_fragment_state =
|
||||
COGL_PIPELINE_FRAGEND_ARBFP_LAYER_FRAGMENT_PROGRAM_STATE_MASK;
|
||||
COGL_PIPELINE_LAYER_STATE_AFFECTS_FRAGMENT_CODEGEN;
|
||||
CoglPipelineEvalFlags flags = COGL_PIPELINE_EVAL_FLAG_IGNORE_TEXTURE_DATA;
|
||||
|
||||
return _cogl_pipeline_equal ((CoglPipeline *)a, (CoglPipeline *)b,
|
||||
@ -1049,9 +1030,7 @@ _cogl_pipeline_fragend_arbfp_pipeline_pre_change_notify (
|
||||
CoglPipelineState change,
|
||||
const CoglColor *new_color)
|
||||
{
|
||||
if (!(change & COGL_PIPELINE_FRAGEND_ARBFP_FRAGMENT_PROGRAM_STATE_MASK))
|
||||
return;
|
||||
|
||||
if ((change & COGL_PIPELINE_STATE_AFFECTS_FRAGMENT_CODEGEN))
|
||||
dirty_arbfp_program_state (pipeline);
|
||||
}
|
||||
|
||||
@ -1073,7 +1052,7 @@ _cogl_pipeline_fragend_arbfp_layer_pre_change_notify (
|
||||
if (!priv)
|
||||
return;
|
||||
|
||||
if (change & COGL_PIPELINE_FRAGEND_ARBFP_LAYER_FRAGMENT_PROGRAM_STATE_MASK)
|
||||
if ((change & COGL_PIPELINE_LAYER_STATE_AFFECTS_FRAGMENT_CODEGEN))
|
||||
{
|
||||
dirty_arbfp_program_state (owner);
|
||||
return;
|
||||
|
@ -319,8 +319,13 @@ _cogl_pipeline_fragend_glsl_start (CoglPipeline *pipeline,
|
||||
* glsl-authority to maximize the chance that other pipelines can
|
||||
* share it.
|
||||
*/
|
||||
authority =
|
||||
_cogl_pipeline_find_codegen_authority (pipeline, user_program);
|
||||
authority = _cogl_pipeline_find_equivalent_parent
|
||||
(pipeline,
|
||||
COGL_PIPELINE_STATE_AFFECTS_FRAGMENT_CODEGEN &
|
||||
~COGL_PIPELINE_STATE_LAYERS,
|
||||
COGL_PIPELINE_LAYER_STATE_AFFECTS_FRAGMENT_CODEGEN,
|
||||
COGL_PIPELINE_FIND_EQUIVALENT_COMPARE_TEXTURE_TARGET);
|
||||
|
||||
authority_priv = get_glsl_priv (authority);
|
||||
if (!authority_priv)
|
||||
{
|
||||
|
@ -127,6 +127,18 @@ typedef enum
|
||||
COGL_PIPELINE_LAYER_STATE_USER_MATRIX |
|
||||
COGL_PIPELINE_LAYER_STATE_POINT_SPRITE_COORDS,
|
||||
|
||||
COGL_PIPELINE_LAYER_STATE_AFFECTS_FRAGMENT_CODEGEN =
|
||||
COGL_PIPELINE_LAYER_STATE_COMBINE |
|
||||
/* FIXME: Only texture target changes should really affect the
|
||||
codegen, but this is difficult to detect */
|
||||
COGL_PIPELINE_LAYER_STATE_TEXTURE |
|
||||
/* On GLES2 we need to use a different varying for the texture
|
||||
lookups when point sprite coords are enabled */
|
||||
#ifdef HAVE_COGL_GLES2
|
||||
COGL_PIPELINE_LAYER_STATE_POINT_SPRITE_COORDS |
|
||||
#endif
|
||||
COGL_PIPELINE_LAYER_STATE_UNIT
|
||||
|
||||
} CoglPipelineLayerState;
|
||||
|
||||
typedef struct
|
||||
@ -363,7 +375,16 @@ typedef enum _CoglPipelineState
|
||||
COGL_PIPELINE_STATE_USER_SHADER |
|
||||
COGL_PIPELINE_STATE_DEPTH |
|
||||
COGL_PIPELINE_STATE_FOG |
|
||||
COGL_PIPELINE_STATE_POINT_SIZE
|
||||
COGL_PIPELINE_STATE_POINT_SIZE,
|
||||
|
||||
COGL_PIPELINE_STATE_AFFECTS_FRAGMENT_CODEGEN =
|
||||
COGL_PIPELINE_STATE_LAYERS |
|
||||
#ifdef HAVE_COGL_GLES2
|
||||
/* Under GLES2 the alpha func becomes part of the fragment program
|
||||
so we can't share programs there */
|
||||
COGL_PIPELINE_STATE_ALPHA_FUNC |
|
||||
#endif
|
||||
COGL_PIPELINE_STATE_USER_SHADER
|
||||
|
||||
} CoglPipelineState;
|
||||
|
||||
@ -458,6 +479,12 @@ typedef struct
|
||||
CoglPipelineLayer *layer;
|
||||
} CoglPipelineLayerCacheEntry;
|
||||
|
||||
/* Flags used for _cogl_pipeline_find_equivalent_parent */
|
||||
typedef enum
|
||||
{
|
||||
COGL_PIPELINE_FIND_EQUIVALENT_COMPARE_TEXTURE_TARGET = 1L<<0
|
||||
} CoglPipelineFindEquivalentFlags;
|
||||
|
||||
/*
|
||||
* CoglPipelineDestroyCallback
|
||||
* @pipeline: The #CoglPipeline that has been destroyed
|
||||
@ -958,6 +985,12 @@ CoglPipeline *
|
||||
_cogl_pipeline_get_authority (CoglPipeline *pipeline,
|
||||
unsigned long difference);
|
||||
|
||||
CoglPipeline *
|
||||
_cogl_pipeline_find_equivalent_parent (CoglPipeline *pipeline,
|
||||
CoglPipelineState pipeline_state,
|
||||
CoglPipelineLayerState layer_state,
|
||||
CoglPipelineFindEquivalentFlags flags);
|
||||
|
||||
CoglHandle
|
||||
_cogl_pipeline_get_layer_texture (CoglPipeline *pipeline,
|
||||
int layer_index);
|
||||
@ -1046,10 +1079,6 @@ gboolean
|
||||
_cogl_pipeline_need_texture_combine_separate
|
||||
(CoglPipelineLayer *combine_authority);
|
||||
|
||||
CoglPipeline *
|
||||
_cogl_pipeline_find_codegen_authority (CoglPipeline *pipeline,
|
||||
CoglHandle user_program);
|
||||
|
||||
void
|
||||
_cogl_pipeline_init_state_hash_functions (void);
|
||||
|
||||
|
@ -6290,51 +6290,6 @@ add_layer_to_array_cb (CoglPipelineLayer *layer,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
layers_codegen_would_differ (CoglPipelineLayer **pipeline0_layers,
|
||||
CoglPipelineLayer **pipeline1_layers,
|
||||
int n_layers)
|
||||
{
|
||||
int i;
|
||||
/* The layer state that affects codegen... */
|
||||
unsigned long codegen_modifiers =
|
||||
COGL_PIPELINE_LAYER_STATE_COMBINE |
|
||||
COGL_PIPELINE_LAYER_STATE_UNIT;
|
||||
|
||||
for (i = 0; i < n_layers; i++)
|
||||
{
|
||||
CoglPipelineLayer *layer0 = pipeline0_layers[i];
|
||||
CoglPipelineLayer *layer1 = pipeline1_layers[i];
|
||||
unsigned long layer_differences;
|
||||
|
||||
if (layer0 == layer1)
|
||||
continue;
|
||||
|
||||
layer_differences =
|
||||
_cogl_pipeline_layer_compare_differences (layer0, layer1);
|
||||
|
||||
if (layer_differences & codegen_modifiers)
|
||||
return TRUE;
|
||||
|
||||
/* When it comes to texture differences the only thing that
|
||||
* affects the codegen is the target enum... */
|
||||
if ((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;
|
||||
}
|
||||
|
||||
/* Determines if we need to handle the RGB and A texture combining
|
||||
* separately or is the same function used for both channel masks and
|
||||
* with the same arguments...
|
||||
@ -6409,45 +6364,73 @@ _cogl_pipeline_need_texture_combine_separate
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* This tries to find the oldest ancestor whos state would generate
|
||||
* the same shader program as the current pipeline. This is a simple
|
||||
* mechanism for reducing the number of programs we have to generate.
|
||||
*/
|
||||
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
|
||||
state matches the given flags. This is mostly used to detect code
|
||||
gen authorities so that we can reduce the numer of programs
|
||||
generated */
|
||||
CoglPipeline *
|
||||
_cogl_pipeline_find_codegen_authority (CoglPipeline *pipeline,
|
||||
CoglHandle user_program)
|
||||
_cogl_pipeline_find_equivalent_parent (CoglPipeline *pipeline,
|
||||
CoglPipelineState pipeline_state,
|
||||
CoglPipelineLayerState layer_state,
|
||||
CoglPipelineFindEquivalentFlags flags)
|
||||
{
|
||||
CoglPipeline *authority0;
|
||||
CoglPipeline *authority1;
|
||||
int n_layers;
|
||||
CoglPipelineLayer **authority0_layers;
|
||||
CoglPipelineLayer **authority1_layers;
|
||||
/* Under GLES2 the alpha func becomes part of the fragment program
|
||||
so we can't share programs there */
|
||||
const int codegen_state = (COGL_PIPELINE_STATE_LAYERS
|
||||
#ifdef HAVE_COGL_GLES2
|
||||
| COGL_PIPELINE_STATE_ALPHA_FUNC
|
||||
#endif
|
||||
);
|
||||
|
||||
/* XXX: we'll need to update this when we add fog support to the
|
||||
* codegen */
|
||||
|
||||
if (user_program != COGL_INVALID_HANDLE)
|
||||
return pipeline;
|
||||
|
||||
/* Find the first pipeline that modifies state that affects the
|
||||
* codegen... */
|
||||
* state or any layer state... */
|
||||
authority0 = _cogl_pipeline_get_authority (pipeline,
|
||||
codegen_state);
|
||||
pipeline_state |
|
||||
COGL_PIPELINE_STATE_LAYERS);
|
||||
|
||||
/* Find the next ancestor after that, that also modifies state
|
||||
* affecting codegen... */
|
||||
/* Find the next ancestor after that, that also modifies the
|
||||
* state... */
|
||||
if (_cogl_pipeline_get_parent (authority0))
|
||||
{
|
||||
authority1 =
|
||||
_cogl_pipeline_get_authority (_cogl_pipeline_get_parent (authority0),
|
||||
codegen_state);
|
||||
pipeline_state |
|
||||
COGL_PIPELINE_STATE_LAYERS);
|
||||
}
|
||||
else
|
||||
return authority0;
|
||||
@ -6457,15 +6440,16 @@ _cogl_pipeline_find_codegen_authority (CoglPipeline *pipeline,
|
||||
for (;;)
|
||||
{
|
||||
AddLayersToArrayState state;
|
||||
int i;
|
||||
|
||||
if (n_layers != cogl_pipeline_get_n_layers (authority1))
|
||||
return authority0;
|
||||
|
||||
/* If the programs differ by anything that isn't part of the
|
||||
layer state then we can't continue */
|
||||
if ((codegen_state & ~COGL_PIPELINE_STATE_LAYERS) &&
|
||||
if (pipeline_state &&
|
||||
(_cogl_pipeline_compare_differences (authority0, authority1) &
|
||||
(codegen_state & ~COGL_PIPELINE_STATE_LAYERS)))
|
||||
pipeline_state))
|
||||
return authority0;
|
||||
|
||||
authority0_layers =
|
||||
@ -6484,8 +6468,10 @@ _cogl_pipeline_find_codegen_authority (CoglPipeline *pipeline,
|
||||
add_layer_to_array_cb,
|
||||
&state);
|
||||
|
||||
if (layers_codegen_would_differ (authority0_layers, authority1_layers,
|
||||
n_layers))
|
||||
for (i = 0; i < n_layers; i++)
|
||||
if (layers_differ_for_find_equivalent (layer_state, flags,
|
||||
authority0_layers[i],
|
||||
authority1_layers[i]))
|
||||
return authority0;
|
||||
|
||||
/* Find the next ancestor after that, that also modifies state
|
||||
@ -6497,7 +6483,8 @@ _cogl_pipeline_find_codegen_authority (CoglPipeline *pipeline,
|
||||
authority0 = authority1;
|
||||
authority1 =
|
||||
_cogl_pipeline_get_authority (_cogl_pipeline_get_parent (authority1),
|
||||
codegen_state);
|
||||
pipeline_state |
|
||||
COGL_PIPELINE_STATE_LAYERS);
|
||||
if (authority1 == authority0)
|
||||
break;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user