Fixed bug 4134 - Render targets lose scale quality after minimizing a fullscreen window

Olli-Samuli Lehmus

If one creates a window with the SDL_WINDOW_FULLSCREEN_DESKTOP flag, and creates a render target with SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "linear"), and afterwards sets SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "nearest"), after minimizing the window, the scale quality hint is lost on the render target. Textures however do keep their interpolation modes.
This commit is contained in:
Sam Lantinga 2018-05-07 19:52:25 -07:00
parent c04dca0dad
commit eb14b635cd
10 changed files with 32 additions and 92 deletions

View File

@ -493,6 +493,21 @@ GetClosestSupportedFormat(SDL_Renderer * renderer, Uint32 format)
return renderer->info.texture_formats[0]; return renderer->info.texture_formats[0];
} }
SDL_ScaleMode SDL_GetScaleMode(void)
{
const char *hint = SDL_GetHint(SDL_HINT_RENDER_SCALE_QUALITY);
if (!hint || SDL_strcasecmp(hint, "nearest") == 0) {
return SDL_ScaleModeNearest;
} else if (SDL_strcasecmp(hint, "linear") == 0) {
return SDL_ScaleModeLinear;
} else if (SDL_strcasecmp(hint, "best") == 0) {
return SDL_ScaleModeBest;
} else {
return (SDL_ScaleMode)SDL_atoi(hint);
}
}
SDL_Texture * SDL_Texture *
SDL_CreateTexture(SDL_Renderer * renderer, Uint32 format, int access, int w, int h) SDL_CreateTexture(SDL_Renderer * renderer, Uint32 format, int access, int w, int h)
{ {
@ -534,6 +549,7 @@ SDL_CreateTexture(SDL_Renderer * renderer, Uint32 format, int access, int w, int
texture->g = 255; texture->g = 255;
texture->b = 255; texture->b = 255;
texture->a = 255; texture->a = 255;
texture->scaleMode = SDL_GetScaleMode();
texture->renderer = renderer; texture->renderer = renderer;
texture->next = renderer->textures; texture->next = renderer->textures;
if (renderer->textures) { if (renderer->textures) {

View File

@ -31,6 +31,13 @@
typedef struct SDL_RenderDriver SDL_RenderDriver; typedef struct SDL_RenderDriver SDL_RenderDriver;
typedef enum
{
SDL_ScaleModeNearest,
SDL_ScaleModeLinear,
SDL_ScaleModeBest
} SDL_ScaleMode;
typedef struct typedef struct
{ {
float x; float x;
@ -55,6 +62,7 @@ struct SDL_Texture
int h; /**< The height of the texture */ int h; /**< The height of the texture */
int modMode; /**< The texture modulation mode */ int modMode; /**< The texture modulation mode */
SDL_BlendMode blendMode; /**< The texture blend mode */ SDL_BlendMode blendMode; /**< The texture blend mode */
SDL_ScaleMode scaleMode; /**< The texture scale mode */
Uint8 r, g, b, a; /**< Texture modulation values */ Uint8 r, g, b, a; /**< Texture modulation values */
SDL_Renderer *renderer; SDL_Renderer *renderer;

View File

@ -664,18 +664,6 @@ D3D_SupportsBlendMode(SDL_Renderer * renderer, SDL_BlendMode blendMode)
return SDL_TRUE; return SDL_TRUE;
} }
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;
}
}
static int static int
D3D_CreateTextureRep(IDirect3DDevice9 *device, D3D_TextureRep *texture, DWORD usage, Uint32 format, D3DFORMAT d3dfmt, int w, int h) D3D_CreateTextureRep(IDirect3DDevice9 *device, D3D_TextureRep *texture, DWORD usage, Uint32 format, D3DFORMAT d3dfmt, int w, int h)
{ {
@ -829,7 +817,7 @@ D3D_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
if (!texturedata) { if (!texturedata) {
return SDL_OutOfMemory(); return SDL_OutOfMemory();
} }
texturedata->scaleMode = GetScaleQuality(); texturedata->scaleMode = (texture->scaleMode == SDL_ScaleModeNearest) ? D3DTEXF_POINT : D3DTEXF_LINEAR;
texture->driverdata = texturedata; texture->driverdata = texturedata;

View File

@ -1161,17 +1161,6 @@ D3D11_SupportsBlendMode(SDL_Renderer * renderer, SDL_BlendMode blendMode)
return SDL_TRUE; return SDL_TRUE;
} }
static D3D11_FILTER
GetScaleQuality(void)
{
const char *hint = SDL_GetHint(SDL_HINT_RENDER_SCALE_QUALITY);
if (!hint || *hint == '0' || SDL_strcasecmp(hint, "nearest") == 0) {
return D3D11_FILTER_MIN_MAG_MIP_POINT;
} else /* if (*hint == '1' || SDL_strcasecmp(hint, "linear") == 0) */ {
return D3D11_FILTER_MIN_MAG_MIP_LINEAR;
}
}
static int static int
D3D11_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture) D3D11_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
{ {
@ -1192,7 +1181,7 @@ D3D11_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
SDL_OutOfMemory(); SDL_OutOfMemory();
return -1; return -1;
} }
textureData->scaleMode = GetScaleQuality(); textureData->scaleMode = (texture->scaleMode == SDL_ScaleModeNearest) ? D3D11_FILTER_MIN_MAG_MIP_POINT : D3D11_FILTER_MIN_MAG_MIP_LINEAR;
texture->driverdata = textureData; texture->driverdata = textureData;

View File

@ -853,8 +853,7 @@ METAL_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
} }
METAL_TextureData *texturedata = [[METAL_TextureData alloc] init]; METAL_TextureData *texturedata = [[METAL_TextureData alloc] init];
const char *hint = SDL_GetHint(SDL_HINT_RENDER_SCALE_QUALITY); if (texture->scaleMode == SDL_ScaleModeNearest) {
if (!hint || *hint == '0' || SDL_strcasecmp(hint, "nearest") == 0) {
texturedata.mtlsampler = data.mtlsamplernearest; texturedata.mtlsampler = data.mtlsamplernearest;
} else { } else {
texturedata.mtlsampler = data.mtlsamplerlinear; texturedata.mtlsampler = data.mtlsamplerlinear;

View File

@ -703,18 +703,6 @@ convert_format(GL_RenderData *renderdata, Uint32 pixel_format,
return SDL_TRUE; 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 static int
GL_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture) GL_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
{ {
@ -803,7 +791,7 @@ GL_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
data->format = format; data->format = format;
data->formattype = type; data->formattype = type;
scaleMode = GetScaleQuality(); scaleMode = (texture->scaleMode == SDL_ScaleModeNearest) ? GL_NEAREST : GL_LINEAR;
renderdata->glEnable(data->type); renderdata->glEnable(data->type);
renderdata->glBindTexture(data->type, data->texture); renderdata->glBindTexture(data->type, data->texture);
renderdata->glTexParameteri(data->type, GL_TEXTURE_MIN_FILTER, scaleMode); renderdata->glTexParameteri(data->type, GL_TEXTURE_MIN_FILTER, scaleMode);

View File

@ -524,18 +524,6 @@ power_of_2(int input)
return value; 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 static int
GLES_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture) GLES_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
{ {
@ -603,7 +591,7 @@ GLES_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
data->format = format; data->format = format;
data->formattype = type; data->formattype = type;
scaleMode = GetScaleQuality(); scaleMode = (texture->scaleMode == SDL_ScaleModeNearest) ? GL_NEAREST : GL_LINEAR;
renderdata->glBindTexture(data->type, data->texture); renderdata->glBindTexture(data->type, data->texture);
renderdata->glTexParameteri(data->type, GL_TEXTURE_MIN_FILTER, scaleMode); renderdata->glTexParameteri(data->type, GL_TEXTURE_MIN_FILTER, scaleMode);
renderdata->glTexParameteri(data->type, GL_TEXTURE_MAG_FILTER, scaleMode); renderdata->glTexParameteri(data->type, GL_TEXTURE_MAG_FILTER, scaleMode);

View File

@ -553,18 +553,6 @@ static void GLES2_UnlockTexture(SDL_Renderer *renderer, SDL_Texture *texture);
static int GLES2_SetRenderTarget(SDL_Renderer * renderer, SDL_Texture * texture); static int GLES2_SetRenderTarget(SDL_Renderer * renderer, SDL_Texture * texture);
static void GLES2_DestroyTexture(SDL_Renderer *renderer, SDL_Texture *texture); static void GLES2_DestroyTexture(SDL_Renderer *renderer, SDL_Texture *texture);
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 static int
GLES2_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture) GLES2_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture)
{ {
@ -625,7 +613,7 @@ GLES2_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture)
data->nv12 = ((texture->format == SDL_PIXELFORMAT_NV12) || (texture->format == SDL_PIXELFORMAT_NV21)); data->nv12 = ((texture->format == SDL_PIXELFORMAT_NV12) || (texture->format == SDL_PIXELFORMAT_NV21));
data->texture_u = 0; data->texture_u = 0;
data->texture_v = 0; data->texture_v = 0;
scaleMode = GetScaleQuality(); scaleMode = (texture->scaleMode == SDL_ScaleModeNearest) ? GL_NEAREST : GL_LINEAR;
/* Allocate a blob for image renderdata */ /* Allocate a blob for image renderdata */
if (texture->access == SDL_TEXTUREACCESS_STREAMING) { if (texture->access == SDL_TEXTUREACCESS_STREAMING) {

View File

@ -186,18 +186,6 @@ TextureNextPow2(unsigned int w)
} }
static int
GetScaleQuality(void)
{
const char *hint = SDL_GetHint(SDL_HINT_RENDER_SCALE_QUALITY);
if (!hint || *hint == '0' || SDL_strcasecmp(hint, "nearest") == 0) {
return GU_NEAREST; /* GU_NEAREST good for tile-map */
} else {
return GU_LINEAR; /* GU_LINEAR good for scaling */
}
}
static int static int
PixelFormatToPSPFMT(Uint32 format) PixelFormatToPSPFMT(Uint32 format)
{ {
@ -514,7 +502,7 @@ void
TextureActivate(SDL_Texture * texture) TextureActivate(SDL_Texture * texture)
{ {
PSP_TextureData *psp_texture = (PSP_TextureData *) texture->driverdata; PSP_TextureData *psp_texture = (PSP_TextureData *) texture->driverdata;
int scaleMode = GetScaleQuality(); int scaleMode = (texture->scaleMode == SDL_ScaleModeNearest) ? GU_NEAREST : GU_LINEAR;
/* Swizzling is useless with small textures. */ /* Swizzling is useless with small textures. */
if (texture->w >= 16 || texture->h >= 16) if (texture->w >= 16 || texture->h >= 16)

View File

@ -587,18 +587,6 @@ SW_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
} }
} }
static int
GetScaleQuality(void)
{
const char *hint = SDL_GetHint(SDL_HINT_RENDER_SCALE_QUALITY);
if (!hint || *hint == '0' || SDL_strcasecmp(hint, "nearest") == 0) {
return 0;
} else {
return 1;
}
}
static int static int
SW_RenderCopyEx(SDL_Renderer * renderer, SDL_Texture * texture, SW_RenderCopyEx(SDL_Renderer * renderer, SDL_Texture * texture,
const SDL_Rect * srcrect, const SDL_FRect * dstrect, const SDL_Rect * srcrect, const SDL_FRect * dstrect,
@ -717,7 +705,7 @@ SW_RenderCopyEx(SDL_Renderer * renderer, SDL_Texture * texture,
if (!retval) { if (!retval) {
SDLgfx_rotozoomSurfaceSizeTrig(tmp_rect.w, tmp_rect.h, angle, &dstwidth, &dstheight, &cangle, &sangle); SDLgfx_rotozoomSurfaceSizeTrig(tmp_rect.w, tmp_rect.h, angle, &dstwidth, &dstheight, &cangle, &sangle);
src_rotated = SDLgfx_rotateSurface(src_clone, angle, dstwidth/2, dstheight/2, GetScaleQuality(), flip & SDL_FLIP_HORIZONTAL, flip & SDL_FLIP_VERTICAL, dstwidth, dstheight, cangle, sangle); src_rotated = SDLgfx_rotateSurface(src_clone, angle, dstwidth/2, dstheight/2, (texture->scaleMode == SDL_ScaleModeNearest) ? 0 : 1, flip & SDL_FLIP_HORIZONTAL, flip & SDL_FLIP_VERTICAL, dstwidth, dstheight, cangle, sangle);
if (src_rotated == NULL) { if (src_rotated == NULL) {
retval = -1; retval = -1;
} }