cogl-material: Use CLAMP_TO_EDGE for WRAP_AUTOMATIC unless overriden

CoglMaterial now sets GL_CLAMP_TO_EDGE if WRAP_MODE_AUTOMATIC is used
unless it is overridden when the material is flushed. The primitives
are still expected to expose repeat semantics so no user visible
changes are made. The idea is that drawing non-repeated textures is
the most common case so if we make clamp_to_ege the default then we
will reduce the number of times we have to override the
material. Avoiding overrides will become important if the overriding
mechanism is replaced with one where the primitive is expected to copy
the material and change that instead.
This commit is contained in:
Neil Roberts 2010-04-01 18:35:32 +01:00
parent e007bc5358
commit 3769862323
3 changed files with 115 additions and 30 deletions

View File

@ -1372,7 +1372,7 @@ _cogl_material_set_wrap_modes_for_layer (CoglMaterialLayer *layer,
GL_CLAMP_TO_EDGE :
GL_CLAMP_TO_BORDER);
else if (layer->wrap_mode_s == COGL_MATERIAL_WRAP_MODE_AUTOMATIC)
wrap_mode_s = GL_REPEAT;
wrap_mode_s = GL_CLAMP_TO_EDGE;
else
wrap_mode_s = layer->wrap_mode_s;
@ -1385,7 +1385,7 @@ _cogl_material_set_wrap_modes_for_layer (CoglMaterialLayer *layer,
GL_CLAMP_TO_EDGE :
GL_CLAMP_TO_BORDER);
else if (layer->wrap_mode_t == COGL_MATERIAL_WRAP_MODE_AUTOMATIC)
wrap_mode_t = GL_REPEAT;
wrap_mode_t = GL_CLAMP_TO_EDGE;
else
wrap_mode_t = layer->wrap_mode_t;
@ -1398,7 +1398,7 @@ _cogl_material_set_wrap_modes_for_layer (CoglMaterialLayer *layer,
GL_CLAMP_TO_EDGE :
GL_CLAMP_TO_BORDER);
else if (layer->wrap_mode_r == COGL_MATERIAL_WRAP_MODE_AUTOMATIC)
wrap_mode_r = GL_REPEAT;
wrap_mode_r = GL_CLAMP_TO_EDGE;
else
wrap_mode_r = layer->wrap_mode_r;

View File

