summaryrefslogtreecommitdiff
path: root/src/openglgraphics.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/openglgraphics.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/openglgraphics.cpp')
-rw-r--r--src/openglgraphics.cpp113
1 files changed, 72 insertions, 41 deletions
diff --git a/src/openglgraphics.cpp b/src/openglgraphics.cpp
index 3cc1b9e3..ea37bdaa 100644
--- a/src/openglgraphics.cpp
+++ b/src/openglgraphics.cpp
@@ -19,14 +19,15 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+#ifdef USE_OPENGL
+
#include "openglgraphics.h"
#include "log.h"
+#include "video.h"
#include "resources/image.h"
-#ifdef USE_OPENGL
-
#ifdef __APPLE__
#include <OpenGL/OpenGL.h>
#endif
@@ -42,6 +43,19 @@ const unsigned int vertexBufSize = 500;
GLuint OpenGLGraphics::mLastImage = 0;
+std::unique_ptr<OpenGLGraphics> OpenGLGraphics::create(SDL_Window *window,
+ const VideoSettings &settings)
+{
+ SDL_GLContext glContext = SDL_GL_CreateContext(window);
+ if (!glContext)
+ return {};
+
+ if (settings.vsync)
+ SDL_GL_SetSwapInterval(1);
+
+ return std::make_unique<OpenGLGraphics>(window, glContext);
+}
+
OpenGLGraphics::OpenGLGraphics(SDL_Window *window, SDL_GLContext glContext)
: mWindow(window)
, mContext(glContext)
@@ -77,6 +91,23 @@ OpenGLGraphics::OpenGLGraphics(SDL_Window *window, SDL_GLContext glContext)
Image::mTextureSize = texSize;
logger->log("OpenGL texture size: %d pixels%s", Image::mTextureSize,
rectTex ? " (rectangle textures)" : "");
+
+ glMatrixMode(GL_TEXTURE);
+ glLoadIdentity();
+
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ glOrtho(0.0, (double)mWidth, (double)mHeight, 0.0, -1.0, 1.0);
+
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
+
+ glEnable(GL_SCISSOR_TEST);
+
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+
+ glEnableClientState(GL_VERTEX_ARRAY);
+ glEnableClientState(GL_TEXTURE_COORD_ARRAY);
}
OpenGLGraphics::~OpenGLGraphics()
@@ -98,15 +129,28 @@ void OpenGLGraphics::setReduceInputLag(bool reduceInputLag)
mReduceInputLag = reduceInputLag;
}
-void OpenGLGraphics::videoResized(int width, int height)
+void OpenGLGraphics::updateSize(int windowWidth, int windowHeight, float scale)
{
- _endDraw();
+ mScale = scale;
- SDL_GL_GetDrawableSize(mWindow, &mWidth, &mHeight);
+ int drawableWidth;
+ int drawableHeight;
+ SDL_GL_GetDrawableSize(mWindow, &drawableWidth, &drawableHeight);
- glViewport(0, 0, mWidth, mHeight);
+ glViewport(0, 0, drawableWidth, drawableHeight);
+
+ float displayScaleX = windowWidth > 0 ? static_cast<float>(drawableWidth) / windowWidth : 1.0f;
+ float displayScaleY = windowHeight > 0 ? static_cast<float>(drawableHeight) / windowHeight : 1.0f;
+
+ mScaleX = mScale * displayScaleX;
+ mScaleY = mScale * displayScaleY;
+
+ mWidth = std::ceil(drawableWidth / mScaleX);
+ mHeight = std::ceil(drawableHeight / mScaleY);
- _beginDraw();
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ glOrtho(0.0, (double)mWidth, (double)mHeight, 0.0, -1.0, 1.0);
}
static inline void drawQuad(Image *image,
@@ -596,32 +640,11 @@ void OpenGLGraphics::updateScreen()
glFinish();
}
-void OpenGLGraphics::_beginDraw()
-{
- glMatrixMode(GL_TEXTURE);
- glLoadIdentity();
-
- glMatrixMode(GL_PROJECTION);
- glLoadIdentity();
-
- glOrtho(0.0, (double)mWidth, (double)mHeight, 0.0, -1.0, 1.0);
-
- glMatrixMode(GL_MODELVIEW);
- glLoadIdentity();
-
- glEnable(GL_SCISSOR_TEST);
-
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-
- glEnableClientState(GL_VERTEX_ARRAY);
- glEnableClientState(GL_TEXTURE_COORD_ARRAY);
-
- pushClipArea(gcn::Rectangle(0, 0, mWidth, mHeight));
-}
-
-void OpenGLGraphics::_endDraw()
+void OpenGLGraphics::windowToLogical(int windowX, int windowY,
+ float &logicalX, float &logicalY) const
{
- popClipArea();
+ logicalX = windowX / mScale;
+ logicalY = windowY / mScale;
}
SDL_Surface *OpenGLGraphics::getScreenshot()
@@ -685,10 +708,14 @@ bool OpenGLGraphics::pushClipArea(gcn::Rectangle area)
glPushMatrix();
glTranslatef(transX, transY, 0);
- glScissor(mClipStack.top().x,
- mHeight - mClipStack.top().y - mClipStack.top().height,
- mClipStack.top().width,
- mClipStack.top().height);
+
+ int x = (int) (mClipStack.top().x * mScaleX);
+ int y = (int) ((mHeight - mClipStack.top().y -
+ mClipStack.top().height) * mScaleY);
+ int width = (int) (mClipStack.top().width * mScaleX);
+ int height = (int) (mClipStack.top().height * mScaleY);
+
+ glScissor(x, y, width, height);
return result;
}
@@ -697,14 +724,18 @@ void OpenGLGraphics::popClipArea()
{
Graphics::popClipArea();
+ glPopMatrix();
+
if (mClipStack.empty())
return;
- glPopMatrix();
- glScissor(mClipStack.top().x,
- mHeight - mClipStack.top().y - mClipStack.top().height,
- mClipStack.top().width,
- mClipStack.top().height);
+ int x = (int) (mClipStack.top().x * mScaleX);
+ int y = (int) ((mHeight - mClipStack.top().y -
+ mClipStack.top().height) * mScaleY);
+ int width = (int) (mClipStack.top().width * mScaleX);
+ int height = (int) (mClipStack.top().height * mScaleY);
+
+ glScissor(x, y, width, height);
}
void OpenGLGraphics::setColor(const gcn::Color& color)