diff options
author | Colin Snover | 2017-10-15 13:26:39 -0500 |
---|---|---|
committer | Colin Snover | 2017-10-15 13:26:39 -0500 |
commit | 7d8d2f80fbc9cf96b3bd03b85a9722b576d23adc (patch) | |
tree | a35cf3cd386219e8c945ba8aacc3e20c442fbf69 /backends/graphics/opengl/opengl-graphics.cpp | |
parent | 7fc86195343adf962054fd52605c3a3cc8b501e9 (diff) | |
parent | 4757c24c683c2f2b8e3b55aa8d7a767aad9e947e (diff) | |
download | scummvm-rg350-7d8d2f80fbc9cf96b3bd03b85a9722b576d23adc.tar.gz scummvm-rg350-7d8d2f80fbc9cf96b3bd03b85a9722b576d23adc.tar.bz2 scummvm-rg350-7d8d2f80fbc9cf96b3bd03b85a9722b576d23adc.zip |
Merge branch 'graphics-backends-improvements'
Diffstat (limited to 'backends/graphics/opengl/opengl-graphics.cpp')
-rw-r--r-- | backends/graphics/opengl/opengl-graphics.cpp | 248 |
1 files changed, 64 insertions, 184 deletions
diff --git a/backends/graphics/opengl/opengl-graphics.cpp b/backends/graphics/opengl/opengl-graphics.cpp index 28ca110d91..7bac4c85cb 100644 --- a/backends/graphics/opengl/opengl-graphics.cpp +++ b/backends/graphics/opengl/opengl-graphics.cpp @@ -53,14 +53,12 @@ namespace OpenGL { OpenGLGraphicsManager::OpenGLGraphicsManager() : _currentState(), _oldState(), _transactionMode(kTransactionNone), _screenChangeID(1 << (sizeof(int) * 8 - 2)), _pipeline(nullptr), - _outputScreenWidth(0), _outputScreenHeight(0), _displayX(0), _displayY(0), - _displayWidth(0), _displayHeight(0), _defaultFormat(), _defaultFormatAlpha(), + _defaultFormat(), _defaultFormatAlpha(), _gameScreen(nullptr), _gameScreenShakeOffset(0), _overlay(nullptr), - _overlayVisible(false), _cursor(nullptr), - _cursorX(0), _cursorY(0), _cursorDisplayX(0),_cursorDisplayY(0), _cursorHotspotX(0), _cursorHotspotY(0), + _cursor(nullptr), + _cursorHotspotX(0), _cursorHotspotY(0), _cursorHotspotXScaled(0), _cursorHotspotYScaled(0), _cursorWidthScaled(0), _cursorHeightScaled(0), - _cursorKeyColor(0), _cursorVisible(false), _cursorDontScale(false), _cursorPaletteEnabled(false), - _forceRedraw(false) + _cursorKeyColor(0), _cursorDontScale(false), _cursorPaletteEnabled(false) #ifdef USE_OSD , _osdMessageChangeRequest(false), _osdMessageAlpha(0), _osdMessageFadeStartTime(0), _osdMessageSurface(nullptr), _osdIconSurface(nullptr) @@ -83,7 +81,7 @@ OpenGLGraphicsManager::~OpenGLGraphicsManager() { #endif } -bool OpenGLGraphicsManager::hasFeature(OSystem::Feature f) { +bool OpenGLGraphicsManager::hasFeature(OSystem::Feature f) const { switch (f) { case OSystem::kFeatureAspectRatioCorrection: case OSystem::kFeatureCursorPalette: @@ -129,7 +127,7 @@ void OpenGLGraphicsManager::setFeatureState(OSystem::Feature f, bool enable) { } } -bool OpenGLGraphicsManager::getFeatureState(OSystem::Feature f) { +bool OpenGLGraphicsManager::getFeatureState(OSystem::Feature f) const { switch (f) { case OSystem::kFeatureAspectRatioCorrection: return _currentState.aspectRatioCorrection; @@ -220,10 +218,9 @@ OSystem::TransactionError OpenGLGraphicsManager::endGFXTransaction() { #endif do { - uint requestedWidth = _currentState.gameWidth; - uint requestedHeight = _currentState.gameHeight; - const uint desiredAspect = getDesiredGameScreenAspect(); - requestedHeight = intToFrac(requestedWidth) / desiredAspect; + const uint desiredAspect = getDesiredGameAspectRatio(); + const uint requestedWidth = _currentState.gameWidth; + const uint requestedHeight = intToFrac(requestedWidth) / desiredAspect; if (!loadVideoMode(requestedWidth, requestedHeight, #ifdef USE_RGB_COLOR @@ -317,7 +314,7 @@ OSystem::TransactionError OpenGLGraphicsManager::endGFXTransaction() { // Update our display area and cursor scaling. This makes sure we pick up // aspect ratio correction and game screen changes correctly. - recalculateDisplayArea(); + recalculateDisplayAreas(); recalculateCursorScaling(); // Something changed, so update the screen change ID. @@ -347,11 +344,11 @@ void OpenGLGraphicsManager::initSize(uint width, uint height, const Graphics::Pi _currentState.gameHeight = height; } -int16 OpenGLGraphicsManager::getWidth() { +int16 OpenGLGraphicsManager::getWidth() const { return _currentState.gameWidth; } -int16 OpenGLGraphicsManager::getHeight() { +int16 OpenGLGraphicsManager::getHeight() const { return _currentState.gameHeight; } @@ -392,6 +389,7 @@ void OpenGLGraphicsManager::updateScreen() { // We only update the screen when there actually have been any changes. if ( !_forceRedraw + && !_cursorNeedsRedraw && !_gameScreen->isDirty() && !(_overlayVisible && _overlay->isDirty()) && !(_cursorVisible && _cursor && _cursor->isDirty()) @@ -401,7 +399,6 @@ void OpenGLGraphicsManager::updateScreen() { ) { return; } - _forceRedraw = false; // Update changes to textures. _gameScreen->updateGLTexture(); @@ -420,14 +417,14 @@ void OpenGLGraphicsManager::updateScreen() { _backBuffer.enableScissorTest(true); } - const GLfloat shakeOffset = _gameScreenShakeOffset * (GLfloat)_displayHeight / _gameScreen->getHeight(); + const GLfloat shakeOffset = _gameScreenShakeOffset * (GLfloat)_gameDrawRect.height() / _gameScreen->getHeight(); // First step: Draw the (virtual) game screen. - g_context.getActivePipeline()->drawTexture(_gameScreen->getGLTexture(), _displayX, _displayY + shakeOffset, _displayWidth, _displayHeight); + g_context.getActivePipeline()->drawTexture(_gameScreen->getGLTexture(), _gameDrawRect.left, _gameDrawRect.top + shakeOffset, _gameDrawRect.width(), _gameDrawRect.height()); // Second step: Draw the overlay if visible. if (_overlayVisible) { - g_context.getActivePipeline()->drawTexture(_overlay->getGLTexture(), 0, 0, _outputScreenWidth, _outputScreenHeight); + g_context.getActivePipeline()->drawTexture(_overlay->getGLTexture(), 0, 0, _overlayDrawRect.width(), _overlayDrawRect.height()); } // Third step: Draw the cursor if visible. @@ -437,8 +434,8 @@ void OpenGLGraphicsManager::updateScreen() { const GLfloat cursorOffset = _overlayVisible ? 0 : shakeOffset; g_context.getActivePipeline()->drawTexture(_cursor->getGLTexture(), - _cursorDisplayX - _cursorHotspotXScaled, - _cursorDisplayY - _cursorHotspotYScaled + cursorOffset, + _cursorX - _cursorHotspotXScaled, + _cursorY - _cursorHotspotYScaled + cursorOffset, _cursorWidthScaled, _cursorHeightScaled); } @@ -464,8 +461,8 @@ void OpenGLGraphicsManager::updateScreen() { // Set the OSD transparency. g_context.getActivePipeline()->setColor(1.0f, 1.0f, 1.0f, _osdMessageAlpha / 100.0f); - int dstX = (_outputScreenWidth - _osdMessageSurface->getWidth()) / 2; - int dstY = (_outputScreenHeight - _osdMessageSurface->getHeight()) / 2; + int dstX = (_windowWidth - _osdMessageSurface->getWidth()) / 2; + int dstY = (_windowHeight - _osdMessageSurface->getHeight()) / 2; // Draw the OSD texture. g_context.getActivePipeline()->drawTexture(_osdMessageSurface->getGLTexture(), @@ -481,7 +478,7 @@ void OpenGLGraphicsManager::updateScreen() { } if (_osdIconSurface) { - int dstX = _outputScreenWidth - _osdIconSurface->getWidth() - kOSDIconRightMargin; + int dstX = _windowWidth - _osdIconSurface->getWidth() - kOSDIconRightMargin; int dstY = kOSDIconTopMargin; // Draw the OSD icon texture. @@ -490,6 +487,8 @@ void OpenGLGraphicsManager::updateScreen() { } #endif + _cursorNeedsRedraw = false; + _forceRedraw = false; refreshScreen(); } @@ -507,7 +506,7 @@ void OpenGLGraphicsManager::setFocusRectangle(const Common::Rect& rect) { void OpenGLGraphicsManager::clearFocusRectangle() { } -int16 OpenGLGraphicsManager::getOverlayWidth() { +int16 OpenGLGraphicsManager::getOverlayWidth() const { if (_overlay) { return _overlay->getWidth(); } else { @@ -515,7 +514,7 @@ int16 OpenGLGraphicsManager::getOverlayWidth() { } } -int16 OpenGLGraphicsManager::getOverlayHeight() { +int16 OpenGLGraphicsManager::getOverlayHeight() const { if (_overlay) { return _overlay->getHeight(); } else { @@ -523,22 +522,6 @@ int16 OpenGLGraphicsManager::getOverlayHeight() { } } -void OpenGLGraphicsManager::showOverlay() { - _overlayVisible = true; - _forceRedraw = true; - - // Update cursor position. - setMousePosition(_cursorX, _cursorY); -} - -void OpenGLGraphicsManager::hideOverlay() { - _overlayVisible = false; - _forceRedraw = true; - - // Update cursor position. - setMousePosition(_cursorX, _cursorY); -} - Graphics::PixelFormat OpenGLGraphicsManager::getOverlayFormat() const { return _overlay->getFormat(); } @@ -551,7 +534,7 @@ void OpenGLGraphicsManager::clearOverlay() { _overlay->fill(0); } -void OpenGLGraphicsManager::grabOverlay(void *buf, int pitch) { +void OpenGLGraphicsManager::grabOverlay(void *buf, int pitch) const { const Graphics::Surface *overlayData = _overlay->getSurface(); const byte *src = (const byte *)overlayData->getPixels(); @@ -564,55 +547,6 @@ void OpenGLGraphicsManager::grabOverlay(void *buf, int pitch) { } } -bool OpenGLGraphicsManager::showMouse(bool visible) { - // In case the mouse cursor visibility changed we need to redraw the whole - // screen even when nothing else changed. - if (_cursorVisible != visible) { - _forceRedraw = true; - } - - bool last = _cursorVisible; - _cursorVisible = visible; - return last; -} - -void OpenGLGraphicsManager::warpMouse(int x, int y) { - int16 currentX = _cursorX; - int16 currentY = _cursorY; - adjustMousePosition(currentX, currentY); - - // Check whether the (virtual) coordinate actually changed. If not, then - // simply do nothing. This avoids ugly "jittering" due to the actual - // output screen having a bigger resolution than the virtual coordinates. - if (currentX == x && currentY == y) { - return; - } - - // Scale the virtual coordinates into actual physical coordinates. - if (_overlayVisible) { - if (!_overlay) { - return; - } - - // It might be confusing that we actually have to handle something - // here when the overlay is visible. This is because for very small - // resolutions we have a minimal overlay size and have to adjust - // for that. - x = (x * _outputScreenWidth) / _overlay->getWidth(); - y = (y * _outputScreenHeight) / _overlay->getHeight(); - } else { - if (!_gameScreen) { - return; - } - - x = (x * _outputScreenWidth) / _gameScreen->getWidth(); - y = (y * _outputScreenHeight) / _gameScreen->getHeight(); - } - - setMousePosition(x, y); - setInternalMousePosition(x, y); -} - namespace { template<typename DstPixel, typename SrcPixel> void applyColorKey(DstPixel *dst, const SrcPixel *src, uint w, uint h, uint dstPitch, uint srcPitch, SrcPixel keyColor, DstPixel alphaMask) { @@ -633,6 +567,18 @@ void applyColorKey(DstPixel *dst, const SrcPixel *src, uint w, uint h, uint dstP } // End of anonymous namespace void OpenGLGraphicsManager::setMouseCursor(const void *buf, uint w, uint h, int hotspotX, int hotspotY, uint32 keycolor, bool dontScale, const Graphics::PixelFormat *format) { + + _cursorKeyColor = keycolor; + _cursorHotspotX = hotspotX; + _cursorHotspotY = hotspotY; + _cursorDontScale = dontScale; + + if (!w || !h) { + delete _cursor; + _cursor = nullptr; + return; + } + Graphics::PixelFormat inputFormat; #ifdef USE_RGB_COLOR if (format) { @@ -668,11 +614,6 @@ void OpenGLGraphicsManager::setMouseCursor(const void *buf, uint w, uint h, int _cursor->enableLinearFiltering(_currentState.filtering); } - _cursorKeyColor = keycolor; - _cursorHotspotX = hotspotX; - _cursorHotspotY = hotspotY; - _cursorDontScale = dontScale; - _cursor->allocate(w, h); if (inputFormat.bytesPerPixel == 1) { // For CLUT8 cursors we can simply copy the input data into the @@ -720,7 +661,6 @@ void OpenGLGraphicsManager::setMouseCursor(const void *buf, uint w, uint h, int updateCursorPalette(); } - // Update the scaling. recalculateCursorScaling(); } @@ -765,8 +705,8 @@ void OpenGLGraphicsManager::osdMessageUpdateSurface() { } // Clip the rect - width = MIN<uint>(width, _displayWidth); - height = MIN<uint>(height, _displayHeight); + width = MIN<uint>(width, _gameDrawRect.width()); + height = MIN<uint>(height, _gameDrawRect.height()); delete _osdMessageSurface; _osdMessageSurface = nullptr; @@ -849,16 +789,13 @@ void OpenGLGraphicsManager::setPalette(const byte *colors, uint start, uint num) updateCursorPalette(); } -void OpenGLGraphicsManager::grabPalette(byte *colors, uint start, uint num) { +void OpenGLGraphicsManager::grabPalette(byte *colors, uint start, uint num) const { assert(_gameScreen->hasPalette()); memcpy(colors, _gamePalette + start * 3, num * 3); } -void OpenGLGraphicsManager::setActualScreenSize(uint width, uint height) { - _outputScreenWidth = width; - _outputScreenHeight = height; - +void OpenGLGraphicsManager::handleResizeImpl(const int width, const int height) { // Setup backbuffer size. _backBuffer.setDimensions(width, height); @@ -873,7 +810,7 @@ void OpenGLGraphicsManager::setActualScreenSize(uint width, uint height) { // anyway. Thus, it should not be a real issue for modern hardware. if ( overlayWidth > (uint)g_context.maxTextureSize || overlayHeight > (uint)g_context.maxTextureSize) { - const frac_t outputAspect = intToFrac(_outputScreenWidth) / _outputScreenHeight; + const frac_t outputAspect = intToFrac(_windowWidth) / _windowHeight; if (outputAspect > (frac_t)FRAC_ONE) { overlayWidth = g_context.maxTextureSize; @@ -906,7 +843,7 @@ void OpenGLGraphicsManager::setActualScreenSize(uint width, uint height) { _overlay->fill(0); // Re-setup the scaling for the screen and cursor - recalculateDisplayArea(); + recalculateDisplayAreas(); recalculateCursorScaling(); // Something changed, so update the screen change ID. @@ -960,8 +897,8 @@ void OpenGLGraphicsManager::notifyContextCreate(const Graphics::PixelFormat &def GL_CALL(glPixelStorei(GL_PACK_ALIGNMENT, 4)); // Refresh the output screen dimensions if some are set up. - if (_outputScreenWidth != 0 && _outputScreenHeight != 0) { - setActualScreenSize(_outputScreenWidth, _outputScreenHeight); + if (_windowWidth != 0 && _windowHeight != 0) { + handleResize(_windowWidth, _windowHeight); } // TODO: Should we try to convert textures into one of those formats if @@ -1031,46 +968,6 @@ void OpenGLGraphicsManager::notifyContextDestroy() { g_context.reset(); } -void OpenGLGraphicsManager::adjustMousePosition(int16 &x, int16 &y) { - if (_overlayVisible) { - // It might be confusing that we actually have to handle something - // here when the overlay is visible. This is because for very small - // resolutions we have a minimal overlay size and have to adjust - // for that. - // This can also happen when the overlay is smaller than the actual - // display size because of texture size limitations. - if (_overlay) { - x = (x * _overlay->getWidth()) / _outputScreenWidth; - y = (y * _overlay->getHeight()) / _outputScreenHeight; - } - } else if (_gameScreen) { - const int16 width = _gameScreen->getWidth(); - const int16 height = _gameScreen->getHeight(); - - x = (x * width) / (int)_outputScreenWidth; - y = (y * height) / (int)_outputScreenHeight; - } -} - -void OpenGLGraphicsManager::setMousePosition(int x, int y) { - // Whenever the mouse position changed we force a screen redraw to reflect - // changes properly. - if (_cursorX != x || _cursorY != y) { - _forceRedraw = true; - } - - _cursorX = x; - _cursorY = y; - - if (_overlayVisible) { - _cursorDisplayX = x; - _cursorDisplayY = y; - } else { - _cursorDisplayX = _displayX + (x * _displayWidth) / _outputScreenWidth; - _cursorDisplayY = _displayY + (y * _displayHeight) / _outputScreenHeight; - } -} - Surface *OpenGLGraphicsManager::createSurface(const Graphics::PixelFormat &format, bool wantAlpha) { GLenum glIntFormat, glFormat, glType; if (format.bytesPerPixel == 1) { @@ -1191,51 +1088,34 @@ bool OpenGLGraphicsManager::getGLPixelFormat(const Graphics::PixelFormat &pixelF } } -frac_t OpenGLGraphicsManager::getDesiredGameScreenAspect() const { - const uint width = _currentState.gameWidth; - const uint height = _currentState.gameHeight; - +bool OpenGLGraphicsManager::gameNeedsAspectRatioCorrection() const { if (_currentState.aspectRatioCorrection) { + const uint width = getWidth(); + const uint height = getHeight(); + // In case we enable aspect ratio correction we force a 4/3 ratio. // But just for 320x200 and 640x400 games, since other games do not need // this. - if ((width == 320 && height == 200) || (width == 640 && height == 400)) { - return intToFrac(4) / 3; - } + return (width == 320 && height == 200) || (width == 640 && height == 400); } - return intToFrac(width) / height; + return false; } -void OpenGLGraphicsManager::recalculateDisplayArea() { - if (!_gameScreen || _outputScreenHeight == 0) { +void OpenGLGraphicsManager::recalculateDisplayAreas() { + if (!_gameScreen) { return; } - const frac_t outputAspect = intToFrac(_outputScreenWidth) / _outputScreenHeight; - const frac_t desiredAspect = getDesiredGameScreenAspect(); - - _displayWidth = _outputScreenWidth; - _displayHeight = _outputScreenHeight; - - // Adjust one dimension for mantaining the aspect ratio. - if (outputAspect < desiredAspect) { - _displayHeight = intToFrac(_displayWidth) / desiredAspect; - } else if (outputAspect > desiredAspect) { - _displayWidth = fracToInt(_displayHeight * desiredAspect); - } - - // We center the screen in the middle for now. - _displayX = (_outputScreenWidth - _displayWidth ) / 2; - _displayY = (_outputScreenHeight - _displayHeight) / 2; + WindowedGraphicsManager::recalculateDisplayAreas(); // Setup drawing limitation for game graphics. // This involves some trickery because OpenGL's viewport coordinate system // is upside down compared to ours. - _backBuffer.setScissorBox(_displayX, - _outputScreenHeight - _displayHeight - _displayY, - _displayWidth, - _displayHeight); + _backBuffer.setScissorBox(_gameDrawRect.left, + _windowHeight - _gameDrawRect.height() - _gameDrawRect.top, + _gameDrawRect.width(), + _gameDrawRect.height()); // Update the cursor position to adjust for new display area. setMousePosition(_cursorX, _cursorY); @@ -1272,8 +1152,8 @@ void OpenGLGraphicsManager::recalculateCursorScaling() { // In case scaling is actually enabled we will scale the cursor according // to the game screen. if (!_cursorDontScale) { - const frac_t screenScaleFactorX = intToFrac(_displayWidth) / _gameScreen->getWidth(); - const frac_t screenScaleFactorY = intToFrac(_displayHeight) / _gameScreen->getHeight(); + const frac_t screenScaleFactorX = intToFrac(_gameDrawRect.width()) / _gameScreen->getWidth(); + const frac_t screenScaleFactorY = intToFrac(_gameDrawRect.height()) / _gameScreen->getHeight(); _cursorHotspotXScaled = fracToInt(_cursorHotspotXScaled * screenScaleFactorX); _cursorWidthScaled = fracToInt(_cursorWidthScaled * screenScaleFactorX); @@ -1284,14 +1164,14 @@ void OpenGLGraphicsManager::recalculateCursorScaling() { } #ifdef USE_OSD -const Graphics::Font *OpenGLGraphicsManager::getFontOSD() { +const Graphics::Font *OpenGLGraphicsManager::getFontOSD() const { return FontMan.getFontByUsage(Graphics::FontManager::kLocalizedFont); } #endif bool OpenGLGraphicsManager::saveScreenshot(const Common::String &filename) const { - const uint width = _outputScreenWidth; - const uint height = _outputScreenHeight; + const uint width = _windowWidth; + const uint height = _windowHeight; // A line of a BMP image must have a size divisible by 4. // We calculate the padding bytes needed here. |