From 0f6e231356305043bc7f66ae1cbe2c3a0607c68a Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Thu, 11 Aug 2011 04:25:46 +0200 Subject: SDL: Implement a hellish workaround to fix bug #3368143. The bug in question is "SDL/OpenGL: Crash when switching renderer backend". To fix it I added a stupid graphics state copying to the SDL backend, in case the graphics manager is switched. The implementation of this is considered a pure workaround, no one should ever do it like this in reality... I just want to die when looking at this... Not sure why I actually committed it. Anyway it at least makes the OpenGL backend testable for those who do not want to fiddle with the config file directly. --- .../graphics/surfacesdl/surfacesdl-graphics.cpp | 5 +- backends/platform/sdl/sdl.cpp | 58 +++++++++++++++++++++- 2 files changed, 61 insertions(+), 2 deletions(-) (limited to 'backends') diff --git a/backends/graphics/surfacesdl/surfacesdl-graphics.cpp b/backends/graphics/surfacesdl/surfacesdl-graphics.cpp index 81c439e7e2..146200148a 100644 --- a/backends/graphics/surfacesdl/surfacesdl-graphics.cpp +++ b/backends/graphics/surfacesdl/surfacesdl-graphics.cpp @@ -249,7 +249,10 @@ void SurfaceSdlGraphicsManager::setFeatureState(OSystem::Feature f, bool enable) } bool SurfaceSdlGraphicsManager::getFeatureState(OSystem::Feature f) { - assert(_transactionMode == kTransactionNone); + // We need to allow this to be called from within a transaction, since we + // currently use it to retreive the graphics state, when switching from + // SDL->OpenGL mode for example. + //assert(_transactionMode == kTransactionNone); switch (f) { case OSystem::kFeatureFullscreenMode: diff --git a/backends/platform/sdl/sdl.cpp b/backends/platform/sdl/sdl.cpp index 63871f5034..ba57841256 100644 --- a/backends/platform/sdl/sdl.cpp +++ b/backends/platform/sdl/sdl.cpp @@ -49,6 +49,7 @@ #include "backends/graphics/surfacesdl/surfacesdl-graphics.h" #ifdef USE_OPENGL #include "backends/graphics/openglsdl/openglsdl-graphics.h" +#include "graphics/cursorman.cpp" #endif #include "icons/scummvm.xpm" @@ -524,6 +525,22 @@ bool OSystem_SDL::setGraphicsMode(int mode) { i = _sdlModesCount; } + // 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". + const int screenWidth = _graphicsManager->getWidth(); + const int screenHeight = _graphicsManager->getHeight(); + const bool arState = _graphicsManager->getFeatureState(kFeatureAspectRatioCorrection); + const bool fullscreen = _graphicsManager->getFeatureState(kFeatureFullscreenMode); + const bool cursorPalette = _graphicsManager->getFeatureState(kFeatureCursorPalette); +#ifdef USE_RGB_COLOR + const Graphics::PixelFormat pixelFormat = _graphicsManager->getScreenFormat(); +#endif + + bool switchedManager = false; + // Loop through modes while (srcMode->name) { if (i == mode) { @@ -535,16 +552,55 @@ bool OSystem_SDL::setGraphicsMode(int mode) { _graphicsManager = new SurfaceSdlGraphicsManager(_eventSource); ((SurfaceSdlGraphicsManager *)_graphicsManager)->initEventObserver(); _graphicsManager->beginGFXTransaction(); + + switchedManager = true; } else if (_graphicsMode < _sdlModesCount && mode >= _sdlModesCount) { debug(1, "switching to OpenGL graphics"); delete _graphicsManager; _graphicsManager = new OpenGLSdlGraphicsManager(_eventSource); ((OpenGLSdlGraphicsManager *)_graphicsManager)->initEventObserver(); _graphicsManager->beginGFXTransaction(); + + switchedManager = true; } _graphicsMode = mode; - return _graphicsManager->setGraphicsMode(srcMode->id); + + if (switchedManager) { +#ifdef USE_RGB_COLOR + _graphicsManager->initSize(screenWidth, screenHeight, &pixelFormat); +#else + _graphicsManager->initSize(screenWidth, screenHeight, 0); +#endif + _graphicsManager->setFeatureState(kFeatureAspectRatioCorrection, arState); + _graphicsManager->setFeatureState(kFeatureFullscreenMode, fullscreen); + _graphicsManager->setFeatureState(kFeatureCursorPalette, cursorPalette); + + // Worst part about this right now, tell the cursor manager to + // resetup the cursor + cursor palette if necessarily + + // First we need to try to setup the old state on the new manager... + if (_graphicsManager->endGFXTransaction() != kTransactionSuccess) { + // Oh my god if this failed the client code might just explode. + return false; + } + + // Next setup the cursor again + CursorMan.pushCursor(0, 0, 0, 0, 0, 0); + CursorMan.popCursor(); + + // Next setup cursor palette if needed + if (cursorPalette) { + CursorMan.pushCursorPalette(0, 0, 0); + CursorMan.popCursorPalette(); + } + + _graphicsManager->beginGFXTransaction(); + // Oh my god if this failed the client code might just explode. + return _graphicsManager->setGraphicsMode(srcMode->id); + } else { + return _graphicsManager->setGraphicsMode(srcMode->id); + } } i++; -- cgit v1.2.3