primitives: validate with _cogl_pipeline_foreach_layer
Switch _cogl_rectangles_with_multitexture_coords to using _cogl_pipeline_foreach_layer to iterate the layers of a pipeline when validating instead of iterating the pipelines internal list, which is risky since any modifications to pipelines (even to an override pipeline derived from the original), could potentially corrupt the list as it is being iterated.
This commit is contained in:
parent
1a3f946cc6
commit
56f36cf9c2
@ -599,7 +599,8 @@ gboolean
|
|||||||
_cogl_pipeline_get_real_blend_enabled (CoglPipeline *pipeline);
|
_cogl_pipeline_get_real_blend_enabled (CoglPipeline *pipeline);
|
||||||
|
|
||||||
gboolean
|
gboolean
|
||||||
_cogl_pipeline_layer_has_user_matrix (CoglPipelineLayer *layer);
|
_cogl_pipeline_layer_has_user_matrix (CoglPipeline *pipeline,
|
||||||
|
int layer_index);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Calls the pre_paint method on the layer texture if there is
|
* Calls the pre_paint method on the layer texture if there is
|
||||||
|
@ -5046,11 +5046,13 @@ _cogl_pipeline_layer_get_texture (CoglPipelineLayer *layer)
|
|||||||
}
|
}
|
||||||
|
|
||||||
gboolean
|
gboolean
|
||||||
_cogl_pipeline_layer_has_user_matrix (CoglPipelineLayer *layer)
|
_cogl_pipeline_layer_has_user_matrix (CoglPipeline *pipeline,
|
||||||
|
int layer_index)
|
||||||
{
|
{
|
||||||
|
CoglPipelineLayer *layer;
|
||||||
CoglPipelineLayer *authority;
|
CoglPipelineLayer *authority;
|
||||||
|
|
||||||
g_return_val_if_fail (_cogl_is_pipeline_layer (layer), FALSE);
|
layer = _cogl_pipeline_get_layer (pipeline, layer_index);
|
||||||
|
|
||||||
authority =
|
authority =
|
||||||
_cogl_pipeline_layer_get_authority (layer,
|
_cogl_pipeline_layer_get_authority (layer,
|
||||||
|
@ -513,7 +513,6 @@ validate_tex_coords_cb (CoglPipeline *pipeline,
|
|||||||
static gboolean
|
static gboolean
|
||||||
_cogl_multitexture_quad_single_primitive (const float *position,
|
_cogl_multitexture_quad_single_primitive (const float *position,
|
||||||
CoglPipeline *pipeline,
|
CoglPipeline *pipeline,
|
||||||
guint32 fallback_layers,
|
|
||||||
const float *user_tex_coords,
|
const float *user_tex_coords,
|
||||||
int user_tex_coords_len)
|
int user_tex_coords_len)
|
||||||
{
|
{
|
||||||
@ -555,41 +554,23 @@ _cogl_multitexture_quad_single_primitive (const float *position,
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct _CoglMutiTexturedRect
|
typedef struct _ValidateLayerState
|
||||||
{
|
{
|
||||||
const float *position; /* x0,y0,x1,y1 */
|
|
||||||
const float *tex_coords; /* (tx0,ty0,tx1,ty1)(tx0,ty0,tx1,ty1)(... */
|
|
||||||
int tex_coords_len; /* number of floats in tex_coords? */
|
|
||||||
};
|
|
||||||
|
|
||||||
static void
|
|
||||||
_cogl_rectangles_with_multitexture_coords (
|
|
||||||
struct _CoglMutiTexturedRect *rects,
|
|
||||||
int n_rects)
|
|
||||||
{
|
|
||||||
CoglPipeline *pipeline;
|
|
||||||
const GList *layers;
|
|
||||||
int n_layers;
|
|
||||||
const GList *tmp;
|
|
||||||
guint32 fallback_layers = 0;
|
|
||||||
gboolean all_use_sliced_quad_fallback = FALSE;
|
|
||||||
int i;
|
int i;
|
||||||
|
int first_layer;
|
||||||
|
CoglPipeline *override_source;
|
||||||
|
gboolean all_use_sliced_quad_fallback;
|
||||||
|
} ValidateLayerState;
|
||||||
|
|
||||||
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
|
static gboolean
|
||||||
|
_cogl_rectangles_validate_layer_cb (CoglPipeline *pipeline,
|
||||||
|
int layer_index,
|
||||||
|
void *user_data)
|
||||||
|
{
|
||||||
|
ValidateLayerState *state = user_data;
|
||||||
|
CoglHandle texture;
|
||||||
|
|
||||||
pipeline = cogl_get_source ();
|
state->i++;
|
||||||
|
|
||||||
layers = _cogl_pipeline_get_layers (pipeline);
|
|
||||||
n_layers = cogl_pipeline_get_n_layers (pipeline);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Validate all the layers of the current source pipeline...
|
|
||||||
*/
|
|
||||||
|
|
||||||
for (tmp = layers, i = 0; tmp != NULL; tmp = tmp->next, i++)
|
|
||||||
{
|
|
||||||
CoglHandle layer = tmp->data;
|
|
||||||
CoglHandle tex_handle;
|
|
||||||
|
|
||||||
/* We need to ensure the mipmaps are ready before deciding
|
/* We need to ensure the mipmaps are ready before deciding
|
||||||
* anything else about the texture because the texture storage
|
* anything else about the texture because the texture storage
|
||||||
@ -631,14 +612,17 @@ _cogl_rectangles_with_multitexture_coords (
|
|||||||
* sure the referenced texture is migrated out of the atlas and
|
* sure the referenced texture is migrated out of the atlas and
|
||||||
* mipmaps are generated.)
|
* mipmaps are generated.)
|
||||||
*/
|
*/
|
||||||
_cogl_pipeline_layer_pre_paint (layer);
|
_cogl_pipeline_pre_paint_for_layer (pipeline, layer_index);
|
||||||
|
|
||||||
tex_handle = _cogl_pipeline_layer_get_texture (layer);
|
texture = _cogl_pipeline_get_layer_texture (pipeline, layer_index);
|
||||||
|
|
||||||
/* COGL_INVALID_HANDLE textures are handled by
|
/* COGL_INVALID_HANDLE textures are handled by
|
||||||
* _cogl_pipeline_flush_gl_state */
|
* _cogl_pipeline_flush_gl_state */
|
||||||
if (tex_handle == COGL_INVALID_HANDLE)
|
if (texture == COGL_INVALID_HANDLE)
|
||||||
continue;
|
return TRUE;
|
||||||
|
|
||||||
|
if (state->i == 0)
|
||||||
|
state->first_layer = layer_index;
|
||||||
|
|
||||||
/* XXX:
|
/* XXX:
|
||||||
* For now, if the first layer is sliced then all other layers are
|
* For now, if the first layer is sliced then all other layers are
|
||||||
@ -649,15 +633,17 @@ _cogl_rectangles_with_multitexture_coords (
|
|||||||
* TODO: Add support for multi-texturing rectangles with sliced
|
* TODO: Add support for multi-texturing rectangles with sliced
|
||||||
* textures if no texture matrices are in use.
|
* textures if no texture matrices are in use.
|
||||||
*/
|
*/
|
||||||
if (cogl_texture_is_sliced (tex_handle))
|
if (cogl_texture_is_sliced (texture))
|
||||||
{
|
{
|
||||||
if (i == 0)
|
if (state->i == 0)
|
||||||
{
|
|
||||||
fallback_layers = ~1; /* fallback all except the first layer */
|
|
||||||
all_use_sliced_quad_fallback = TRUE;
|
|
||||||
if (tmp->next)
|
|
||||||
{
|
{
|
||||||
static gboolean warning_seen = FALSE;
|
static gboolean warning_seen = FALSE;
|
||||||
|
|
||||||
|
if (!state->override_source)
|
||||||
|
state->override_source = cogl_pipeline_copy (pipeline);
|
||||||
|
_cogl_pipeline_prune_to_n_layers (state->override_source, 1);
|
||||||
|
state->all_use_sliced_quad_fallback = TRUE;
|
||||||
|
|
||||||
if (!warning_seen)
|
if (!warning_seen)
|
||||||
g_warning ("Skipping layers 1..n of your pipeline since "
|
g_warning ("Skipping layers 1..n of your pipeline since "
|
||||||
"the first layer is sliced. We don't currently "
|
"the first layer is sliced. We don't currently "
|
||||||
@ -665,47 +651,89 @@ _cogl_rectangles_with_multitexture_coords (
|
|||||||
"textures but assume layer 0 is the most "
|
"textures but assume layer 0 is the most "
|
||||||
"important to keep");
|
"important to keep");
|
||||||
warning_seen = TRUE;
|
warning_seen = TRUE;
|
||||||
}
|
|
||||||
break;
|
return FALSE;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
static gboolean warning_seen = FALSE;
|
static gboolean warning_seen = FALSE;
|
||||||
|
|
||||||
|
_COGL_GET_CONTEXT (ctx, FALSE);
|
||||||
|
|
||||||
if (!warning_seen)
|
if (!warning_seen)
|
||||||
g_warning ("Skipping layer %d of your pipeline consisting of "
|
g_warning ("Skipping layer %d of your pipeline consisting of "
|
||||||
"a sliced texture (unsuported for multi texturing)",
|
"a sliced texture (unsuported for multi texturing)",
|
||||||
i);
|
state->i);
|
||||||
warning_seen = TRUE;
|
warning_seen = TRUE;
|
||||||
|
|
||||||
/* NB: marking for fallback will replace the layer with
|
/* Note: currently only 2D textures can be sliced. */
|
||||||
* a default transparent texture */
|
cogl_pipeline_set_layer_texture (pipeline, layer_index,
|
||||||
fallback_layers |= (1 << i);
|
ctx->default_gl_texture_2d_tex);
|
||||||
continue;
|
return TRUE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef COGL_ENABLE_DEBUG
|
||||||
/* If the texture can't be repeated with the GPU (e.g. because it has
|
/* If the texture can't be repeated with the GPU (e.g. because it has
|
||||||
* waste or if using GL_TEXTURE_RECTANGLE_ARB) then we don't support
|
* waste or if using GL_TEXTURE_RECTANGLE_ARB) then if a texture matrix
|
||||||
* multi texturing since we don't know if the result will end up trying
|
* is also in use we don't know if the result will end up trying
|
||||||
* to texture from the waste area. */
|
* to texture from the waste area.
|
||||||
if (_cogl_pipeline_layer_has_user_matrix (layer)
|
*
|
||||||
&& !_cogl_texture_can_hardware_repeat (tex_handle))
|
* Note: we check can_hardware_repeat() first since it's cheaper.
|
||||||
|
*
|
||||||
|
* Note: cases where the texture coordinates will require repeating
|
||||||
|
* will be caught by later validation.
|
||||||
|
*/
|
||||||
|
if (!_cogl_texture_can_hardware_repeat (texture) &&
|
||||||
|
_cogl_pipeline_layer_has_user_matrix (pipeline, layer_index))
|
||||||
{
|
{
|
||||||
static gboolean warning_seen = FALSE;
|
static gboolean warning_seen = FALSE;
|
||||||
if (!warning_seen)
|
if (!warning_seen)
|
||||||
g_warning ("Skipping layer %d of your pipeline since a custom "
|
g_warning ("layer %d of your pipeline uses a custom "
|
||||||
"texture matrix was given for a texture that can't be "
|
"texture matrix but because the texture doesn't "
|
||||||
"repeated using the GPU and the result may try to "
|
"support hardware repeating you may see artefacts "
|
||||||
"sample beyond the bounds of the texture ",
|
"due to sampling beyond the texture's bounds.",
|
||||||
i);
|
state->i);
|
||||||
warning_seen = TRUE;
|
warning_seen = TRUE;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/* NB: marking for fallback will replace the layer with
|
return TRUE;
|
||||||
* a default transparent texture */
|
}
|
||||||
fallback_layers |= (1 << i);
|
|
||||||
continue;
|
struct _CoglMutiTexturedRect
|
||||||
}
|
{
|
||||||
}
|
const float *position; /* x0,y0,x1,y1 */
|
||||||
|
const float *tex_coords; /* (tx0,ty0,tx1,ty1)(tx0,ty0,tx1,ty1)(... */
|
||||||
|
int tex_coords_len; /* number of floats in tex_coords? */
|
||||||
|
};
|
||||||
|
|
||||||
|
static void
|
||||||
|
_cogl_rectangles_with_multitexture_coords (
|
||||||
|
struct _CoglMutiTexturedRect *rects,
|
||||||
|
int n_rects)
|
||||||
|
{
|
||||||
|
CoglPipeline *pipeline;
|
||||||
|
ValidateLayerState state;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
|
||||||
|
|
||||||
|
pipeline = cogl_get_source ();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Validate all the layers of the current source pipeline...
|
||||||
|
*/
|
||||||
|
state.i = -1;
|
||||||
|
state.first_layer = 0;
|
||||||
|
state.override_source = NULL;
|
||||||
|
state.all_use_sliced_quad_fallback = FALSE;
|
||||||
|
cogl_pipeline_foreach_layer (pipeline,
|
||||||
|
_cogl_rectangles_validate_layer_cb,
|
||||||
|
&state);
|
||||||
|
|
||||||
|
if (state.override_source)
|
||||||
|
pipeline = state.override_source;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Emit geometry for each of the rectangles...
|
* Emit geometry for each of the rectangles...
|
||||||
@ -713,17 +741,16 @@ _cogl_rectangles_with_multitexture_coords (
|
|||||||
|
|
||||||
for (i = 0; i < n_rects; i++)
|
for (i = 0; i < n_rects; i++)
|
||||||
{
|
{
|
||||||
CoglHandle first_layer, tex_handle;
|
CoglHandle texture;
|
||||||
const float default_tex_coords[4] = {0.0, 0.0, 1.0, 1.0};
|
const float default_tex_coords[4] = {0.0, 0.0, 1.0, 1.0};
|
||||||
const float *tex_coords;
|
const float *tex_coords;
|
||||||
gboolean clamp_s, clamp_t;
|
gboolean clamp_s, clamp_t;
|
||||||
|
|
||||||
if (!all_use_sliced_quad_fallback)
|
if (!state.all_use_sliced_quad_fallback)
|
||||||
{
|
{
|
||||||
gboolean success =
|
gboolean success =
|
||||||
_cogl_multitexture_quad_single_primitive (rects[i].position,
|
_cogl_multitexture_quad_single_primitive (rects[i].position,
|
||||||
pipeline,
|
pipeline,
|
||||||
fallback_layers,
|
|
||||||
rects[i].tex_coords,
|
rects[i].tex_coords,
|
||||||
rects[i].tex_coords_len);
|
rects[i].tex_coords_len);
|
||||||
|
|
||||||
@ -738,23 +765,23 @@ _cogl_rectangles_with_multitexture_coords (
|
|||||||
/* If multitexturing failed or we are drawing with a sliced texture
|
/* If multitexturing failed or we are drawing with a sliced texture
|
||||||
* then we only support a single layer so we pluck out the texture
|
* then we only support a single layer so we pluck out the texture
|
||||||
* from the first pipeline layer... */
|
* from the first pipeline layer... */
|
||||||
layers = _cogl_pipeline_get_layers (pipeline);
|
texture = _cogl_pipeline_get_layer_texture (pipeline, state.first_layer);
|
||||||
first_layer = layers->data;
|
|
||||||
tex_handle = _cogl_pipeline_layer_get_texture (first_layer);
|
|
||||||
|
|
||||||
if (rects[i].tex_coords)
|
if (rects[i].tex_coords)
|
||||||
tex_coords = rects[i].tex_coords;
|
tex_coords = rects[i].tex_coords;
|
||||||
else
|
else
|
||||||
tex_coords = default_tex_coords;
|
tex_coords = default_tex_coords;
|
||||||
|
|
||||||
clamp_s = (_cogl_pipeline_layer_get_wrap_mode_s (first_layer) ==
|
clamp_s = (cogl_pipeline_get_layer_wrap_mode_s (pipeline,
|
||||||
|
state.first_layer) ==
|
||||||
COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE);
|
COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE);
|
||||||
clamp_t = (_cogl_pipeline_layer_get_wrap_mode_t (first_layer) ==
|
clamp_t = (cogl_pipeline_get_layer_wrap_mode_t (pipeline,
|
||||||
|
state.first_layer) ==
|
||||||
COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE);
|
COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE);
|
||||||
|
|
||||||
COGL_NOTE (DRAW, "Drawing Tex Quad (Multi-Prim Mode)");
|
COGL_NOTE (DRAW, "Drawing Tex Quad (Multi-Prim Mode)");
|
||||||
|
|
||||||
_cogl_texture_quad_multiple_primitives (tex_handle,
|
_cogl_texture_quad_multiple_primitives (texture,
|
||||||
pipeline,
|
pipeline,
|
||||||
clamp_s, clamp_t,
|
clamp_s, clamp_t,
|
||||||
rects[i].position,
|
rects[i].position,
|
||||||
@ -764,11 +791,8 @@ _cogl_rectangles_with_multitexture_coords (
|
|||||||
tex_coords[3]);
|
tex_coords[3]);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
if (state.override_source)
|
||||||
/* XXX: The current journal doesn't handle changes to the model view matrix
|
cogl_object_unref (pipeline);
|
||||||
* so for now we force a flush at the end of every primitive. */
|
|
||||||
_cogl_journal_flush ();
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -971,8 +995,8 @@ typedef struct _ValidateState
|
|||||||
CoglPipeline *pipeline;
|
CoglPipeline *pipeline;
|
||||||
} ValidateState;
|
} ValidateState;
|
||||||
|
|
||||||
gboolean
|
static gboolean
|
||||||
validate_layer_cb (CoglPipeline *pipeline,
|
_cogl_polygon_validate_layer_cb (CoglPipeline *pipeline,
|
||||||
int layer_index,
|
int layer_index,
|
||||||
void *user_data)
|
void *user_data)
|
||||||
{
|
{
|
||||||
@ -1029,7 +1053,7 @@ cogl_polygon (const CoglTextureVertex *vertices,
|
|||||||
validate_state.original_pipeline = pipeline;
|
validate_state.original_pipeline = pipeline;
|
||||||
validate_state.pipeline = pipeline;
|
validate_state.pipeline = pipeline;
|
||||||
cogl_pipeline_foreach_layer (pipeline,
|
cogl_pipeline_foreach_layer (pipeline,
|
||||||
validate_layer_cb,
|
_cogl_polygon_validate_layer_cb,
|
||||||
&validate_state);
|
&validate_state);
|
||||||
pipeline = validate_state.pipeline;
|
pipeline = validate_state.pipeline;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user