From 40dff443364acf998c6cc0d9d45f3a152aba9b05 Mon Sep 17 00:00:00 2001
From: "Ryan C. Gordon" <[EMAIL REDACTED]>
Date: Sun, 18 Sep 2022 18:01:02 -0400
Subject: [PATCH] video: Added SDL12COMPAT_MAX_VIDMODE hint to clamp max
reported resolution.
---
README.md | 12 ++++++++++++
src/SDL12_compat.c | 27 +++++++++++++++++++++------
2 files changed, 33 insertions(+), 6 deletions(-)
diff --git a/README.md b/README.md
index fc5e47516..201740d72 100644
--- a/README.md
+++ b/README.md
@@ -228,6 +228,18 @@ The available options are:
will create the window at the originally-requested size. If this variable
isn't specified, it defaults to 1.0 (no scaling).
+- SDL12COMPAT_MAX_VIDMODE: (checked during SDL_Init)
+ This is a string in the form of `WxH`, where `W` is the maximum width
+ and `H` is the maximum height (for example: `640x480`). The list of valid
+ resolutions that will be reported by SDL_ListModes and SDL_VideoModeOK will
+ not include any dimensions that are wider or taller than these sizes. A size
+ of zero will be ignored, so for `0x480` a resolution of 1920x480 would be
+ accepted). If not specified, or set to `0x0`, no resolution clamping is done.
+ This is for old software-rendered games that might always choose the largest
+ resolution offered, but never conceived of 4K displays. In these cases, it
+ might be better for them to use a smaller resolution and let sdl12-compat
+ scale their output up with the GPU.
+
- SDL_MOUSE_RELATIVE_SCALING: (checked during SDL_SetVideoMode)
If enabled, relative mouse motion is scaled when the application is
running at a non-native resolution. This may be required with some
diff --git a/src/SDL12_compat.c b/src/SDL12_compat.c
index 6ec6fb971..0787ac3d5 100644
--- a/src/SDL12_compat.c
+++ b/src/SDL12_compat.c
@@ -1970,11 +1970,15 @@ VidModeSizeGreater(SDL12_Rect *mode1, SDL12_Rect *mode2)
}
static int
-AddVidModeToList(VideoModeList *vmode, SDL12_Rect *mode)
+AddVidModeToList(VideoModeList *vmode, SDL12_Rect *mode, const Uint16 maxw, const Uint16 maxh)
{
void *ptr = NULL;
int i;
+ if ( (maxw && (mode->w > maxw)) || (maxh && (mode->h > maxh)) ) {
+ return 0; /* clamp this one out as too big. */
+ }
+
/* make sure we don't have this one already (with a different refresh rate, etc). */
for (i = 0; i < vmode->nummodes; i++) {
if ((vmode->modeslist12[i].w == mode->w) && (vmode->modeslist12[i].h == mode->h)) {
@@ -2038,21 +2042,32 @@ static int
Init12VidModes(void)
{
const int total = SDL20_GetNumDisplayModes(VideoDisplayIndex);
+ const char *maxmodestr;
VideoModeList *vmode = NULL;
void *ptr = NULL;
int i, j;
SDL12_Rect prev_mode = { 0, 0, 0, 0 }, current_mode = { 0, 0, 0, 0 };
/* We only want to enable fake modes if OpenGL Logical Scaling is enabled. */
const SDL_bool use_fake_modes = SDL12Compat_GetHintBoolean("SDL12COMPAT_OPENGL_SCALING", SDL_TRUE);
-
- WantOpenGLScaling = use_fake_modes;
+ Uint16 maxw = 0;
+ Uint16 maxh = 0;
if (VideoModesCount > 0) {
return 0; /* already did this. */
}
+ WantOpenGLScaling = use_fake_modes;
+
SDL_assert(VideoModes == NULL);
+ maxmodestr = SDL12Compat_GetHint("SDL12COMPAT_MAX_VIDMODE");
+ if (maxmodestr) {
+ unsigned int w, h;
+ SDL_sscanf(maxmodestr, "%ux%u", &w, &h);
+ maxw = (Uint16) SDL_clamp(w, 0, 0xFFFF);
+ maxh = (Uint16) SDL_clamp(h, 0, 0xFFFF);
+ }
+
for (i = 0; i < total; ++i) {
SDL_DisplayMode mode;
@@ -2098,14 +2113,14 @@ Init12VidModes(void)
if (use_fake_modes) {
for (j = 0; j < (int) SDL_arraysize(fake_modes); ++j) {
if (VidModeSizeGreater(&prev_mode, &fake_modes[j]) && VidModeSizeGreater(&fake_modes[j], ¤t_mode)) {
- if (AddVidModeToList(vmode, &fake_modes[j])) {
+ if (AddVidModeToList(vmode, &fake_modes[j], maxw, maxh)) {
return SDL20_OutOfMemory();
}
}
}
}
- if (AddVidModeToList(vmode, ¤t_mode)) {
+ if (AddVidModeToList(vmode, ¤t_mode, maxw, maxh)) {
return SDL20_OutOfMemory();
}
@@ -2117,7 +2132,7 @@ Init12VidModes(void)
if (use_fake_modes) {
for (i = 0; i < (int) SDL_arraysize(fake_modes); ++i) {
if (VidModeSizeGreater(&prev_mode, &fake_modes[i])) {
- if (AddVidModeToList(vmode, &fake_modes[i])) {
+ if (AddVidModeToList(vmode, &fake_modes[i], maxw, maxh)) {
return SDL20_OutOfMemory();
}
}