From b32cd4f84b19f80126fa09be9da0db4c11e3d223 Mon Sep 17 00:00:00 2001
From: Sam Lantinga <[EMAIL REDACTED]>
Date: Wed, 5 Mar 2025 18:56:59 -0800
Subject: [PATCH] Make texture scale mode a part of the 2D renderer draw state
Also added texture addressing mode support to the PSP and Vita renderers (untested)
Fixes https://github.com/libsdl-org/SDL/issues/12461
(cherry picked from commit cb099ebd4f82bf85403fbc60713a6d463972a798)
---
include/SDL3/SDL_surface.h | 1 +
src/render/SDL_render.c | 9 +-
src/render/SDL_sysrender.h | 3 +-
src/render/direct3d/SDL_render_d3d.c | 70 ++++----
src/render/direct3d11/SDL_render_d3d11.c | 22 +--
src/render/direct3d12/SDL_render_d3d12.c | 22 +--
src/render/gpu/SDL_render_gpu.c | 18 +-
src/render/metal/SDL_render_metal.m | 7 +-
src/render/opengl/SDL_render_gl.c | 157 ++++++++++--------
src/render/opengles2/SDL_render_gles2.c | 130 +++++++++------
src/render/ps2/SDL_render_ps2.c | 26 ++-
src/render/psp/SDL_render_psp.c | 62 +++++--
src/render/software/SDL_render_sw.c | 25 ++-
src/render/vitagxm/SDL_render_vita_gxm.c | 61 ++++---
.../vitagxm/SDL_render_vita_gxm_tools.c | 6 +
.../vitagxm/SDL_render_vita_gxm_tools.h | 1 +
.../vitagxm/SDL_render_vita_gxm_types.h | 2 +
src/render/vulkan/SDL_render_vulkan.c | 18 +-
test/testautomation_render.c | 131 +++++++++++++++
19 files changed, 473 insertions(+), 298 deletions(-)
diff --git a/include/SDL3/SDL_surface.h b/include/SDL3/SDL_surface.h
index 603a23cd9ab85..7bff7cfb287e4 100644
--- a/include/SDL3/SDL_surface.h
+++ b/include/SDL3/SDL_surface.h
@@ -82,6 +82,7 @@ typedef Uint32 SDL_SurfaceFlags;
*/
typedef enum SDL_ScaleMode
{
+ SDL_SCALEMODE_INVALID = -1,
SDL_SCALEMODE_NEAREST, /**< nearest pixel sampling */
SDL_SCALEMODE_LINEAR /**< linear filtering */
} SDL_ScaleMode;
diff --git a/src/render/SDL_render.c b/src/render/SDL_render.c
index 82ecb884588b3..422755906c8b9 100644
--- a/src/render/SDL_render.c
+++ b/src/render/SDL_render.c
@@ -573,6 +573,9 @@ static SDL_RenderCommand *PrepQueueCmdDraw(SDL_Renderer *renderer, const SDL_Ren
cmd->data.draw.color = *color;
cmd->data.draw.blend = blendMode;
cmd->data.draw.texture = texture;
+ if (texture) {
+ cmd->data.draw.texture_scale_mode = texture->scaleMode;
+ }
cmd->data.draw.texture_address_mode = SDL_TEXTURE_ADDRESS_CLAMP;
}
}
@@ -1962,8 +1965,6 @@ bool SDL_GetTextureBlendMode(SDL_Texture *texture, SDL_BlendMode *blendMode)
bool SDL_SetTextureScaleMode(SDL_Texture *texture, SDL_ScaleMode scaleMode)
{
- SDL_Renderer *renderer;
-
CHECK_TEXTURE_MAGIC(texture, false);
if (scaleMode != SDL_SCALEMODE_NEAREST &&
@@ -1971,12 +1972,10 @@ bool SDL_SetTextureScaleMode(SDL_Texture *texture, SDL_ScaleMode scaleMode)
return SDL_InvalidParamError("scaleMode");
}
- renderer = texture->renderer;
texture->scaleMode = scaleMode;
+
if (texture->native) {
return SDL_SetTextureScaleMode(texture->native, scaleMode);
- } else {
- renderer->SetTextureScaleMode(renderer, texture, scaleMode);
}
return true;
}
diff --git a/src/render/SDL_sysrender.h b/src/render/SDL_sysrender.h
index 9d39dfd3a55e6..bbafefdc70f6f 100644
--- a/src/render/SDL_sysrender.h
+++ b/src/render/SDL_sysrender.h
@@ -34,6 +34,7 @@ extern "C" {
typedef enum SDL_TextureAddressMode
{
+ SDL_TEXTURE_ADDRESS_INVALID = -1,
SDL_TEXTURE_ADDRESS_AUTO,
SDL_TEXTURE_ADDRESS_CLAMP,
SDL_TEXTURE_ADDRESS_WRAP,
@@ -155,6 +156,7 @@ typedef struct SDL_RenderCommand
SDL_FColor color;
SDL_BlendMode blend;
SDL_Texture *texture;
+ SDL_ScaleMode texture_scale_mode;
SDL_TextureAddressMode texture_address_mode;
} draw;
struct
@@ -224,7 +226,6 @@ struct SDL_Renderer
bool (*LockTexture)(SDL_Renderer *renderer, SDL_Texture *texture,
const SDL_Rect *rect, void **pixels, int *pitch);
void (*UnlockTexture)(SDL_Renderer *renderer, SDL_Texture *texture);
- void (*SetTextureScaleMode)(SDL_Renderer *renderer, SDL_Texture *texture, SDL_ScaleMode scaleMode);
bool (*SetRenderTarget)(SDL_Renderer *renderer, SDL_Texture *texture);
SDL_Surface *(*RenderReadPixels)(SDL_Renderer *renderer, const SDL_Rect *rect);
bool (*RenderPresent)(SDL_Renderer *renderer);
diff --git a/src/render/direct3d/SDL_render_d3d.c b/src/render/direct3d/SDL_render_d3d.c
index ccb5b3c3433c6..f70b56170bae8 100644
--- a/src/render/direct3d/SDL_render_d3d.c
+++ b/src/render/direct3d/SDL_render_d3d.c
@@ -60,7 +60,7 @@ typedef struct
bool updateSize;
bool beginScene;
bool enableSeparateAlphaBlend;
- D3DTEXTUREFILTERTYPE scaleMode[3];
+ SDL_ScaleMode scaleMode[3];
SDL_TextureAddressMode addressMode[3];
IDirect3DSurface9 *defaultRenderTarget;
IDirect3DSurface9 *currentRenderTarget;
@@ -89,7 +89,6 @@ typedef struct
typedef struct
{
D3D_TextureRep texture;
- D3DTEXTUREFILTERTYPE scaleMode;
D3D9_Shader shader;
const float *shader_params;
@@ -274,10 +273,14 @@ static void D3D_InitRenderState(D3D_RenderData *data)
IDirect3DDevice9_SetTransform(device, D3DTS_VIEW, &matrix);
// Reset our current scale mode
- SDL_memset(data->scaleMode, 0xFF, sizeof(data->scaleMode));
+ for (int i = 0; i < SDL_arraysize(data->scaleMode); ++i) {
+ data->scaleMode[i] = SDL_SCALEMODE_INVALID;
+ }
// Reset our current address mode
- SDL_zeroa(data->addressMode);
+ for (int i = 0; i < SDL_arraysize(data->addressMode); ++i) {
+ data->addressMode[i] = SDL_TEXTURE_ADDRESS_INVALID;
+ }
// Start the render with beginScene
data->beginScene = true;
@@ -533,7 +536,6 @@ static bool D3D_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SDL_
if (!texturedata) {
return false;
}
- texturedata->scaleMode = (texture->scaleMode == SDL_SCALEMODE_NEAREST) ? D3DTEXF_POINT : D3DTEXF_LINEAR;
texture->internal = texturedata;
@@ -736,17 +738,6 @@ static void D3D_UnlockTexture(SDL_Renderer *renderer, SDL_Texture *texture)
}
}
-static void D3D_SetTextureScaleMode(SDL_Renderer *renderer, SDL_Texture *texture, SDL_ScaleMode scaleMode)
-{
- D3D_TextureData *texturedata = (D3D_TextureData *)texture->internal;
-
- if (!texturedata) {
- return;
- }
-
- texturedata->scaleMode = (scaleMode == SDL_SCALEMODE_NEAREST) ? D3DTEXF_POINT : D3DTEXF_LINEAR;
-}
-
static bool D3D_SetRenderTargetInternal(SDL_Renderer *renderer, SDL_Texture *texture)
{
D3D_RenderData *data = (D3D_RenderData *)renderer->internal;
@@ -926,12 +917,22 @@ static bool BindTextureRep(IDirect3DDevice9 *device, D3D_TextureRep *texture, DW
return true;
}
-static void UpdateTextureScaleMode(D3D_RenderData *data, D3D_TextureData *texturedata, unsigned index)
+static void UpdateTextureScaleMode(D3D_RenderData *data, SDL_ScaleMode scaleMode, unsigned index)
{
- if (texturedata->scaleMode != data->scaleMode[index]) {
- IDirect3DDevice9_SetSamplerState(data->device, index, D3DSAMP_MINFILTER, texturedata->scaleMode);
- IDirect3DDevice9_SetSamplerState(data->device, index, D3DSAMP_MAGFILTER, texturedata->scaleMode);
- data->scaleMode[index] = texturedata->scaleMode;
+ if (scaleMode != data->scaleMode[index]) {
+ switch (scaleMode) {
+ case SDL_SCALEMODE_NEAREST:
+ IDirect3DDevice9_SetSamplerState(data->device, index, D3DSAMP_MINFILTER, D3DTEXF_POINT);
+ IDirect3DDevice9_SetSamplerState(data->device, index, D3DSAMP_MAGFILTER, D3DTEXF_POINT);
+ break;
+ case SDL_SCALEMODE_LINEAR:
+ IDirect3DDevice9_SetSamplerState(data->device, index, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
+ IDirect3DDevice9_SetSamplerState(data->device, index, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
+ break;
+ default:
+ break;
+ }
+ data->scaleMode[index] = scaleMode;
}
}
@@ -954,7 +955,7 @@ static void UpdateTextureAddressMode(D3D_RenderData *data, SDL_TextureAddressMod
}
}
-static bool SetupTextureState(D3D_RenderData *data, SDL_Texture *texture, SDL_TextureAddressMode addressMode, D3D9_Shader *shader, const float **shader_params)
+static bool SetupTextureState(D3D_RenderData *data, SDL_Texture *texture, D3D9_Shader *shader, const float **shader_params)
{
D3D_TextureData *texturedata = (D3D_TextureData *)texture->internal;
@@ -962,9 +963,6 @@ static bool SetupTextureState(D3D_RenderData *data, SDL_Texture *texture, SDL_Te
return SDL_SetError("Texture is not currently available");
}
- UpdateTextureScaleMode(data, texturedata, 0);
- UpdateTextureAddressMode(data, addressMode, 0);
-
*shader = texturedata->shader;
*shader_params = texturedata->shader_params;
@@ -973,11 +971,6 @@ static bool SetupTextureState(D3D_RenderData *data, SDL_Texture *texture, SDL_Te
}
#ifdef SDL_HAVE_YUV
if (texturedata->yuv) {
- UpdateTextureScaleMode(data, texturedata, 1);
- UpdateTextureScaleMode(data, texturedata, 2);
- UpdateTextureAddressMode(data, addressMode, 1);
- UpdateTextureAddressMode(data, addressMode, 2);
-
if (!BindTextureRep(data->device, &texturedata->utexture, 1)) {
return false;
}
@@ -1012,7 +1005,7 @@ static bool SetDrawState(D3D_RenderData *data, const SDL_RenderCommand *cmd)
IDirect3DDevice9_SetTexture(data->device, 2, NULL);
}
#endif
- if (texture && !SetupTextureState(data, texture, cmd->data.draw.texture_address_mode, &shader, &shader_params)) {
+ if (texture && !SetupTextureState(data, texture, &shader, &shader_params)) {
return false;
}
@@ -1049,6 +1042,20 @@ static bool SetDrawState(D3D_RenderData *data, const SDL_RenderCommand *cmd)
#endif
}
+ if (texture) {
+ D3D_TextureData *texturedata = (D3D_TextureData *)texture->internal;
+
+ UpdateTextureScaleMode(data, cmd->data.draw.texture_scale_mode, 0);
+ UpdateTextureAddressMode(data, cmd->data.draw.texture_address_mode, 0);
+
+ if (texturedata && texturedata->yuv) {
+ UpdateTextureScaleMode(data, cmd->data.draw.texture_scale_mode, 1);
+ UpdateTextureScaleMode(data, cmd->data.draw.texture_scale_mode, 2);
+ UpdateTextureAddressMode(data, cmd->data.draw.texture_address_mode, 1);
+ UpdateTextureAddressMode(data, cmd->data.draw.texture_address_mode, 2);
+ }
+ }
+
if (blend != data->drawstate.blend) {
if (blend == SDL_BLENDMODE_NONE) {
IDirect3DDevice9_SetRenderState(data->device, D3DRS_ALPHABLENDENABLE, FALSE);
@@ -1653,7 +1660,6 @@ static bool D3D_CreateRenderer(SDL_Renderer *renderer, SDL_Window *window, SDL_P
#endif
renderer->LockTexture = D3D_LockTexture;
renderer->UnlockTexture = D3D_UnlockTexture;
- renderer->SetTextureScaleMode = D3D_SetTextureScaleMode;
renderer->SetRenderTarget = D3D_SetRenderTarget;
renderer->QueueSetViewport = D3D_QueueNoOp;
renderer->QueueSetDrawColor = D3D_QueueNoOp;
diff --git a/src/render/direct3d11/SDL_render_d3d11.c b/src/render/direct3d11/SDL_render_d3d11.c
index dc1a7229c0a0a..60f646fd1eefc 100644
--- a/src/render/direct3d11/SDL_render_d3d11.c
+++ b/src/render/direct3d11/SDL_render_d3d11.c
@@ -122,7 +122,6 @@ typedef struct
ID3D11Texture2D *stagingTexture;
int lockedTexturePositionX;
int lockedTexturePositionY;
- D3D11_FILTER scaleMode;
D3D11_Shader shader;
const float *YCbCr_matrix;
#ifdef SDL_HAVE_YUV
@@ -1172,7 +1171,6 @@ static bool D3D11_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SD
if (!textureData) {
return false;
}
- textureData->scaleMode = (texture->scaleMode == SDL_SCALEMODE_NEAREST) ? D3D11_FILTER_MIN_MAG_MIP_POINT : D3D11_FILTER_MIN_MAG_MIP_LINEAR;
texture->internal = textureData;
@@ -1796,17 +1794,6 @@ static void D3D11_UnlockTexture(SDL_Renderer *renderer, SDL_Texture *texture)
SAFE_RELEASE(textureData->stagingTexture);
}
-static void D3D11_SetTextureScaleMode(SDL_Renderer *renderer, SDL_Texture *texture, SDL_ScaleMode scaleMode)
-{
- D3D11_TextureData *textureData = (D3D11_TextureData *)texture->internal;
-
- if (!textureData) {
- return;
- }
-
- textureData->scaleMode = (scaleMode == SDL_SCALEMODE_NEAREST) ? D3D11_FILTER_MIN_MAG_MIP_POINT : D3D11_FILTER_MIN_MAG_MIP_LINEAR;
-}
-
static bool D3D11_SetRenderTarget(SDL_Renderer *renderer, SDL_Texture *texture)
{
D3D11_RenderData *rendererData = (D3D11_RenderData *)renderer->internal;
@@ -2318,8 +2305,8 @@ static bool D3D11_SetCopyState(SDL_Renderer *renderer, const SDL_RenderCommand *
D3D11_SetupShaderConstants(renderer, cmd, texture, &constants);
- switch (textureData->scaleMode) {
- case D3D11_FILTER_MIN_MAG_MIP_POINT:
+ switch (cmd->data.draw.texture_scale_mode) {
+ case SDL_SCALEMODE_NEAREST:
switch (cmd->data.draw.texture_address_mode) {
case SDL_TEXTURE_ADDRESS_CLAMP:
textureSampler = rendererData->samplers[D3D11_SAMPLER_NEAREST_CLAMP];
@@ -2331,7 +2318,7 @@ static bool D3D11_SetCopyState(SDL_Renderer *renderer, const SDL_RenderCommand *
return SDL_SetError("Unknown texture address mode: %d", cmd->data.draw.texture_address_mode);
}
break;
- case D3D11_FILTER_MIN_MAG_MIP_LINEAR:
+ case SDL_SCALEMODE_LINEAR:
switch (cmd->data.draw.texture_address_mode) {
case SDL_TEXTURE_ADDRESS_CLAMP:
textureSampler = rendererData->samplers[D3D11_SAMPLER_LINEAR_CLAMP];
@@ -2344,7 +2331,7 @@ static bool D3D11_SetCopyState(SDL_Renderer *renderer, const SDL_RenderCommand *
}
break;
default:
- return SDL_SetError("Unknown scale mode: %d", textureData->scaleMode);
+ return SDL_SetError("Unknown scale mode: %d", cmd->data.draw.texture_scale_mode);
}
#ifdef SDL_HAVE_YUV
if (textureData->yuv) {
@@ -2712,7 +2699,6 @@ static bool D3D11_CreateRenderer(SDL_Renderer *renderer, SDL_Window *window, SDL
#endif
renderer->LockTexture = D3D11_LockTexture;
renderer->UnlockTexture = D3D11_UnlockTexture;
- renderer->SetTextureScaleMode = D3D11_SetTextureScaleMode;
renderer->SetRenderTarget = D3D11_SetRenderTarget;
renderer->QueueSetViewport = D3D11_QueueNoOp;
renderer->QueueSetDrawColor = D3D11_QueueNoOp;
diff --git a/src/render/direct3d12/SDL_render_d3d12.c b/src/render/direct3d12/SDL_render_d3d12.c
index 06535f0ecb226..946ad828a3a7e 100644
--- a/src/render/direct3d12/SDL_render_d3d12.c
+++ b/src/render/direct3d12/SDL_render_d3d12.c
@@ -124,7 +124,6 @@ typedef struct
DXGI_FORMAT mainTextureFormat;
ID3D12Resource *stagingBuffer;
D3D12_RESOURCE_STATES stagingResourceState;
- D3D12_FILTER scaleMode;
D3D12_Shader shader;
const float *YCbCr_matrix;
#ifdef SDL_HAVE_YUV
@@ -1574,7 +1573,6 @@ static bool D3D12_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SD
if (!textureData) {
return false;
}
- textureData->scaleMode = (texture->scaleMode == SDL_SCALEMODE_NEAREST) ? D3D12_FILTER_MIN_MAG_MIP_POINT : D3D12_FILTER_MIN_MAG_MIP_LINEAR;
texture->internal = textureData;
textureData->mainTextureFormat = textureFormat;
@@ -2244,17 +2242,6 @@ static void D3D12_UnlockTexture(SDL_Renderer *renderer, SDL_Texture *texture)
D3D_SAFE_RELEASE(textureData->stagingBuffer);
}
-static void D3D12_SetTextureScaleMode(SDL_Renderer *renderer, SDL_Texture *texture, SDL_ScaleMode scaleMode)
-{
- D3D12_TextureData *textureData = (D3D12_TextureData *)texture->internal;
-
- if (!textureData) {
- return;
- }
-
- textureData->scaleMode = (scaleMode == SDL_SCALEMODE_NEAREST) ? D3D12_FILTER_MIN_MAG_MIP_POINT : D3D12_FILTER_MIN_MAG_MIP_LINEAR;
-}
-
static bool D3D12_SetRenderTarget(SDL_Renderer *renderer, SDL_Texture *texture)
{
D3D12_RenderData *rendererData = (D3D12_RenderData *)renderer->internal;
@@ -2745,8 +2732,8 @@ static bool D3D12_SetCopyState(SDL_Renderer *renderer, const SDL_RenderCommand *
D3D12_SetupShaderConstants(renderer, cmd, texture, &constants);
- switch (textureData->scaleMode) {
- case D3D12_FILTER_MIN_MAG_MIP_POINT:
+ switch (cmd->data.draw.texture_scale_mode) {
+ case SDL_SCALEMODE_NEAREST:
switch (cmd->data.draw.texture_address_mode) {
case SDL_TEXTURE_ADDRESS_CLAMP:
textureSampler = &rendererData->samplers[D3D12_SAMPLER_NEAREST_CLAMP];
@@ -2758,7 +2745,7 @@ static bool D3D12_SetCopyState(SDL_Renderer *renderer, const SDL_RenderCommand *
return SDL_SetError("Unknown texture address mode: %d", cmd->data.draw.texture_address_mode);
}
break;
- case D3D12_FILTER_MIN_MAG_MIP_LINEAR:
+ case SDL_SCALEMODE_LINEAR:
switch (cmd->data.draw.texture_address_mode) {
case SDL_TEXTURE_ADDRESS_CLAMP:
textureSampler = &rendererData->samplers[D3D12_SAMPLER_LINEAR_CLAMP];
@@ -2771,7 +2758,7 @@ static bool D3D12_SetCopyState(SDL_Renderer *renderer, const SDL_RenderCommand *
}
break;
default:
- return SDL_SetError("Unknown scale mode: %d", textureData->scaleMode);
+ return SDL_SetError("Unknown scale mode: %d", cmd->data.draw.texture_scale_mode);
}
#ifdef SDL_HAVE_YUV
if (textureData->yuv) {
@@ -3248,7 +3235,6 @@ bool D3D12_CreateRenderer(SDL_Renderer *renderer, SDL_Window *window, SDL_Proper
#endif
renderer->LockTexture = D3D12_LockTexture;
renderer->UnlockTexture = D3D12_UnlockTexture;
- renderer->SetTextureScaleMode = D3D12_SetTextureScaleMode;
renderer->SetRenderTarget = D3D12_SetRenderTarget;
renderer->QueueSetViewport = D3D12_QueueNoOp;
renderer->QueueSetDrawColor = D3D12_QueueNoOp;
diff --git a/src/render/gpu/SDL_render_gpu.c b/src/render/gpu/SDL_render_gpu.c
index 73c1dbe795d00..52694291548cb 100644
--- a/src/render/gpu/SDL_render_gpu.c
+++ b/src/render/gpu/SDL_render_gpu.c
@@ -335,11 +335,6 @@ static void GPU_UnlockTexture(SDL_Renderer *renderer, SDL_Texture *texture)
GPU_UpdateTexture(renderer, texture, rect, pixels, data->pitch);
}
-static void GPU_SetTextureScaleMode(SDL_Renderer *renderer, SDL_Texture *texture, SDL_ScaleMode scale_mode)
-{
- // nothing to do in this backend.
-}
-
static bool GPU_SetRenderTarget(SDL_Renderer *renderer, SDL_Texture *texture)
{
GPU_RenderData *data = (GPU_RenderData *)renderer->internal;
@@ -494,8 +489,7 @@ static void PushUniforms(GPU_RenderData *data, SDL_RenderCommand *cmd)
SDL_PushGPUVertexUniformData(data->state.command_buffer, 0, &uniforms, sizeof(uniforms));
}
-static SDL_GPUSampler **SamplerPointer(
- GPU_RenderData *data, SDL_TextureAddressMode address_mode, SDL_ScaleMode scale_mode)
+static SDL_GPUSampler **SamplerPointer(GPU_RenderData *data, SDL_TextureAddressMode address_mode, SDL_ScaleMode scale_mode)
{
return &data->samplers[scale_mode][address_mode - 1];
}
@@ -575,7 +569,7 @@ static void Draw(
if (tdata) {
SDL_GPUTextureSamplerBinding sampler_bind;
SDL_zero(sampler_bind);
- sampler_bind.sampler = *SamplerPointer(data, cmd->data.draw.texture_address_mode, cmd->data.draw.texture->scaleMode);
+ sampler_bind.sampler = *SamplerPointer(data, cmd->data.draw.texture_address_mode, cmd->data.draw.texture_scale_mode);
sampler_bind.texture = tdata->texture;
SDL_BindGPUFragmentSamplers(pass, 0, &sampler_bind, 1);
}
@@ -785,6 +779,8 @@ static bool GPU_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd,
same texture, we can combine them all into a single draw call. */
SDL_Texture *thistexture = cmd->data.draw.texture;
SDL_BlendMode thisblend = cmd->data.draw.blend;
+ SDL_ScaleMode thisscalemode = cmd->data.draw.texture_scale_mode;
+ SDL_TextureAddressMode thisaddressmode = cmd->data.draw.texture_address_mode;
const SDL_RenderCommandType thiscmdtype = cmd->command;
SDL_RenderCommand *finalcmd = cmd;
SDL_RenderCommand *nextcmd = cmd->next;
@@ -795,7 +791,10 @@ static bool GPU_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd,
const SDL_RenderCommandType nextcmdtype = nextcmd->command;
if (nextcmdtype != thiscmdtype) {
break; // can't go any further on this draw call, different render command up next.
- } else if (nextcmd->data.draw.texture != thistexture || nextcmd->data.draw.blend != thisblend) {
+ } else if (nextcmd->data.draw.texture != thistexture ||
+ nextcmd->data.draw.texture_scale_mode != thisscalemode ||
+ nextcmd->data.draw.texture_address_mode != thisaddressmode ||
+ nextcmd->data.draw.blend != thisblend) {
// FIXME should we check address mode too?
break; // can't go any further on this draw call, different texture/blendmode copy up next.
} else {
@@ -1176,7 +1175,6 @@ static bool GPU_CreateRenderer(SDL_Renderer *renderer, SDL_Window *window, SDL_P
renderer->UpdateTexture = GPU_UpdateTexture;
renderer->LockTexture = GPU_LockTexture;
renderer->UnlockTexture = GPU_UnlockTexture;
- renderer->SetTextureScaleMode = GPU_SetTextureScaleMode;
renderer->SetRenderTarget = GPU_SetRenderTarget;
renderer->QueueSetViewport = GPU_QueueNoOp;
renderer->QueueSetDrawColor = GPU_QueueNoOp;
diff --git a/src/render/metal/SDL_render_metal.m b/src/render/metal/SDL_render_metal.m
index 63d9770d5025a..3bba129a67414 100644
--- a/src/render/metal/SDL_render_metal.m
+++ b/src/render/metal/SDL_render_metal.m
@@ -1070,10 +1070,6 @@ static void METAL_UnlockTexture(SDL_Renderer *renderer, SDL_Texture *texture)
}
}
-static void METAL_SetTextureScaleMode(SDL_Renderer *renderer, SDL_Texture *texture, SDL_ScaleMode scaleMode)
-{
-}
-
static bool METAL_SetRenderTarget(SDL_Renderer *renderer, SDL_Texture *texture)
{
@autoreleasepool {
@@ -1473,7 +1469,7 @@ static bool SetCopyState(SDL_Renderer *renderer, const SDL_RenderCommand *cmd, c
if (texture != statecache->texture) {
id<MTLSamplerState> mtlsampler;
- if (texture->scaleMode == SDL_SCALEMODE_NEAREST) {
+ if (cmd->data.draw.texture_scale_mode == SDL_SCALEMODE_NEAREST) {
switch (cmd->data.draw.texture_address_mode) {
case SDL_TEXTURE_ADDRESS_CLAMP:
mtlsampler = data.mtlsamplers[SDL_METAL_SAMPLER_NEAREST_CLAMP];
@@ -2129,7 +2125,6 @@ in case we want to use it later (recreating the renderer)
#endif
renderer->LockTexture = METAL_LockTexture;
renderer->UnlockTexture = METAL_UnlockTexture;
- renderer->SetTextureScaleMode = METAL_SetTextureScaleMode;
renderer->SetRenderTarget = METAL_SetRenderTarget;
renderer->QueueSetViewport = METAL_QueueSetViewport;
renderer->QueueSetDrawColor = METAL_QueueNoOp;
diff --git a/src/render/opengl/SDL_render_gl.c b/src/render/opengl/SDL_render_gl.c
index d5344382aa9ef..fecd365d07469 100644
--- a/src/render/opengl/SDL_render_gl.c
+++ b/src/render/opengl/SDL_render_gl.c
@@ -137,7 +137,6 @@ typedef struct
void *pixels;
int pitch;
SDL_Rect locked_rect;
-
#ifdef SDL_HAVE_YUV
// YUV texture support
bool yuv;
@@ -147,7 +146,8 @@ typedef struct
GLuint vtexture;
bool vtexture_external;
#endif
-
+ SDL_ScaleMode texture_scale_mode;
+ SDL_TextureAddressMode texture_address_mode;
GL_FBOList *fbo;
} GL_TextureData;
@@ -447,7 +447,6 @@ static bool GL_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SDL_P
GLint internalFormat;
GLenum format, type;
int texture_w, texture_h;
- GLenum scaleMode;
GL_ActivateRenderer(renderer);
@@ -536,11 +535,10 @@ static bool GL_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SDL_P
data->format = format;
data->formattype = type;
- scaleMode = (texture->scaleMode == SDL_SCALEMODE_NEAREST) ? GL_NEAREST : GL_LINEAR;
+ data->texture_scale_mode = SDL_SCALEMODE_INVALID;
+ data->texture_address_mode = SDL_TEXTURE_ADDRESS_INVALID;
renderdata->glEnable(textype);
renderdata->glBindTexture(textype, data->texture);
- renderdata->glTexParameteri(textype, GL_TEXTURE_MIN_FILTER, scaleMode);
- renderdata->glTexParameteri(textype, GL_TEXTURE_MAG_FILTER, scaleMode);
#ifdef SDL_PLATFORM_MACOS
#ifndef GL_TEXTURE_STORAGE_HINT_APPLE
#define GL_TEXTURE_STORAGE_HINT_APPLE 0x85BC
@@ -596,19 +594,11 @@ static bool GL_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SDL_P
}
renderdata->glBindTexture(textype, data->utexture);
- renderdata->glTexParameteri(textype, GL_TEXTURE_MIN_FILTER,
- scaleMode);
- renderdata->glTexParameteri(textype, GL_TEXTURE_MAG_FILTER,
- scaleMode);
renderdata->glTexImage2D(textype, 0, internalFormat, (texture_w + 1) / 2,
(texture_h + 1) / 2, 0, format, type, NULL);
SDL_SetNumberProperty(props, SDL_PROP_TEXTURE_OPENGL_TEXTURE_U_NUMBER, data->utexture);
renderdata->glBindTexture(textype, data->vtexture);
- renderdata->glTexParameteri(textype, GL_TEXTURE_MIN_FILTER,
- scaleMode);
- renderdata->glTexParameteri(textype, GL_TEXTURE_MAG_FILTER,
- scaleMode);
renderdata->glTexImage2D(textype, 0, internalFormat, (texture_w + 1) / 2,
(texture_h + 1) / 2, 0, format, type, NULL);
SDL_SetNumberProperty(props, SDL_PROP_TEXTURE_OPENGL_TEXTURE_V_NUMBER, data->vtexture);
@@ -625,10 +615,6 @@ static bool GL_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SDL_P
renderdata->glGenTextures(1, &data->utexture);
}
renderdata->glBindTexture(textype, data->utexture);
- renderdata->glTexParameteri(textype, GL_TEXTURE_MIN_FILTER,
- scaleMode);
- renderdata->glTexParameteri(textype, GL_TEXTURE_MAG_FILTER,
- scaleMode);
renderdata->glTexImage2D(textype, 0, GL_LUMINANCE_ALPHA, (texture_w + 1) / 2,
(texture_h + 1) / 2, 0, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, NULL);
SDL_SetNumberProperty(props, SDL_PROP_TEXTURE_OPENGL_TEXTURE_UV_NUMBER, data->utexture);
@@ -822,38 +808,6 @@ static void GL_UnlockTexture(SDL_Renderer *renderer, SDL_Texture *texture)
GL_UpdateTexture(renderer, texture, rect, pixels, data->pitch);
}
-static void GL_SetTextureScaleMode(SDL_Renderer *renderer, SDL_Texture *texture, SDL_ScaleMode scaleMode)
-{
- GL_RenderData *renderdata = (GL_RenderData *)renderer->internal;
- const GLenum textype = renderdata->textype;
- GL_TextureData *data = (GL_TextureData *)texture->internal;
- GLenum glScaleMode = (scaleMode == SDL_SCALEMODE_NEAREST) ? GL_NEAREST : GL_LINEAR;
-
- renderdata->glBindTexture(textype, data->texture);
- renderdata->glTexParameteri(textype, GL_TEXTURE_MIN_FILTER, glScaleMode);
- renderdata->glTexParameteri(textype, GL_TEXTURE_MAG_FILTER, glScaleMode);
-
-#ifdef SDL_HAVE_YUV
- if (texture->format == SDL_PIXELFORMAT_YV12 ||
- texture->format == SDL_PIXELFORMAT_IYUV) {
- renderdata->glBindTexture(textype, data->utexture);
- renderdata->glTexParameteri(textype, GL_TEXTURE_MIN_FILTER, glScaleMode);
- renderdata->glTexParameteri(textype, GL_TEXTURE_MAG_FILTER, glScaleMode);
-
- renderdata->glBindTexture(textype, data->vtexture);
- renderdata->glTexParameteri(textype, GL_TEXTURE_MIN_FILTER, glScaleMode);
- renderdata->glTexParameteri(textype, GL_TEXTURE_MAG_FILTER, glScaleMode);
- }
-
- if (texture->format == SDL_PIXELFORMAT_NV12 ||
- texture->format == SDL_PIXELFORMAT_NV21) {
- renderdata->glBindTexture(textype, data->utexture);
- renderdata->glTexParameteri(textype, GL_TEXTURE_MIN_FILTER, glScaleMode);
- renderdata->glTexParameteri(textype, GL_TEXTURE_MAG_FILTER, glScaleMode);
- }
-#endif
-}
-
static bool GL_SetRenderTarget(SDL_Renderer *renderer, SDL_Texture *texture)
{
GL_RenderData *data = (GL_RenderData *)renderer->internal;
@@ -1120,6 +1074,23 @@ 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_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 bool SetTextureAddressMode(GL_RenderData *data, GLenum textype, SDL_TextureAddressMode addressMode)
{
switch (addressMode) {
@@ -1140,53 +1111,91 @@ static bool SetTextureAddressMode(GL_RenderData *data, GLenum textype, SDL_Textu
static bool SetCopyState(GL_RenderData *data, const SDL_RenderCommand *cmd)
{
SDL_Texture *texture = cmd->data.draw.texture;
- const GL_TextureData *texturedata = (GL_TextureData *)texture->internal;
+ GL_TextureData *texturedata = (GL_TextureData *)texture->internal;
+ const GLenum textype = data->textype;
SetDrawState(data, cmd, texturedata->shader, texturedata->shader_params);
if (texture != data->drawstate.texture) {
- const GLenum textype = data->textype;
#ifdef SDL_HAVE_YUV
if (texturedata->yuv) {
- if (data->GL_ARB_multitexture_supported) {
- data->glActiveTextureARB(GL_TEXTURE2_ARB);
- }
+ data->glActiveTextureARB(GL_TEXTURE2_ARB);
data->glBindTexture(textype, texturedata->vtexture);
- if (!SetTextureAddressMode(data, textype, cmd->data.draw.texture_address_mode)) {
+ data->glActiveTextureARB(GL_TEXTURE1_ARB);
+ data->glBindTexture(textype, texturedata->utexture);
+ }
+ if (texturedata->nv12) {
+ data->glActiveTextureARB(GL_TEXTURE1_ARB);
+ data->glBindTexture(textype, texturedata->utexture);
+ }
+#endif
+ if (data->GL_ARB_multitexture_supported) {
+ data->glActiveTextureARB(GL_TEXTURE0_ARB);
+ }
+ data->glBindTexture(textype, texturedata->texture);
+
+ data->drawstate.texture = texture;
+ }
+
+ if (cmd->data.draw.texture_scale_mode != texturedata->texture_scale_mode) {
+#ifdef SDL_HAVE_YUV
+ if (texturedata->yuv) {
+ data->glActiveTextureARB(GL_TEXTURE2);
+ if (!SetTextureScaleMode(data, textype, cmd->data.draw.texture_scale_mode)) {
return false;
}
- if (data->GL_ARB_mu
(Patch may be truncated, please check the link at the top of this post.)