From 6e02b9d5d672559697b7d8c6da4b42ecec0f18c5 Mon Sep 17 00:00:00 2001 From: Pawel Kolodziejski Date: Tue, 12 May 2020 23:46:03 +0200 Subject: [PATCH] SDL: Based on PR #1624 and more sync with ScummVM --- backends/graphics/graphics.h | 10 - .../graphics/openglsdl/openglsdl-graphics.cpp | 25 +- .../graphics/openglsdl/openglsdl-graphics.h | 35 +- backends/graphics/resvm-graphics.h | 71 ++++ backends/graphics/sdl/resvm-sdl-graphics.cpp | 143 +------ backends/graphics/sdl/resvm-sdl-graphics.h | 76 +--- backends/graphics/sdl/sdl-graphics.cpp | 363 +++++++++++++++++- backends/graphics/sdl/sdl-graphics.h | 103 ++++- .../surfacesdl/surfacesdl-graphics.cpp | 31 +- .../graphics/surfacesdl/surfacesdl-graphics.h | 19 +- backends/modular-backend.cpp | 1 + backends/modular-backend.h | 3 +- backends/platform/sdl/sdl.cpp | 201 +++++++++- backends/platform/sdl/sdl.h | 44 ++- 14 files changed, 852 insertions(+), 273 deletions(-) create mode 100644 backends/graphics/resvm-graphics.h diff --git a/backends/graphics/graphics.h b/backends/graphics/graphics.h index d06f48d4f28..f672fb22862 100644 --- a/backends/graphics/graphics.h +++ b/backends/graphics/graphics.h @@ -76,13 +76,6 @@ public: virtual void beginGFXTransaction() = 0; virtual OSystem::TransactionError endGFXTransaction() = 0; - // ResidualVM specific method - virtual void setupScreen(uint screenW, uint screenH, bool fullscreen, bool accel3d) = 0; - // ResidualVM specific method - virtual Graphics::PixelBuffer getScreenPixelBuffer() = 0; - // ResidualVM specific method - virtual void suggestSideTextures(Graphics::Surface *left, Graphics::Surface *right) = 0; - virtual int16 getHeight() const = 0; virtual int16 getWidth() const = 0; virtual void setPalette(const byte *colors, uint start, uint num) = 0; @@ -110,9 +103,6 @@ public: virtual void setMouseCursor(const void *buf, uint w, uint h, int hotspotX, int hotspotY, uint32 keycolor, bool dontScale = false, const Graphics::PixelFormat *format = NULL) = 0; virtual void setCursorPalette(const byte *colors, uint start, uint num) = 0; - // ResidualVM specific method - virtual bool lockMouse(bool lock) = 0; - virtual void displayMessageOnOSD(const char *msg) {} virtual void displayActivityIconOnOSD(const Graphics::Surface *icon) {} diff --git a/backends/graphics/openglsdl/openglsdl-graphics.cpp b/backends/graphics/openglsdl/openglsdl-graphics.cpp index bbfe3592c96..42643f98276 100644 --- a/backends/graphics/openglsdl/openglsdl-graphics.cpp +++ b/backends/graphics/openglsdl/openglsdl-graphics.cpp @@ -44,18 +44,25 @@ #include "image/bmp.h" #endif -OpenGLSdlGraphicsManager::OpenGLSdlGraphicsManager(SdlEventSource *sdlEventSource, SdlWindow *window, const Capabilities &capabilities) - : - ResVmSdlGraphicsManager(sdlEventSource, window, capabilities), +OpenGLSdlGraphicsManager::OpenGLSdlGraphicsManager(SdlEventSource *eventSource, SdlWindow *window, const Capabilities &capabilities) + : ResVmSdlGraphicsManager(eventSource, window), #if SDL_VERSION_ATLEAST(2, 0, 0) _glContext(nullptr), #endif + _capabilities(capabilities), + _overlayVisible(false), _overlayScreen(nullptr), _overlayBackground(nullptr), _gameRect(), + _fullscreen(false), + _lockAspectRatio(true), _frameBuffer(nullptr), - _surfaceRenderer(nullptr) { + _surfaceRenderer(nullptr), + _engineRequestedWidth(0), + _engineRequestedHeight(0) { ConfMan.registerDefault("antialiasing", 0); + ConfMan.registerDefault("aspect_ratio", true); + ConfMan.registerDefault("vsync", true); _sideTextures[0] = _sideTextures[1] = nullptr; @@ -86,8 +93,12 @@ bool OpenGLSdlGraphicsManager::getFeatureState(OSystem::Feature f) const { switch (f) { case OSystem::kFeatureVSync: return isVSyncEnabled(); + case OSystem::kFeatureFullscreenMode: + return _fullscreen; + case OSystem::kFeatureAspectRatioCorrection: + return _lockAspectRatio; default: - return ResVmSdlGraphicsManager::getFeatureState(f); + return false; } } @@ -99,8 +110,10 @@ void OpenGLSdlGraphicsManager::setFeatureState(OSystem::Feature f, bool enable) createOrUpdateScreen(); } break; + case OSystem::kFeatureAspectRatioCorrection: + _lockAspectRatio = enable; + break; default: - ResVmSdlGraphicsManager::setFeatureState(f, enable); break; } } diff --git a/backends/graphics/openglsdl/openglsdl-graphics.h b/backends/graphics/openglsdl/openglsdl-graphics.h index f1ea2941ca9..fab949e3d06 100644 --- a/backends/graphics/openglsdl/openglsdl-graphics.h +++ b/backends/graphics/openglsdl/openglsdl-graphics.h @@ -39,7 +39,22 @@ namespace OpenGL { */ class OpenGLSdlGraphicsManager : public ResVmSdlGraphicsManager { public: - OpenGLSdlGraphicsManager(SdlEventSource *sdlEventSource, SdlWindow *window, const Capabilities &capabilities); + /** + * Capabilities of the current device + */ + struct Capabilities { + /** + * Is the device capable of rendering to OpenGL framebuffers + */ + bool openGLFrameBuffer; + + /** Supported levels of MSAA when using the OpenGL renderers */ + Common::Array openGLAntiAliasLevels; + + Capabilities() : openGLFrameBuffer(false) {} + }; + + OpenGLSdlGraphicsManager(SdlEventSource *eventSource, SdlWindow *window, const Capabilities &capabilities); virtual ~OpenGLSdlGraphicsManager(); // GraphicsManager API - Features @@ -48,6 +63,10 @@ public: virtual void setFeatureState(OSystem::Feature f, bool enable) override; // GraphicsManager API - Graphics mode +#ifdef USE_RGB_COLOR + virtual Graphics::PixelFormat getScreenFormat() const override { return _screenFormat; } +#endif + virtual int getScreenChangeID() const override { return _screenChangeCount; } virtual void setupScreen(uint gameWidth, uint gameHeight, bool fullscreen, bool accel3d) override; virtual Graphics::PixelBuffer getScreenPixelBuffer() override; virtual int16 getHeight() const override; @@ -59,6 +78,7 @@ public: // GraphicsManager API - Overlay virtual void showOverlay() override; virtual void hideOverlay() override; + virtual Graphics::PixelFormat getOverlayFormat() const override { return _overlayFormat; } virtual void clearOverlay() override; virtual void grabOverlay(void *buf, int pitch) const override; virtual void copyRectToOverlay(const void *buf, int pitch, int x, int y, int w, int h) override; @@ -85,6 +105,8 @@ protected: void deinitializeRenderer(); #endif + const Capabilities &_capabilities; + Math::Rect2d _gameRect; struct OpenGLPixelFormat { @@ -118,14 +140,25 @@ protected: virtual int getGraphicsModeScale(int mode) const override { return 1; } + uint _engineRequestedWidth, _engineRequestedHeight; + + int _screenChangeCount; int _antialiasing; bool _vsync; + bool _fullscreen; + bool _lockAspectRatio; + bool _overlayVisible; OpenGL::TiledSurface *_overlayScreen; OpenGL::TiledSurface *_overlayBackground; OpenGL::Texture *_sideTextures[2]; OpenGL::SurfaceRenderer *_surfaceRenderer; + Graphics::PixelFormat _overlayFormat; +#ifdef USE_RGB_COLOR + Graphics::PixelFormat _screenFormat; +#endif + void initializeOpenGLContext() const; void drawOverlay(); void drawSideTextures(); diff --git a/backends/graphics/resvm-graphics.h b/backends/graphics/resvm-graphics.h new file mode 100644 index 00000000000..8814ab1e887 --- /dev/null +++ b/backends/graphics/resvm-graphics.h @@ -0,0 +1,71 @@ +/* ResidualVM - Graphic Adventure Engine + * + * ResidulVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#ifndef BACKENDS_GRAPHICS_RESVM_ABSTRACT_H +#define BACKENDS_GRAPHICS_RESVM_ABSTRACT_H + +#include "common/system.h" +#include "common/noncopyable.h" +#include "common/keyboard.h" + +#include "graphics/mode.h" +#include "graphics/palette.h" + +#include "backends/graphics/graphics.h" + +/** + * Abstract class for graphics manager. Subclasses + * implement the real functionality. + */ +class ResVmGraphicsManager : public GraphicsManager { +public: + // Methods not used by ResidualVM +#ifdef USE_RGB_COLOR + virtual Common::List getSupportedFormats() const { + Common::List supportedFormats; + return supportedFormats; + } +#endif + virtual void initSize(uint width, uint height, const Graphics::PixelFormat *format = NULL) {} + virtual void beginGFXTransaction() {} + virtual OSystem::TransactionError endGFXTransaction() { return OSystem::kTransactionSuccess; } + virtual void setPalette(const byte *colors, uint start, uint num) {} + virtual void grabPalette(byte *colors, uint start, uint num) const {} + virtual void copyRectToScreen(const void *buf, int pitch, int x, int y, int w, int h) {} + virtual Graphics::Surface *lockScreen() { return nullptr; } + virtual void unlockScreen() {} + virtual void fillScreen(uint32 col) {} + virtual void setShakePos(int shakeXOffset, int shakeYOffset) {}; + virtual void setFocusRectangle(const Common::Rect& rect) {} + virtual void clearFocusRectangle() {} + virtual void setMouseCursor(const void *buf, uint w, uint h, int hotspotX, int hotspotY, uint32 keycolor, bool dontScale = false, const Graphics::PixelFormat *format = NULL) {} + virtual void setCursorPalette(const byte *colors, uint start, uint num) {} + + // ResidualVM specific methods + virtual void setupScreen(uint screenW, uint screenH, bool fullscreen, bool accel3d) = 0; + virtual Graphics::PixelBuffer getScreenPixelBuffer() = 0; + virtual void suggestSideTextures(Graphics::Surface *left, Graphics::Surface *right) = 0; + virtual void saveScreenshot() {} + virtual bool lockMouse(bool lock) = 0; +}; + +#endif diff --git a/backends/graphics/sdl/resvm-sdl-graphics.cpp b/backends/graphics/sdl/resvm-sdl-graphics.cpp index 144f01283b0..117411849d9 100644 --- a/backends/graphics/sdl/resvm-sdl-graphics.cpp +++ b/backends/graphics/sdl/resvm-sdl-graphics.cpp @@ -30,22 +30,9 @@ #include "common/textconsole.h" #include "common/file.h" -static const OSystem::GraphicsMode s_supportedGraphicsModes[] = { - {0, 0, 0} -}; - -ResVmSdlGraphicsManager::ResVmSdlGraphicsManager(SdlEventSource *source, SdlWindow *window, const Capabilities &capabilities) : - SdlGraphicsManager(source, window), - _fullscreen(false), - _lockAspectRatio(true), - _overlayVisible(false), - _screenChangeCount(0), - _capabilities(capabilities), - _engineRequestedWidth(0), - _engineRequestedHeight(0) { +ResVmSdlGraphicsManager::ResVmSdlGraphicsManager(SdlEventSource *source, SdlWindow *window) : + SdlGraphicsManager(source, window) { ConfMan.registerDefault("fullscreen_res", "desktop"); - ConfMan.registerDefault("aspect_ratio", true); - ConfMan.registerDefault("vsync", true); } ResVmSdlGraphicsManager::~ResVmSdlGraphicsManager() { @@ -84,109 +71,6 @@ Common::Rect ResVmSdlGraphicsManager::getPreferredFullscreenResolution() { return _window->getDesktopResolution(); } -void ResVmSdlGraphicsManager::resetGraphicsScale() { - setGraphicsMode(0); -} - -void ResVmSdlGraphicsManager::setFeatureState(OSystem::Feature f, bool enable) { - switch (f) { - case OSystem::kFeatureAspectRatioCorrection: - _lockAspectRatio = enable; - break; - default: - break; - } -} - -bool ResVmSdlGraphicsManager::getFeatureState(OSystem::Feature f) const { - switch (f) { - case OSystem::kFeatureFullscreenMode: - return _fullscreen; - case OSystem::kFeatureAspectRatioCorrection: - return _lockAspectRatio; - default: - return false; - } -} - -const OSystem::GraphicsMode *ResVmSdlGraphicsManager::getSupportedGraphicsModes() const { - return s_supportedGraphicsModes; -} - -int ResVmSdlGraphicsManager::getDefaultGraphicsMode() const { - return 0;// ResidualVM: not use it -} - -void ResVmSdlGraphicsManager::beginGFXTransaction() { - // ResidualVM: not use it -} - -OSystem::TransactionError ResVmSdlGraphicsManager::endGFXTransaction() { - // ResidualVM: not use it - return OSystem::kTransactionSuccess; -} - -#ifdef USE_RGB_COLOR -Common::List ResVmSdlGraphicsManager::getSupportedFormats() const { - // ResidualVM: not use it - return _supportedFormats; -} -#endif - -bool ResVmSdlGraphicsManager::setGraphicsMode(int mode) { - // ResidualVM: not use it - return true; -} - -int ResVmSdlGraphicsManager::getGraphicsMode() const { - // ResidualVM: not use it - return 0; -} - -void ResVmSdlGraphicsManager::initSize(uint w, uint h, const Graphics::PixelFormat *format) { - // ResidualVM: not use it -} - -void ResVmSdlGraphicsManager::copyRectToScreen(const void *src, int pitch, int x, int y, int w, int h) { - // ResidualVM: not use it -} - -Graphics::Surface *ResVmSdlGraphicsManager::lockScreen() { - return NULL; // ResidualVM: not use it -} - -void ResVmSdlGraphicsManager::unlockScreen() { - // ResidualVM: not use it -} - -void ResVmSdlGraphicsManager::fillScreen(uint32 col) { - // ResidualVM: not use it -} - -void ResVmSdlGraphicsManager::setPalette(const byte *colors, uint start, uint num) { - // ResidualVM: not use it -} - -void ResVmSdlGraphicsManager::grabPalette(byte *colors, uint start, uint num) const { - // ResidualVM: not use it -} - -void ResVmSdlGraphicsManager::setCursorPalette(const byte *colors, uint start, uint num) { - // ResidualVM: not use it -} - -void ResVmSdlGraphicsManager::setShakePos(int shakeXOffset, int shakeYOffset) { - // ResidualVM: not use it -} - -void ResVmSdlGraphicsManager::setFocusRectangle(const Common::Rect &rect) { - // ResidualVM: not use it -} - -void ResVmSdlGraphicsManager::clearFocusRectangle() { - // ResidualVM: not use it -} - #pragma mark - #pragma mark --- Mouse --- #pragma mark - @@ -219,22 +103,7 @@ bool ResVmSdlGraphicsManager::isMouseLocked() const { #endif } -void ResVmSdlGraphicsManager::setMouseCursor(const void *buf, uint w, uint h, int hotspot_x, int hotspot_y, uint32 keycolor, bool dontScale, const Graphics::PixelFormat *format) { - // ResidualVM: not use it -} - -#pragma mark - -#pragma mark --- On Screen Display --- -#pragma mark - - -#ifdef USE_OSD -void OpenGLResVmSdlGraphicsManager::displayMessageOnOSD(const char *msg) { - // ResidualVM: not use it -} -#endif - bool ResVmSdlGraphicsManager::notifyEvent(const Common::Event &event) { - //ResidualVM specific: switch ((int)event.type) { case Common::EVENT_KEYDOWN: if (event.kbd.hasFlags(Common::KBD_ALT) && event.kbd.keycode == Common::KEYCODE_s) { @@ -251,15 +120,9 @@ bool ResVmSdlGraphicsManager::notifyEvent(const Common::Event &event) { return false; } -void ResVmSdlGraphicsManager::notifyVideoExpose() { - //ResidualVM specific: - //updateScreen(); -} - bool ResVmSdlGraphicsManager::notifyMousePosition(Common::Point &mouse) { transformMouseCoordinates(mouse); - // ResidualVM: not use that: - //setMousePos(mouse.x, mouse.y); + return true; } diff --git a/backends/graphics/sdl/resvm-sdl-graphics.h b/backends/graphics/sdl/resvm-sdl-graphics.h index dec28109620..e9f570def18 100644 --- a/backends/graphics/sdl/resvm-sdl-graphics.h +++ b/backends/graphics/sdl/resvm-sdl-graphics.h @@ -39,79 +39,22 @@ class SdlEventSource; */ class ResVmSdlGraphicsManager : public SdlGraphicsManager { public: - /** - * Capabilities of the current device - */ - struct Capabilities { - /** - * Is the device capable of rendering to OpenGL framebuffers - */ - bool openGLFrameBuffer; - - /** Supported levels of MSAA when using the OpenGL renderers */ - Common::Array openGLAntiAliasLevels; - - Capabilities() : openGLFrameBuffer(false) {} - }; - - ResVmSdlGraphicsManager(SdlEventSource *source, SdlWindow *window, const Capabilities &capabilities); + ResVmSdlGraphicsManager(SdlEventSource *source, SdlWindow *window); ~ResVmSdlGraphicsManager() override; // SdlGraphicsManager API void activateManager() override; void deactivateManager() override; - void notifyVideoExpose() override; + void notifyVideoExpose() override {} bool notifyMousePosition(Common::Point &mouse) override; - // GraphicsManager API - Features - void setFeatureState(OSystem::Feature f, bool enable) override; - bool getFeatureState(OSystem::Feature f) const override; - - // GraphicsManager API - Graphics mode - const OSystem::GraphicsMode *getSupportedGraphicsModes() const override; - int getDefaultGraphicsMode() const override; - bool setGraphicsMode(int mode) override; - int getGraphicsMode() const override; - void resetGraphicsScale() override; -#ifdef USE_RGB_COLOR - Graphics::PixelFormat getScreenFormat() const override { return _screenFormat; } - Common::List getSupportedFormats() const override; -#endif - void initSize(uint w, uint h, const Graphics::PixelFormat *format = nullptr) override; - int getScreenChangeID() const override { return _screenChangeCount; } - void beginGFXTransaction() override; - OSystem::TransactionError endGFXTransaction() override; - -protected: - // PaletteManager API - void setPalette(const byte *colors, uint start, uint num) override; - void grabPalette(byte *colors, uint start, uint num) const override; - public: // GraphicsManager API - Draw methods - void copyRectToScreen(const void *buf, int pitch, int x, int y, int w, int h) override; - Graphics::Surface *lockScreen() override; - void unlockScreen() override; - void fillScreen(uint32 col) override; - void setShakePos(int shakeXOffset, int shakeYOffset) override; void saveScreenshot() override; - // GraphicsManager API - Focus Rectangle - void setFocusRectangle(const Common::Rect& rect) override; - void clearFocusRectangle() override; - - // GraphicsManager API - Overlay - Graphics::PixelFormat getOverlayFormat() const override { return _overlayFormat; } - // GraphicsManager API - Mouse bool showMouse(bool visible) override; bool lockMouse(bool lock) override; // ResidualVM specific method - void setMouseCursor(const void *buf, uint w, uint h, int hotspotX, int hotspotY, uint32 keycolor, bool dontScale = false, const Graphics::PixelFormat *format = nullptr) override; - void setCursorPalette(const byte *colors, uint start, uint num) override; - -#ifdef USE_OSD - void displayMessageOnOSD(const char *msg) override; -#endif // Common::EventObserver API bool notifyEvent(const Common::Event &event) override; @@ -123,21 +66,6 @@ public: bool isMouseLocked() const; protected: - const Capabilities &_capabilities; - - bool _fullscreen; - bool _lockAspectRatio; - uint _engineRequestedWidth, _engineRequestedHeight; - - int _screenChangeCount; - - bool _overlayVisible; - Graphics::PixelFormat _overlayFormat; - -#ifdef USE_RGB_COLOR - Graphics::PixelFormat _screenFormat; - Common::List _supportedFormats; -#endif /** Obtain the user configured fullscreen resolution, or default to the desktop resolution */ Common::Rect getPreferredFullscreenResolution(); diff --git a/backends/graphics/sdl/sdl-graphics.cpp b/backends/graphics/sdl/sdl-graphics.cpp index 2e74d72d018..4d2c1aeebf2 100644 --- a/backends/graphics/sdl/sdl-graphics.cpp +++ b/backends/graphics/sdl/sdl-graphics.cpp @@ -1,6 +1,6 @@ -/* ResidualVM - A 3D game interpreter +/* ScummVM - Graphic Adventure Engine * - * ResidualVM is the legal property of its developers, whose names + * ScummVM is the legal property of its developers, whose names * are too numerous to list here. Please refer to the COPYRIGHT * file distributed with this source distribution. * @@ -22,28 +22,46 @@ #include "backends/graphics/sdl/sdl-graphics.h" #include "backends/platform/sdl/sdl-sys.h" +#include "backends/platform/sdl/sdl.h" #include "backends/events/sdl/resvm-sdl-events.h" #include "backends/keymapper/action.h" #include "backends/keymapper/keymap.h" -#include "common/textconsole.h" -#include "backends/platform/sdl/sdl.h" #include "common/config-manager.h" #include "common/fs.h" #include "common/textconsole.h" #include "common/translation.h" +//#include "graphics/scaler/aspect.h" // ResidualVM +#if 0 // ResidualVM +#ifdef USE_OSD +#include "common/translation.h" +#endif +#endif // ResidualVM SdlGraphicsManager::SdlGraphicsManager(SdlEventSource *source, SdlWindow *window) - : _eventSource(source), _window(window) { -} - -SdlGraphicsManager::~SdlGraphicsManager() { + : _eventSource(source), _window(window)// ResidualVM not used: , _hwScreen(nullptr) { +#if 0 // ResidualVM +#if SDL_VERSION_ATLEAST(2, 0, 0) + , _allowWindowSizeReset(false), _hintedWidth(0), _hintedHeight(0), _lastFlags(0) +#endif +#endif // ResidualVM +{ + // ResidualVM - not used: + //SDL_GetMouseState(&_cursorX, &_cursorY); } void SdlGraphicsManager::activateManager() { _eventSource->setGraphicsManager(this); + + // Register the graphics manager as a event observer + g_system->getEventManager()->getEventDispatcher()->registerObserver(this, 10, false); } void SdlGraphicsManager::deactivateManager() { + // Unregister the event observer + if (g_system->getEventManager()->getEventDispatcher()) { + g_system->getEventManager()->getEventDispatcher()->unregisterObserver(this); + } + _eventSource->setGraphicsManager(0); } @@ -78,6 +96,275 @@ bool SdlGraphicsManager::setState(const State &state) { return true; } } + +#if 0 // ResidualVM +bool SdlGraphicsManager::defaultGraphicsModeConfig() const { + const Common::ConfigManager::Domain *transientDomain = ConfMan.getDomain(Common::ConfigManager::kTransientDomain); + if (transientDomain && transientDomain->contains("gfx_mode")) { + const Common::String &mode = transientDomain->getVal("gfx_mode"); + if (!mode.equalsIgnoreCase("normal") && !mode.equalsIgnoreCase("default")) { + return false; + } + } + + const Common::ConfigManager::Domain *gameDomain = ConfMan.getActiveDomain(); + if (gameDomain && gameDomain->contains("gfx_mode")) { + const Common::String &mode = gameDomain->getVal("gfx_mode"); + if (!mode.equalsIgnoreCase("normal") && !mode.equalsIgnoreCase("default")) { + return false; + } + } + + return true; +} + +int SdlGraphicsManager::getGraphicsModeIdByName(const Common::String &name) const { + if (name == "normal" || name == "default") { + return getDefaultGraphicsMode(); + } + + const OSystem::GraphicsMode *mode = getSupportedGraphicsModes(); + while (mode && mode->name != nullptr) { + if (name.equalsIgnoreCase(mode->name)) { + return mode->id; + } + ++mode; + } + return -1; +} + +void SdlGraphicsManager::initSizeHint(const Graphics::ModeList &modes) { +#if SDL_VERSION_ATLEAST(2, 0, 0) + const bool useDefault = defaultGraphicsModeConfig(); + + int scale = getGraphicsModeScale(getGraphicsModeIdByName(ConfMan.get("gfx_mode"))); + if (scale == -1) { + warning("Unknown scaler; defaulting to 1"); + scale = 1; + } + + int16 bestWidth = 0, bestHeight = 0; + const Graphics::ModeList::const_iterator end = modes.end(); + for (Graphics::ModeList::const_iterator it = modes.begin(); it != end; ++it) { + int16 width = it->width, height = it->height; + + // TODO: Normalize AR correction by passing a PAR in the mode list + // instead of checking the dimensions here like this, since not all + // 320x200/640x400 uses are with non-square pixels (e.g. DreamWeb). + if (ConfMan.getBool("aspect_ratio")) { + if ((width == 320 && height == 200) || (width == 640 && height == 400)) { + height = real2Aspect(height); + } + } + + if (!useDefault || width <= 320) { + width *= scale; + height *= scale; + } + + if (bestWidth < width) { + bestWidth = width; + } + + if (bestHeight < height) { + bestHeight = height; + } + } + + _hintedWidth = bestWidth; + _hintedHeight = bestHeight; +#endif +} + +bool SdlGraphicsManager::showMouse(const bool visible) { + if (visible == _cursorVisible) { + return visible; + } + + int showCursor = SDL_DISABLE; + if (visible) { + // _cursorX and _cursorY are currently always clipped to the active + // area, so we need to ask SDL where the system's mouse cursor is + // instead + int x, y; + SDL_GetMouseState(&x, &y); + if (!_activeArea.drawRect.contains(Common::Point(x, y))) { + showCursor = SDL_ENABLE; + } + } + SDL_ShowCursor(showCursor); + + return WindowedGraphicsManager::showMouse(visible); +} + +bool SdlGraphicsManager::notifyMousePosition(Common::Point &mouse) { + int showCursor = SDL_DISABLE; + bool valid = true; + if (_activeArea.drawRect.contains(mouse)) { + _cursorLastInActiveArea = true; + } else { + mouse.x = CLIP(mouse.x, _activeArea.drawRect.left, _activeArea.drawRect.right - 1); + mouse.y = CLIP(mouse.y, _activeArea.drawRect.top, _activeArea.drawRect.bottom - 1); + + if (_window->mouseIsGrabbed() || + // Keep the mouse inside the game area during dragging to prevent an + // event mismatch where the mouseup event gets lost because it is + // performed outside of the game area + (_cursorLastInActiveArea && SDL_GetMouseState(nullptr, nullptr) != 0)) { + setSystemMousePosition(mouse.x, mouse.y); + } else { + // Allow the in-game mouse to get a final movement event to the edge + // of the window if the mouse was moved out of the game area + if (_cursorLastInActiveArea) { + _cursorLastInActiveArea = false; + } else if (_cursorVisible) { + // Keep sending events to the game if the cursor is invisible, + // since otherwise if a game lets you skip a cutscene by + // clicking and the user moved the mouse outside the active + // area, the clicks wouldn't do anything, which would be + // confusing + valid = false; + } + + if (_cursorVisible) { + showCursor = SDL_ENABLE; + } + } + } + + SDL_ShowCursor(showCursor); + if (valid) { + setMousePosition(mouse.x, mouse.y); + mouse = convertWindowToVirtual(mouse.x, mouse.y); + } + return valid; +} + +void SdlGraphicsManager::setSystemMousePosition(const int x, const int y) { + assert(_window); + if (!_window->warpMouseInWindow(x, y)) { + const Common::Point mouse = convertWindowToVirtual(x, y); + _eventSource->fakeWarpMouse(mouse.x, mouse.y); + } +} + +void SdlGraphicsManager::handleResizeImpl(const int width, const int height, const int xdpi, const int ydpi) { + _forceRedraw = true; +} + +#if SDL_VERSION_ATLEAST(2, 0, 0) +bool SdlGraphicsManager::createOrUpdateWindow(int width, int height, const Uint32 flags) { + if (!_window) { + return false; + } + + // We only update the actual window when flags change (which usually means + // fullscreen mode is entered/exited), when updates are forced so that we + // do not reset the window size whenever a game makes a call to change the + // size or pixel format of the internal game surface (since a user may have + // resized the game window), or when the launcher is visible (since a user + // may change the scaler, which should reset the window size) + if (!_window->getSDLWindow() || _lastFlags != flags || _overlayVisible || _allowWindowSizeReset) { + const bool fullscreen = (flags & (SDL_WINDOW_FULLSCREEN | SDL_WINDOW_FULLSCREEN_DESKTOP)) != 0; + if (!fullscreen) { + if (_hintedWidth) { + width = _hintedWidth; + } + if (_hintedHeight) { + height = _hintedHeight; + } + } + + if (!_window->createOrUpdateWindow(width, height, flags)) { + return false; + } + + _lastFlags = flags; + _allowWindowSizeReset = false; + } + + return true; +} +#endif + +void SdlGraphicsManager::saveScreenshot() { + Common::String filename; + + Common::String screenshotsPath; + OSystem_SDL *sdl_g_system = dynamic_cast(g_system); + if (sdl_g_system) + screenshotsPath = sdl_g_system->getScreenshotsPath(); + + // Use the name of the running target as a base for screenshot file names + Common::String currentTarget = ConfMan.getActiveDomainName(); + +#ifdef USE_PNG + const char *extension = "png"; +#else + const char *extension = "bmp"; +#endif + + for (int n = 0;; n++) { + filename = Common::String::format("scummvm%s%s-%05d.%s", currentTarget.empty() ? "" : "-", + currentTarget.c_str(), n, extension); + + Common::FSNode file = Common::FSNode(screenshotsPath + filename); + if (!file.exists()) { + break; + } + } + + if (saveScreenshot(screenshotsPath + filename)) { + if (screenshotsPath.empty()) + debug("Saved screenshot '%s' in current directory", filename.c_str()); + else + debug("Saved screenshot '%s' in directory '%s'", filename.c_str(), screenshotsPath.c_str()); + } else { + if (screenshotsPath.empty()) + warning("Could not save screenshot in current directory"); + else + warning("Could not save screenshot in directory '%s'", screenshotsPath.c_str()); + } +} + +bool SdlGraphicsManager::notifyEvent(const Common::Event &event) { + if (event.type != Common::EVENT_CUSTOM_BACKEND_ACTION_START) { + return false; + } + + switch ((CustomEventAction) event.customType) { + case kActionToggleMouseCapture: + getWindow()->toggleMouseGrab(); + return true; + + case kActionToggleFullscreen: + toggleFullScreen(); + return true; + + case kActionSaveScreenshot: + saveScreenshot(); + return true; + + default: + return false; + } +} + +void SdlGraphicsManager::toggleFullScreen() { + if (!g_system->hasFeature(OSystem::kFeatureFullscreenMode)) + return; + + beginGFXTransaction(); + setFeatureState(OSystem::kFeatureFullscreenMode, !getFeatureState(OSystem::kFeatureFullscreenMode)); + endGFXTransaction(); +#ifdef USE_OSD + if (getFeatureState(OSystem::kFeatureFullscreenMode)) + displayMessageOnOSD(_("Fullscreen mode")); + else + displayMessageOnOSD(_("Windowed mode")); +#endif +} +#endif // ResidualVM Common::Keymap *SdlGraphicsManager::getKeymap() { using namespace Common; @@ -102,5 +389,65 @@ Common::Keymap *SdlGraphicsManager::getKeymap() { act->setCustomBackendActionEvent(kActionSaveScreenshot); keymap->addAction(act); + if (hasFeature(OSystem::kFeatureAspectRatioCorrection)) { + act = new Action("ASPT", _("Toggle aspect ratio correction")); + act->addDefaultInputMapping("C+A+a"); + act->setCustomBackendActionEvent(kActionToggleAspectRatioCorrection); + keymap->addAction(act); + } +#if 0 // ResidualVM: not used + if (hasFeature(OSystem::kFeatureFilteringMode)) { + act = new Action("FILT", _("Toggle linear filtered scaling")); + act->addDefaultInputMapping("C+A+f"); + act->setCustomBackendActionEvent(kActionToggleFilteredScaling); + keymap->addAction(act); + } + + if (hasFeature(OSystem::kFeatureStretchMode)) { + act = new Action("STCH", _("Cycle through stretch modes")); + act->addDefaultInputMapping("C+A+s"); + act->setCustomBackendActionEvent(kActionCycleStretchMode); + keymap->addAction(act); + } + + act = new Action("SCL+", _("Increase the scale factor")); + act->addDefaultInputMapping("C+A+PLUS"); + act->addDefaultInputMapping("C+A+KP_PLUS"); + act->setCustomBackendActionEvent(kActionIncreaseScaleFactor); + keymap->addAction(act); + + act = new Action("SCL-", _("Decrease the scale factor")); + act->addDefaultInputMapping("C+A+MINUS"); + act->addDefaultInputMapping("C+A+KP_MINUS"); + act->setCustomBackendActionEvent(kActionDecreaseScaleFactor); + keymap->addAction(act); + +#ifdef USE_SCALERS + struct ActionEntry { + const char *id; + const char *description; + }; + static const ActionEntry filters[] = { + { "FLT1", _s("Switch to nearest neighbour scaling") }, + { "FLT2", _s("Switch to AdvMame 2x/3x scaling") }, +#ifdef USE_HQ_SCALERS + { "FLT3", _s("Switch to HQ 2x/3x scaling") }, +#endif + { "FLT4", _s("Switch to 2xSai scaling") }, + { "FLT5", _s("Switch to Super2xSai scaling") }, + { "FLT6", _s("Switch to SuperEagle scaling") }, + { "FLT7", _s("Switch to TV 2x scaling") }, + { "FLT8", _s("Switch to DotMatrix scaling") } + }; + + for (uint i = 0; i < ARRAYSIZE(filters); i++) { + act = new Action(filters[i].id, filters[i].description); + act->addDefaultInputMapping(String::format("C+A+%d", i + 1)); + act->addDefaultInputMapping(String::format("C+A+KP%d", i + 1)); + act->setCustomBackendActionEvent(kActionSetScaleFilter1 + i); + keymap->addAction(act); + } +#endif +#endif // ResidualVM return keymap; } diff --git a/backends/graphics/sdl/sdl-graphics.h b/backends/graphics/sdl/sdl-graphics.h index 141da1b1036..f33390f71a6 100644 --- a/backends/graphics/sdl/sdl-graphics.h +++ b/backends/graphics/sdl/sdl-graphics.h @@ -23,7 +23,7 @@ #ifndef BACKENDS_GRAPHICS_SDL_SDLGRAPHICS_H #define BACKENDS_GRAPHICS_SDL_SDLGRAPHICS_H -#include "backends/graphics/graphics.h" +#include "backends/graphics/resvm-graphics.h" #include "backends/platform/sdl/sdl-window.h" #include "common/events.h" @@ -31,15 +31,18 @@ class SdlEventSource; +#if 0 // ResidualVM - not used +#ifndef __SYMBIAN32__ +#define USE_OSD 1 +#endif +#endif /** * Base class for a SDL based graphics manager. - * - * It features a few extra a few extra features required by SdlEventSource. */ -class SdlGraphicsManager : virtual public GraphicsManager, public Common::EventObserver { +class SdlGraphicsManager : virtual public ResVmGraphicsManager, public Common::EventObserver { public: SdlGraphicsManager(SdlEventSource *source, SdlWindow *window); - virtual ~SdlGraphicsManager(); + virtual ~SdlGraphicsManager() {} /** * Makes this graphics manager active. That means it should be ready to @@ -82,6 +85,7 @@ public: * coordinates (may be either game screen or overlay). * * @param point Mouse coordinates to transform. + * !! ResidualVM specific: */ virtual void transformMouseCoordinates(Common::Point &point) = 0; @@ -98,10 +102,19 @@ public: * @returns true if the mouse was in a valid position for the game and * should cause the event to be sent to the game. */ - virtual bool notifyMousePosition(Common::Point &mouse) = 0; + virtual bool notifyMousePosition(Common::Point &mouse) = 0; // ResidualVM specific + +#if 0 // ResidualVM - not used + virtual bool showMouse(const bool visible) override; +#endif virtual bool saveScreenshot(const Common::String &filename) const { return false; } - virtual void saveScreenshot() {} + virtual void saveScreenshot() {} // ResidualVM specific + +#if 0 // ResidualVM - not used + // Override from Common::EventObserver + virtual bool notifyEvent(const Common::Event &event) override; +#endif /** * A (subset) of the graphic manager's state. This is used when switching @@ -119,20 +132,23 @@ public: }; /** - * Queries the current state of the graphic manager. + * Gets the current state of the graphics manager. */ State getState() const; /** - * Setup a basic state of the graphic manager. + * Sets up a basic state of the graphics manager. */ bool setState(const State &state); /** - * Queries the SDL window. + * @returns the SDL window. */ SdlWindow *getWindow() const { return _window; } +#if 0 // ResidualVM - not used + virtual void initSizeHint(const Graphics::ModeList &modes) override; +#endif Common::Keymap *getKeymap(); protected: @@ -141,16 +157,81 @@ protected: kActionToggleMouseCapture, kActionSaveScreenshot, kActionToggleAspectRatioCorrection +#if 0 // ResidualVM - not used + kActionToggleFilteredScaling, + kActionCycleStretchMode, + kActionIncreaseScaleFactor, + kActionDecreaseScaleFactor, + kActionSetScaleFilter1, + kActionSetScaleFilter2, + kActionSetScaleFilter3, + kActionSetScaleFilter4, + kActionSetScaleFilter5, + kActionSetScaleFilter6, + kActionSetScaleFilter7, + kActionSetScaleFilter8 +#endif }; +#if 0 // ResidualVM - not used + virtual int getGraphicsModeScale(int mode) const = 0; + + bool defaultGraphicsModeConfig() const; + int getGraphicsModeIdByName(const Common::String &name) const; + + /** + * Gets the dimensions of the window directly from SDL instead of from the + * values stored by the graphics manager. + */ + void getWindowSizeFromSdl(int *width, int *height) const { +#if SDL_VERSION_ATLEAST(2, 0, 0) + assert(_window); + SDL_GetWindowSize(_window->getSDLWindow(), width, height); +#else + assert(_hwScreen); + + if (width) { + *width = _hwScreen->w; + } + + if (height) { + *height = _hwScreen->h; + } +#endif + } + + virtual void setSystemMousePosition(const int x, const int y) override; + + virtual void handleResizeImpl(const int width, const int height, const int xdpi, const int ydpi) override; +#endif + #if SDL_VERSION_ATLEAST(2, 0, 0) public: - void unlockWindowSize() {} + void unlockWindowSize() { +#if 0 // ResidualVM - not used + _allowWindowSizeReset = true; + _hintedWidth = 0; + _hintedHeight = 0; #endif + } protected: +#if 0 // ResidualVM - not used + Uint32 _lastFlags; + bool _allowWindowSizeReset; + int _hintedWidth, _hintedHeight; + + bool createOrUpdateWindow(const int width, const int height, const Uint32 flags); +#endif +#endif + + SDL_Surface *_hwScreen; // ResidualVM - not used SdlEventSource *_eventSource; SdlWindow *_window; +#if 0 // ResidualVM - not used +private: + void toggleFullScreen(); +#endif }; #endif diff --git a/backends/graphics/surfacesdl/surfacesdl-graphics.cpp b/backends/graphics/surfacesdl/surfacesdl-graphics.cpp index 4451a0e9183..ca108a8cd65 100644 --- a/backends/graphics/surfacesdl/surfacesdl-graphics.cpp +++ b/backends/graphics/surfacesdl/surfacesdl-graphics.cpp @@ -40,9 +40,9 @@ #define SDL_FULLSCREEN 0x40000000 #endif -SurfaceSdlGraphicsManager::SurfaceSdlGraphicsManager(SdlEventSource *sdlEventSource, SdlWindow *window, const Capabilities &capabilities) +SurfaceSdlGraphicsManager::SurfaceSdlGraphicsManager(SdlEventSource *sdlEventSource, SdlWindow *window) : - ResVmSdlGraphicsManager(sdlEventSource, window, capabilities), + ResVmSdlGraphicsManager(sdlEventSource, window), #if SDL_VERSION_ATLEAST(2, 0, 0) _renderer(nullptr), _screenTexture(nullptr), #endif @@ -50,8 +50,15 @@ SurfaceSdlGraphicsManager::SurfaceSdlGraphicsManager(SdlEventSource *sdlEventSou _subScreen(0), _overlayscreen(0), _overlayDirty(true), - _gameRect() - { + _overlayVisible(false), + _fullscreen(false), + _lockAspectRatio(true), + _screenChangeCount(0), + _gameRect(), + _engineRequestedWidth(0), + _engineRequestedHeight(0) { + ConfMan.registerDefault("aspect_ratio", true); + _sideSurfaces[0] = _sideSurfaces[1] = nullptr; } @@ -73,9 +80,21 @@ bool SurfaceSdlGraphicsManager::hasFeature(OSystem::Feature f) const { #if SDL_VERSION_ATLEAST(2, 0, 0) (f == OSystem::kFeatureFullscreenToggleKeepsContext) || #endif + (f == OSystem::kFeatureAspectRatioCorrection) || (f == OSystem::kFeatureFullscreenMode); } +bool SurfaceSdlGraphicsManager::getFeatureState(OSystem::Feature f) const { + switch (f) { + case OSystem::kFeatureFullscreenMode: + return _fullscreen; + case OSystem::kFeatureAspectRatioCorrection: + return _lockAspectRatio; + default: + return false; + } +} + void SurfaceSdlGraphicsManager::setFeatureState(OSystem::Feature f, bool enable) { switch (f) { case OSystem::kFeatureFullscreenMode: @@ -84,8 +103,10 @@ void SurfaceSdlGraphicsManager::setFeatureState(OSystem::Feature f, bool enable) createOrUpdateScreen(); } break; + case OSystem::kFeatureAspectRatioCorrection: + _lockAspectRatio = enable; + break; default: - ResVmSdlGraphicsManager::setFeatureState(f, enable); break; } } diff --git a/backends/graphics/surfacesdl/surfacesdl-graphics.h b/backends/graphics/surfacesdl/surfacesdl-graphics.h index 489c386b807..12dddea4c22 100644 --- a/backends/graphics/surfacesdl/surfacesdl-graphics.h +++ b/backends/graphics/surfacesdl/surfacesdl-graphics.h @@ -32,14 +32,19 @@ */ class SurfaceSdlGraphicsManager : public ResVmSdlGraphicsManager { public: - SurfaceSdlGraphicsManager(SdlEventSource *sdlEventSource, SdlWindow *window, const Capabilities &capabilities); + SurfaceSdlGraphicsManager(SdlEventSource *sdlEventSource, SdlWindow *window); virtual ~SurfaceSdlGraphicsManager(); // GraphicsManager API - Features virtual bool hasFeature(OSystem::Feature f) const override; virtual void setFeatureState(OSystem::Feature f, bool enable) override; + virtual bool getFeatureState(OSystem::Feature f) const override; // GraphicsManager API - Graphics mode +#ifdef USE_RGB_COLOR + virtual Graphics::PixelFormat getScreenFormat() const override { return _screenFormat; } +#endif + virtual int getScreenChangeID() const override { return _screenChangeCount; } virtual void setupScreen(uint gameWidth, uint gameHeight, bool fullscreen, bool accel3d) override; virtual Graphics::PixelBuffer getScreenPixelBuffer() override; virtual int16 getHeight() const override; @@ -51,6 +56,7 @@ public: // GraphicsManager API - Overlay virtual void showOverlay() override; virtual void hideOverlay() override; + virtual Graphics::PixelFormat getOverlayFormat() const override { return _overlayFormat; } virtual void clearOverlay() override; virtual void grabOverlay(void *buf, int pitch) const override; virtual void copyRectToOverlay(const void *buf, int pitch, int x, int y, int w, int h) override; @@ -83,6 +89,17 @@ protected: SDL_Surface *_overlayscreen; bool _overlayDirty; + bool _overlayVisible; + + Graphics::PixelFormat _overlayFormat; +#ifdef USE_RGB_COLOR + Graphics::PixelFormat _screenFormat; +#endif + uint _engineRequestedWidth, _engineRequestedHeight; + + bool _fullscreen; + bool _lockAspectRatio; + int _screenChangeCount; Math::Rect2d _gameRect; diff --git a/backends/modular-backend.cpp b/backends/modular-backend.cpp index daf060cd6fc..f7f98739dbb 100644 --- a/backends/modular-backend.cpp +++ b/backends/modular-backend.cpp @@ -23,6 +23,7 @@ #include "backends/modular-backend.h" #include "backends/graphics/graphics.h" +#include "backends/graphics/resvm-graphics.h" // ResidualVM specific #include "backends/mutex/mutex.h" #include "gui/EventRecorder.h" diff --git a/backends/modular-backend.h b/backends/modular-backend.h index a4e81e5e44a..81cd7eecbd3 100644 --- a/backends/modular-backend.h +++ b/backends/modular-backend.h @@ -26,6 +26,7 @@ #include "backends/base-backend.h" class GraphicsManager; +class ResVmGraphicsManager; // ResidualVM specific class MutexManager; /** @@ -149,7 +150,7 @@ protected: //@{ MutexManager *_mutexManager; - GraphicsManager *_graphicsManager; + ResVmGraphicsManager *_graphicsManager; // ResidualVM: was GraphicsManager Audio::Mixer *_mixer; //@} diff --git a/backends/platform/sdl/sdl.cpp b/backends/platform/sdl/sdl.cpp index e5c2f022b18..aa76d570f3e 100644 --- a/backends/platform/sdl/sdl.cpp +++ b/backends/platform/sdl/sdl.cpp @@ -75,6 +75,15 @@ OSystem_SDL::OSystem_SDL() : +#if 0 // ResidualVM - not used +#ifdef USE_OPENGL + _graphicsModes(), + _graphicsMode(0), + _firstGLMode(0), + _defaultSDLMode(0), + _defaultGLMode(0), +#endif // ResidualVM +#endif _inited(false), _initedSDL(false), #ifdef USE_SDL_NET @@ -221,9 +230,32 @@ void OSystem_SDL::initBackend() { } if (_graphicsManager == 0) { +#if 0 // ResidualVM - not used +#ifdef USE_OPENGL + // Setup a list with both SDL and OpenGL graphics modes. We only do + // this whenever the subclass did not already set up an graphics + // manager yet. This is because we don't know the type of the graphics + // manager of the subclass, thus we cannot easily switch between the + // OpenGL one and the set up one. It also is to be expected that the + // subclass does not want any switching of graphics managers anyway. + setupGraphicsModes(); + + if (ConfMan.hasKey("gfx_mode")) { + // If the gfx_mode is from OpenGL, create the OpenGL graphics manager + Common::String gfxMode(ConfMan.get("gfx_mode")); + for (uint i = _firstGLMode; i < _graphicsModeIds.size(); ++i) { + if (!scumm_stricmp(_graphicsModes[i].name, gfxMode.c_str())) { + _graphicsManager = new OpenGLSdlGraphicsManager(_eventSource, _window); + _graphicsMode = i; + break; + } + } + } +#endif // ResidualVM +#endif if (_graphicsManager == 0) { - _graphicsManager = new SurfaceSdlGraphicsManager(_eventSource, _window, _capabilities); + _graphicsManager = new SurfaceSdlGraphicsManager(_eventSource, _window); } } @@ -261,7 +293,7 @@ void OSystem_SDL::initBackend() { dynamic_cast(_graphicsManager)->activateManager(); } -// ResidualVM specific code +// ResidualVM specific code - Start #ifdef USE_OPENGL void OSystem_SDL::detectFramebufferSupport() { _capabilities.openGLFrameBuffer = false; @@ -432,8 +464,8 @@ void OSystem_SDL::setWindowCaption(const char *caption) { } // ResidualVM specific code -void OSystem_SDL::setupScreen(uint screenW, uint screenH, bool fullscreen, bool accel3d) { #ifdef USE_OPENGL +void OSystem_SDL::setupScreen(uint screenW, uint screenH, bool fullscreen, bool accel3d) { bool switchedManager = false; if (accel3d && !dynamic_cast(_graphicsManager)) { switchedManager = true; @@ -449,15 +481,19 @@ void OSystem_SDL::setupScreen(uint screenW, uint screenH, bool fullscreen, bool if (accel3d) { _graphicsManager = sdlGraphicsManager = new OpenGLSdlGraphicsManager(_eventSource, _window, _capabilities); } else { - _graphicsManager = sdlGraphicsManager = new SurfaceSdlGraphicsManager(_eventSource, _window, _capabilities); + _graphicsManager = sdlGraphicsManager = new SurfaceSdlGraphicsManager(_eventSource, _window); } sdlGraphicsManager->activateManager(); } -#endif ModularBackend::setupScreen(screenW, screenH, fullscreen, accel3d); } +Common::Array OSystem_SDL::getSupportedAntiAliasingLevels() const { + return _capabilities.openGLAntiAliasLevels; +} +#endif + void OSystem_SDL::launcherInitSize(uint w, uint h) { Common::String rendererConfig = ConfMan.get("renderer"); Graphics::RendererType desiredRendererType = Graphics::parseRendererTypeCode(rendererConfig); @@ -468,9 +504,6 @@ void OSystem_SDL::launcherInitSize(uint w, uint h) { setupScreen(w, h, fullscreen, matchingRendererType != Graphics::kRendererTypeTinyGL); } -Common::Array OSystem_SDL::getSupportedAntiAliasingLevels() const { - return _capabilities.openGLAntiAliasLevels; -} // End of ResidualVM specific code void OSystem_SDL::quit() { @@ -696,6 +729,158 @@ Common::String OSystem_SDL::getScreenshotsPath() { path += "/"; return path; } + +#if 0 // ResidualVM - not used +#ifdef USE_OPENGL + +const OSystem::GraphicsMode *OSystem_SDL::getSupportedGraphicsModes() const { + if (_graphicsModes.empty()) { + return _graphicsManager->getSupportedGraphicsModes(); + } else { + return _graphicsModes.begin(); + } +} + +int OSystem_SDL::getDefaultGraphicsMode() const { + if (_graphicsModes.empty()) { + return _graphicsManager->getDefaultGraphicsMode(); + } else { + // Return the default graphics mode from the current graphics manager + if (_graphicsMode < _firstGLMode) + return _defaultSDLMode; + else + return _defaultGLMode; + } +} + +bool OSystem_SDL::setGraphicsMode(int mode) { + if (_graphicsModes.empty()) { + return _graphicsManager->setGraphicsMode(mode); + } + + // Check whether a invalid mode is requested. + if (mode < 0 || (uint)mode >= _graphicsModeIds.size()) { + return false; + } + + // Very hacky way to set up the old graphics manager state, in case we + // switch from SDL->OpenGL or OpenGL->SDL. + // + // This is a probably temporary workaround to fix bugs like #3368143 + // "SDL/OpenGL: Crash when switching renderer backend". + SdlGraphicsManager *sdlGraphicsManager = dynamic_cast(_graphicsManager); + SdlGraphicsManager::State state = sdlGraphicsManager->getState(); + + bool switchedManager = false; + + // If the new mode and the current mode are not from the same graphics + // manager, delete and create the new mode graphics manager + if (_graphicsMode >= _firstGLMode && mode < _firstGLMode) { + debug(1, "switching to plain SDL graphics"); + sdlGraphicsManager->deactivateManager(); + delete _graphicsManager; + _graphicsManager = sdlGraphicsManager = new SurfaceSdlGraphicsManager(_eventSource, _window); + + switchedManager = true; + } else if (_graphicsMode < _firstGLMode && mode >= _firstGLMode) { + debug(1, "switching to OpenGL graphics"); + sdlGraphicsManager->deactivateManager(); + delete _graphicsManager; + _graphicsManager = sdlGraphicsManager = new OpenGLSdlGraphicsManager(_eventSource, _window); + + switchedManager = true; + } + + _graphicsMode = mode; + + if (switchedManager) { + sdlGraphicsManager->activateManager(); + + // This failing will probably have bad consequences... + if (!sdlGraphicsManager->setState(state)) { + return false; + } + + // Next setup the cursor again + CursorMan.pushCursor(0, 0, 0, 0, 0, 0); + CursorMan.popCursor(); + + // Next setup cursor palette if needed + if (_graphicsManager->getFeatureState(kFeatureCursorPalette)) { + CursorMan.pushCursorPalette(0, 0, 0); + CursorMan.popCursorPalette(); + } + + _graphicsManager->beginGFXTransaction(); + // Oh my god if this failed the client code might just explode. + return _graphicsManager->setGraphicsMode(_graphicsModeIds[mode]); + } else { + return _graphicsManager->setGraphicsMode(_graphicsModeIds[mode]); + } +} + +int OSystem_SDL::getGraphicsMode() const { + if (_graphicsModes.empty()) { + return _graphicsManager->getGraphicsMode(); + } else { + return _graphicsMode; + } +} + +void OSystem_SDL::setupGraphicsModes() { + _graphicsModes.clear(); + _graphicsModeIds.clear(); + _defaultSDLMode = _defaultGLMode = -1; + + // Count the number of graphics modes + const OSystem::GraphicsMode *srcMode; + int defaultMode; + + GraphicsManager *manager = new SurfaceSdlGraphicsManager(_eventSource, _window); + srcMode = manager->getSupportedGraphicsModes(); + defaultMode = manager->getDefaultGraphicsMode(); + while (srcMode->name) { + if (defaultMode == srcMode->id) { + _defaultSDLMode = _graphicsModes.size(); + } + _graphicsModes.push_back(*srcMode); + srcMode++; + } + delete manager; + assert(_defaultSDLMode != -1); + + _firstGLMode = _graphicsModes.size(); + manager = new OpenGLSdlGraphicsManager(_eventSource, _window); + srcMode = manager->getSupportedGraphicsModes(); + defaultMode = manager->getDefaultGraphicsMode(); + while (srcMode->name) { + if (defaultMode == srcMode->id) { + _defaultGLMode = _graphicsModes.size(); + } + _graphicsModes.push_back(*srcMode); + srcMode++; + } + delete manager; + manager = nullptr; + assert(_defaultGLMode != -1); + + // Set a null mode at the end + GraphicsMode nullMode; + memset(&nullMode, 0, sizeof(nullMode)); + _graphicsModes.push_back(nullMode); + + // Set new internal ids for all modes + int i = 0; + OSystem::GraphicsMode *mode = _graphicsModes.begin(); + while (mode->name) { + _graphicsModeIds.push_back(mode->id); + mode->id = i++; + mode++; + } +} +#endif +#endif // ResidualVM + char *OSystem_SDL::convertEncoding(const char *to, const char *from, const char *string, size_t length) { #if SDL_VERSION_ATLEAST(1, 2, 10) int zeroBytes = 1; diff --git a/backends/platform/sdl/sdl.h b/backends/platform/sdl/sdl.h index 1862730902d..65327bf61d4 100644 --- a/backends/platform/sdl/sdl.h +++ b/backends/platform/sdl/sdl.h @@ -30,8 +30,11 @@ #include "backends/events/sdl/sdl-events.h" #include "backends/log/log.h" #include "backends/platform/sdl/sdl-window.h" -// ResidualVM specific code -#include "backends/graphics/sdl/resvm-sdl-graphics.h" +// ResidualVM - Start +#ifdef USE_OPENGL +#include "backends/graphics/openglsdl/openglsdl-graphics.h" +#endif +// ResidualVM - End #include "common/array.h" @@ -92,12 +95,13 @@ public: //Screenshots virtual Common::String getScreenshotsPath(); - // ResidualVM specific code + // ResidualVM - Start +#ifdef USE_OPENGL virtual void setupScreen(uint screenW, uint screenH, bool fullscreen, bool accel3d) override; - // ResidualVM specific code - virtual void launcherInitSize(uint w, uint h) override; - // ResidualVM specific code Common::Array getSupportedAntiAliasingLevels() const; +#endif + virtual void launcherInitSize(uint w, uint h) override; + // ResidualVM - End protected: bool _inited; @@ -133,11 +137,13 @@ protected: */ SdlWindow *_window; - // ResidualVM specific code + // ResidualVM specific code - start +#ifdef USE_OPENGL // Graphics capabilities void detectFramebufferSupport(); void detectAntiAliasingSupport(); - ResVmSdlGraphicsManager::Capabilities _capabilities; + OpenGLSdlGraphicsManager::Capabilities _capabilities; +#endif // End of ResidualVM specific code virtual Common::EventSource *getDefaultEventSource() override { return _eventSource; } @@ -156,6 +162,28 @@ protected: virtual Common::String getDefaultLogFileName() { return Common::String(); } virtual Common::WriteStream *createLogFile(); Backends::Log::Log *_logger; + +#if 0 // ResidualVM - not used +#ifdef USE_OPENGL + typedef Common::Array GraphicsModeArray; + GraphicsModeArray _graphicsModes; + Common::Array _graphicsModeIds; + int _graphicsMode; + int _firstGLMode; + int _defaultSDLMode; + int _defaultGLMode; + + /** + * Creates the merged graphics modes list + */ + void setupGraphicsModes(); + + virtual const OSystem::GraphicsMode *getSupportedGraphicsModes() const override; + virtual int getDefaultGraphicsMode() const override; + virtual bool setGraphicsMode(int mode) override; + virtual int getGraphicsMode() const override; +#endif +#endif // ResidulVM protected: virtual char *convertEncoding(const char *to, const char *from, const char *string, size_t length) override; };