From ef19c7201549c3ec07aab2479c44ee259d616efe Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Tue, 2 Sep 2025 17:48:02 -0700 Subject: [PATCH] Set the texture scale and address mode when creating a texture Fixes https://github.com/libsdl-org/sdl2-compat/issues/506 --- src/render/opengl/SDL_render_gl.c | 93 ++++++++++++++----------- src/render/opengles2/SDL_render_gles2.c | 19 ++++- 2 files changed, 68 insertions(+), 44 deletions(-) diff --git a/src/render/opengl/SDL_render_gl.c b/src/render/opengl/SDL_render_gl.c index 8d59923658..7bd048cab0 100644 --- a/src/render/opengl/SDL_render_gl.c +++ b/src/render/opengl/SDL_render_gl.c @@ -442,6 +442,43 @@ static bool convert_format(Uint32 pixel_format, GLint *internalFormat, GLenum *f return true; } +static bool SetTextureScaleMode(GL_RenderData *data, GLenum textype, SDL_ScaleMode scaleMode) +{ + switch (scaleMode) { + case SDL_SCALEMODE_NEAREST: + data->glTexParameteri(textype, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + data->glTexParameteri(textype, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + break; + case SDL_SCALEMODE_PIXELART: // Uses linear sampling + case SDL_SCALEMODE_LINEAR: + data->glTexParameteri(textype, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + data->glTexParameteri(textype, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + break; + default: + return SDL_SetError("Unknown texture scale mode: %d", scaleMode); + } + return true; +} + +static GLint TranslateAddressMode(SDL_TextureAddressMode addressMode) +{ + switch (addressMode) { + case SDL_TEXTURE_ADDRESS_CLAMP: + return GL_CLAMP_TO_EDGE; + case SDL_TEXTURE_ADDRESS_WRAP: + return GL_REPEAT; + default: + SDL_assert(!"Unknown texture address mode"); + return GL_CLAMP_TO_EDGE; + } +} + +static void SetTextureAddressMode(GL_RenderData *data, GLenum textype, SDL_TextureAddressMode addressModeU, SDL_TextureAddressMode addressModeV) +{ + data->glTexParameteri(textype, GL_TEXTURE_WRAP_S, TranslateAddressMode(addressModeU)); + data->glTexParameteri(textype, GL_TEXTURE_WRAP_T, TranslateAddressMode(addressModeV)); +} + static bool GL_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SDL_PropertiesID create_props) { GL_RenderData *renderdata = (GL_RenderData *)renderer->internal; @@ -538,11 +575,13 @@ static bool GL_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SDL_P data->format = format; data->formattype = type; - data->texture_scale_mode = SDL_SCALEMODE_INVALID; - data->texture_address_mode_u = SDL_TEXTURE_ADDRESS_INVALID; - data->texture_address_mode_v = SDL_TEXTURE_ADDRESS_INVALID; + data->texture_scale_mode = texture->scaleMode; + data->texture_address_mode_u = SDL_TEXTURE_ADDRESS_CLAMP; + data->texture_address_mode_v = SDL_TEXTURE_ADDRESS_CLAMP; renderdata->glEnable(textype); renderdata->glBindTexture(textype, data->texture); + SetTextureScaleMode(renderdata, textype, data->texture_scale_mode); + SetTextureAddressMode(renderdata, textype, data->texture_address_mode_u, data->texture_address_mode_v); #ifdef SDL_PLATFORM_MACOS #ifndef GL_TEXTURE_STORAGE_HINT_APPLE #define GL_TEXTURE_STORAGE_HINT_APPLE 0x85BC @@ -574,10 +613,11 @@ static bool GL_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SDL_P renderdata->glTexImage2D(textype, 0, internalFormat, texture_w, texture_h, 0, format, type, NULL); } - renderdata->glDisable(textype); if (!GL_CheckError("glTexImage2D()", renderer)) { return false; } + SetTextureScaleMode(renderdata, textype, data->texture_scale_mode); + SetTextureAddressMode(renderdata, textype, data->texture_address_mode_u, data->texture_address_mode_v); #ifdef SDL_HAVE_YUV if (texture->format == SDL_PIXELFORMAT_YV12 || @@ -600,11 +640,15 @@ static bool GL_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SDL_P renderdata->glBindTexture(textype, data->utexture); renderdata->glTexImage2D(textype, 0, internalFormat, (texture_w + 1) / 2, (texture_h + 1) / 2, 0, format, type, NULL); + SetTextureScaleMode(renderdata, textype, data->texture_scale_mode); + SetTextureAddressMode(renderdata, textype, data->texture_address_mode_u, data->texture_address_mode_v); SDL_SetNumberProperty(props, SDL_PROP_TEXTURE_OPENGL_TEXTURE_U_NUMBER, data->utexture); renderdata->glBindTexture(textype, data->vtexture); renderdata->glTexImage2D(textype, 0, internalFormat, (texture_w + 1) / 2, (texture_h + 1) / 2, 0, format, type, NULL); + SetTextureScaleMode(renderdata, textype, data->texture_scale_mode); + SetTextureAddressMode(renderdata, textype, data->texture_address_mode_u, data->texture_address_mode_v); SDL_SetNumberProperty(props, SDL_PROP_TEXTURE_OPENGL_TEXTURE_V_NUMBER, data->vtexture); } @@ -621,6 +665,8 @@ static bool GL_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SDL_P renderdata->glBindTexture(textype, data->utexture); renderdata->glTexImage2D(textype, 0, GL_LUMINANCE_ALPHA, (texture_w + 1) / 2, (texture_h + 1) / 2, 0, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, NULL); + SetTextureScaleMode(renderdata, textype, data->texture_scale_mode); + SetTextureAddressMode(renderdata, textype, data->texture_address_mode_u, data->texture_address_mode_v); SDL_SetNumberProperty(props, SDL_PROP_TEXTURE_OPENGL_TEXTURE_UV_NUMBER, data->utexture); } #endif @@ -660,6 +706,8 @@ static bool GL_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SDL_P } #endif // SDL_HAVE_YUV + renderdata->glDisable(textype); + return GL_CheckError("", renderer); } @@ -1083,43 +1131,6 @@ static bool SetDrawState(GL_RenderData *data, const SDL_RenderCommand *cmd, cons return true; } -static bool SetTextureScaleMode(GL_RenderData *data, GLenum textype, SDL_ScaleMode scaleMode) -{ - switch (scaleMode) { - case SDL_SCALEMODE_NEAREST: - data->glTexParameteri(textype, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - data->glTexParameteri(textype, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - break; - case SDL_SCALEMODE_PIXELART: // Uses linear sampling - case SDL_SCALEMODE_LINEAR: - data->glTexParameteri(textype, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - data->glTexParameteri(textype, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - break; - default: - return SDL_SetError("Unknown texture scale mode: %d", scaleMode); - } - return true; -} - -static GLint TranslateAddressMode(SDL_TextureAddressMode addressMode) -{ - switch (addressMode) { - case SDL_TEXTURE_ADDRESS_CLAMP: - return GL_CLAMP_TO_EDGE; - case SDL_TEXTURE_ADDRESS_WRAP: - return GL_REPEAT; - default: - SDL_assert(!"Unknown texture address mode"); - return GL_CLAMP_TO_EDGE; - } -} - -static void SetTextureAddressMode(GL_RenderData *data, GLenum textype, SDL_TextureAddressMode addressModeU, SDL_TextureAddressMode addressModeV) -{ - data->glTexParameteri(textype, GL_TEXTURE_WRAP_S, TranslateAddressMode(addressModeU)); - data->glTexParameteri(textype, GL_TEXTURE_WRAP_T, TranslateAddressMode(addressModeV)); -} - static bool SetCopyState(GL_RenderData *data, const SDL_RenderCommand *cmd) { SDL_Texture *texture = cmd->data.draw.texture; diff --git a/src/render/opengles2/SDL_render_gles2.c b/src/render/opengles2/SDL_render_gles2.c index ec4211fd02..8854c524fa 100644 --- a/src/render/opengles2/SDL_render_gles2.c +++ b/src/render/opengles2/SDL_render_gles2.c @@ -1658,9 +1658,9 @@ static bool GLES2_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SD data->texture_u = 0; data->texture_v = 0; #endif - data->texture_scale_mode = SDL_SCALEMODE_INVALID; - data->texture_address_mode_u = SDL_TEXTURE_ADDRESS_INVALID; - data->texture_address_mode_v = SDL_TEXTURE_ADDRESS_INVALID; + data->texture_scale_mode = texture->scaleMode; + data->texture_address_mode_u = SDL_TEXTURE_ADDRESS_CLAMP; + data->texture_address_mode_v = SDL_TEXTURE_ADDRESS_CLAMP; // Allocate a blob for image renderdata if (texture->access == SDL_TEXTUREACCESS_STREAMING) { @@ -1707,6 +1707,13 @@ static bool GLES2_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SD renderdata->glActiveTexture(GL_TEXTURE2); renderdata->glBindTexture(data->texture_type, data->texture_v); renderdata->glTexImage2D(data->texture_type, 0, format, (texture->w + 1) / 2, (texture->h + 1) / 2, 0, format, type, NULL); + if (!GL_CheckError("glTexImage2D()", renderer)) { + SDL_free(data->pixel_data); + SDL_free(data); + return false; + } + SetTextureScaleMode(renderdata, data->texture_type, data->texture_scale_mode); + SetTextureAddressMode(renderdata, data->texture_type, data->texture_address_mode_u, data->texture_address_mode_v); SDL_SetNumberProperty(SDL_GetTextureProperties(texture), SDL_PROP_TEXTURE_OPENGLES2_TEXTURE_V_NUMBER, data->texture_v); data->texture_u = (GLuint)SDL_GetNumberProperty(create_props, SDL_PROP_TEXTURE_CREATE_OPENGLES2_TEXTURE_U_NUMBER, 0); @@ -1728,6 +1735,8 @@ static bool GLES2_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SD SDL_free(data); return false; } + SetTextureScaleMode(renderdata, data->texture_type, data->texture_scale_mode); + SetTextureAddressMode(renderdata, data->texture_type, data->texture_address_mode_u, data->texture_address_mode_v); SDL_SetNumberProperty(SDL_GetTextureProperties(texture), SDL_PROP_TEXTURE_OPENGLES2_TEXTURE_U_NUMBER, data->texture_u); if (!SDL_GetYCbCRtoRGBConversionMatrix(texture->colorspace, texture->w, texture->h, 8)) { @@ -1755,6 +1764,8 @@ static bool GLES2_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SD SDL_free(data); return false; } + SetTextureScaleMode(renderdata, data->texture_type, data->texture_scale_mode); + SetTextureAddressMode(renderdata, data->texture_type, data->texture_address_mode_u, data->texture_address_mode_v); SDL_SetNumberProperty(SDL_GetTextureProperties(texture), SDL_PROP_TEXTURE_OPENGLES2_TEXTURE_UV_NUMBER, data->texture_u); if (!SDL_GetYCbCRtoRGBConversionMatrix(texture->colorspace, texture->w, texture->h, 8)) { @@ -1785,6 +1796,8 @@ static bool GLES2_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SD return false; } } + SetTextureScaleMode(renderdata, data->texture_type, data->texture_scale_mode); + SetTextureAddressMode(renderdata, data->texture_type, data->texture_address_mode_u, data->texture_address_mode_v); SDL_SetNumberProperty(SDL_GetTextureProperties(texture), SDL_PROP_TEXTURE_OPENGLES2_TEXTURE_NUMBER, data->texture); SDL_SetNumberProperty(SDL_GetTextureProperties(texture), SDL_PROP_TEXTURE_OPENGLES2_TEXTURE_TARGET_NUMBER, data->texture_type);