From 11411bb5ef0658fc5e17b3459b722b5510a4cd89 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Mon, 8 Sep 2025 17:06:59 -0400 Subject: [PATCH] renderer: Don't use wrapping on NPOT textures if the renderer can't handle it. Fixes #13887. --- src/render/SDL_render.c | 20 ++++++++++++++++---- src/render/SDL_sysrender.h | 1 + src/render/opengl/SDL_render_gl.c | 3 +++ src/render/opengles2/SDL_render_gles2.c | 6 ++++++ 4 files changed, 26 insertions(+), 4 deletions(-) diff --git a/src/render/SDL_render.c b/src/render/SDL_render.c index 5bbd691ef0..19b8222344 100644 --- a/src/render/SDL_render.c +++ b/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); diff --git a/src/render/SDL_sysrender.h b/src/render/SDL_sysrender.h index d42f536294..96a7dd5eac 100644 --- a/src/render/SDL_sysrender.h +++ b/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; diff --git a/src/render/opengl/SDL_render_gl.c b/src/render/opengl/SDL_render_gl.c index 7bd048cab0..d2430901af 100644 --- a/src/render/opengl/SDL_render_gl.c +++ b/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; diff --git a/src/render/opengles2/SDL_render_gles2.c b/src/render/opengles2/SDL_render_gles2.c index 8854c524fa..f01f63ac0c 100644 --- a/src/render/opengles2/SDL_render_gles2.c +++ b/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);