From de2bbe3b9738ef95b2529db989570770ef434f9d Mon Sep 17 00:00:00 2001 From: Colin Snover Date: Wed, 19 Jul 2017 19:15:12 -0500 Subject: BACKENDS: Refactor OpenGL & SDL graphics backends This patch refactors the OpenGL and SDL graphics backends, primarily to unify window scaling and mouse handling, and to fix coordinate mapping between the ScummVM window and the virtual game screen when they have different aspect ratios. Unified code for these two backends has been moved to a new header-only WindowedGraphicsManager class, so named because it contains code for managing graphics managers that interact with a windowing system and render virtual screens within a larger physical content window. The biggest behavioral change here is with the coordinate system mapping: Previously, mouse offsets were converted by mapping the whole space within the window as input to the virtual game screen without maintaining aspect ratio. This was done to prevent 'stickiness' when the mouse cursor was within the window but outside of the virtual game screen, but it caused noticeable distortion of mouse movement speed on the axis with blank space. Instead of introducing mouse speed distortion to prevent stickiness, this patch changes coordinate transformation to show the system cursor when the mouse moves outside of the virtual game screen when mouse grab is off, or by holding the mouse inside the virtual game screen (instead of the entire window) when mouse grab is on. This patch also improves some other properties of the GraphicsManager/PaletteManager interfaces: * Nullipotent operations (getWidth, getHeight, etc.) of the PaletteManager/GraphicsManager interfaces are now const * Methods marked `virtual` but not inherited by any subclass have been de-virtualized * Extra unnecessary calculations of hardware height in SurfaceSdlGraphicsManager have been removed * Methods have been renamed where appropriate for clarity (setWindowSize -> handleResize, etc.) * C++11 support improved with `override` specifier added on overridden virtual methods in subclasses (primarily to avoid myself accidentally creating new methods in the subclasses by changing types/names during refactoring) Additional refactoring can and should be done at some point to continue to deduplicate code between the OpenGL and SDL backends. Since the primary goal here was to improve the coordinate mapping, full refactoring of these backends was not completed here. --- backends/graphics/opengl/opengl-graphics.cpp | 221 +++++++-------------------- 1 file changed, 53 insertions(+), 168 deletions(-) (limited to 'backends/graphics/opengl/opengl-graphics.cpp') diff --git a/backends/graphics/opengl/opengl-graphics.cpp b/backends/graphics/opengl/opengl-graphics.cpp index 28ca110d91..d98dcda599 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), _cursorVisible(false), _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(); @@ -568,7 +551,7 @@ 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; + _cursorNeedsRedraw = true; } bool last = _cursorVisible; @@ -576,43 +559,6 @@ bool OpenGLGraphicsManager::showMouse(bool 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 void applyColorKey(DstPixel *dst, const SrcPixel *src, uint w, uint h, uint dstPitch, uint srcPitch, SrcPixel keyColor, DstPixel alphaMask) { @@ -720,7 +666,6 @@ void OpenGLGraphicsManager::setMouseCursor(const void *buf, uint w, uint h, int updateCursorPalette(); } - // Update the scaling. recalculateCursorScaling(); } @@ -765,8 +710,8 @@ void OpenGLGraphicsManager::osdMessageUpdateSurface() { } // Clip the rect - width = MIN(width, _displayWidth); - height = MIN(height, _displayHeight); + width = MIN(width, _gameDrawRect.width()); + height = MIN(height, _gameDrawRect.height()); delete _osdMessageSurface; _osdMessageSurface = nullptr; @@ -849,16 +794,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 +815,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 +848,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 +902,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 +973,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 +1093,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 +1157,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 +1169,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. -- cgit v1.2.3 From da0a8db704f610994d665dfd7c080b49476ce76d Mon Sep 17 00:00:00 2001 From: Colin Snover Date: Wed, 13 Sep 2017 00:43:56 -0500 Subject: BACKENDS: Also hide mouse cursor outside game area when an engine has hidden the cursor The only reason we show the system cursor outside the game area is to show users where their mouse is when the window is resized and the mouse is outside the game area. If the game cannot be interacted with, then the mouse also does not need to be shown in the black areas. --- backends/graphics/opengl/opengl-graphics.cpp | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) (limited to 'backends/graphics/opengl/opengl-graphics.cpp') diff --git a/backends/graphics/opengl/opengl-graphics.cpp b/backends/graphics/opengl/opengl-graphics.cpp index d98dcda599..f3ea372b2a 100644 --- a/backends/graphics/opengl/opengl-graphics.cpp +++ b/backends/graphics/opengl/opengl-graphics.cpp @@ -58,7 +58,7 @@ OpenGLGraphicsManager::OpenGLGraphicsManager() _cursor(nullptr), _cursorHotspotX(0), _cursorHotspotY(0), _cursorHotspotXScaled(0), _cursorHotspotYScaled(0), _cursorWidthScaled(0), _cursorHeightScaled(0), - _cursorKeyColor(0), _cursorVisible(false), _cursorDontScale(false), _cursorPaletteEnabled(false) + _cursorKeyColor(0), _cursorDontScale(false), _cursorPaletteEnabled(false) #ifdef USE_OSD , _osdMessageChangeRequest(false), _osdMessageAlpha(0), _osdMessageFadeStartTime(0), _osdMessageSurface(nullptr), _osdIconSurface(nullptr) @@ -547,18 +547,6 @@ void OpenGLGraphicsManager::grabOverlay(void *buf, int pitch) const { } } -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) { - _cursorNeedsRedraw = true; - } - - bool last = _cursorVisible; - _cursorVisible = visible; - return last; -} - namespace { template void applyColorKey(DstPixel *dst, const SrcPixel *src, uint w, uint h, uint dstPitch, uint srcPitch, SrcPixel keyColor, DstPixel alphaMask) { -- cgit v1.2.3 From 5d8cf6ba42c71e37530e83bb766b60bf1388a904 Mon Sep 17 00:00:00 2001 From: Colin Snover Date: Wed, 13 Sep 2017 00:47:44 -0500 Subject: BACKENDS: Fix GraphicsManager handling of empty cursors The SDL graphics manager was just ignoring calls from CursorMan to set the cursor to a blank cursor, which meant engines that did not immediately send a cursor to CursorMan at startup would still show the launcher's cursor (usually with a broken palette). The OpenGL graphics manager would try to generate and draw an invalid cursor surface when receiving an empty cursor. --- backends/graphics/opengl/opengl-graphics.cpp | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) (limited to 'backends/graphics/opengl/opengl-graphics.cpp') diff --git a/backends/graphics/opengl/opengl-graphics.cpp b/backends/graphics/opengl/opengl-graphics.cpp index f3ea372b2a..7bac4c85cb 100644 --- a/backends/graphics/opengl/opengl-graphics.cpp +++ b/backends/graphics/opengl/opengl-graphics.cpp @@ -567,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) { @@ -602,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 -- cgit v1.2.3