summaryrefslogtreecommitdiff
path: root/src/video.cpp
diff options
context:
space:
mode:
authorThorbjørn Lindeijer <bjorn@lindeijer.nl>2024-03-05 10:21:43 +0100
committerThorbjørn Lindeijer <bjorn@lindeijer.nl>2024-03-22 20:26:26 +0100
commita06db62288bc3fdbf3f25bcfa046c20510036665 (patch)
tree5ad510ebc223364f8d8f59f84d5bb8081a2822b1 /src/video.cpp
parent944b99f3a2e87a080666174dc1e2e2b543519904 (diff)
downloadmana-a06db62288bc3fdbf3f25bcfa046c20510036665.tar.gz
mana-a06db62288bc3fdbf3f25bcfa046c20510036665.tar.bz2
mana-a06db62288bc3fdbf3f25bcfa046c20510036665.tar.xz
mana-a06db62288bc3fdbf3f25bcfa046c20510036665.zip
Added support for scaling the output
* Added "Scale" user option, which can either by "Auto" or an explicit scaling factor. Its maximum value depends on the current resolution. The "Auto" factor is based on keeping the logical resolution on at least 800x600, wheres the maximum scale is based on keeping the logical resolution on at least 640x480. * Enabled support for High DPI. This means the rendering target can now have a different resolution than the window size, which can happen on macOS, Windows and Wayland. The resulting scale is multiplied by the above user-controlled scale. Currently, this looks ugly for non-integer scales, which are not used on macOS and can only be configured on some Wayland compositors. Has not been tested on Windows. * Simplified OpenGL initialization (moved out of _beginDraw). * Made sure _beginDraw/_endDraw sets a clip area also for SDLGraphics.
Diffstat (limited to 'src/video.cpp')
-rw-r--r--src/video.cpp69
1 files changed, 43 insertions, 26 deletions
diff --git a/src/video.cpp b/src/video.cpp
index 9e69ec27..7ab21d12 100644
--- a/src/video.cpp
+++ b/src/video.cpp
@@ -31,6 +31,26 @@
#include <algorithm>
+int VideoSettings::scale() const
+{
+ if (userScale == 0)
+ return autoScale();
+
+ return std::clamp(userScale, 1, maxScale());
+}
+
+int VideoSettings::autoScale() const
+{
+ // Automatic scaling factor based on at least 800x600 logical resolution
+ return std::max(1, std::min(width / 800, height / 600));
+}
+
+int VideoSettings::maxScale() const
+{
+ // Logical resolution needs to stay at least 640x480
+ return std::max(1, std::min(width / 640, height / 480));
+}
+
Video::~Video()
{
mGraphics.reset(); // reset graphics first
@@ -66,7 +86,7 @@ Graphics *Video::initialize(const VideoSettings &settings)
}
}
- int windowFlags = SDL_WINDOW_RESIZABLE;
+ int windowFlags = SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI;
const char *videoMode = "windowed";
switch (mSettings.windowMode)
@@ -115,40 +135,27 @@ Graphics *Video::initialize(const VideoSettings &settings)
}
}
+ // Make sure the resolution is reflected in current settings
+ SDL_GetWindowSize(mWindow, &mSettings.width, &mSettings.height);
+
#ifdef USE_OPENGL
if (mSettings.openGL)
{
- SDL_GLContext glContext = SDL_GL_CreateContext(mWindow);
- if (!glContext)
+ mGraphics = OpenGLGraphics::create(mWindow, mSettings);
+ if (!mGraphics)
{
logger->log("Failed to create OpenGL context, falling back to SDL renderer: %s",
SDL_GetError());
mSettings.openGL = false;
}
- else
- {
- if (mSettings.vsync)
- SDL_GL_SetSwapInterval(1);
-
- mGraphics = std::make_unique<OpenGLGraphics>(mWindow, glContext);
- return mGraphics.get();
- }
}
#endif
- int rendererFlags = 0;
- if (settings.vsync)
- rendererFlags |= SDL_RENDERER_PRESENTVSYNC;
+ if (!mGraphics)
+ mGraphics = SDLGraphics::create(mWindow, mSettings);
- SDL_Renderer *renderer = SDL_CreateRenderer(mWindow, -1, rendererFlags);
- if (!renderer)
- {
- logger->error(strprintf("Failed to create renderer: %s",
- SDL_GetError()));
- return nullptr;
- }
+ mGraphics->updateSize(mSettings.width, mSettings.height, mSettings.scale());
- mGraphics = std::make_unique<SDLGraphics>(mWindow, renderer);
return mGraphics.get();
}
@@ -206,7 +213,9 @@ bool Video::apply(const VideoSettings &settings)
return false;
}
- if (settings.windowMode == WindowMode::Windowed) {
+ if (settings.windowMode == WindowMode::Windowed &&
+ (settings.width != mSettings.width ||
+ settings.height != mSettings.height)) {
#ifdef __APPLE__
// Workaround SDL2 issue when setting the window size on a window
// which the user has put in fullscreen. Unfortunately, this mode can't
@@ -216,16 +225,24 @@ bool Video::apply(const VideoSettings &settings)
SDL_SetWindowSize(mWindow, settings.width, settings.height);
}
- mGraphics->setVSync(settings.vsync);
-
mSettings = settings;
- // Make sure the resolution is reflected in current settings
SDL_GetWindowSize(mWindow, &mSettings.width, &mSettings.height);
+ mGraphics->setVSync(mSettings.vsync);
+ mGraphics->updateSize(mSettings.width, mSettings.height, mSettings.scale());
+
return true;
}
+void Video::windowSizeChanged(int width, int height)
+{
+ mSettings.width = width;
+ mSettings.height = height;
+
+ mGraphics->updateSize(width, height, mSettings.scale());
+}
+
bool Video::initDisplayModes()
{
const int displayIndex = mSettings.display;