From 38ed0f219942d2b40980c4edcbcb9067aadf3072 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Sun, 13 Mar 2011 11:18:35 -0700 Subject: [PATCH] Added the SDL_HINT_RENDER_SCALE_QUALITY hint, which defaults to nearest pixel sampling. --- include/SDL_hints.h | 12 ++++++++++ src/render/direct3d/SDL_render_d3d.c | 30 +++++++++++++++++++++---- src/render/opengl/SDL_render_gl.c | 14 +++++++++++- src/render/opengles/SDL_render_gles.c | 15 ++++++++++++- src/render/opengles2/SDL_render_gles2.c | 17 +++++++++++--- 5 files changed, 79 insertions(+), 9 deletions(-) diff --git a/include/SDL_hints.h b/include/SDL_hints.h index 8fa6fb2d5..8f2288637 100644 --- a/include/SDL_hints.h +++ b/include/SDL_hints.h @@ -97,6 +97,18 @@ extern "C" { */ #define SDL_HINT_RENDER_OPENGL_SHADERS "SDL_RENDER_OPENGL_SHADERS" +/** + * \brief A variable controlling the scaling quality + * + * This variable can be set to the following values: + * "0" or "nearest" - Nearest pixel sampling + * "1" or "linear" - Linear filtering (supported by OpenGL and Direct3D) + * "2" or "best" - Anisotropic filtering (supported by Direct3D) + * + * By default nearest pixel sampling is used + */ +#define SDL_HINT_RENDER_SCALE_QUALITY "SDL_RENDER_SCALE_QUALITY" + /** * \brief A variable controlling whether updates to the SDL 1.2 screen surface should be synchronized with the vertical refresh, to avoid tearing. * diff --git a/src/render/direct3d/SDL_render_d3d.c b/src/render/direct3d/SDL_render_d3d.c index 7cf117df8..47144d417 100644 --- a/src/render/direct3d/SDL_render_d3d.c +++ b/src/render/direct3d/SDL_render_d3d.c @@ -26,6 +26,7 @@ #include "../../core/windows/SDL_windows.h" +#include "SDL_hints.h" #include "SDL_loadso.h" #include "SDL_syswm.h" #include "../SDL_sysrender.h" @@ -137,11 +138,13 @@ typedef struct D3DPRESENT_PARAMETERS pparams; SDL_bool updateSize; SDL_bool beginScene; + D3DTEXTUREFILTERTYPE scaleMode; } D3D_RenderData; typedef struct { IDirect3DTexture9 *texture; + D3DTEXTUREFILTERTYPE scaleMode; } D3D_TextureData; typedef struct @@ -451,6 +454,7 @@ D3D_CreateRenderer(SDL_Window * window, Uint32 flags) return NULL; } data->beginScene = SDL_TRUE; + data->scaleMode = D3DTEXF_FORCE_DWORD; /* Get presentation parameters to fill info */ result = IDirect3DDevice9_GetSwapChain(data->device, 0, &chain); @@ -537,6 +541,20 @@ D3D_WindowEvent(SDL_Renderer * renderer, const SDL_WindowEvent *event) } } +static D3DTEXTUREFILTERTYPE +GetScaleQuality(void) +{ + const char *hint = SDL_GetHint(SDL_HINT_RENDER_SCALE_QUALITY); + + if (!hint || *hint == '0' || SDL_strcasecmp(hint, "nearest") == 0) { + return D3DTEXF_POINT; + } else if (*hint == '1' || SDL_strcasecmp(hint, "linear") == 0) { + return D3DTEXF_LINEAR; + } else { + return D3DTEXF_ANISOTROPIC; + } +} + static int D3D_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture) { @@ -553,6 +571,7 @@ D3D_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture) SDL_OutOfMemory(); return -1; } + data->scaleMode = GetScaleQuality(); texture->driverdata = data; @@ -1018,10 +1037,13 @@ D3D_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture, D3D_SetBlendMode(data, texture->blendMode); - IDirect3DDevice9_SetSamplerState(data->device, 0, D3DSAMP_MINFILTER, - D3DTEXF_LINEAR); - IDirect3DDevice9_SetSamplerState(data->device, 0, D3DSAMP_MAGFILTER, - D3DTEXF_LINEAR); + if (texturedata->scaleMode != data->scaleMode) { + IDirect3DDevice9_SetSamplerState(data->device, 0, D3DSAMP_MINFILTER, + texturedata->scaleMode); + IDirect3DDevice9_SetSamplerState(data->device, 0, D3DSAMP_MAGFILTER, + texturedata->scaleMode); + data->scaleMode = texturedata->scaleMode; + } result = IDirect3DDevice9_SetTexture(data->device, 0, (IDirect3DBaseTexture9 *) diff --git a/src/render/opengl/SDL_render_gl.c b/src/render/opengl/SDL_render_gl.c index 3f1ed9e83..07fc44dee 100644 --- a/src/render/opengl/SDL_render_gl.c +++ b/src/render/opengl/SDL_render_gl.c @@ -393,6 +393,18 @@ convert_format(GL_RenderData *renderdata, Uint32 pixel_format, return SDL_TRUE; } +static GLenum +GetScaleQuality(void) +{ + const char *hint = SDL_GetHint(SDL_HINT_RENDER_SCALE_QUALITY); + + if (!hint || *hint == '0' || SDL_strcasecmp(hint, "nearest") == 0) { + return GL_NEAREST; + } else { + return GL_LINEAR; + } +} + static int GL_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture) { @@ -455,7 +467,7 @@ GL_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture) data->format = format; data->formattype = type; - data->scaleMode = GL_LINEAR; + data->scaleMode = GetScaleQuality(); renderdata->glEnable(data->type); renderdata->glBindTexture(data->type, data->texture); renderdata->glTexParameteri(data->type, GL_TEXTURE_WRAP_S, diff --git a/src/render/opengles/SDL_render_gles.c b/src/render/opengles/SDL_render_gles.c index a3556a2ae..e936d2522 100644 --- a/src/render/opengles/SDL_render_gles.c +++ b/src/render/opengles/SDL_render_gles.c @@ -23,6 +23,7 @@ #if SDL_VIDEO_RENDER_OGL_ES && !SDL_RENDER_DISABLED +#include "SDL_hints.h" #include "SDL_opengles.h" #include "../SDL_sysrender.h" @@ -292,6 +293,18 @@ power_of_2(int input) return value; } +static GLenum +GetScaleQuality(void) +{ + const char *hint = SDL_GetHint(SDL_HINT_RENDER_SCALE_QUALITY); + + if (!hint || *hint == '0' || SDL_strcasecmp(hint, "nearest") == 0) { + return GL_NEAREST; + } else { + return GL_LINEAR; + } +} + static int GLES_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture) { @@ -345,7 +358,7 @@ GLES_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture) data->format = format; data->formattype = type; - data->scaleMode = GL_LINEAR; + data->scaleMode = GetScaleQuality(); glBindTexture(data->type, data->texture); glTexParameteri(data->type, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(data->type, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); diff --git a/src/render/opengles2/SDL_render_gles2.c b/src/render/opengles2/SDL_render_gles2.c index 979dcb008..a5660c28f 100644 --- a/src/render/opengles2/SDL_render_gles2.c +++ b/src/render/opengles2/SDL_render_gles2.c @@ -24,6 +24,7 @@ #if SDL_VIDEO_RENDER_OGL_ES2 && !SDL_RENDER_DISABLED +#include "SDL_hints.h" #include "SDL_opengles2.h" #include "../SDL_sysrender.h" #include "SDL_shaders_gles2.h" @@ -234,6 +235,18 @@ static void GLES2_UnlockTexture(SDL_Renderer *renderer, SDL_Texture *texture); static int GLES2_UpdateTexture(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *rect, const void *pixels, int pitch); +static GLenum +GetScaleQuality(void) +{ + const char *hint = SDL_GetHint(SDL_HINT_RENDER_SCALE_QUALITY); + + if (!hint || *hint == '0' || SDL_strcasecmp(hint, "nearest") == 0) { + return GL_NEAREST; + } else { + return GL_LINEAR; + } +} + static int GLES2_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture) { @@ -266,7 +279,7 @@ GLES2_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture) tdata->texture_type = GL_TEXTURE_2D; tdata->pixel_format = format; tdata->pixel_type = type; - tdata->scaleMode = GL_LINEAR; + tdata->scaleMode = GetScaleQuality(); /* Allocate a blob for image data */ if (texture->access == SDL_TEXTUREACCESS_STREAMING) @@ -286,8 +299,6 @@ GLES2_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture) glGenTextures(1, &tdata->texture); glActiveTexture(GL_TEXTURE0); glBindTexture(tdata->texture_type, tdata->texture); - glTexParameteri(tdata->texture_type, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(tdata->texture_type, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(tdata->texture_type, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(tdata->texture_type, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexImage2D(tdata->texture_type, 0, format, texture->w, texture->h, 0, format, type, NULL);