Pārlūkot izejas kodu

renderer: Don't use wrapping on NPOT textures if the renderer can't handle it.

Fixes #13887.
Ryan C. Gordon 4 dienas atpakaļ
vecāks
revīzija
11411bb5ef

+ 16 - 4
src/render/SDL_render.c

@@ -4306,6 +4306,11 @@ static bool SDL_RenderTextureTiled_Iterate(SDL_Renderer *renderer, SDL_Texture *
     return true;
 }
 
+static bool IsNPOT(int x)
+{
+    return (x <= 0) || ((x & (x - 1)) != 0);
+}
+
 bool SDL_RenderTextureTiled(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_FRect *srcrect, float scale, const SDL_FRect *dstrect)
 {
     SDL_FRect real_srcrect;
@@ -4350,11 +4355,18 @@ bool SDL_RenderTextureTiled(SDL_Renderer *renderer, SDL_Texture *texture, const
 
     texture->last_command_generation = renderer->render_command_generation;
 
+    bool do_wrapping = !renderer->software &&
+                        (!srcrect ||
+                            (real_srcrect.x == 0.0f && real_srcrect.y == 0.0f &&
+                             real_srcrect.w == (float)texture->w && real_srcrect.h == (float)texture->h));
+    if (do_wrapping) {
+        if (renderer->npot_texture_wrap_unsupported && (IsNPOT((int) real_srcrect.w) || IsNPOT((int) real_srcrect.h))) {
+            do_wrapping = false;
+        }
+    }
+
     // See if we can use geometry with repeating texture coordinates
-    if (!renderer->software &&
-        (!srcrect ||
-         (real_srcrect.x == 0.0f && real_srcrect.y == 0.0f &&
-          real_srcrect.w == (float)texture->w && real_srcrect.h == (float)texture->h))) {
+    if (do_wrapping) {
         return SDL_RenderTextureTiled_Wrap(renderer, texture, &real_srcrect, scale, dstrect);
     } else {
         return SDL_RenderTextureTiled_Iterate(renderer, texture, &real_srcrect, scale, dstrect);

+ 1 - 0
src/render/SDL_sysrender.h

@@ -269,6 +269,7 @@ struct SDL_Renderer
     SDL_PixelFormat *texture_formats;
     int num_texture_formats;
     bool software;
+    bool npot_texture_wrap_unsupported;
 
     // The window associated with the renderer
     SDL_Window *window;

+ 3 - 0
src/render/opengl/SDL_render_gl.c

@@ -1785,6 +1785,9 @@ static bool GL_CreateRenderer(SDL_Renderer *renderer, SDL_Window *window, SDL_Pr
         }
     }
 
+    // texture-rectangle doesn't support GL_REPEAT, it has to be the full NPOT extension (or real OpenGL 2.0+)
+    renderer->npot_texture_wrap_unsupported = !non_power_of_two_supported;
+
     data->textype = GL_TEXTURE_2D;
     if (non_power_of_two_supported) {
         data->GL_ARB_texture_non_power_of_two_supported = true;

+ 6 - 0
src/render/opengles2/SDL_render_gles2.c

@@ -2295,6 +2295,12 @@ static bool GLES2_CreateRenderer(SDL_Renderer *renderer, SDL_Window *window, SDL
         data->GL_EXT_blend_minmax_supported = true;
     }
 
+    // Full NPOT textures (that can use GL_REPEAT, etc) are a core feature of GLES3,
+    //  and an extension in GLES2.
+    if ((major < 3) && !SDL_GL_ExtensionSupported("GL_ARB_texture_non_power_of_two")) {
+        renderer->npot_texture_wrap_unsupported = true;
+    }
+
     // Set up parameters for rendering
     data->glDisable(GL_DEPTH_TEST);
     data->glDisable(GL_CULL_FACE);