diff --git a/include/SDL_render.h b/include/SDL_render.h index c2a995afb..f98c18437 100644 --- a/include/SDL_render.h +++ b/include/SDL_render.h @@ -85,6 +85,16 @@ typedef struct SDL_RendererInfo int max_texture_height; /**< The maximum texture height */ } SDL_RendererInfo; +/** + * \brief The scaling mode for a texture. + */ +typedef enum +{ + SDL_ScaleModeNearest, /**< nearest pixel sampling */ + SDL_ScaleModeLinear, /**< linear filtering */ + SDL_ScaleModeBest /**< anisotropic filtering */ +} SDL_ScaleMode; + /** * \brief The access pattern allowed for a texture. */ @@ -366,6 +376,35 @@ extern DECLSPEC int SDLCALL SDL_SetTextureBlendMode(SDL_Texture * texture, extern DECLSPEC int SDLCALL SDL_GetTextureBlendMode(SDL_Texture * texture, SDL_BlendMode *blendMode); +/** + * \brief Set the scale mode used for texture scale operations. + * + * \param texture The texture to update. + * \param scaleMode ::SDL_ScaleMode to use for texture scaling. + * + * \return 0 on success, or -1 if the texture is not valid. + * + * \note If the scale mode is not supported, the closest supported mode is + * chosen. + * + * \sa SDL_GetTextureScaleMode() + */ +extern DECLSPEC int SDLCALL SDL_SetTextureScaleMode(SDL_Texture * texture, + SDL_ScaleMode scaleMode); + +/** + * \brief Get the scale mode used for texture scale operations. + * + * \param texture The texture to query. + * \param scaleMode A pointer filled in with the current scale mode. + * + * \return 0 on success, or -1 if the texture is not valid. + * + * \sa SDL_SetTextureScaleMode() + */ +extern DECLSPEC int SDLCALL SDL_GetTextureScaleMode(SDL_Texture * texture, + SDL_ScaleMode *scaleMode); + /** * \brief Update the given texture rectangle with new pixel data. * diff --git a/src/dynapi/SDL_dynapi_overrides.h b/src/dynapi/SDL_dynapi_overrides.h index c391ecf56..91eac25e1 100644 --- a/src/dynapi/SDL_dynapi_overrides.h +++ b/src/dynapi/SDL_dynapi_overrides.h @@ -737,3 +737,5 @@ #define SDL_GameControllerSetPlayerIndex SDL_GameControllerSetPlayerIndex_REAL #define SDL_JoystickFromPlayerIndex SDL_JoystickFromPlayerIndex_REAL #define SDL_JoystickSetPlayerIndex SDL_JoystickSetPlayerIndex_REAL +#define SDL_SetTextureScaleMode SDL_SetTextureScaleMode_REAL +#define SDL_GetTextureScaleMode SDL_GetTextureScaleMode_REAL diff --git a/src/dynapi/SDL_dynapi_procs.h b/src/dynapi/SDL_dynapi_procs.h index 2aa438d6c..5ceba2a6c 100644 --- a/src/dynapi/SDL_dynapi_procs.h +++ b/src/dynapi/SDL_dynapi_procs.h @@ -793,3 +793,5 @@ SDL_DYNAPI_PROC(SDL_GameController*,SDL_GameControllerFromPlayerIndex,(int a),(a SDL_DYNAPI_PROC(void,SDL_GameControllerSetPlayerIndex,(SDL_GameController *a, int b),(a,b),) SDL_DYNAPI_PROC(SDL_Joystick*,SDL_JoystickFromPlayerIndex,(int a),(a),return) SDL_DYNAPI_PROC(void,SDL_JoystickSetPlayerIndex,(SDL_Joystick *a, int b),(a,b),) +SDL_DYNAPI_PROC(int,SDL_SetTextureScaleMode,(SDL_Texture *a, SDL_ScaleMode b),(a,b),return) +SDL_DYNAPI_PROC(int,SDL_GetTextureScaleMode,(SDL_Texture *a, SDL_ScaleMode *b),(a,b),return) diff --git a/src/render/SDL_render.c b/src/render/SDL_render.c index f223d92fc..1ff0548e1 100644 --- a/src/render/SDL_render.c +++ b/src/render/SDL_render.c @@ -1388,6 +1388,33 @@ SDL_GetTextureBlendMode(SDL_Texture * texture, SDL_BlendMode *blendMode) return 0; } +int +SDL_SetTextureScaleMode(SDL_Texture * texture, SDL_ScaleMode scaleMode) +{ + SDL_Renderer *renderer; + + CHECK_TEXTURE_MAGIC(texture, -1); + + renderer = texture->renderer; + renderer->SetTextureScaleMode(renderer, texture, scaleMode); + texture->scaleMode = scaleMode; + if (texture->native) { + return SDL_SetTextureScaleMode(texture->native, scaleMode); + } + return 0; +} + +int +SDL_GetTextureScaleMode(SDL_Texture * texture, SDL_ScaleMode *scaleMode) +{ + CHECK_TEXTURE_MAGIC(texture, -1); + + if (scaleMode) { + *scaleMode = texture->scaleMode; + } + return 0; +} + static int SDL_UpdateTextureYUV(SDL_Texture * texture, const SDL_Rect * rect, const void *pixels, int pitch) diff --git a/src/render/SDL_sysrender.h b/src/render/SDL_sysrender.h index a93e21c58..b76c570bf 100644 --- a/src/render/SDL_sysrender.h +++ b/src/render/SDL_sysrender.h @@ -32,13 +32,6 @@ typedef struct SDL_RenderDriver SDL_RenderDriver; -typedef enum -{ - SDL_ScaleModeNearest, - SDL_ScaleModeLinear, - SDL_ScaleModeBest -} SDL_ScaleMode; - /* Define the SDL texture structure */ struct SDL_Texture { @@ -146,6 +139,7 @@ struct SDL_Renderer int (*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); int (*SetRenderTarget) (SDL_Renderer * renderer, SDL_Texture * texture); int (*RenderReadPixels) (SDL_Renderer * renderer, const SDL_Rect * rect, Uint32 format, void * pixels, int pitch); diff --git a/src/render/direct3d/SDL_render_d3d.c b/src/render/direct3d/SDL_render_d3d.c index 63df321b2..119c04231 100644 --- a/src/render/direct3d/SDL_render_d3d.c +++ b/src/render/direct3d/SDL_render_d3d.c @@ -722,6 +722,18 @@ 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->driverdata; + + if (!texturedata) { + return; + } + + texturedata->scaleMode = (scaleMode == SDL_ScaleModeNearest) ? D3DTEXF_POINT : D3DTEXF_LINEAR; +} + static int D3D_SetRenderTargetInternal(SDL_Renderer * renderer, SDL_Texture * texture) { @@ -1704,6 +1716,7 @@ D3D_CreateRenderer(SDL_Window * window, Uint32 flags) renderer->UpdateTextureYUV = D3D_UpdateTextureYUV; renderer->LockTexture = D3D_LockTexture; renderer->UnlockTexture = D3D_UnlockTexture; + renderer->SetTextureScaleMode = D3D_SetTextureScaleMode; renderer->SetRenderTarget = D3D_SetRenderTarget; renderer->QueueSetViewport = D3D_QueueSetViewport; renderer->QueueSetDrawColor = D3D_QueueSetViewport; /* SetViewport and SetDrawColor are (currently) no-ops. */ diff --git a/src/render/direct3d11/SDL_render_d3d11.c b/src/render/direct3d11/SDL_render_d3d11.c index f7b899553..7ae0d02e8 100644 --- a/src/render/direct3d11/SDL_render_d3d11.c +++ b/src/render/direct3d11/SDL_render_d3d11.c @@ -1523,6 +1523,18 @@ 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->driverdata; + + if (!textureData) { + return; + } + + textureData->scaleMode = (scaleMode == SDL_ScaleModeNearest) ? D3D11_FILTER_MIN_MAG_MIP_POINT : D3D11_FILTER_MIN_MAG_MIP_LINEAR; +} + static int D3D11_SetRenderTarget(SDL_Renderer * renderer, SDL_Texture * texture) { @@ -2498,6 +2510,7 @@ D3D11_CreateRenderer(SDL_Window * window, Uint32 flags) renderer->UpdateTextureYUV = D3D11_UpdateTextureYUV; renderer->LockTexture = D3D11_LockTexture; renderer->UnlockTexture = D3D11_UnlockTexture; + renderer->SetTextureScaleMode = D3D11_SetTextureScaleMode; renderer->SetRenderTarget = D3D11_SetRenderTarget; renderer->QueueSetViewport = D3D11_QueueSetViewport; renderer->QueueSetDrawColor = D3D11_QueueSetViewport; /* SetViewport and SetDrawColor are (currently) no-ops. */ diff --git a/src/render/metal/SDL_render_metal.m b/src/render/metal/SDL_render_metal.m index bf424680b..f8ab1fcd6 100644 --- a/src/render/metal/SDL_render_metal.m +++ b/src/render/metal/SDL_render_metal.m @@ -946,6 +946,18 @@ METAL_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture) texturedata.hasdata = YES; }} +static void +METAL_SetTextureScaleMode(SDL_Renderer * renderer, SDL_Texture * texture, SDL_ScaleMode scaleMode) +{ @autoreleasepool { + METAL_TextureData *texturedata = (__bridge METAL_TextureData *)texture->driverdata; + + if (scaleMode == SDL_ScaleModeNearest) { + texturedata.mtlsampler = data.mtlsamplernearest; + } else { + texturedata.mtlsampler = data.mtlsamplerlinear; + } +}} + static int METAL_SetRenderTarget(SDL_Renderer * renderer, SDL_Texture * texture) { @autoreleasepool { @@ -1763,6 +1775,7 @@ METAL_CreateRenderer(SDL_Window * window, Uint32 flags) renderer->UpdateTextureYUV = METAL_UpdateTextureYUV; renderer->LockTexture = METAL_LockTexture; renderer->UnlockTexture = METAL_UnlockTexture; + renderer->SetTextureScaleMode = METAL_SetTextureScaleMode; renderer->SetRenderTarget = METAL_SetRenderTarget; renderer->QueueSetViewport = METAL_QueueSetViewport; renderer->QueueSetDrawColor = METAL_QueueSetDrawColor; diff --git a/src/render/opengl/SDL_render_gl.c b/src/render/opengl/SDL_render_gl.c index ed6da0854..ca5698ff3 100644 --- a/src/render/opengl/SDL_render_gl.c +++ b/src/render/opengl/SDL_render_gl.c @@ -768,6 +768,43 @@ 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->driverdata; + const GLenum textype = renderdata->textype; + GL_TextureData *data = (GL_TextureData *) texture->driverdata; + GLenum glScaleMode = (scaleMode == SDL_ScaleModeNearest) ? GL_NEAREST : GL_LINEAR; + + renderdata->glEnable(textype); + renderdata->glBindTexture(textype, data->texture); + renderdata->glTexParameteri(textype, GL_TEXTURE_MIN_FILTER, glScaleMode); + renderdata->glTexParameteri(textype, GL_TEXTURE_MAG_FILTER, glScaleMode); + renderdata->glDisable(textype); + + if (texture->format == SDL_PIXELFORMAT_YV12 || + texture->format == SDL_PIXELFORMAT_IYUV) { + renderdata->glEnable(textype); + 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); + renderdata->glDisable(textype); + } + + if (texture->format == SDL_PIXELFORMAT_NV12 || + texture->format == SDL_PIXELFORMAT_NV21) { + renderdata->glEnable(textype); + renderdata->glBindTexture(textype, data->utexture); + renderdata->glTexParameteri(textype, GL_TEXTURE_MIN_FILTER, glScaleMode); + renderdata->glTexParameteri(textype, GL_TEXTURE_MAG_FILTER, glScaleMode); + renderdata->glDisable(textype); + } +} + static int GL_SetRenderTarget(SDL_Renderer * renderer, SDL_Texture * texture) { @@ -1577,6 +1614,7 @@ GL_CreateRenderer(SDL_Window * window, Uint32 flags) renderer->UpdateTextureYUV = GL_UpdateTextureYUV; renderer->LockTexture = GL_LockTexture; renderer->UnlockTexture = GL_UnlockTexture; + renderer->SetTextureScaleMode = GL_SetTextureScaleMode; renderer->SetRenderTarget = GL_SetRenderTarget; renderer->QueueSetViewport = GL_QueueSetViewport; renderer->QueueSetDrawColor = GL_QueueSetViewport; /* SetViewport and SetDrawColor are (currently) no-ops. */ diff --git a/src/render/opengles/SDL_render_gles.c b/src/render/opengles/SDL_render_gles.c index dd5610b63..d29ea2602 100644 --- a/src/render/opengles/SDL_render_gles.c +++ b/src/render/opengles/SDL_render_gles.c @@ -492,6 +492,19 @@ GLES_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture) GLES_UpdateTexture(renderer, texture, &rect, data->pixels, data->pitch); } +static void +GLES_SetTextureScaleMode(SDL_Renderer * renderer, SDL_Texture * texture, SDL_ScaleMode scaleMode) +{ + GLES_RenderData *renderdata = (GLES_RenderData *) renderer->driverdata; + const GLenum textype = renderdata->textype; + GLES_TextureData *data = (GLES_TextureData *) texture->driverdata; + GLenum glScaleMode = (scaleMode == SDL_ScaleModeNearest) ? GL_NEAREST : GL_LINEAR; + + renderdata->glBindTexture(data->type, data->texture); + renderdata->glTexParameteri(data->type, GL_TEXTURE_MIN_FILTER, glScaleMode); + renderdata->glTexParameteri(data->type, GL_TEXTURE_MAG_FILTER, glScaleMode); +} + static int GLES_SetRenderTarget(SDL_Renderer * renderer, SDL_Texture * texture) { @@ -1141,6 +1154,7 @@ GLES_CreateRenderer(SDL_Window * window, Uint32 flags) renderer->UpdateTexture = GLES_UpdateTexture; renderer->LockTexture = GLES_LockTexture; renderer->UnlockTexture = GLES_UnlockTexture; + renderer->SetTextureScaleMode = GLES_SetTextureScaleMode; renderer->SetRenderTarget = GLES_SetRenderTarget; renderer->QueueSetViewport = GLES_QueueSetViewport; renderer->QueueSetDrawColor = GLES_QueueSetViewport; /* SetViewport and SetDrawColor are (currently) no-ops. */ diff --git a/src/render/opengles2/SDL_render_gles2.c b/src/render/opengles2/SDL_render_gles2.c index 3d76ae3f7..f68aaa83d 100644 --- a/src/render/opengles2/SDL_render_gles2.c +++ b/src/render/opengles2/SDL_render_gles2.c @@ -1743,6 +1743,36 @@ 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->driverdata; + GLES2_TextureData *data = (GLES2_TextureData *) texture->driverdata; + GLenum glScaleMode = (scaleMode == SDL_ScaleModeNearest) ? GL_NEAREST : GL_LINEAR; + + 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); + } + + 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 int GLES2_SetRenderTarget(SDL_Renderer * renderer, SDL_Texture * texture) { @@ -2064,6 +2094,7 @@ GLES2_CreateRenderer(SDL_Window *window, Uint32 flags) renderer->UpdateTextureYUV = GLES2_UpdateTextureYUV; renderer->LockTexture = GLES2_LockTexture; renderer->UnlockTexture = GLES2_UnlockTexture; + renderer->SetTextureScaleMode = GLES2_SetTextureScaleMode; renderer->SetRenderTarget = GLES2_SetRenderTarget; renderer->QueueSetViewport = GLES2_QueueSetViewport; renderer->QueueSetDrawColor = GLES2_QueueSetViewport; /* SetViewport and SetDrawColor are (currently) no-ops. */ diff --git a/src/render/psp/SDL_render_psp.c b/src/render/psp/SDL_render_psp.c index 15cbd2427..9c9eb17de 100644 --- a/src/render/psp/SDL_render_psp.c +++ b/src/render/psp/SDL_render_psp.c @@ -428,6 +428,12 @@ 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 int PSP_SetRenderTarget(SDL_Renderer * renderer, SDL_Texture * texture) { @@ -938,6 +944,7 @@ PSP_CreateRenderer(SDL_Window * window, Uint32 flags) renderer->UpdateTexture = PSP_UpdateTexture; renderer->LockTexture = PSP_LockTexture; renderer->UnlockTexture = PSP_UnlockTexture; + renderer->SetTextureScaleMode = PSP_SetTextureScaleMode; renderer->SetRenderTarget = PSP_SetRenderTarget; renderer->QueueSetViewport = PSP_QueueSetViewport; renderer->QueueSetDrawColor = PSP_QueueSetViewport; /* SetViewport and SetDrawColor are (currently) no-ops. */ diff --git a/src/render/software/SDL_render_sw.c b/src/render/software/SDL_render_sw.c index 0c191c211..02809be9c 100644 --- a/src/render/software/SDL_render_sw.c +++ b/src/render/software/SDL_render_sw.c @@ -179,6 +179,11 @@ SW_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture) { } +static void +SW_SetTextureScaleMode(SDL_Renderer * renderer, SDL_Texture * texture, SDL_ScaleMode scaleMode) +{ +} + static int SW_SetRenderTarget(SDL_Renderer * renderer, SDL_Texture * texture) { @@ -830,6 +835,7 @@ SW_CreateRendererForSurface(SDL_Surface * surface) renderer->UpdateTexture = SW_UpdateTexture; renderer->LockTexture = SW_LockTexture; renderer->UnlockTexture = SW_UnlockTexture; + renderer->SetTextureScaleMode = SW_SetTextureScaleMode; renderer->SetRenderTarget = SW_SetRenderTarget; renderer->QueueSetViewport = SW_QueueSetViewport; renderer->QueueSetDrawColor = SW_QueueSetViewport; /* SetViewport and SetDrawColor are (currently) no-ops. */ diff --git a/src/video/directfb/SDL_DirectFB_render.c b/src/video/directfb/SDL_DirectFB_render.c index 7294a5f6c..3f65c53cb 100644 --- a/src/video/directfb/SDL_DirectFB_render.c +++ b/src/video/directfb/SDL_DirectFB_render.c @@ -550,6 +550,11 @@ DirectFB_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture) } } +static void +DirectFB_SetTextureScaleMode() +{ +} + #if 0 static void DirectFB_DirtyTexture(SDL_Renderer * renderer, SDL_Texture * texture, @@ -966,6 +971,7 @@ DirectFB_CreateRenderer(SDL_Window * window, Uint32 flags) renderer->UpdateTexture = DirectFB_UpdateTexture; renderer->LockTexture = DirectFB_LockTexture; renderer->UnlockTexture = DirectFB_UnlockTexture; + renderer->SetTextureScaleMode = DirectFB_SetTextureScaleMode; renderer->QueueSetViewport = DirectFB_QueueSetViewport; renderer->QueueSetDrawColor = DirectFB_QueueSetViewport; /* SetViewport and SetDrawColor are (currently) no-ops. */ renderer->QueueDrawPoints = DirectFB_QueueDrawPoints;