diff --git a/gl/cogl-texture.c b/gl/cogl-texture.c index bf2eef304..a1c5e7d75 100644 --- a/gl/cogl-texture.c +++ b/gl/cogl-texture.c @@ -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) ); - } }