diff options
-rw-r--r-- | backends/graphics/opengl/opengl-graphics.cpp | 117 | ||||
-rw-r--r-- | backends/graphics/opengl/opengl-graphics.h | 11 | ||||
-rw-r--r-- | backends/graphics/openglsdl/openglsdl-graphics.cpp | 135 | ||||
-rw-r--r-- | backends/graphics/openglsdl/openglsdl-graphics.h | 2 | ||||
-rw-r--r-- | backends/graphics/sdl/sdl-graphics.cpp | 2 |
5 files changed, 193 insertions, 74 deletions
diff --git a/backends/graphics/opengl/opengl-graphics.cpp b/backends/graphics/opengl/opengl-graphics.cpp index ac3f561f9e..a0ffa1fcd2 100644 --- a/backends/graphics/opengl/opengl-graphics.cpp +++ b/backends/graphics/opengl/opengl-graphics.cpp @@ -46,7 +46,8 @@ OpenGLGraphicsManager::OpenGLGraphicsManager() _cursorNeedsRedraw(false), _cursorPaletteDisabled(true), _cursorVisible(false), _cursorKeyColor(0), _cursorTargetScale(1), - _formatBGR(false) { + _formatBGR(false), + _aspectX(0), _aspectY(0), _aspectWidth(0), _aspectHeight(0) { memset(&_oldVideoMode, 0, sizeof(_oldVideoMode)); memset(&_videoMode, 0, sizeof(_videoMode)); @@ -56,6 +57,7 @@ OpenGLGraphicsManager::OpenGLGraphicsManager() _videoMode.scaleFactor = 2; _videoMode.fullscreen = false; _videoMode.antialiasing = false; + _videoMode.aspectRatioCorrection = 0; _gamePalette = (byte *)calloc(sizeof(byte) * 4, 256); _cursorPalette = (byte *)calloc(sizeof(byte) * 4, 256); @@ -801,10 +803,10 @@ void OpenGLGraphicsManager::refreshCursor() { void OpenGLGraphicsManager::refreshCursorScale() { // Get the window minimum scale factor. The cursor will mantain its original aspect // ratio, and we do not want it to get too big if only one dimension is resized - float scaleFactor = MIN((float)_videoMode.hardwareWidth / _videoMode.screenWidth, + float screenScaleFactor = MIN((float)_videoMode.hardwareWidth / _videoMode.screenWidth, (float)_videoMode.hardwareHeight / _videoMode.screenHeight); - if (_cursorTargetScale >= scaleFactor && _videoMode.scaleFactor >= scaleFactor) { + if (_cursorTargetScale >= screenScaleFactor && _videoMode.scaleFactor >= screenScaleFactor) { // If the cursor target scale and the video mode scale factor are bigger than // the current window scale, do not scale the cursor for the overlay _cursorState.rW = _cursorState.w; @@ -813,17 +815,34 @@ void OpenGLGraphicsManager::refreshCursorScale() { _cursorState.rHotY = _cursorState.hotY; } else { // Otherwise, scale the cursor for the overlay - _cursorState.rW = _cursorState.w * (scaleFactor - _cursorTargetScale + 1); - _cursorState.rH = _cursorState.h * (scaleFactor - _cursorTargetScale + 1); - _cursorState.rHotX = _cursorState.hotX * (scaleFactor - _cursorTargetScale + 1); - _cursorState.rHotY = _cursorState.hotY * (scaleFactor - _cursorTargetScale + 1); + float targetScaleFactor = MIN(_cursorTargetScale, _videoMode.scaleFactor); + _cursorState.rW = _cursorState.w * (screenScaleFactor - targetScaleFactor + 1); + _cursorState.rH = _cursorState.h * (screenScaleFactor - targetScaleFactor + 1); + _cursorState.rHotX = _cursorState.hotX * (screenScaleFactor - targetScaleFactor + 1); + _cursorState.rHotY = _cursorState.hotY * (screenScaleFactor - targetScaleFactor + 1); } // Always scale the cursor for the game - _cursorState.vW = _cursorState.w * scaleFactor; - _cursorState.vH = _cursorState.h * scaleFactor; - _cursorState.vHotX = _cursorState.hotX * scaleFactor; - _cursorState.vHotY = _cursorState.hotY * scaleFactor; + _cursorState.vW = _cursorState.w * screenScaleFactor; + _cursorState.vH = _cursorState.h * screenScaleFactor; + _cursorState.vHotX = _cursorState.hotX * screenScaleFactor; + _cursorState.vHotY = _cursorState.hotY * screenScaleFactor; +} + +void OpenGLGraphicsManager::refreshAspectRatio() { + _aspectWidth = _videoMode.hardwareWidth; + _aspectHeight = _videoMode.hardwareHeight; + + float aspectRatio = (float)_videoMode.hardwareWidth / _videoMode.hardwareHeight; + float desiredAspectRatio = getAspectRatio(); + + if (aspectRatio < desiredAspectRatio) + _aspectHeight = (int)(_aspectWidth / desiredAspectRatio + 0.5f); + else if (aspectRatio > desiredAspectRatio) + _aspectWidth = (int)(_aspectHeight * desiredAspectRatio + 0.5f); + + _aspectX = (_videoMode.hardwareWidth - _aspectWidth) / 2; + _aspectY = (_videoMode.hardwareHeight - _aspectHeight) / 2; } void OpenGLGraphicsManager::getGLPixelFormat(Graphics::PixelFormat pixelFormat, byte &bpp, GLenum &glFormat, GLenum &gltype) { @@ -873,7 +892,7 @@ void OpenGLGraphicsManager::internUpdateScreen() { glTranslatef(0, _shakePos * scaleFactor, 0); CHECK_GL_ERROR(); // Draw the game screen - _gameTexture->drawTexture(0, 0, _videoMode.hardwareWidth, _videoMode.hardwareHeight); + _gameTexture->drawTexture(_aspectX, _aspectY, _aspectWidth, _aspectHeight); glPopMatrix(); @@ -883,7 +902,7 @@ void OpenGLGraphicsManager::internUpdateScreen() { refreshOverlay(); // Draw the overlay - _overlayTexture->drawTexture(0, 0, _videoMode.hardwareWidth, _videoMode.hardwareHeight); + _overlayTexture->drawTexture(_aspectX, _aspectY, _aspectWidth, _aspectHeight); } if (_cursorVisible) { @@ -1046,6 +1065,8 @@ bool OpenGLGraphicsManager::loadGFXMode() { refreshCursorScale(); + refreshAspectRatio(); + internUpdateScreen(); return true; @@ -1081,27 +1102,77 @@ void OpenGLGraphicsManager::setAspectRatioCorrection(int ratio) { if (_transactionMode == kTransactionActive) { if (ratio == -1) - _videoMode.aspectRatioCorrection = (_videoMode.aspectRatioCorrection + 1) % 4; + _videoMode.aspectRatioCorrection = (_videoMode.aspectRatioCorrection + 1) % 5; else _videoMode.aspectRatioCorrection = ratio; _transactionDetails.needHotswap = true; } } +Common::String OpenGLGraphicsManager::getAspectRatioName() { + switch (_videoMode.aspectRatioCorrection) { + case kAspectRatioNone: + return "None"; + case kAspectRatioConserve: + return "Conserve"; + case kAspectRatio4_3: + return "4/3"; + case kAspectRatio16_9: + return "16/9"; + case kAspectRatio16_10: + return "16/10"; + } + return ""; +} + +float OpenGLGraphicsManager::getAspectRatio() { + switch (_videoMode.aspectRatioCorrection) { + case kAspectRatioConserve: + return (float)_videoMode.screenWidth / _videoMode.screenHeight; + case kAspectRatio4_3: + return 4.0f / 3.0f; + case kAspectRatio16_9: + return 16.0f / 9.0f; + case kAspectRatio16_10: + return 16.0f / 10.0f; + default: + return (float)_videoMode.hardwareWidth / _videoMode.hardwareHeight; + } +} + void OpenGLGraphicsManager::adjustMouseEvent(const Common::Event &event) { if (!event.synthetic) { Common::Event newEvent(event); newEvent.synthetic = true; - if (!_overlayVisible) { - newEvent.mouse.x /= _videoMode.scaleFactor; - newEvent.mouse.y /= _videoMode.scaleFactor; - //if (_videoMode.aspectRatioCorrection) - // newEvent.mouse.y = aspect2Real(newEvent.mouse.y); + + if (!_videoMode.aspectRatioCorrection) { + if (_videoMode.hardwareWidth != _videoMode.overlayWidth) + newEvent.mouse.x = newEvent.mouse.x * _videoMode.overlayWidth / _videoMode.hardwareWidth; + if (_videoMode.hardwareHeight != _videoMode.overlayHeight) + newEvent.mouse.y = newEvent.mouse.y * _videoMode.overlayHeight / _videoMode.hardwareHeight; + + if (!_overlayVisible) { + newEvent.mouse.x /= _videoMode.scaleFactor; + newEvent.mouse.y /= _videoMode.scaleFactor; + } + + } else { + newEvent.mouse.x -= _aspectX; + newEvent.mouse.y -= _aspectY; + + if (_overlayVisible) { + if (_aspectWidth != _videoMode.overlayWidth) + newEvent.mouse.x = newEvent.mouse.x * _videoMode.overlayWidth / _aspectWidth; + if (_aspectHeight != _videoMode.overlayHeight) + newEvent.mouse.y = newEvent.mouse.y * _videoMode.overlayHeight / _aspectHeight; + } else { + if (_aspectWidth != _videoMode.screenWidth) + newEvent.mouse.x = newEvent.mouse.x * _videoMode.screenWidth / _aspectWidth; + if (_aspectHeight != _videoMode.screenHeight) + newEvent.mouse.y = newEvent.mouse.y * _videoMode.screenHeight / _aspectHeight; + } } - if (_videoMode.hardwareWidth != _videoMode.overlayWidth) - newEvent.mouse.x = newEvent.mouse.x * _videoMode.overlayWidth / _videoMode.hardwareWidth; - if (_videoMode.hardwareHeight != _videoMode.overlayHeight) - newEvent.mouse.y = newEvent.mouse.y * _videoMode.overlayHeight / _videoMode.hardwareHeight; + g_system->getEventManager()->pushEvent(newEvent); } } diff --git a/backends/graphics/opengl/opengl-graphics.h b/backends/graphics/opengl/opengl-graphics.h index efc8114e3d..ee14df836e 100644 --- a/backends/graphics/opengl/opengl-graphics.h +++ b/backends/graphics/opengl/opengl-graphics.h @@ -133,6 +133,7 @@ protected: kAspectRatioNone, kAspectRatioConserve, kAspectRatio4_3, + kAspectRatio16_9, kAspectRatio16_10 }; @@ -140,6 +141,7 @@ protected: bool setup; bool fullscreen; + int activeFullscreenMode; int aspectRatioCorrection; int mode; @@ -162,7 +164,16 @@ protected: virtual void unloadGFXMode(); virtual void setScale(int newScale); + + int _aspectX; + int _aspectY; + int _aspectWidth; + int _aspectHeight; + virtual void setAspectRatioCorrection(int mode); + virtual void refreshAspectRatio(); + virtual Common::String getAspectRatioName(); + virtual float getAspectRatio(); bool _formatBGR; diff --git a/backends/graphics/openglsdl/openglsdl-graphics.cpp b/backends/graphics/openglsdl/openglsdl-graphics.cpp index ea01727238..4dac109a01 100644 --- a/backends/graphics/openglsdl/openglsdl-graphics.cpp +++ b/backends/graphics/openglsdl/openglsdl-graphics.cpp @@ -126,15 +126,10 @@ Common::List<Graphics::PixelFormat> OpenGLSdlGraphicsManager::getSupportedFormat void OpenGLSdlGraphicsManager::warpMouse(int x, int y) { if (_cursorState.x != x || _cursorState.y != y) { - int y1 = y; - - /*if (_videoMode.aspectRatioCorrection && !_overlayVisible) - y1 = real2Aspect(y);*/ - if (!_overlayVisible) - SDL_WarpMouse(x * _videoMode.scaleFactor, y1 * _videoMode.scaleFactor); + SDL_WarpMouse(x * _videoMode.scaleFactor, y * _videoMode.scaleFactor); else - SDL_WarpMouse(x, y1); + SDL_WarpMouse(x, y); setMousePos(x, y); } @@ -153,7 +148,22 @@ bool OpenGLSdlGraphicsManager::loadGFXMode() { if (!_screenResized) { _videoMode.hardwareWidth = _videoMode.overlayWidth; _videoMode.hardwareHeight = _videoMode.overlayHeight; + + float screenAspectRatio = (float)_videoMode.screenWidth / _videoMode.screenHeight; + float desiredAspectRatio = getAspectRatio(); + + // Do not downscale dimensions, only enlarge them if needed + if (screenAspectRatio > desiredAspectRatio) + _videoMode.hardwareHeight = (int)(_videoMode.overlayWidth / desiredAspectRatio + 0.5f); + else if (screenAspectRatio < desiredAspectRatio) + _videoMode.hardwareWidth = (int)(_videoMode.overlayHeight * desiredAspectRatio + 0.5f); + + // Only adjust the overlay height if it is bigger than original one. If + // the width is modified it can break the overlay. + if (_videoMode.hardwareHeight > _videoMode.overlayHeight) + _videoMode.overlayHeight = _videoMode.hardwareHeight; } + _screenResized = false; // Setup OpenGL attributes for SDL @@ -166,34 +176,45 @@ bool OpenGLSdlGraphicsManager::loadGFXMode() { // Find the best mode for fullscreen if (_videoMode.fullscreen) { SDL_Rect const* const*availableModes = SDL_ListModes(NULL, SDL_FULLSCREEN | SDL_OPENGL); - const SDL_Rect *bestMode = NULL; - uint bestMetric = (uint)-1; - - // Iterate over all available fullscreen modes - while (const SDL_Rect *mode = *availableModes++) { - if (mode->w < _videoMode.hardwareWidth) - continue; - if (mode->h < _videoMode.hardwareHeight) - continue; - - uint metric = mode->w * mode->h - _videoMode.hardwareWidth * _videoMode.hardwareHeight; - if (metric > bestMetric) - continue; - - bestMode = mode; - bestMetric = metric; - } - if (bestMode) { - // If there is a suiting mode, use it - _videoMode.hardwareWidth = bestMode->w; - _videoMode.hardwareHeight = bestMode->h; + if (_videoMode.activeFullscreenMode == -1) { + const SDL_Rect *bestMode = availableModes[0]; + int bestModeIndex = 0; + uint bestMetric = (uint)-1; + + // Iterate over all available fullscreen modes + for (int i = 0; const SDL_Rect *mode = availableModes[i]; i++) { + if (mode->w < _videoMode.hardwareWidth) + continue; + if (mode->h < _videoMode.hardwareHeight) + continue; + + uint metric = mode->w * mode->h - _videoMode.hardwareWidth * _videoMode.hardwareHeight; + if (metric > bestMetric) + continue; + + bestMode = mode; + bestMetric = metric; + bestModeIndex = i; + } + + if (bestMode) { + // If there is a suiting mode, use it + _videoMode.hardwareWidth = bestMode->w; + _videoMode.hardwareHeight = bestMode->h; + + _videoMode.activeFullscreenMode = bestModeIndex; + } } else { - // If the last mode was in fullscreen, cancel GFX load - if (_oldVideoMode.fullscreen) - return false; + if (!availableModes[_videoMode.activeFullscreenMode]) + _videoMode.activeFullscreenMode = 0; - _videoMode.fullscreen = false; + if (availableModes[_videoMode.activeFullscreenMode]) { + _videoMode.hardwareWidth = availableModes[_videoMode.activeFullscreenMode]->w; + _videoMode.hardwareHeight = availableModes[_videoMode.activeFullscreenMode]->h; + } else { + return false; + } } } @@ -249,16 +270,11 @@ bool OpenGLSdlGraphicsManager::handleScalerHotkeys(Common::KeyCode key) { endGFXTransaction(); #ifdef USE_OSD char buffer[128]; - if (_videoMode.aspectRatioCorrection) - sprintf(buffer, "Enabled aspect ratio correction\n%d x %d -> %d x %d", - _videoMode.screenWidth, _videoMode.screenHeight, - _hwscreen->w, _hwscreen->h - ); - else - sprintf(buffer, "Disabled aspect ratio correction\n%d x %d -> %d x %d", - _videoMode.screenWidth, _videoMode.screenHeight, - _hwscreen->w, _hwscreen->h - ); + sprintf(buffer, "Current aspect ratio mode: %s\n%d x %d -> %d x %d", + getAspectRatioName().c_str(), + _videoMode.screenWidth, _videoMode.screenHeight, + _hwscreen->w, _hwscreen->h + ); displayMessageOnOSD(buffer); #endif internUpdateScreen(); @@ -318,7 +334,8 @@ bool OpenGLSdlGraphicsManager::handleScalerHotkeys(Common::KeyCode key) { } void OpenGLSdlGraphicsManager::setFullscreenMode(bool enable) { - if (_oldVideoMode.setup && _oldVideoMode.fullscreen == enable) + if (_oldVideoMode.setup && _oldVideoMode.fullscreen == enable && + _oldVideoMode.activeFullscreenMode == _videoMode.activeFullscreenMode) return; if (_transactionMode == kTransactionActive) { @@ -337,15 +354,27 @@ bool OpenGLSdlGraphicsManager::isScalerHotkey(const Common::Event &event) { return false; } -void OpenGLSdlGraphicsManager::toggleFullScreen() { +void OpenGLSdlGraphicsManager::toggleFullScreen(bool loop) { beginGFXTransaction(); - setFullscreenMode(!_videoMode.fullscreen); + if (_videoMode.fullscreen && loop) { + _videoMode.activeFullscreenMode += 1; + setFullscreenMode(true); + } else { + _videoMode.activeFullscreenMode = -1; + setFullscreenMode(!_videoMode.fullscreen); + } endGFXTransaction(); #ifdef USE_OSD + char buffer[128]; if (_videoMode.fullscreen) - displayMessageOnOSD("Fullscreen mode"); + sprintf(buffer, "Fullscreen mode\n%d x %d", + _hwscreen->w, _hwscreen->h + ); else - displayMessageOnOSD("Windowed mode"); + sprintf(buffer, "Windowed mode\n%d x %d", + _hwscreen->w, _hwscreen->h + ); + displayMessageOnOSD(buffer); #endif } @@ -356,7 +385,15 @@ bool OpenGLSdlGraphicsManager::notifyEvent(const Common::Event &event) { if (event.kbd.hasFlags(Common::KBD_ALT) && (event.kbd.keycode == Common::KEYCODE_RETURN || event.kbd.keycode == (Common::KeyCode)SDLK_KP_ENTER)) { - toggleFullScreen(); + toggleFullScreen(false); + return true; + } + + // Ctrl-Alt-Return and Ctrl-Alt-Enter switches between full screen modes + if (event.kbd.hasFlags(Common::KBD_CTRL|Common::KBD_ALT) && + (event.kbd.keycode == Common::KEYCODE_RETURN || + event.kbd.keycode == (Common::KeyCode)SDLK_KP_ENTER)) { + toggleFullScreen(true); return true; } @@ -381,7 +418,7 @@ bool OpenGLSdlGraphicsManager::notifyEvent(const Common::Event &event) { } // Ctrl-Alt-<key> will change the GFX mode - if ((event.kbd.flags & (Common::KBD_CTRL|Common::KBD_ALT)) == (Common::KBD_CTRL|Common::KBD_ALT)) { + if (event.kbd.hasFlags(Common::KBD_CTRL|Common::KBD_ALT)) { if (handleScalerHotkeys(event.kbd.keycode)) return true; } diff --git a/backends/graphics/openglsdl/openglsdl-graphics.h b/backends/graphics/openglsdl/openglsdl-graphics.h index f11782131c..2db9c2dbe6 100644 --- a/backends/graphics/openglsdl/openglsdl-graphics.h +++ b/backends/graphics/openglsdl/openglsdl-graphics.h @@ -63,7 +63,7 @@ protected: virtual bool handleScalerHotkeys(Common::KeyCode key); virtual bool isScalerHotkey(const Common::Event &event); - virtual void toggleFullScreen(); + virtual void toggleFullScreen(bool loop); // Hardware screen SDL_Surface *_hwscreen; diff --git a/backends/graphics/sdl/sdl-graphics.cpp b/backends/graphics/sdl/sdl-graphics.cpp index c2f859a949..2d61cec185 100644 --- a/backends/graphics/sdl/sdl-graphics.cpp +++ b/backends/graphics/sdl/sdl-graphics.cpp @@ -2153,7 +2153,7 @@ bool SdlGraphicsManager::notifyEvent(const Common::Event &event) { } // Ctrl-Alt-<key> will change the GFX mode - if ((event.kbd.flags & (Common::KBD_CTRL|Common::KBD_ALT)) == (Common::KBD_CTRL|Common::KBD_ALT)) { + if (event.kbd.hasFlags(Common::KBD_CTRL|Common::KBD_ALT)) { if (handleScalerHotkeys(event.kbd.keycode)) return true; } |