From 7b291db0d5c4ff59ae62753bd0e073700fd68ca7 Mon Sep 17 00:00:00 2001 From: Christian Speckner Date: Tue, 17 Dec 2019 19:34:41 +0100 Subject: [PATCH] Native retina support. --- .vscode/settings.json | 67 +++++++++++++++++++++- src/common/FrameBufferSDL2.cxx | 34 ++++++++++- src/common/FrameBufferSDL2.hxx | 16 ++++++ src/common/sdl_blitter/BilinearBlitter.cxx | 5 ++ src/common/sdl_blitter/QisBlitter.cxx | 5 ++ 5 files changed, 125 insertions(+), 2 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index 1fd50bc44..40ad65881 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -28,6 +28,71 @@ "__cxx_version": "cpp", "string": "cpp", "type_traits": "cpp", - "ostream": "cpp" + "ostream": "cpp", + "__bit_reference": "cpp", + "__config": "cpp", + "__debug": "cpp", + "__errc": "cpp", + "__hash_table": "cpp", + "__locale": "cpp", + "__mutex_base": "cpp", + "__node_handle": "cpp", + "__nullptr": "cpp", + "__split_buffer": "cpp", + "__string": "cpp", + "__threading_support": "cpp", + "__tree": "cpp", + "__tuple": "cpp", + "algorithm": "cpp", + "atomic": "cpp", + "bit": "cpp", + "bitset": "cpp", + "cctype": "cpp", + "chrono": "cpp", + "clocale": "cpp", + "cmath": "cpp", + "codecvt": "cpp", + "complex": "cpp", + "condition_variable": "cpp", + "cstdarg": "cpp", + "cstddef": "cpp", + "cstdint": "cpp", + "cstdio": "cpp", + "cstdlib": "cpp", + "cstring": "cpp", + "ctime": "cpp", + "cwchar": "cpp", + "cwctype": "cpp", + "deque": "cpp", + "exception": "cpp", + "fstream": "cpp", + "initializer_list": "cpp", + "ios": "cpp", + "iosfwd": "cpp", + "iostream": "cpp", + "iterator": "cpp", + "limits": "cpp", + "list": "cpp", + "map": "cpp", + "mutex": "cpp", + "new": "cpp", + "numeric": "cpp", + "optional": "cpp", + "queue": "cpp", + "random": "cpp", + "ratio": "cpp", + "set": "cpp", + "sstream": "cpp", + "stack": "cpp", + "stdexcept": "cpp", + "streambuf": "cpp", + "string_view": "cpp", + "system_error": "cpp", + "typeinfo": "cpp", + "unordered_map": "cpp", + "vector": "cpp", + "memory_resource": "cpp", + "cfenv": "cpp", + "cinttypes": "cpp" } } diff --git a/src/common/FrameBufferSDL2.cxx b/src/common/FrameBufferSDL2.cxx index 7fc949736..a7687b8c4 100644 --- a/src/common/FrameBufferSDL2.cxx +++ b/src/common/FrameBufferSDL2.cxx @@ -33,7 +33,9 @@ FrameBufferSDL2::FrameBufferSDL2(OSystem& osystem) myWindow(nullptr), myRenderer(nullptr), myCenter(false), - myRenderTargetSupport(false) + myRenderTargetSupport(false), + myScaleX(1), + myScaleY(1) { ASSERT_MAIN_THREAD; @@ -263,6 +265,7 @@ bool FrameBufferSDL2::setVideoMode(const string& title, const VideoMode& mode) posY = BSPF::clamp(posY, y0 + 50, y1 - 50); } uInt32 flags = mode.fsIndex != -1 ? SDL_WINDOW_FULLSCREEN_DESKTOP : 0; + flags |= SDL_WINDOW_ALLOW_HIGHDPI; // macOS seems to have issues with destroying the window, and wants to // keep the same handle @@ -321,7 +324,9 @@ bool FrameBufferSDL2::setVideoMode(const string& title, const VideoMode& mode) SDL_SetHint(SDL_HINT_RENDER_DRIVER, video.c_str()); myRenderer = SDL_CreateRenderer(myWindow, -1, renderFlags); + detectFeatures(); + calculateScaleFactors(); if(myRenderer == nullptr) { @@ -513,3 +518,30 @@ bool FrameBufferSDL2::hasRenderTargetSupport() const { return myRenderTargetSupport; } + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void FrameBufferSDL2::calculateScaleFactors() +{ + if (myRenderer == nullptr) { + myScaleX = myScaleY = 1; + return; + } + + int windowW, windowH, renderW, renderH; + + SDL_GetWindowSize(myWindow, &windowW, &windowH); + SDL_GetRendererOutputSize(myRenderer, &renderW, &renderH); + + myScaleX = renderW / windowW; + myScaleY = renderH / windowH; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +uInt8 FrameBufferSDL2::scaleX() const { + return myScaleX; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +uInt8 FrameBufferSDL2::scaleY() const { + return myScaleY; +} diff --git a/src/common/FrameBufferSDL2.hxx b/src/common/FrameBufferSDL2.hxx index ff89e1110..d75610829 100644 --- a/src/common/FrameBufferSDL2.hxx +++ b/src/common/FrameBufferSDL2.hxx @@ -134,6 +134,16 @@ class FrameBufferSDL2 : public FrameBuffer */ bool hasRenderTargetSupport() const; + /** + Retina scale factor, x direction; + */ + uInt8 scaleX() const; + + /** + Retina scale Factor, y direction; + */ + uInt8 scaleY() const; + protected: ////////////////////////////////////////////////////////////////////// // The following are derived from protected methods in FrameBuffer.hxx @@ -208,6 +218,8 @@ class FrameBufferSDL2 : public FrameBuffer */ bool detectRenderTargetSupport(); + void calculateScaleFactors(); + private: // The SDL video buffer SDL_Window* myWindow; @@ -222,8 +234,12 @@ class FrameBufferSDL2 : public FrameBuffer // last position of windowed window Common::Point myWindowedPos; + // Does the renderer support render targets? bool myRenderTargetSupport; + // Retina scale factors + uInt32 myScaleX, myScaleY; + private: // Following constructors and assignment operators not supported FrameBufferSDL2() = delete; diff --git a/src/common/sdl_blitter/BilinearBlitter.cxx b/src/common/sdl_blitter/BilinearBlitter.cxx index 92e3b292e..0cfacbcba 100644 --- a/src/common/sdl_blitter/BilinearBlitter.cxx +++ b/src/common/sdl_blitter/BilinearBlitter.cxx @@ -57,6 +57,11 @@ void BilinearBlitter::reinitialize( mySrcRect = srcRect; myDstRect = destRect; myAttributes = attributes; + + myDstRect.x *= myFB.scaleX(); + myDstRect.y *= myFB.scaleY(); + myDstRect.w *= myFB.scaleX(); + myDstRect.h *= myFB.scaleY(); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/common/sdl_blitter/QisBlitter.cxx b/src/common/sdl_blitter/QisBlitter.cxx index 64b5ff692..a9dd85292 100644 --- a/src/common/sdl_blitter/QisBlitter.cxx +++ b/src/common/sdl_blitter/QisBlitter.cxx @@ -65,6 +65,11 @@ void QisBlitter::reinitialize( mySrcRect = srcRect; myDstRect = destRect; myAttributes = attributes; + + myDstRect.x *= myFB.scaleX(); + myDstRect.y *= myFB.scaleY(); + myDstRect.w *= myFB.scaleX(); + myDstRect.h *= myFB.scaleY(); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -