_multitexture_quad_single_primitive: avoid wrap overrides
This avoids using the wrap mode overrides mechanism to implement _cogl_multitexture_quad_single_primitive which requires memsetting a fairly large array. This updates it to use cogl_pipeline_foreach_layer() and we now derive an override_material to handle changes to the wrap modes instead of using the CoglPipelineWrapModeOverrides.
This commit is contained in:
parent
e73b67e59b
commit
7bbe207b65
@ -331,6 +331,138 @@ _cogl_texture_quad_multiple_primitives (CoglHandle tex_handle,
|
|||||||
&state);
|
&state);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef struct _ValidateTexCoordsState
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
int n_layers;
|
||||||
|
const float *user_tex_coords;
|
||||||
|
int user_tex_coords_len;
|
||||||
|
float *final_tex_coords;
|
||||||
|
CoglPipeline *override_pipeline;
|
||||||
|
gboolean needs_multiple_primitives;
|
||||||
|
} ValidateTexCoordsState;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Validate the texture coordinates for this rectangle.
|
||||||
|
*/
|
||||||
|
static gboolean
|
||||||
|
validate_tex_coords_cb (CoglPipeline *pipeline,
|
||||||
|
int layer_index,
|
||||||
|
void *user_data)
|
||||||
|
{
|
||||||
|
ValidateTexCoordsState *state = user_data;
|
||||||
|
CoglHandle texture;
|
||||||
|
const float *in_tex_coords;
|
||||||
|
float *out_tex_coords;
|
||||||
|
float default_tex_coords[4] = {0.0, 0.0, 1.0, 1.0};
|
||||||
|
CoglTransformResult transform_result;
|
||||||
|
|
||||||
|
state->i++;
|
||||||
|
|
||||||
|
texture = _cogl_pipeline_get_layer_texture (pipeline, layer_index);
|
||||||
|
|
||||||
|
/* NB: NULL textures are handled by _cogl_pipeline_flush_gl_state */
|
||||||
|
if (!texture)
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
/* FIXME: we should be able to avoid this copying when no
|
||||||
|
* transform is required by the texture backend and the user
|
||||||
|
* has supplied enough coordinates for all the layers.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* If the user didn't supply texture coordinates for this layer
|
||||||
|
then use the default coords */
|
||||||
|
if (state->i >= state->user_tex_coords_len / 4)
|
||||||
|
in_tex_coords = default_tex_coords;
|
||||||
|
else
|
||||||
|
in_tex_coords = &state->user_tex_coords[state->i * 4];
|
||||||
|
|
||||||
|
out_tex_coords = &state->final_tex_coords[state->i * 4];
|
||||||
|
|
||||||
|
memcpy (out_tex_coords, in_tex_coords, sizeof (float) * 4);
|
||||||
|
|
||||||
|
/* Convert the texture coordinates to GL.
|
||||||
|
*/
|
||||||
|
transform_result =
|
||||||
|
_cogl_texture_transform_quad_coords_to_gl (texture,
|
||||||
|
out_tex_coords);
|
||||||
|
/* If the texture has waste or we are using GL_TEXTURE_RECT we
|
||||||
|
* can't handle texture repeating so we can't use the layer if
|
||||||
|
* repeating is required.
|
||||||
|
*
|
||||||
|
* NB: We already know that no texture matrix is being used if the
|
||||||
|
* texture doesn't support hardware repeat.
|
||||||
|
*/
|
||||||
|
if (transform_result == COGL_TRANSFORM_SOFTWARE_REPEAT)
|
||||||
|
{
|
||||||
|
if (state->i == 0)
|
||||||
|
{
|
||||||
|
if (state->n_layers > 1)
|
||||||
|
{
|
||||||
|
static gboolean warning_seen = FALSE;
|
||||||
|
if (!warning_seen)
|
||||||
|
g_warning ("Skipping layers 1..n of your material since "
|
||||||
|
"the first layer doesn't support hardware "
|
||||||
|
"repeat (e.g. because of waste or use of "
|
||||||
|
"GL_TEXTURE_RECTANGLE_ARB) and you supplied "
|
||||||
|
"texture coordinates outside the range [0,1]."
|
||||||
|
"Falling back to software repeat assuming "
|
||||||
|
"layer 0 is the most important one keep");
|
||||||
|
warning_seen = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (state->override_pipeline)
|
||||||
|
cogl_object_unref (state->override_pipeline);
|
||||||
|
state->needs_multiple_primitives = TRUE;
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
static gboolean warning_seen = FALSE;
|
||||||
|
if (!warning_seen)
|
||||||
|
g_warning ("Skipping layer %d of your material "
|
||||||
|
"since you have supplied texture coords "
|
||||||
|
"outside the range [0,1] but the texture "
|
||||||
|
"doesn't support hardware repeat (e.g. "
|
||||||
|
"because of waste or use of "
|
||||||
|
"GL_TEXTURE_RECTANGLE_ARB). This isn't "
|
||||||
|
"supported with multi-texturing.", state->i);
|
||||||
|
warning_seen = TRUE;
|
||||||
|
|
||||||
|
cogl_pipeline_set_layer_texture (texture, layer_index, NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* By default WRAP_MODE_AUTOMATIC becomes to CLAMP_TO_EDGE. If
|
||||||
|
the texture coordinates need repeating then we'll override
|
||||||
|
this to GL_REPEAT. Otherwise we'll leave it at CLAMP_TO_EDGE
|
||||||
|
so that it won't blend in pixels from the opposite side when
|
||||||
|
the full texture is drawn with GL_LINEAR filter mode */
|
||||||
|
if (transform_result == COGL_TRANSFORM_HARDWARE_REPEAT)
|
||||||
|
{
|
||||||
|
if (cogl_pipeline_get_layer_wrap_mode_s (pipeline, layer_index) ==
|
||||||
|
COGL_PIPELINE_WRAP_MODE_AUTOMATIC)
|
||||||
|
{
|
||||||
|
if (!state->override_pipeline)
|
||||||
|
state->override_pipeline = cogl_pipeline_copy (pipeline);
|
||||||
|
cogl_pipeline_set_layer_wrap_mode_s (state->override_pipeline,
|
||||||
|
layer_index,
|
||||||
|
COGL_PIPELINE_WRAP_MODE_REPEAT);
|
||||||
|
}
|
||||||
|
if (cogl_pipeline_get_layer_wrap_mode_t (pipeline, layer_index) ==
|
||||||
|
COGL_PIPELINE_WRAP_MODE_AUTOMATIC)
|
||||||
|
{
|
||||||
|
if (!state->override_pipeline)
|
||||||
|
state->override_pipeline = cogl_pipeline_copy (pipeline);
|
||||||
|
cogl_pipeline_set_layer_wrap_mode_t (state->override_pipeline,
|
||||||
|
layer_index,
|
||||||
|
COGL_PIPELINE_WRAP_MODE_REPEAT);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
/* This path supports multitexturing but only when each of the layers is
|
/* This path supports multitexturing but only when each of the layers is
|
||||||
* handled with a single GL texture. Also if repeating is necessary then
|
* handled with a single GL texture. Also if repeating is necessary then
|
||||||
* _cogl_texture_can_hardware_repeat() must return TRUE.
|
* _cogl_texture_can_hardware_repeat() must return TRUE.
|
||||||
@ -355,130 +487,35 @@ _cogl_multitexture_quad_single_primitive (const float *position,
|
|||||||
int user_tex_coords_len)
|
int user_tex_coords_len)
|
||||||
{
|
{
|
||||||
int n_layers = cogl_pipeline_get_n_layers (pipeline);
|
int n_layers = cogl_pipeline_get_n_layers (pipeline);
|
||||||
|
ValidateTexCoordsState state;
|
||||||
float *final_tex_coords = alloca (sizeof (float) * 4 * n_layers);
|
float *final_tex_coords = alloca (sizeof (float) * 4 * n_layers);
|
||||||
const GList *layers;
|
|
||||||
GList *tmp;
|
|
||||||
int i;
|
|
||||||
CoglPipelineWrapModeOverrides wrap_mode_overrides;
|
|
||||||
/* This will be set to point to wrap_mode_overrides when an override
|
|
||||||
is needed */
|
|
||||||
CoglPipelineWrapModeOverrides *wrap_mode_overrides_p = NULL;
|
|
||||||
|
|
||||||
_COGL_GET_CONTEXT (ctx, FALSE);
|
_COGL_GET_CONTEXT (ctx, FALSE);
|
||||||
|
|
||||||
memset (&wrap_mode_overrides, 0, sizeof (wrap_mode_overrides));
|
state.i = -1;
|
||||||
|
state.n_layers = n_layers;
|
||||||
|
state.user_tex_coords = user_tex_coords;
|
||||||
|
state.user_tex_coords_len = user_tex_coords_len;
|
||||||
|
state.final_tex_coords = final_tex_coords;
|
||||||
|
state.override_pipeline = NULL;
|
||||||
|
state.needs_multiple_primitives = FALSE;
|
||||||
|
|
||||||
/*
|
cogl_pipeline_foreach_layer (pipeline,
|
||||||
* Validate the texture coordinates for this rectangle.
|
validate_tex_coords_cb,
|
||||||
*/
|
&state);
|
||||||
layers = _cogl_pipeline_get_layers (pipeline);
|
|
||||||
for (tmp = (GList *)layers, i = 0; tmp != NULL; tmp = tmp->next, i++)
|
|
||||||
{
|
|
||||||
CoglHandle layer = (CoglHandle)tmp->data;
|
|
||||||
CoglHandle tex_handle;
|
|
||||||
const float *in_tex_coords;
|
|
||||||
float *out_tex_coords;
|
|
||||||
float default_tex_coords[4] = {0.0, 0.0, 1.0, 1.0};
|
|
||||||
CoglTransformResult transform_result;
|
|
||||||
|
|
||||||
tex_handle = _cogl_pipeline_layer_get_texture (layer);
|
if (state.needs_multiple_primitives)
|
||||||
|
|
||||||
/* COGL_INVALID_HANDLE textures are handled by
|
|
||||||
* _cogl_pipeline_flush_gl_state */
|
|
||||||
if (tex_handle == COGL_INVALID_HANDLE)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
/* If the user didn't supply texture coordinates for this layer
|
|
||||||
then use the default coords */
|
|
||||||
if (i >= user_tex_coords_len / 4)
|
|
||||||
in_tex_coords = default_tex_coords;
|
|
||||||
else
|
|
||||||
in_tex_coords = &user_tex_coords[i * 4];
|
|
||||||
|
|
||||||
out_tex_coords = &final_tex_coords[i * 4];
|
|
||||||
|
|
||||||
memcpy (out_tex_coords, in_tex_coords, sizeof (GLfloat) * 4);
|
|
||||||
|
|
||||||
/* Convert the texture coordinates to GL.
|
|
||||||
*/
|
|
||||||
transform_result =
|
|
||||||
_cogl_texture_transform_quad_coords_to_gl (tex_handle,
|
|
||||||
out_tex_coords);
|
|
||||||
/* If the texture has waste or we are using GL_TEXTURE_RECT we
|
|
||||||
* can't handle texture repeating so we can't use the layer if
|
|
||||||
* repeating is required.
|
|
||||||
*
|
|
||||||
* NB: We already know that no texture matrix is being used if the
|
|
||||||
* texture doesn't support hardware repeat.
|
|
||||||
*/
|
|
||||||
if (transform_result == COGL_TRANSFORM_SOFTWARE_REPEAT)
|
|
||||||
{
|
|
||||||
if (i == 0)
|
|
||||||
{
|
|
||||||
if (n_layers > 1)
|
|
||||||
{
|
|
||||||
static gboolean warning_seen = FALSE;
|
|
||||||
if (!warning_seen)
|
|
||||||
g_warning ("Skipping layers 1..n of your material since "
|
|
||||||
"the first layer doesn't support hardware "
|
|
||||||
"repeat (e.g. because of waste or use of "
|
|
||||||
"GL_TEXTURE_RECTANGLE_ARB) and you supplied "
|
|
||||||
"texture coordinates outside the range [0,1]."
|
|
||||||
"Falling back to software repeat assuming "
|
|
||||||
"layer 0 is the most important one keep");
|
|
||||||
warning_seen = TRUE;
|
|
||||||
}
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
static gboolean warning_seen = FALSE;
|
|
||||||
if (!warning_seen)
|
|
||||||
g_warning ("Skipping layer %d of your material "
|
|
||||||
"since you have supplied texture coords "
|
|
||||||
"outside the range [0,1] but the texture "
|
|
||||||
"doesn't support hardware repeat (e.g. "
|
|
||||||
"because of waste or use of "
|
|
||||||
"GL_TEXTURE_RECTANGLE_ARB). This isn't "
|
|
||||||
"supported with multi-texturing.", i);
|
|
||||||
warning_seen = TRUE;
|
|
||||||
|
|
||||||
/* NB: marking for fallback will replace the layer with
|
if (state.override_pipeline)
|
||||||
* a default transparent texture */
|
pipeline = state.override_pipeline;
|
||||||
fallback_layers |= (1 << i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* By default WRAP_MODE_AUTOMATIC becomes to CLAMP_TO_EDGE. If
|
|
||||||
the texture coordinates need repeating then we'll override
|
|
||||||
this to GL_REPEAT. Otherwise we'll leave it at CLAMP_TO_EDGE
|
|
||||||
so that it won't blend in pixels from the opposite side when
|
|
||||||
the full texture is drawn with GL_LINEAR filter mode */
|
|
||||||
if (transform_result == COGL_TRANSFORM_HARDWARE_REPEAT)
|
|
||||||
{
|
|
||||||
if (_cogl_pipeline_layer_get_wrap_mode_s (layer) ==
|
|
||||||
COGL_PIPELINE_WRAP_MODE_AUTOMATIC)
|
|
||||||
{
|
|
||||||
wrap_mode_overrides.values[i].s
|
|
||||||
= COGL_PIPELINE_WRAP_MODE_OVERRIDE_REPEAT;
|
|
||||||
wrap_mode_overrides_p = &wrap_mode_overrides;
|
|
||||||
}
|
|
||||||
if (_cogl_pipeline_layer_get_wrap_mode_t (layer) ==
|
|
||||||
COGL_PIPELINE_WRAP_MODE_AUTOMATIC)
|
|
||||||
{
|
|
||||||
wrap_mode_overrides.values[i].t
|
|
||||||
= COGL_PIPELINE_WRAP_MODE_OVERRIDE_REPEAT;
|
|
||||||
wrap_mode_overrides_p = &wrap_mode_overrides;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_cogl_journal_log_quad (position,
|
_cogl_journal_log_quad (position,
|
||||||
pipeline,
|
pipeline,
|
||||||
n_layers,
|
n_layers,
|
||||||
fallback_layers,
|
0, /* we don't need fallback layers */
|
||||||
0, /* don't replace the layer0 texture */
|
0, /* don't replace the layer0 texture */
|
||||||
wrap_mode_overrides_p,
|
NULL, /* we never use wrap mode overrides */
|
||||||
final_tex_coords,
|
final_tex_coords,
|
||||||
n_layers * 4);
|
n_layers * 4);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user