mirror of
https://github.com/brl/mutter.git
synced 2024-12-27 05:12:15 +00:00
Bug 1305 - NPOT textures unaligned to a pixel sometimes have
border artifacts * clutter/cogl/gl/cogl-texture.c: Set the wrap mode of a texture on demand Instead of setting the wrap mode once per texture at creation, it is now changed whenever the texture is drawn. The previous value is cached so that it isn't changed if the value is the same. This is used in _cogl_texture_quad_hw to only enable GL_REPEAT mode when the coordinates are not in the range [0,1]. Otherwise it can pull in pixels from the other edge when the texture is rendered off-pixel.
This commit is contained in:
parent
f4465ccb05
commit
be655b05ad
@ -763,6 +763,29 @@ _cogl_texture_size_supported (GLenum gl_target,
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
_cogl_texture_set_wrap_mode_parameter (CoglTexture *tex,
|
||||
GLenum wrap_mode)
|
||||
{
|
||||
/* Only set the wrap mode if it's different from the current
|
||||
value to avoid too many GL calls */
|
||||
if (tex->wrap_mode != wrap_mode)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < tex->slice_gl_handles->len; i++)
|
||||
{
|
||||
GLuint texnum = g_array_index (tex->slice_gl_handles, GLuint, i);
|
||||
|
||||
GE( glBindTexture (tex->gl_target, texnum) );
|
||||
GE( glTexParameteri (tex->gl_target, GL_TEXTURE_WRAP_S, wrap_mode) );
|
||||
GE( glTexParameteri (tex->gl_target, GL_TEXTURE_WRAP_T, wrap_mode) );
|
||||
}
|
||||
|
||||
tex->wrap_mode = wrap_mode;
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
_cogl_texture_slices_create (CoglTexture *tex)
|
||||
{
|
||||
@ -890,15 +913,10 @@ _cogl_texture_slices_create (CoglTexture *tex)
|
||||
n_slices);
|
||||
|
||||
g_array_set_size (tex->slice_gl_handles, n_slices);
|
||||
|
||||
|
||||
/* Hardware repeated tiling if supported, else tile in software*/
|
||||
if (cogl_features_available (COGL_FEATURE_TEXTURE_NPOT)
|
||||
&& n_slices == 1)
|
||||
tex->wrap_mode = GL_REPEAT;
|
||||
else
|
||||
tex->wrap_mode = GL_CLAMP_TO_EDGE;
|
||||
|
||||
|
||||
/* Wrap mode not yet set */
|
||||
tex->wrap_mode = GL_FALSE;
|
||||
|
||||
/* Generate a "working set" of GL texture objects
|
||||
* (some implementations might supported faster
|
||||
* re-binding between textures inside a set) */
|
||||
@ -930,11 +948,6 @@ _cogl_texture_slices_create (CoglTexture *tex)
|
||||
GE( glTexParameteri (tex->gl_target, GL_TEXTURE_MIN_FILTER,
|
||||
tex->min_filter) );
|
||||
|
||||
GE( glTexParameteri (tex->gl_target, GL_TEXTURE_WRAP_S,
|
||||
tex->wrap_mode) );
|
||||
GE( glTexParameteri (tex->gl_target, GL_TEXTURE_WRAP_T,
|
||||
tex->wrap_mode) );
|
||||
|
||||
if (tex->auto_mipmap)
|
||||
GE( glTexParameteri (tex->gl_target, GL_GENERATE_MIPMAP,
|
||||
GL_TRUE) );
|
||||
@ -1507,7 +1520,10 @@ cogl_texture_new_from_foreign (GLuint gl_handle,
|
||||
tex->min_filter = gl_min_filter;
|
||||
tex->mag_filter = gl_mag_filter;
|
||||
tex->max_waste = 0;
|
||||
|
||||
|
||||
/* Wrap mode not yet set */
|
||||
tex->wrap_mode = GL_FALSE;
|
||||
|
||||
/* Create slice arrays */
|
||||
tex->slice_x_spans =
|
||||
g_array_sized_new (FALSE, FALSE,
|
||||
@ -1533,24 +1549,7 @@ cogl_texture_new_from_foreign (GLuint gl_handle,
|
||||
g_array_append_val (tex->slice_y_spans, y_span);
|
||||
|
||||
g_array_append_val (tex->slice_gl_handles, gl_handle);
|
||||
|
||||
/* Force appropriate wrap parameter */
|
||||
if (cogl_features_available (COGL_FEATURE_TEXTURE_NPOT) &&
|
||||
gl_target == GL_TEXTURE_2D)
|
||||
{
|
||||
/* Hardware repeated tiling */
|
||||
tex->wrap_mode = GL_REPEAT;
|
||||
GE( glTexParameteri (tex->gl_target, GL_TEXTURE_WRAP_S, GL_REPEAT) );
|
||||
GE( glTexParameteri (tex->gl_target, GL_TEXTURE_WRAP_T, GL_REPEAT) );
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Any tiling will be done in software */
|
||||
tex->wrap_mode = GL_CLAMP_TO_EDGE;
|
||||
GE( glTexParameteri (tex->gl_target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE) );
|
||||
GE( glTexParameteri (tex->gl_target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE) );
|
||||
}
|
||||
|
||||
|
||||
return _cogl_texture_handle_new (tex);
|
||||
}
|
||||
|
||||
@ -1952,6 +1951,10 @@ _cogl_texture_quad_sw (CoglTexture *tex,
|
||||
|
||||
cogl_enable (enable_flags);
|
||||
|
||||
/* 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 */
|
||||
_cogl_texture_set_wrap_mode_parameter (tex, GL_CLAMP_TO_EDGE);
|
||||
|
||||
/* If the texture coordinates are backwards then swap both the
|
||||
geometry and texture coordinates so that the texture will be
|
||||
flipped but we can still use the same algorithm to iterate the
|
||||
@ -2129,7 +2132,19 @@ _cogl_texture_quad_hw (CoglTexture *tex,
|
||||
enable_flags |= COGL_ENABLE_BACKFACE_CULLING;
|
||||
|
||||
cogl_enable (enable_flags);
|
||||
|
||||
|
||||
|
||||
/* If the texture coords are all in the range [0,1] then we want to
|
||||
clamp the coords to the edge otherwise it can pull in edge pixels
|
||||
from the wrong side when scaled */
|
||||
if (tx1 >= 0 && tx1 <= COGL_FIXED_1
|
||||
&& tx2 >= 0 && tx2 <= COGL_FIXED_1
|
||||
&& ty1 >= 0 && ty1 <= COGL_FIXED_1
|
||||
&& ty2 >= 0 && ty2 <= COGL_FIXED_1)
|
||||
_cogl_texture_set_wrap_mode_parameter (tex, GL_CLAMP_TO_EDGE);
|
||||
else
|
||||
_cogl_texture_set_wrap_mode_parameter (tex, GL_REPEAT);
|
||||
|
||||
GE( glTexCoordPointer (2, GL_FLOAT, 0, tex_coords) );
|
||||
GE( glVertexPointer (2, GL_FLOAT, 0, quad_coords) );
|
||||
|
||||
@ -2295,15 +2310,7 @@ cogl_texture_polygon (CoglHandle handle,
|
||||
|
||||
/* Temporarily change the wrapping mode on all of the slices to use
|
||||
a transparent border */
|
||||
for (i = 0; i < tex->slice_gl_handles->len; i++)
|
||||
{
|
||||
GE( glBindTexture (tex->gl_target,
|
||||
g_array_index (tex->slice_gl_handles, GLuint, i)) );
|
||||
GE( glTexParameteri (tex->gl_target, GL_TEXTURE_WRAP_S,
|
||||
GL_CLAMP_TO_BORDER) );
|
||||
GE( glTexParameteri (tex->gl_target, GL_TEXTURE_WRAP_T,
|
||||
GL_CLAMP_TO_BORDER) );
|
||||
}
|
||||
_cogl_texture_set_wrap_mode_parameter (tex, GL_CLAMP_TO_BORDER);
|
||||
|
||||
tex_num = 0;
|
||||
|
||||
@ -2350,13 +2357,4 @@ cogl_texture_polygon (CoglHandle handle,
|
||||
GE( glDrawArrays (GL_TRIANGLE_FAN, 0, n_vertices) );
|
||||
}
|
||||
}
|
||||
|
||||
/* Restore the wrapping mode */
|
||||
for (i = 0; i < tex->slice_gl_handles->len; i++)
|
||||
{
|
||||
GE( glBindTexture (tex->gl_target,
|
||||
g_array_index (tex->slice_gl_handles, GLuint, i)) );
|
||||
GE( glTexParameteri (tex->gl_target, GL_TEXTURE_WRAP_S, tex->wrap_mode) );
|
||||
GE( glTexParameteri (tex->gl_target, GL_TEXTURE_WRAP_T, tex->wrap_mode) );
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user