diff --git a/include/SDL3/SDL_surface.h b/include/SDL3/SDL_surface.h index 603a23cd9a..7bff7cfb28 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 5ab1bf7eb0..6c591cb3f3 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; } } @@ -1964,8 +1967,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 && @@ -1973,12 +1974,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 4d87ad6a06..58692388ff 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 ccb5b3c343..f70b56170b 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 dc1a7229c0..60f646fd1e 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 06535f0ecb..946ad828a3 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 73c1dbe795..5269429154 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 63d9770d50..3bba129a67 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 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 @@ static bool METAL_CreateRenderer(SDL_Renderer *renderer, SDL_Window *window, SDL #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 d5344382aa..fecd365d07 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,41 +1111,23 @@ 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)) { - return false; - } - - if (data->GL_ARB_multitexture_supported) { - data->glActiveTextureARB(GL_TEXTURE1_ARB); - } + data->glActiveTextureARB(GL_TEXTURE1_ARB); data->glBindTexture(textype, texturedata->utexture); - - if (!SetTextureAddressMode(data, textype, cmd->data.draw.texture_address_mode)) { - return false; - } } if (texturedata->nv12) { - if (data->GL_ARB_multitexture_supported) { - data->glActiveTextureARB(GL_TEXTURE1_ARB); - } + data->glActiveTextureARB(GL_TEXTURE1_ARB); data->glBindTexture(textype, texturedata->utexture); - - if (!SetTextureAddressMode(data, textype, cmd->data.draw.texture_address_mode)) { - return false; - } } #endif if (data->GL_ARB_multitexture_supported) { @@ -1182,11 +1135,67 @@ static bool SetCopyState(GL_RenderData *data, const SDL_RenderCommand *cmd) } 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; + } + + data->glActiveTextureARB(GL_TEXTURE1); + if (!SetTextureScaleMode(data, textype, cmd->data.draw.texture_scale_mode)) { + return false; + } + + data->glActiveTextureARB(GL_TEXTURE0); + } else if (texturedata->nv12) { + data->glActiveTextureARB(GL_TEXTURE1); + if (!SetTextureScaleMode(data, textype, cmd->data.draw.texture_scale_mode)) { + return false; + } + + data->glActiveTextureARB(GL_TEXTURE0); + } +#endif + if (!SetTextureScaleMode(data, textype, cmd->data.draw.texture_scale_mode)) { + return false; + } + + texturedata->texture_scale_mode = cmd->data.draw.texture_scale_mode; + } + + if (cmd->data.draw.texture_address_mode != texturedata->texture_address_mode) { +#ifdef SDL_HAVE_YUV + if (texturedata->yuv) { + data->glActiveTextureARB(GL_TEXTURE2); + if (!SetTextureAddressMode(data, textype, cmd->data.draw.texture_address_mode)) { + return false; + } + + data->glActiveTextureARB(GL_TEXTURE1); + if (!SetTextureAddressMode(data, textype, cmd->data.draw.texture_address_mode)) { + return false; + } + + data->glActiveTextureARB(GL_TEXTURE0_ARB); + } else if (texturedata->nv12) { + data->glActiveTextureARB(GL_TEXTURE1); + if (!SetTextureAddressMode(data, textype, cmd->data.draw.texture_address_mode)) { + return false; + } + + data->glActiveTextureARB(GL_TEXTURE0); + } +#endif if (!SetTextureAddressMode(data, textype, cmd->data.draw.texture_address_mode)) { return false; } - data->drawstate.texture = texture; + texturedata->texture_address_mode = cmd->data.draw.texture_address_mode; } return true; @@ -1372,6 +1381,8 @@ static bool GL_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd, v 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; @@ -1381,7 +1392,10 @@ static bool GL_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd, v 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) { break; // can't go any further on this draw call, different texture/blendmode copy up next. } else { finalcmd = nextcmd; // we can combine copy operations here. Mark this one as the furthest okay command. @@ -1656,7 +1670,6 @@ static bool GL_CreateRenderer(SDL_Renderer *renderer, SDL_Window *window, SDL_Pr #endif renderer->LockTexture = GL_LockTexture; renderer->UnlockTexture = GL_UnlockTexture; - renderer->SetTextureScaleMode = GL_SetTextureScaleMode; renderer->SetRenderTarget = GL_SetRenderTarget; renderer->QueueSetViewport = GL_QueueNoOp; renderer->QueueSetDrawColor = GL_QueueNoOp; diff --git a/src/render/opengles2/SDL_render_gles2.c b/src/render/opengles2/SDL_render_gles2.c index 0e142a7858..7d697eea65 100644 --- a/src/render/opengles2/SDL_render_gles2.c +++ b/src/render/opengles2/SDL_render_gles2.c @@ -76,6 +76,8 @@ typedef struct GLES2_TextureData GLuint texture_u; GLuint texture_u_external; #endif + SDL_ScaleMode texture_scale_mode; + SDL_TextureAddressMode texture_address_mode; GLES2_FBOList *fbo; } GLES2_TextureData; @@ -1029,6 +1031,23 @@ static bool SetDrawState(GLES2_RenderData *data, const SDL_RenderCommand *cmd, c return true; } +static bool SetTextureScaleMode(GLES2_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(GLES2_RenderData *data, GLenum textype, SDL_TextureAddressMode addressMode) { switch (addressMode) { @@ -1051,6 +1070,7 @@ static bool SetCopyState(SDL_Renderer *renderer, const SDL_RenderCommand *cmd, v GLES2_RenderData *data = (GLES2_RenderData *)renderer->internal; GLES2_ImageSource sourceType = GLES2_IMAGESOURCE_TEXTURE_ABGR; SDL_Texture *texture = cmd->data.draw.texture; + GLES2_TextureData *tdata = (GLES2_TextureData *)texture->internal; int ret; // Pick an appropriate shader @@ -1172,19 +1192,66 @@ static bool SetCopyState(SDL_Renderer *renderer, const SDL_RenderCommand *cmd, v ret = SetDrawState(data, cmd, sourceType, vertices); if (texture != data->drawstate.texture) { - GLES2_TextureData *tdata = (GLES2_TextureData *)texture->internal; #ifdef SDL_HAVE_YUV if (tdata->yuv) { data->glActiveTexture(GL_TEXTURE2); data->glBindTexture(tdata->texture_type, tdata->texture_v); + data->glActiveTexture(GL_TEXTURE1); + data->glBindTexture(tdata->texture_type, tdata->texture_u); + + data->glActiveTexture(GL_TEXTURE0); + } else if (tdata->nv12) { + data->glActiveTexture(GL_TEXTURE1); + data->glBindTexture(tdata->texture_type, tdata->texture_u); + + data->glActiveTexture(GL_TEXTURE0); + } +#endif + data->glBindTexture(tdata->texture_type, tdata->texture); + + data->drawstate.texture = texture; + } + + if (cmd->data.draw.texture_scale_mode != tdata->texture_scale_mode) { +#ifdef SDL_HAVE_YUV + if (tdata->yuv) { + data->glActiveTexture(GL_TEXTURE2); + if (!SetTextureScaleMode(data, tdata->texture_type, cmd->data.draw.texture_scale_mode)) { + return false; + } + + data->glActiveTexture(GL_TEXTURE1); + if (!SetTextureScaleMode(data, tdata->texture_type, cmd->data.draw.texture_scale_mode)) { + return false; + } + + data->glActiveTexture(GL_TEXTURE0); + } else if (tdata->nv12) { + data->glActiveTexture(GL_TEXTURE1); + if (!SetTextureScaleMode(data, tdata->texture_type, cmd->data.draw.texture_scale_mode)) { + return false; + } + + data->glActiveTexture(GL_TEXTURE0); + } +#endif + if (!SetTextureScaleMode(data, tdata->texture_type, cmd->data.draw.texture_scale_mode)) { + return false; + } + + tdata->texture_scale_mode = cmd->data.draw.texture_scale_mode; + } + + if (cmd->data.draw.texture_address_mode != tdata->texture_address_mode) { +#ifdef SDL_HAVE_YUV + if (tdata->yuv) { + data->glActiveTexture(GL_TEXTURE2); if (!SetTextureAddressMode(data, tdata->texture_type, cmd->data.draw.texture_address_mode)) { return false; } data->glActiveTexture(GL_TEXTURE1); - data->glBindTexture(tdata->texture_type, tdata->texture_u); - if (!SetTextureAddressMode(data, tdata->texture_type, cmd->data.draw.texture_address_mode)) { return false; } @@ -1192,8 +1259,6 @@ static bool SetCopyState(SDL_Renderer *renderer, const SDL_RenderCommand *cmd, v data->glActiveTexture(GL_TEXTURE0); } else if (tdata->nv12) { data->glActiveTexture(GL_TEXTURE1); - data->glBindTexture(tdata->texture_type, tdata->texture_u); - if (!SetTextureAddressMode(data, tdata->texture_type, cmd->data.draw.texture_address_mode)) { return false; } @@ -1201,13 +1266,11 @@ static bool SetCopyState(SDL_Renderer *renderer, const SDL_RenderCommand *cmd, v data->glActiveTexture(GL_TEXTURE0); } #endif - data->glBindTexture(tdata->texture_type, tdata->texture); - if (!SetTextureAddressMode(data, tdata->texture_type, cmd->data.draw.texture_address_mode)) { return false; } - data->drawstate.texture = texture; + tdata->texture_address_mode = cmd->data.draw.texture_address_mode; } return ret; @@ -1384,6 +1447,8 @@ static bool GLES2_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; @@ -1393,7 +1458,10 @@ static bool GLES2_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) { break; // can't go any further on this draw call, different texture/blendmode copy up next. } else { finalcmd = nextcmd; // we can combine copy operations here. Mark this one as the furthest okay command. @@ -1486,7 +1554,6 @@ static bool GLES2_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SD GLES2_TextureData *data; GLenum format; GLenum type; - GLenum scaleMode; GLES2_ActivateRenderer(renderer); @@ -1544,7 +1611,8 @@ static bool GLES2_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SD data->texture_u = 0; data->texture_v = 0; #endif - 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; // Allocate a blob for image renderdata if (texture->access == SDL_TEXTUREACCESS_STREAMING) { @@ -1583,8 +1651,6 @@ static bool GLES2_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SD } renderdata->glActiveTexture(GL_TEXTURE2); renderdata->glBindTexture(data->texture_type, data->texture_v); - renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MIN_FILTER, scaleMode); - renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MAG_FILTER, scaleMode); renderdata->glTexImage2D(data->texture_type, 0, format, (texture->w + 1) / 2, (texture->h + 1) / 2, 0, format, type, NULL); SDL_SetNumberProperty(SDL_GetTextureProperties(texture), SDL_PROP_TEXTURE_OPENGLES2_TEXTURE_V_NUMBER, data->texture_v); @@ -1599,8 +1665,6 @@ static bool GLES2_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SD } renderdata->glActiveTexture(GL_TEXTURE1); renderdata->glBindTexture(data->texture_type, data->texture_u); - renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MIN_FILTER, scaleMode); - renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MAG_FILTER, scaleMode); renderdata->glTexImage2D(data->texture_type, 0, format, (texture->w + 1) / 2, (texture->h + 1) / 2, 0, format, type, NULL); if (!GL_CheckError("glTexImage2D()", renderer)) { return false; @@ -1622,8 +1686,6 @@ static bool GLES2_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SD } renderdata->glActiveTexture(GL_TEXTURE1); renderdata->glBindTexture(data->texture_type, data->texture_u); - renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MIN_FILTER, scaleMode); - renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MAG_FILTER, scaleMode); renderdata->glTexImage2D(data->texture_type, 0, GL_LUMINANCE_ALPHA, (texture->w + 1) / 2, (texture->h + 1) / 2, 0, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, NULL); if (!GL_CheckError("glTexImage2D()", renderer)) { return false; @@ -1648,8 +1710,6 @@ static bool GLES2_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SD texture->internal = data; renderdata->glActiveTexture(GL_TEXTURE0); renderdata->glBindTexture(data->texture_type, data->texture); - renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MIN_FILTER, scaleMode); - renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MAG_FILTER, scaleMode); if (texture->format != SDL_PIXELFORMAT_EXTERNAL_OES) { renderdata->glTexImage2D(data->texture_type, 0, format, texture->w, texture->h, 0, format, type, NULL); if (!GL_CheckError("glTexImage2D()", renderer)) { @@ -1900,37 +1960,6 @@ static void GLES2_UnlockTexture(SDL_Renderer *renderer, SDL_Texture *texture) GLES2_UpdateTexture(renderer, texture, &rect, tdata->pixel_data, tdata->pitch); } -static void GLES2_SetTextureScaleMode(SDL_Renderer *renderer, SDL_Texture *texture, SDL_ScaleMode scaleMode) -{ - GLES2_RenderData *renderdata = (GLES2_RenderData *)renderer->internal; - GLES2_TextureData *data = (GLES2_TextureData *)texture->internal; - GLenum glScaleMode = (scaleMode == SDL_SCALEMODE_NEAREST) ? GL_NEAREST : GL_LINEAR; - -#ifdef SDL_HAVE_YUV - if (data->yuv) { - renderdata->glActiveTexture(GL_TEXTURE2); - renderdata->glBindTexture(data->texture_type, data->texture_v); - renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MIN_FILTER, glScaleMode); - renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MAG_FILTER, glScaleMode); - - renderdata->glActiveTexture(GL_TEXTURE1); - renderdata->glBindTexture(data->texture_type, data->texture_u); - renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MIN_FILTER, glScaleMode); - renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MAG_FILTER, glScaleMode); - } else if (data->nv12) { - renderdata->glActiveTexture(GL_TEXTURE1); - renderdata->glBindTexture(data->texture_type, data->texture_u); - renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MIN_FILTER, glScaleMode); - renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MAG_FILTER, glScaleMode); - } -#endif - - renderdata->glActiveTexture(GL_TEXTURE0); - renderdata->glBindTexture(data->texture_type, data->texture); - renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MIN_FILTER, glScaleMode); - renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MAG_FILTER, glScaleMode); -} - static bool GLES2_SetRenderTarget(SDL_Renderer *renderer, SDL_Texture *texture) { GLES2_RenderData *data = (GLES2_RenderData *)renderer->internal; @@ -2151,7 +2180,6 @@ static bool GLES2_CreateRenderer(SDL_Renderer *renderer, SDL_Window *window, SDL #endif renderer->LockTexture = GLES2_LockTexture; renderer->UnlockTexture = GLES2_UnlockTexture; - renderer->SetTextureScaleMode = GLES2_SetTextureScaleMode; renderer->SetRenderTarget = GLES2_SetRenderTarget; renderer->QueueSetViewport = GLES2_QueueNoOp; renderer->QueueSetDrawColor = GLES2_QueueNoOp; diff --git a/src/render/ps2/SDL_render_ps2.c b/src/render/ps2/SDL_render_ps2.c index ddcab9e2ab..713192c908 100644 --- a/src/render/ps2/SDL_render_ps2.c +++ b/src/render/ps2/SDL_render_ps2.c @@ -195,21 +195,6 @@ static bool PS2_UpdateTexture(SDL_Renderer *renderer, SDL_Texture *texture, return true; } -static void PS2_SetTextureScaleMode(SDL_Renderer *renderer, SDL_Texture *texture, SDL_ScaleMode scaleMode) -{ - GSTEXTURE *ps2_texture = (GSTEXTURE *)texture->internal; - /* - set texture filtering according to scaleMode - supported hint values are nearest (0, default) or linear (1) - gskit scale mode is either GS_FILTER_NEAREST (good for tile-map) - or GS_FILTER_LINEAR (good for scaling) - */ - uint32_t gsKitScaleMode = (scaleMode == SDL_SCALEMODE_NEAREST - ? GS_FILTER_NEAREST - : GS_FILTER_LINEAR); - ps2_texture->Filter = gsKitScaleMode; -} - static bool PS2_SetRenderTarget(SDL_Renderer *renderer, SDL_Texture *texture) { return true; @@ -458,6 +443,16 @@ static bool PS2_RenderGeometry(SDL_Renderer *renderer, void *vertices, SDL_Rende const GSPRIMUVPOINT *verts = (GSPRIMUVPOINT *) (vertices + cmd->data.draw.first); GSTEXTURE *ps2_tex = (GSTEXTURE *)cmd->data.draw.texture->internal; + switch (cmd->data.draw.texture_scale_mode) { + case SDL_SCALEMODE_NEAREST: + ps2_tex->Filter = GS_FILTER_NEAREST; + break; + case SDL_SCALEMODE_LINEAR: + ps2_tex->Filter = GS_FILTER_LINEAR; + break; + default: + break; + } gsKit_TexManager_bind(data->gsGlobal, ps2_tex); gsKit_prim_list_triangle_goraud_texture_uv_3d(data->gsGlobal, ps2_tex, count, verts); } else { @@ -695,7 +690,6 @@ static bool PS2_CreateRenderer(SDL_Renderer *renderer, SDL_Window *window, SDL_P renderer->UpdateTexture = PS2_UpdateTexture; renderer->LockTexture = PS2_LockTexture; renderer->UnlockTexture = PS2_UnlockTexture; - renderer->SetTextureScaleMode = PS2_SetTextureScaleMode; renderer->SetRenderTarget = PS2_SetRenderTarget; renderer->QueueSetViewport = PS2_QueueSetViewport; renderer->QueueSetDrawColor = PS2_QueueNoOp; diff --git a/src/render/psp/SDL_render_psp.c b/src/render/psp/SDL_render_psp.c index 3ce5036fc4..14f43ba8cf 100644 --- a/src/render/psp/SDL_render_psp.c +++ b/src/render/psp/SDL_render_psp.c @@ -75,6 +75,8 @@ typedef struct unsigned int color; int shadeModel; SDL_Texture *texture; + SDL_ScaleMode texture_scale_mode; + SDL_TextureAddressMode texture_address_mode; } PSP_BlendState; typedef struct @@ -538,20 +540,44 @@ static bool TextureShouldSwizzle(PSP_TextureData *psp_texture, SDL_Texture *text return !((texture->access == SDL_TEXTUREACCESS_TARGET) && InVram(psp_texture->data)) && texture->access != SDL_TEXTUREACCESS_STREAMING && (texture->w >= 16 || texture->h >= 16); } +static void SetTextureAddressMode(SDL_TextureAddressMode addressMode) +{ + switch (addressMode) { + case SDL_TEXTURE_ADDRESS_CLAMP: + sceGuTexWrap(GU_CLAMP, GU_CLAMP); + break; + case SDL_TEXTURE_ADDRESS_WRAP: + sceGuTexWrap(GU_REPEAT, GU_REPEAT); + break; + default: + break; + } +} + +static void SetTextureScaleMode(SDL_ScaleMode scaleMode) +{ + switch (scaleMode) { + case SDL_SCALEMODE_NEAREST: + sceGuTexFilter(GU_NEAREST, GU_NEAREST); + break; + case SDL_SCALEMODE_LINEAR: + sceGuTexFilter(GU_LINEAR, GU_LINEAR); + break; + default: + break; + } +} + static void TextureActivate(SDL_Texture *texture) { PSP_TextureData *psp_texture = (PSP_TextureData *)texture->internal; - int scaleMode = (texture->scaleMode == SDL_SCALEMODE_NEAREST) ? GU_NEAREST : GU_LINEAR; // Swizzling is useless with small textures. if (TextureShouldSwizzle(psp_texture, texture)) { TextureSwizzle(psp_texture, NULL); } - sceGuTexWrap(GU_REPEAT, GU_REPEAT); sceGuTexMode(psp_texture->format, 0, 0, psp_texture->swizzled); - sceGuTexFilter(scaleMode, scaleMode); // GU_NEAREST good for tile-map - // GU_LINEAR good for scaling sceGuTexImage(0, psp_texture->textureWidth, psp_texture->textureHeight, psp_texture->textureWidth, psp_texture->data); } @@ -608,11 +634,6 @@ static void PSP_UnlockTexture(SDL_Renderer *renderer, SDL_Texture *texture) PSP_UpdateTexture(renderer, texture, &rect, psp_texture->data, psp_texture->pitch); } -static void PSP_SetTextureScaleMode(SDL_Renderer *renderer, SDL_Texture *texture, SDL_ScaleMode scaleMode) -{ - // Nothing to do because TextureActivate takes care of it -} - static bool PSP_SetRenderTarget(SDL_Renderer *renderer, SDL_Texture *texture) { return true; @@ -1034,6 +1055,11 @@ static void PSP_SetBlendState(PSP_RenderData *data, PSP_BlendState *state) } } + if (state->texture) { + SetTextureScaleMode(state->texture_scale_mode); + SetTextureAddressMode(state->texture_address_mode); + } + *current = *state; } @@ -1117,6 +1143,8 @@ static bool PSP_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd, PSP_BlendState state = { .color = drawstate.color, .texture = NULL, + .texture_scale_mode = SDL_SCALEMODE_INVALID, + .texture_address_mode = SDL_TEXTURE_ADDRESS_INVALID, .mode = cmd->data.draw.blend, .shadeModel = GU_FLAT }; @@ -1132,6 +1160,8 @@ static bool PSP_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd, PSP_BlendState state = { .color = drawstate.color, .texture = NULL, + .texture_scale_mode = SDL_SCALEMODE_INVALID, + .texture_address_mode = SDL_TEXTURE_ADDRESS_INVALID, .mode = cmd->data.draw.blend, .shadeModel = GU_FLAT }; @@ -1147,6 +1177,8 @@ static bool PSP_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd, PSP_BlendState state = { .color = drawstate.color, .texture = NULL, + .texture_scale_mode = SDL_SCALEMODE_INVALID, + .texture_address_mode = SDL_TEXTURE_ADDRESS_INVALID, .mode = cmd->data.draw.blend, .shadeModel = GU_FLAT }; @@ -1162,6 +1194,8 @@ static bool PSP_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd, PSP_BlendState state = { .color = drawstate.color, .texture = cmd->data.draw.texture, + .texture_scale_mode = cmd->data.draw.texture_scale_mode, + .texture_address_mode = cmd->data.draw.texture_address_mode, .mode = cmd->data.draw.blend, .shadeModel = GU_SMOOTH }; @@ -1176,6 +1210,8 @@ static bool PSP_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd, PSP_BlendState state = { .color = drawstate.color, .texture = cmd->data.draw.texture, + .texture_scale_mode = cmd->data.draw.texture_scale_mode, + .texture_address_mode = cmd->data.draw.texture_address_mode, .mode = cmd->data.draw.blend, .shadeModel = GU_SMOOTH }; @@ -1197,11 +1233,12 @@ static bool PSP_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd, const VertTCV *verts = (VertTCV *)(gpumem + cmd->data.draw.first); PSP_BlendState state = { .color = drawstate.color, - .texture = NULL, + .texture = cmd->data.draw.texture, + .texture_scale_mode = cmd->data.draw.texture_scale_mode, + .texture_address_mode = cmd->data.draw.texture_address_mode, .mode = cmd->data.draw.blend, - .shadeModel = GU_FLAT + .shadeModel = GU_SMOOTH }; - TextureActivate(cmd->data.draw.texture); PSP_SetBlendState(data, &state); sceGuDrawArray(GU_TRIANGLES, GU_TEXTURE_32BITF | GU_COLOR_8888 | GU_VERTEX_32BITF | GU_TRANSFORM_2D, count, 0, verts); } @@ -1310,7 +1347,6 @@ static bool PSP_CreateRenderer(SDL_Renderer *renderer, SDL_Window *window, SDL_P renderer->UpdateTexture = PSP_UpdateTexture; renderer->LockTexture = PSP_LockTexture; renderer->UnlockTexture = PSP_UnlockTexture; - renderer->SetTextureScaleMode = PSP_SetTextureScaleMode; renderer->SetRenderTarget = PSP_SetRenderTarget; renderer->QueueSetViewport = PSP_QueueNoOp; renderer->QueueSetDrawColor = PSP_QueueNoOp; diff --git a/src/render/software/SDL_render_sw.c b/src/render/software/SDL_render_sw.c index 2231724a7a..37359be5a9 100644 --- a/src/render/software/SDL_render_sw.c +++ b/src/render/software/SDL_render_sw.c @@ -171,10 +171,6 @@ static void SW_UnlockTexture(SDL_Renderer *renderer, SDL_Texture *texture) { } -static void SW_SetTextureScaleMode(SDL_Renderer *renderer, SDL_Texture *texture, SDL_ScaleMode scaleMode) -{ -} - static bool SW_SetRenderTarget(SDL_Renderer *renderer, SDL_Texture *texture) { SW_RenderData *data = (SW_RenderData *)renderer->internal; @@ -317,7 +313,7 @@ static bool Blit_to_Screen(SDL_Surface *src, SDL_Rect *srcrect, SDL_Surface *sur static bool SW_RenderCopyEx(SDL_Renderer *renderer, SDL_Surface *surface, SDL_Texture *texture, const SDL_Rect *srcrect, const SDL_Rect *final_rect, - const double angle, const SDL_FPoint *center, const SDL_FlipMode flip, float scale_x, float scale_y) + const double angle, const SDL_FPoint *center, const SDL_FlipMode flip, float scale_x, float scale_y, const SDL_ScaleMode scaleMode) { SDL_Surface *src = (SDL_Surface *)texture->internal; SDL_Rect tmp_rect; @@ -412,7 +408,7 @@ static bool SW_RenderCopyEx(SDL_Renderer *renderer, SDL_Surface *surface, SDL_Te result = false; } else { SDL_SetSurfaceBlendMode(src_clone, SDL_BLENDMODE_NONE); - result = SDL_BlitSurfaceScaled(src_clone, srcrect, src_scaled, &scale_rect, texture->scaleMode); + result = SDL_BlitSurfaceScaled(src_clone, srcrect, src_scaled, &scale_rect, scaleMode); SDL_DestroySurface(src_clone); src_clone = src_scaled; src_scaled = NULL; @@ -429,7 +425,7 @@ static bool SW_RenderCopyEx(SDL_Renderer *renderer, SDL_Surface *surface, SDL_Te SDLgfx_rotozoomSurfaceSizeTrig(tmp_rect.w, tmp_rect.h, angle, center, &rect_dest, &cangle, &sangle); src_rotated = SDLgfx_rotateSurface(src_clone, angle, - (texture->scaleMode == SDL_SCALEMODE_NEAREST) ? 0 : 1, flip & SDL_FLIP_HORIZONTAL, flip & SDL_FLIP_VERTICAL, + (scaleMode == SDL_SCALEMODE_NEAREST) ? 0 : 1, flip & SDL_FLIP_HORIZONTAL, flip & SDL_FLIP_VERTICAL, &rect_dest, cangle, sangle, center); if (!src_rotated) { result = false; @@ -460,7 +456,7 @@ static bool SW_RenderCopyEx(SDL_Renderer *renderer, SDL_Surface *surface, SDL_Te SDL_SetSurfaceColorMod(src_rotated, rMod, gMod, bMod); } // Renderer scaling, if needed - result = Blit_to_Screen(src_rotated, NULL, surface, &tmp_rect, scale_x, scale_y, texture->scaleMode); + result = Blit_to_Screen(src_rotated, NULL, surface, &tmp_rect, scale_x, scale_y, scaleMode); } else { /* The NONE blend mode requires three steps to get the pixels onto the destination surface. * First, the area where the rotated pixels will be blitted to get set to zero. @@ -470,7 +466,7 @@ static bool SW_RenderCopyEx(SDL_Renderer *renderer, SDL_Surface *surface, SDL_Te SDL_Rect mask_rect = tmp_rect; SDL_SetSurfaceBlendMode(mask_rotated, SDL_BLENDMODE_NONE); // Renderer scaling, if needed - result = Blit_to_Screen(mask_rotated, NULL, surface, &mask_rect, scale_x, scale_y, texture->scaleMode); + result = Blit_to_Screen(mask_rotated, NULL, surface, &mask_rect, scale_x, scale_y, scaleMode); if (result) { /* The next step copies the alpha value. This is done with the BLEND blend mode and * by modulating the source colors with 0. Since the destination is all zeros, this @@ -479,7 +475,7 @@ static bool SW_RenderCopyEx(SDL_Renderer *renderer, SDL_Surface *surface, SDL_Te SDL_SetSurfaceColorMod(src_rotated, 0, 0, 0); mask_rect = tmp_rect; // Renderer scaling, if needed - result = Blit_to_Screen(src_rotated, NULL, surface, &mask_rect, scale_x, scale_y, texture->scaleMode); + result = Blit_to_Screen(src_rotated, NULL, surface, &mask_rect, scale_x, scale_y, scaleMode); if (result) { /* The last step gets the color values in place. The ADD blend mode simply adds them to * the destination (where the color values are all zero). However, because the ADD blend @@ -492,7 +488,7 @@ static bool SW_RenderCopyEx(SDL_Renderer *renderer, SDL_Surface *surface, SDL_Te } else { SDL_SetSurfaceBlendMode(src_rotated_rgb, SDL_BLENDMODE_ADD); // Renderer scaling, if needed - result = Blit_to_Screen(src_rotated_rgb, NULL, surface, &tmp_rect, scale_x, scale_y, texture->scaleMode); + result = Blit_to_Screen(src_rotated_rgb, NULL, surface, &tmp_rect, scale_x, scale_y, scaleMode); SDL_DestroySurface(src_rotated_rgb); } } @@ -858,7 +854,7 @@ static bool SW_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd, v SDL_SetSurfaceColorMod(src, 255, 255, 255); SDL_SetSurfaceAlphaMod(src, 255); - SDL_BlitSurfaceScaled(src, srcrect, tmp, &r, texture->scaleMode); + SDL_BlitSurfaceScaled(src, srcrect, tmp, &r, cmd->data.draw.texture_scale_mode); SDL_SetSurfaceColorMod(tmp, rMod, gMod, bMod); SDL_SetSurfaceAlphaMod(tmp, alphaMod); @@ -869,7 +865,7 @@ static bool SW_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd, v // No need to set back r/g/b/a/blendmode to 'src' since it's done in PrepTextureForCopy() } } else { - SDL_BlitSurfaceScaled(src, srcrect, surface, dstrect, texture->scaleMode); + SDL_BlitSurfaceScaled(src, srcrect, surface, dstrect, cmd->data.draw.texture_scale_mode); } } break; @@ -889,7 +885,7 @@ static bool SW_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd, v SW_RenderCopyEx(renderer, surface, cmd->data.draw.texture, ©data->srcrect, ©data->dstrect, copydata->angle, ©data->center, copydata->flip, - copydata->scale_x, copydata->scale_y); + copydata->scale_x, copydata->scale_y, cmd->data.draw.texture_scale_mode); break; } @@ -1135,7 +1131,6 @@ bool SW_CreateRendererForSurface(SDL_Renderer *renderer, SDL_Surface *surface, S renderer->UpdateTexture = SW_UpdateTexture; renderer->LockTexture = SW_LockTexture; renderer->UnlockTexture = SW_UnlockTexture; - renderer->SetTextureScaleMode = SW_SetTextureScaleMode; renderer->SetRenderTarget = SW_SetRenderTarget; renderer->QueueSetViewport = SW_QueueNoOp; renderer->QueueSetDrawColor = SW_QueueNoOp; diff --git a/src/render/vitagxm/SDL_render_vita_gxm.c b/src/render/vitagxm/SDL_render_vita_gxm.c index acf31c3db2..c992135f36 100644 --- a/src/render/vitagxm/SDL_render_vita_gxm.c +++ b/src/render/vitagxm/SDL_render_vita_gxm.c @@ -70,8 +70,6 @@ static bool VITA_GXM_LockTexture(SDL_Renderer *renderer, SDL_Texture *texture, static void VITA_GXM_UnlockTexture(SDL_Renderer *renderer, SDL_Texture *texture); -static void VITA_GXM_SetTextureScaleMode(SDL_Renderer *renderer, SDL_Texture *texture, SDL_ScaleMode scaleMode); - static bool VITA_GXM_SetRenderTarget(SDL_Renderer *renderer, SDL_Texture *texture); @@ -216,7 +214,6 @@ static bool VITA_GXM_CreateRenderer(SDL_Renderer *renderer, SDL_Window *window, #endif renderer->LockTexture = VITA_GXM_LockTexture; renderer->UnlockTexture = VITA_GXM_UnlockTexture; - renderer->SetTextureScaleMode = VITA_GXM_SetTextureScaleMode; renderer->SetRenderTarget = VITA_GXM_SetRenderTarget; renderer->QueueSetViewport = VITA_GXM_QueueNoOp; renderer->QueueSetDrawColor = VITA_GXM_QueueSetDrawColor; @@ -295,9 +292,10 @@ static bool VITA_GXM_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, return SDL_OutOfMemory(); } - texture->internal = vita_texture; + vita_texture->scale_mode = SDL_SCALEMODE_INVALID; + vita_texture->address_mode = SDL_TEXTURE_ADDRESS_INVALID; - VITA_GXM_SetTextureScaleMode(renderer, texture, texture->scaleMode); + texture->internal = vita_texture; #ifdef SDL_HAVE_YUV vita_texture->yuv = ((texture->format == SDL_PIXELFORMAT_IYUV) || (texture->format == SDL_PIXELFORMAT_YV12)); @@ -582,25 +580,6 @@ static void VITA_GXM_UnlockTexture(SDL_Renderer *renderer, SDL_Texture *texture) // This really improves framerate when using lock/unlock. } -static void VITA_GXM_SetTextureScaleMode(SDL_Renderer *renderer, SDL_Texture *texture, SDL_ScaleMode scaleMode) -{ - VITA_GXM_TextureData *vita_texture = (VITA_GXM_TextureData *)texture->internal; - - /* - set texture filtering according to scaleMode - supported hint values are nearest (0, default) or linear (1) - vitaScaleMode is either SCE_GXM_TEXTURE_FILTER_POINT (good for tile-map) - or SCE_GXM_TEXTURE_FILTER_LINEAR (good for scaling) - */ - - int vitaScaleMode = (scaleMode == SDL_SCALEMODE_NEAREST - ? SCE_GXM_TEXTURE_FILTER_POINT - : SCE_GXM_TEXTURE_FILTER_LINEAR); - gxm_texture_set_filters(vita_texture->tex, vitaScaleMode, vitaScaleMode); - - return; -} - static bool VITA_GXM_SetRenderTarget(SDL_Renderer *renderer, SDL_Texture *texture) { return true; @@ -909,9 +888,41 @@ static bool SetDrawState(VITA_GXM_RenderData *data, const SDL_RenderCommand *cmd } } + if (texture) { + VITA_GXM_TextureData *vita_texture = (VITA_GXM_TextureData *)texture->internal; + + if (cmd->data.draw.texture_scale_mode != vita_texture->scale_mode) { + switch (cmd->data.draw.texture_scale_mode) { + case SDL_SCALEMODE_NEAREST: + gxm_texture_set_filters(vita_texture->tex, SCE_GXM_TEXTURE_FILTER_POINT, SCE_GXM_TEXTURE_FILTER_POINT); + break; + case SDL_SCALEMODE_LINEAR: + gxm_texture_set_filters(vita_texture->tex, SCE_GXM_TEXTURE_FILTER_LINEAR, SCE_GXM_TEXTURE_FILTER_LINEAR); + break; + default: + break; + } + vita_texture->scale_mode = cmd->data.draw.texture_scale_mode; + } + + if (cmd->data.draw.texture_address_mode != vita_texture->address_mode) { + switch (cmd->data.draw.texture_address_mode) { + case SDL_TEXTURE_ADDRESS_CLAMP: + gxm_texture_set_address_mode(vita_texture->tex, SCE_GXM_TEXTURE_ADDR_CLAMP, SCE_GXM_TEXTURE_ADDR_CLAMP); + break; + case SDL_TEXTURE_ADDRESS_WRAP: + gxm_texture_set_address_mode(vita_texture->tex, SCE_GXM_TEXTURE_ADDR_REPEAT, SCE_GXM_TEXTURE_ADDR_REPEAT); + break; + default: + break; + } + vita_texture->address_mode = cmd->data.draw.texture_address_mode; + } + } + if (texture != data->drawstate.texture) { if (texture) { - VITA_GXM_TextureData *vita_texture = (VITA_GXM_TextureData *)cmd->data.draw.texture->internal; + VITA_GXM_TextureData *vita_texture = (VITA_GXM_TextureData *)texture->internal; sceGxmSetFragmentTexture(data->gxm_context, 0, &vita_texture->tex->gxm_tex); } data->drawstate.texture = texture; diff --git a/src/render/vitagxm/SDL_render_vita_gxm_tools.c b/src/render/vitagxm/SDL_render_vita_gxm_tools.c index 9140a62ca6..48af7b8f69 100644 --- a/src/render/vitagxm/SDL_render_vita_gxm_tools.c +++ b/src/render/vitagxm/SDL_render_vita_gxm_tools.c @@ -1122,6 +1122,12 @@ gxm_texture *create_gxm_texture(VITA_GXM_RenderData *data, unsigned int w, unsig return texture; } +void gxm_texture_set_address_mode(gxm_texture *texture, SceGxmTextureAddrMode u_mode, SceGxmTextureAddrMode v_mode) +{ + sceGxmTextureSetUAddrMode(&texture->gxm_tex, u_mode); + sceGxmTextureSetVAddrMode(&texture->gxm_tex, v_mode); +} + void gxm_texture_set_filters(gxm_texture *texture, SceGxmTextureFilter min_filter, SceGxmTextureFilter mag_filter) { sceGxmTextureSetMinFilter(&texture->gxm_tex, min_filter); diff --git a/src/render/vitagxm/SDL_render_vita_gxm_tools.h b/src/render/vitagxm/SDL_render_vita_gxm_tools.h index 023f859892..36c6f400be 100644 --- a/src/render/vitagxm/SDL_render_vita_gxm_tools.h +++ b/src/render/vitagxm/SDL_render_vita_gxm_tools.h @@ -49,6 +49,7 @@ void gxm_finish(SDL_Renderer *renderer); gxm_texture *create_gxm_texture(VITA_GXM_RenderData *data, unsigned int w, unsigned int h, SceGxmTextureFormat format, unsigned int isRenderTarget, unsigned int *return_w, unsigned int *return_h, unsigned int *return_pitch, float *return_wscale); void free_gxm_texture(VITA_GXM_RenderData *data, gxm_texture *texture); +void gxm_texture_set_address_mode(gxm_texture *texture, SceGxmTextureAddrMode u_mode, SceGxmTextureAddrMode v_mode); void gxm_texture_set_filters(gxm_texture *texture, SceGxmTextureFilter min_filter, SceGxmTextureFilter mag_filter); SceGxmTextureFormat gxm_texture_get_format(const gxm_texture *texture); diff --git a/src/render/vitagxm/SDL_render_vita_gxm_types.h b/src/render/vitagxm/SDL_render_vita_gxm_types.h index 19962c7359..e23137f632 100644 --- a/src/render/vitagxm/SDL_render_vita_gxm_types.h +++ b/src/render/vitagxm/SDL_render_vita_gxm_types.h @@ -205,6 +205,8 @@ typedef struct float wscale; bool yuv; bool nv12; + SDL_ScaleMode scale_mode; + SDL_TextureAddressMode address_mode; } VITA_GXM_TextureData; #endif // SDL_RENDER_VITA_GXM_TYPES_H diff --git a/src/render/vulkan/SDL_render_vulkan.c b/src/render/vulkan/SDL_render_vulkan.c index d2157c30a7..65af0a527f 100644 --- a/src/render/vulkan/SDL_render_vulkan.c +++ b/src/render/vulkan/SDL_render_vulkan.c @@ -255,7 +255,6 @@ typedef struct VkRenderPass mainRenderpasses[VULKAN_RENDERPASS_COUNT]; VkFramebuffer mainFramebuffer; VULKAN_Buffer stagingBuffer; - VkFilter scaleMode; SDL_Rect lockedRect; int width; int height; @@ -2600,7 +2599,6 @@ static bool VULKAN_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, S } else { textureData->shader = SHADER_ADVANCED; } - textureData->scaleMode = (texture->scaleMode == SDL_SCALEMODE_NEAREST) ? VK_FILTER_NEAREST : VK_FILTER_LINEAR; #ifdef SDL_HAVE_YUV // YUV textures must have even width and height. Also create Ycbcr conversion @@ -3093,17 +3091,6 @@ static void VULKAN_UnlockTexture(SDL_Renderer *renderer, SDL_Texture *texture) VULKAN_DestroyBuffer(rendererData, &textureData->stagingBuffer); } -static void VULKAN_SetTextureScaleMode(SDL_Renderer *renderer, SDL_Texture *texture, SDL_ScaleMode scaleMode) -{ - VULKAN_TextureData *textureData = (VULKAN_TextureData *)texture->internal; - - if (!textureData) { - return; - } - - textureData->scaleMode = (scaleMode == SDL_SCALEMODE_NEAREST) ? VK_FILTER_NEAREST : VK_FILTER_LINEAR; -} - static bool VULKAN_SetRenderTarget(SDL_Renderer *renderer, SDL_Texture *texture) { VULKAN_RenderData *rendererData = (VULKAN_RenderData *)renderer->internal; @@ -3775,7 +3762,7 @@ static bool VULKAN_SetCopyState(SDL_Renderer *renderer, const SDL_RenderCommand VULKAN_SetupShaderConstants(renderer, cmd, texture, &constants); - switch (textureData->scaleMode) { + switch (cmd->data.draw.texture_scale_mode) { case VK_FILTER_NEAREST: switch (cmd->data.draw.texture_address_mode) { case SDL_TEXTURE_ADDRESS_CLAMP: @@ -3801,7 +3788,7 @@ static bool VULKAN_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); } if (textureData->mainImage.imageLayout != VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) { @@ -4290,7 +4277,6 @@ static bool VULKAN_CreateRenderer(SDL_Renderer *renderer, SDL_Window *window, SD #endif renderer->LockTexture = VULKAN_LockTexture; renderer->UnlockTexture = VULKAN_UnlockTexture; - renderer->SetTextureScaleMode = VULKAN_SetTextureScaleMode; renderer->SetRenderTarget = VULKAN_SetRenderTarget; renderer->QueueSetViewport = VULKAN_QueueNoOp; renderer->QueueSetDrawColor = VULKAN_QueueNoOp; diff --git a/test/testautomation_render.c b/test/testautomation_render.c index 1275097e9e..7fdcd0af22 100644 --- a/test/testautomation_render.c +++ b/test/testautomation_render.c @@ -1695,6 +1695,132 @@ static int SDLCALL render_testUVWrapping(void *arg) return TEST_COMPLETED; } +/** + * Tests texture state changes + */ +static int SDLCALL render_testTextureState(void *arg) +{ + const Uint8 pixels[8] = { + 0x00, 0x00, 0x00, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF + }; + const SDL_Color expected[] = { + /* Step 0: plain copy */ + { 0x00, 0x00, 0x00, 0xFF }, + { 0xFF, 0xFF, 0xFF, 0xFF }, + /* Step 1: color mod to red */ + { 0x00, 0x00, 0x00, 0xFF }, + { 0xFF, 0x00, 0x00, 0xFF }, + /* Step 2: alpha mod to 128 (cleared to green) */ + { 0x00, 0x7F, 0x00, 0xFF }, + { 0x80, 0xFF, 0x80, 0xFF }, + /* Step 3: nearest stretch */ + { 0xFF, 0xFF, 0xFF, 0xFF }, + { 0x00, 0xFF, 0x00, 0xFF }, + /* Step 4: linear stretch */ + { 0x80, 0x80, 0x80, 0xFF }, + { 0x00, 0xFF, 0x00, 0xFF }, + }; + SDL_Texture *texture; + SDL_Rect rect; + SDL_FRect dst; + int i; + + /* Clear surface to green */ + SDL_SetRenderDrawColor(renderer, 0, 255, 0, SDL_ALPHA_OPAQUE); + SDL_RenderClear(renderer); + + /* Create 2-pixel surface. */ + texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA32, SDL_TEXTUREACCESS_STATIC, 2, 1); + SDLTest_AssertCheck(texture != NULL, "Verify SDL_CreateTexture() result"); + if (texture == NULL) { + return TEST_ABORTED; + } + SDL_UpdateTexture(texture, NULL, pixels, sizeof(pixels)); + + dst.x = 0.0f; + dst.y = 0.0f; + dst.w = 2.0f; + dst.h = 1.0f; + + /* Step 0: plain copy */ + SDL_RenderTexture(renderer, texture, NULL, &dst); + dst.y += 1; + + /* Step 1: color mod to red */ + SDL_SetTextureColorMod(texture, 0xFF, 0x00, 0x00); + SDL_RenderTexture(renderer, texture, NULL, &dst); + SDL_SetTextureColorMod(texture, 0xFF, 0xFF, 0xFF); + dst.y += 1; + + /* Step 2: alpha mod to 128 */ + SDL_SetTextureAlphaMod(texture, 0x80); + SDL_RenderTexture(renderer, texture, NULL, &dst); + SDL_SetTextureAlphaMod(texture, 0xFF); + dst.y += 1; + + /* Step 3: nearest stretch */ + dst.w = 1; + SDL_SetTextureScaleMode(texture, SDL_SCALEMODE_NEAREST); + SDL_RenderTexture(renderer, texture, NULL, &dst); + dst.y += 1; + + /* Step 4: linear stretch */ + dst.w = 1; + SDL_SetTextureScaleMode(texture, SDL_SCALEMODE_LINEAR); + SDL_RenderTexture(renderer, texture, NULL, &dst); + dst.y += 1; + + /* Verify results */ + rect.x = 0; + rect.y = 0; + rect.w = 2; + rect.h = 1; + for (i = 0; i < SDL_arraysize(expected); ) { + const int MAX_DELTA = 1; + SDL_Color actual; + int deltaR, deltaG, deltaB, deltaA; + SDL_Surface *surface = SDL_RenderReadPixels(renderer, &rect); + + SDL_ReadSurfacePixel(surface, 0, 0, &actual.r, &actual.g, &actual.b, &actual.a); + deltaR = (actual.r - expected[i].r); + deltaG = (actual.g - expected[i].g); + deltaB = (actual.b - expected[i].b); + deltaA = (actual.a - expected[i].a); + SDLTest_AssertCheck(SDL_abs(deltaR) <= MAX_DELTA && + SDL_abs(deltaG) <= MAX_DELTA && + SDL_abs(deltaB) <= MAX_DELTA && + SDL_abs(deltaA) <= MAX_DELTA, + "Validate left pixel at step %d, expected %d,%d,%d,%d, got %d,%d,%d,%d", i/2, + expected[i].r, expected[i].g, expected[i].b, expected[i].a, + actual.r, actual.g, actual.b, actual.a); + ++i; + + SDL_ReadSurfacePixel(surface, 1, 0, &actual.r, &actual.g, &actual.b, &actual.a); + deltaR = (actual.r - expected[i].r); + deltaG = (actual.g - expected[i].g); + deltaB = (actual.b - expected[i].b); + deltaA = (actual.a - expected[i].a); + SDLTest_AssertCheck(SDL_abs(deltaR) <= MAX_DELTA && + SDL_abs(deltaG) <= MAX_DELTA && + SDL_abs(deltaB) <= MAX_DELTA && + SDL_abs(deltaA) <= MAX_DELTA, + "Validate right pixel at step %d, expected %d,%d,%d,%d, got %d,%d,%d,%d", i/2, + expected[i].r, expected[i].g, expected[i].b, expected[i].a, + actual.r, actual.g, actual.b, actual.a); + ++i; + + SDL_DestroySurface(surface); + + rect.y += 1; + } + + /* Clean up. */ + SDL_DestroyTexture(texture); + + return TEST_COMPLETED; +} + /* ================= Test References ================== */ /* Render test cases */ @@ -1750,6 +1876,10 @@ static const SDLTest_TestCaseReference renderTestUVWrapping = { render_testUVWrapping, "render_testUVWrapping", "Tests geometry UV wrapping", TEST_ENABLED }; +static const SDLTest_TestCaseReference renderTestTextureState = { + render_testTextureState, "render_testTextureState", "Tests texture state changes", TEST_ENABLED +}; + /* Sequence of Render test cases */ static const SDLTest_TestCaseReference *renderTests[] = { &renderTestGetNumRenderDrivers, @@ -1765,6 +1895,7 @@ static const SDLTest_TestCaseReference *renderTests[] = { &renderTestClipRect, &renderTestLogicalSize, &renderTestUVWrapping, + &renderTestTextureState, NULL };