@ -57,7 +57,7 @@ typedef struct _TextureSlicedQuadState
float quad_len_y;
gboolean flipped_x;
gboolean flipped_y;
CoglMaterialWrapModeOverrides wrap_mode_overrides;
CoglMaterialWrapModeOverrides *wrap_mode_overrides;
} TextureSlicedQuadState;
typedef struct _TextureSlicedPolygonState
@ -117,7 +117,7 @@ log_quad_sub_textures_cb (CoglHandle texture_handle,
1, /* one layer */
0, /* don't need to use fallbacks */
gl_handle, /* replace the layer0 texture */
&state->wrap_mode_overrides, /* use CLAMP_TO_EDGE */
state->wrap_mode_overrides, /* use GL_CLAMP_TO_EDGE */
subtexture_coords,
4);
}
@ -148,10 +148,12 @@ _cogl_texture_quad_multiple_primitives (CoglHandle tex_handle,
float ty_2)
{
TextureSlicedQuadState state;
CoglMaterialWrapModeOverrides wrap_mode_overrides;
gboolean tex_virtual_flipped_x;
gboolean tex_virtual_flipped_y;
gboolean quad_flipped_x;
gboolean quad_flipped_y;
CoglHandle first_layer;
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
@ -253,14 +255,28 @@ _cogl_texture_quad_multiple_primitives (CoglHandle tex_handle,
position = replacement_position;
}
state.wrap_mode_overrides = NULL;
memset (&state.wrap_mode_overrides, 0, sizeof (state.wrap_mode_overrides));
/* We can't use hardware repeat so we need to set clamp to edge
otherwise it might pull in edge pixels from the other side */
state.wrap_mode_overrides.values[0].s =
otherwise it might pull in edge pixels from the other side. By
default WRAP_MODE_AUTOMATIC becomes CLAMP_TO_EDGE so we only need
to override if the wrap mode is repeat */
first_layer = cogl_material_get_layers (material)->data;
if (cogl_material_layer_get_wrap_mode_s (first_layer) ==
COGL_MATERIAL_WRAP_MODE_REPEAT)
{
state.wrap_mode_overrides = &wrap_mode_overrides;
wrap_mode_overrides.values[0].s =
COGL_MATERIAL_WRAP_MODE_OVERRIDE_CLAMP_TO_EDGE;
state.wrap_mode_overrides.values[0].t =
}
if (cogl_material_layer_get_wrap_mode_t (first_layer) ==
COGL_MATERIAL_WRAP_MODE_REPEAT)
{
state.wrap_mode_overrides = &wrap_mode_overrides;
wrap_mode_overrides.values[0].t =
COGL_MATERIAL_WRAP_MODE_OVERRIDE_CLAMP_TO_EDGE;
}
state.material = material;
@ -340,6 +356,9 @@ _cogl_multitexture_quad_single_primitive (const float *position,
GList *tmp;
int i;
CoglMaterialWrapModeOverrides wrap_mode_overrides;
/* This will be set to point to wrap_mode_overrides when an override
is needed */
CoglMaterialWrapModeOverrides *wrap_mode_overrides_p = NULL;
_COGL_GET_CONTEXT (ctx, FALSE);
@ -357,7 +376,6 @@ _cogl_multitexture_quad_single_primitive (const float *position,
float *out_tex_coords;
float default_tex_coords[4] = {0.0, 0.0, 1.0, 1.0};
CoglTransformResult transform_result;
unsigned long auto_wrap_mode;
tex_handle = cogl_material_layer_get_texture (layer);
@ -427,20 +445,28 @@ _cogl_multitexture_quad_single_primitive (const float *position,
}
}
/* If we're not repeating then we want to clamp the coords
to the edge otherwise it can pull in edge pixels from the
wrong side when scaled */
/* 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)
auto_wrap_mode = COGL_MATERIAL_WRAP_MODE_OVERRIDE_REPEAT;
else
auto_wrap_mode = COGL_MATERIAL_WRAP_MODE_OVERRIDE_CLAMP_TO_EDGE;
{
if (cogl_material_layer_get_wrap_mode_s (layer) ==
COGL_MATERIAL_WRAP_MODE_AUTOMATIC)
wrap_mode_overrides.values[i].s = auto_wrap_mode;
{
wrap_mode_overrides.values[i].s
= COGL_MATERIAL_WRAP_MODE_OVERRIDE_REPEAT;
wrap_mode_overrides_p = &wrap_mode_overrides;
}
if (cogl_material_layer_get_wrap_mode_t (layer) ==
COGL_MATERIAL_WRAP_MODE_AUTOMATIC)
wrap_mode_overrides.values[i].t = auto_wrap_mode;
{
wrap_mode_overrides.values[i].t
= COGL_MATERIAL_WRAP_MODE_OVERRIDE_REPEAT;
wrap_mode_overrides_p = &wrap_mode_overrides;
}
}
}
_cogl_journal_log_quad (position,
@ -448,7 +474,7 @@ _cogl_multitexture_quad_single_primitive (const float *position,
n_layers,
fallback_layers,
0, /* don't replace the layer0 texture */
&wrap_mode_overrides,
wrap_mode_overrides_p,
final_tex_coords,
n_layers * 4);
@ -891,7 +917,9 @@ _cogl_multitexture_polygon_single_primitive (const CoglTextureVertex *vertices,
unsigned int n_layers,
unsigned int stride,
gboolean use_color,
guint32 fallback_layers)
guint32 fallback_layers,
CoglMaterialWrapModeOverrides *
wrap_mode_overrides)
{
CoglHandle material;
const GList *layers;
@ -959,6 +987,11 @@ _cogl_multitexture_polygon_single_primitive (const CoglTextureVertex *vertices,
if (use_color)
options.flags |= COGL_MATERIAL_FLUSH_SKIP_GL_COLOR;
options.fallback_layers = fallback_layers;
if (wrap_mode_overrides)
{
options.flags |= COGL_MATERIAL_FLUSH_WRAP_MODE_OVERRIDES;
options.wrap_mode_overrides = *wrap_mode_overrides;
}
_cogl_material_flush_gl_state (ctx->source_material, &options);
GE (glDrawArrays (GL_TRIANGLE_FAN, 0, n_vertices));
@ -980,6 +1013,8 @@ cogl_polygon (const CoglTextureVertex *vertices,
gsize stride_bytes;
GLfloat *v;
int prev_n_texcoord_arrays_enabled;
CoglMaterialWrapModeOverrides wrap_mode_overrides;
CoglMaterialWrapModeOverrides *wrap_mode_overrides_p = NULL;
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
@ -994,6 +1029,8 @@ cogl_polygon (const CoglTextureVertex *vertices,
layers = cogl_material_get_layers (ctx->source_material);
n_layers = g_list_length ((GList *)layers);
memset (&wrap_mode_overrides, 0, sizeof (wrap_mode_overrides));
for (tmp = layers, i = 0; tmp != NULL; tmp = tmp->next, i++)
{
CoglHandle layer = tmp->data;
@ -1066,6 +1103,24 @@ cogl_polygon (const CoglTextureVertex *vertices,
fallback_layers |= (1 << i);
continue;
}
/* By default COGL_MATERIAL_WRAP_MODE_AUTOMATIC becomes
GL_CLAMP_TO_EDGE but we want the polygon API to use GL_REPEAT
to maintain compatibility with previous releases */
if (cogl_material_layer_get_wrap_mode_s (layer) ==
COGL_MATERIAL_WRAP_MODE_AUTOMATIC)
{
wrap_mode_overrides.values[i].s =
COGL_MATERIAL_WRAP_MODE_OVERRIDE_REPEAT;
wrap_mode_overrides_p = &wrap_mode_overrides;
}
if (cogl_material_layer_get_wrap_mode_t (layer) ==
COGL_MATERIAL_WRAP_MODE_AUTOMATIC)
{
wrap_mode_overrides.values[i].t =
COGL_MATERIAL_WRAP_MODE_OVERRIDE_REPEAT;
wrap_mode_overrides_p = &wrap_mode_overrides;
}
}
/* Our data is arranged like:
@ -1130,7 +1185,8 @@ cogl_polygon (const CoglTextureVertex *vertices,
n_layers,
stride,
use_color,
fallback_layers);
fallback_layers,
wrap_mode_overrides_p);
/* Reset the size of the logged vertex array because rendering
rectangles expects it to start at 0 */

View File

@ -1530,6 +1530,12 @@ enable_state_for_drawing_buffer (CoglVertexBuffer *buffer)
if (buffer->new_attributes)
cogl_vertex_buffer_submit_real (buffer);
options.flags =
COGL_MATERIAL_FLUSH_FALLBACK_MASK |
COGL_MATERIAL_FLUSH_DISABLE_MASK;
memset (&options.wrap_mode_overrides, 0,
sizeof (options.wrap_mode_overrides));
for (tmp = buffer->submitted_vbos; tmp != NULL; tmp = tmp->next)
{
CoglVertexBufferVBO *cogl_vbo = tmp->data;
@ -1668,6 +1674,32 @@ enable_state_for_drawing_buffer (CoglVertexBuffer *buffer)
*/
fallback_layers |= (1 << i);
}
/* By default COGL_MATERIAL_WRAP_MODE_AUTOMATIC becomes
GL_CLAMP_TO_EDGE but we want GL_REPEAT to maintain
compatibility with older versions of Cogl so we'll override
it */
if (cogl_material_layer_get_wrap_mode_s (layer) ==
COGL_MATERIAL_WRAP_MODE_AUTOMATIC)
{
options.wrap_mode_overrides.values[i].s =
COGL_MATERIAL_WRAP_MODE_OVERRIDE_REPEAT;
options.flags |= COGL_MATERIAL_FLUSH_WRAP_MODE_OVERRIDES;
}
if (cogl_material_layer_get_wrap_mode_t (layer) ==
COGL_MATERIAL_WRAP_MODE_AUTOMATIC)
{
options.wrap_mode_overrides.values[i].t =
COGL_MATERIAL_WRAP_MODE_OVERRIDE_REPEAT;
options.flags |= COGL_MATERIAL_FLUSH_WRAP_MODE_OVERRIDES;
}
if (_cogl_material_layer_get_wrap_mode_r (layer) ==
COGL_MATERIAL_WRAP_MODE_AUTOMATIC)
{
options.wrap_mode_overrides.values[i].r =
COGL_MATERIAL_WRAP_MODE_OVERRIDE_REPEAT;
options.flags |= COGL_MATERIAL_FLUSH_WRAP_MODE_OVERRIDES;
}
}
for (i = max_texcoord_attrib_unit + 1; i < ctx->n_texcoord_arrays_enabled; i++)
@ -1682,9 +1714,6 @@ enable_state_for_drawing_buffer (CoglVertexBuffer *buffer)
* always be done first when preparing to draw. */
_cogl_framebuffer_flush_state (_cogl_get_framebuffer (), 0);
options.flags =
COGL_MATERIAL_FLUSH_FALLBACK_MASK |
COGL_MATERIAL_FLUSH_DISABLE_MASK;
options.fallback_layers = fallback_layers;
options.disable_layers = disable_layers;