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 | |
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'
35 files changed, 1284 insertions, 1223 deletions
diff --git a/backends/events/default/default-events.cpp b/backends/events/default/default-events.cpp index c7c39da069..667914b023 100644 --- a/backends/events/default/default-events.cpp +++ b/backends/events/default/default-events.cpp @@ -254,4 +254,30 @@ void DefaultEventManager::pushEvent(const Common::Event &event) { _artificialEventSource.addEvent(event); } +void DefaultEventManager::purgeMouseEvents() { + _dispatcher.dispatch(); + + Common::Queue<Common::Event> filteredQueue; + while (!_eventQueue.empty()) { + Common::Event event = _eventQueue.pop(); + switch (event.type) { + case Common::EVENT_MOUSEMOVE: + case Common::EVENT_LBUTTONDOWN: + case Common::EVENT_LBUTTONUP: + case Common::EVENT_RBUTTONDOWN: + case Common::EVENT_RBUTTONUP: + case Common::EVENT_WHEELUP: + case Common::EVENT_WHEELDOWN: + case Common::EVENT_MBUTTONDOWN: + case Common::EVENT_MBUTTONUP: + // do nothing + break; + default: + filteredQueue.push(event); + break; + } + } + _eventQueue = filteredQueue; +} + #endif // !defined(DISABLE_DEFAULT_EVENTMANAGER) diff --git a/backends/events/default/default-events.h b/backends/events/default/default-events.h index f378fb9ff0..38406c25aa 100644 --- a/backends/events/default/default-events.h +++ b/backends/events/default/default-events.h @@ -80,6 +80,7 @@ public: virtual void init(); virtual bool pollEvent(Common::Event &event); virtual void pushEvent(const Common::Event &event); + virtual void purgeMouseEvents() override; virtual Common::Point getMousePos() const { return _mousePos; } virtual int getButtonState() const { return _buttonState; } diff --git a/backends/events/sdl/sdl-events.cpp b/backends/events/sdl/sdl-events.cpp index fb5a4c9b09..91ca0f5df6 100644 --- a/backends/events/sdl/sdl-events.cpp +++ b/backends/events/sdl/sdl-events.cpp @@ -75,7 +75,7 @@ static uint32 convUTF8ToUTF32(const char *src) { #endif SdlEventSource::SdlEventSource() - : EventSource(), _scrollLock(false), _joystick(0), _lastScreenID(0), _graphicsManager(0) + : EventSource(), _scrollLock(false), _joystick(0), _lastScreenID(0), _graphicsManager(0), _queuedFakeMouseMove(false) #if SDL_VERSION_ATLEAST(2, 0, 0) , _queuedFakeKeyUp(false), _fakeKeyUp() #endif @@ -158,7 +158,7 @@ int SdlEventSource::mapKey(SDLKey sdlKey, SDLMod mod, Uint16 unicode) { } else if (key >= Common::KEYCODE_UP && key <= Common::KEYCODE_PAGEDOWN) { return key; } else if (unicode) { - // Return unicode in case it's stil set and wasn't filtered. + // Return unicode in case it's still set and wasn't filtered. return unicode; } else if (key >= 'a' && key <= 'z' && (mod & KMOD_SHIFT)) { return key & ~0x20; @@ -169,14 +169,15 @@ int SdlEventSource::mapKey(SDLKey sdlKey, SDLMod mod, Uint16 unicode) { } } -void SdlEventSource::processMouseEvent(Common::Event &event, int x, int y) { +bool SdlEventSource::processMouseEvent(Common::Event &event, int x, int y) { event.mouse.x = x; event.mouse.y = y; if (_graphicsManager) { - _graphicsManager->notifyMousePos(Common::Point(x, y)); - _graphicsManager->transformMouseCoordinates(event.mouse); + return _graphicsManager->notifyMousePosition(event.mouse); } + + return true; } bool SdlEventSource::handleKbdMouse(Common::Event &event) { @@ -308,8 +309,7 @@ bool SdlEventSource::handleKbdMouse(Common::Event &event) { if (_km.x != oldKmX || _km.y != oldKmY) { event.type = Common::EVENT_MOUSEMOVE; - processMouseEvent(event, _km.x / MULTIPLIER, _km.y / MULTIPLIER); - return true; + return processMouseEvent(event, _km.x / MULTIPLIER, _km.y / MULTIPLIER); } } } @@ -508,6 +508,12 @@ bool SdlEventSource::pollEvent(Common::Event &event) { return true; } + if (_queuedFakeMouseMove) { + event = _fakeMouseMove; + _queuedFakeMouseMove = false; + return true; + } + SDL_Event ev; while (SDL_PollEvent(&ev)) { preprocessEvents(&ev); @@ -549,7 +555,9 @@ bool SdlEventSource::dispatchSDLEvent(SDL_Event &ev, Common::Event &event) { // with a mouse wheel event. However, SDL2 does not supply // these, thus we use whatever we got last time. It seems // these are always stored in _km.x, _km.y. - processMouseEvent(event, _km.x / MULTIPLIER, _km.y / MULTIPLIER); + if (!processMouseEvent(event, _km.x / MULTIPLIER, _km.y / MULTIPLIER)) { + return false; + } if (yDir < 0) { event.type = Common::EVENT_WHEELDOWN; return true; @@ -740,12 +748,12 @@ bool SdlEventSource::handleKeyUp(SDL_Event &ev, Common::Event &event) { bool SdlEventSource::handleMouseMotion(SDL_Event &ev, Common::Event &event) { event.type = Common::EVENT_MOUSEMOVE; - processMouseEvent(event, ev.motion.x, ev.motion.y); + // update KbdMouse _km.x = ev.motion.x * MULTIPLIER; _km.y = ev.motion.y * MULTIPLIER; - return true; + return processMouseEvent(event, ev.motion.x, ev.motion.y); } bool SdlEventSource::handleMouseButtonDown(SDL_Event &ev, Common::Event &event) { @@ -766,12 +774,11 @@ bool SdlEventSource::handleMouseButtonDown(SDL_Event &ev, Common::Event &event) else return false; - processMouseEvent(event, ev.button.x, ev.button.y); // update KbdMouse _km.x = ev.button.x * MULTIPLIER; _km.y = ev.button.y * MULTIPLIER; - return true; + return processMouseEvent(event, ev.button.x, ev.button.y); } bool SdlEventSource::handleMouseButtonUp(SDL_Event &ev, Common::Event &event) { @@ -785,21 +792,21 @@ bool SdlEventSource::handleMouseButtonUp(SDL_Event &ev, Common::Event &event) { #endif else return false; - processMouseEvent(event, ev.button.x, ev.button.y); + // update KbdMouse _km.x = ev.button.x * MULTIPLIER; _km.y = ev.button.y * MULTIPLIER; - return true; + return processMouseEvent(event, ev.button.x, ev.button.y); } bool SdlEventSource::handleJoyButtonDown(SDL_Event &ev, Common::Event &event) { if (ev.jbutton.button == JOY_BUT_LMOUSE) { event.type = Common::EVENT_LBUTTONDOWN; - processMouseEvent(event, _km.x / MULTIPLIER, _km.y / MULTIPLIER); + return processMouseEvent(event, _km.x / MULTIPLIER, _km.y / MULTIPLIER); } else if (ev.jbutton.button == JOY_BUT_RMOUSE) { event.type = Common::EVENT_RBUTTONDOWN; - processMouseEvent(event, _km.x / MULTIPLIER, _km.y / MULTIPLIER); + return processMouseEvent(event, _km.x / MULTIPLIER, _km.y / MULTIPLIER); } else { event.type = Common::EVENT_KEYDOWN; switch (ev.jbutton.button) { @@ -820,17 +827,17 @@ bool SdlEventSource::handleJoyButtonDown(SDL_Event &ev, Common::Event &event) { event.kbd.ascii = mapKey(SDLK_F5, (SDLMod)ev.key.keysym.mod, 0); break; } + return true; } - return true; } bool SdlEventSource::handleJoyButtonUp(SDL_Event &ev, Common::Event &event) { if (ev.jbutton.button == JOY_BUT_LMOUSE) { event.type = Common::EVENT_LBUTTONUP; - processMouseEvent(event, _km.x / MULTIPLIER, _km.y / MULTIPLIER); + return processMouseEvent(event, _km.x / MULTIPLIER, _km.y / MULTIPLIER); } else if (ev.jbutton.button == JOY_BUT_RMOUSE) { event.type = Common::EVENT_RBUTTONUP; - processMouseEvent(event, _km.x / MULTIPLIER, _km.y / MULTIPLIER); + return processMouseEvent(event, _km.x / MULTIPLIER, _km.y / MULTIPLIER); } else { event.type = Common::EVENT_KEYUP; switch (ev.jbutton.button) { @@ -851,8 +858,8 @@ bool SdlEventSource::handleJoyButtonUp(SDL_Event &ev, Common::Event &event) { event.kbd.ascii = mapKey(SDLK_F5, (SDLMod)ev.key.keysym.mod, 0); break; } + return true; } - return true; } bool SdlEventSource::handleJoyAxisMotion(SDL_Event &ev, Common::Event &event) { @@ -968,9 +975,8 @@ bool SdlEventSource::remapKey(SDL_Event &ev, Common::Event &event) { event.kbd.keycode = Common::KEYCODE_F5; event.kbd.ascii = mapKey(SDLK_F5, ev.key.keysym.mod, 0); } - // Nap center (space) to tab (default action ) + // Map center (space) to tab (default action) // I wanted to map the calendar button but the calendar comes up - // else if (ev.key.keysym.sym == SDLK_SPACE) { event.type = Common::EVENT_KEYDOWN; event.kbd.keycode = Common::KEYCODE_TAB; @@ -1003,6 +1009,12 @@ void SdlEventSource::resetKeyboardEmulation(int16 x_max, int16 y_max) { _km.joy_y = 0; } +void SdlEventSource::fakeWarpMouse(const int x, const int y) { + _queuedFakeMouseMove = true; + _fakeMouseMove.type = Common::EVENT_MOUSEMOVE; + _fakeMouseMove.mouse = Common::Point(x, y); +} + bool SdlEventSource::handleResizeEvent(Common::Event &event, int w, int h) { if (_graphicsManager) { _graphicsManager->notifyResize(w, h); diff --git a/backends/events/sdl/sdl-events.h b/backends/events/sdl/sdl-events.h index cf445e9e2c..5fd3cb7ea5 100644 --- a/backends/events/sdl/sdl-events.h +++ b/backends/events/sdl/sdl-events.h @@ -51,6 +51,12 @@ public: */ virtual void resetKeyboardEmulation(int16 x_max, int16 y_max); + /** + * Emulates a mouse movement that would normally be caused by a mouse warp + * of the system mouse. + */ + void fakeWarpMouse(const int x, const int y); + protected: /** @name Keyboard mouse emulation * Disabled by fingolfin 2004-12-18. @@ -117,7 +123,7 @@ protected: * Assigns the mouse coords to the mouse event. Furthermore notify the * graphics manager about the position change. */ - virtual void processMouseEvent(Common::Event &event, int x, int y); + virtual bool processMouseEvent(Common::Event &event, int x, int y); /** * Remaps key events. This allows platforms to configure @@ -156,6 +162,18 @@ protected: */ SDLKey obtainKeycode(const SDL_keysym keySym); + /** + * Whether _fakeMouseMove contains an event we need to send. + */ + bool _queuedFakeMouseMove; + + /** + * A fake mouse motion event sent when the graphics manager is told to warp + * the mouse but the system mouse is unable to be warped (e.g. because the + * window is not focused). + */ + Common::Event _fakeMouseMove; + #if SDL_VERSION_ATLEAST(2, 0, 0) /** * Whether _fakeKeyUp contains an event we need to send. diff --git a/backends/graphics/dinguxsdl/dinguxsdl-graphics.cpp b/backends/graphics/dinguxsdl/dinguxsdl-graphics.cpp index 10605f45a7..3de6439d1a 100644 --- a/backends/graphics/dinguxsdl/dinguxsdl-graphics.cpp +++ b/backends/graphics/dinguxsdl/dinguxsdl-graphics.cpp @@ -487,14 +487,6 @@ bool DINGUXSdlGraphicsManager::getFeatureState(OSystem::Feature f) { } } -SurfaceSdlGraphicsManager::MousePos *DINGUXSdlGraphicsManager::getMouseCurState() { - return &_mouseCurState; -} - -SurfaceSdlGraphicsManager::VideoState *DINGUXSdlGraphicsManager::getVideoMode() { - return &_videoMode; -} - void DINGUXSdlGraphicsManager::warpMouse(int x, int y) { if (_mouseCurState.x != x || _mouseCurState.y != y) { if (_videoMode.mode == GFX_HALF && !_overlayVisible) { diff --git a/backends/graphics/dinguxsdl/dinguxsdl-graphics.h b/backends/graphics/dinguxsdl/dinguxsdl-graphics.h index 8a356106ad..89ee1411f1 100644 --- a/backends/graphics/dinguxsdl/dinguxsdl-graphics.h +++ b/backends/graphics/dinguxsdl/dinguxsdl-graphics.h @@ -36,26 +36,23 @@ class DINGUXSdlGraphicsManager : public SurfaceSdlGraphicsManager { public: DINGUXSdlGraphicsManager(SdlEventSource *boss, SdlWindow *window); - bool hasFeature(OSystem::Feature f); - void setFeatureState(OSystem::Feature f, bool enable); - bool getFeatureState(OSystem::Feature f); - int getDefaultGraphicsMode() const; - - void initSize(uint w, uint h); - const OSystem::GraphicsMode *getSupportedGraphicsModes() const; - bool setGraphicsMode(const char *name); - bool setGraphicsMode(int mode); - void setGraphicsModeIntern(); - void internUpdateScreen(); - void showOverlay(); - void hideOverlay(); - bool loadGFXMode(); - void drawMouse(); - void undrawMouse(); - virtual void warpMouse(int x, int y); - - SurfaceSdlGraphicsManager::MousePos *getMouseCurState(); - SurfaceSdlGraphicsManager::VideoState *getVideoMode(); + bool hasFeature(OSystem::Feature f) const override; + void setFeatureState(OSystem::Feature f, bool enable) override; + bool getFeatureState(OSystem::Feature f) override; + int getDefaultGraphicsMode() const override; + + void initSize(uint w, uint h) override; + const OSystem::GraphicsMode *getSupportedGraphicsModes() const override; + bool setGraphicsMode(const char *name) override; + bool setGraphicsMode(int mode) override; + void setGraphicsModeIntern() override; + void internUpdateScreen() override; + void showOverlay() override; + void hideOverlay() override; + bool loadGFXMode() override; + void drawMouse() override; + void undrawMouse() override; + void warpMouse(int x, int y) override; virtual void transformMouseCoordinates(Common::Point &point); }; diff --git a/backends/graphics/gph/gph-graphics.cpp b/backends/graphics/gph/gph-graphics.cpp index 767fb57e11..e2c84114c4 100644 --- a/backends/graphics/gph/gph-graphics.cpp +++ b/backends/graphics/gph/gph-graphics.cpp @@ -477,7 +477,7 @@ bool GPHGraphicsManager::loadGFXMode() { return true; } -bool GPHGraphicsManager::hasFeature(OSystem::Feature f) { +bool GPHGraphicsManager::hasFeature(OSystem::Feature f) const { return (f == OSystem::kFeatureAspectRatioCorrection) || (f == OSystem::kFeatureCursorPalette); @@ -497,7 +497,7 @@ void GPHGraphicsManager::setFeatureState(OSystem::Feature f, bool enable) { } } -bool GPHGraphicsManager::getFeatureState(OSystem::Feature f) { +bool GPHGraphicsManager::getFeatureState(OSystem::Feature f) const { assert(_transactionMode == kTransactionNone); switch (f) { @@ -510,14 +510,6 @@ bool GPHGraphicsManager::getFeatureState(OSystem::Feature f) { } } -SurfaceSdlGraphicsManager::MousePos *GPHGraphicsManager::getMouseCurState() { - return &_mouseCurState; -} - -SurfaceSdlGraphicsManager::VideoState *GPHGraphicsManager::getVideoMode() { - return &_videoMode; -} - void GPHGraphicsManager::warpMouse(int x, int y) { if (_mouseCurState.x != x || _mouseCurState.y != y) { if (_videoMode.mode == GFX_HALF && !_overlayVisible) { diff --git a/backends/graphics/gph/gph-graphics.h b/backends/graphics/gph/gph-graphics.h index 152d29ddf4..69e3b8947f 100644 --- a/backends/graphics/gph/gph-graphics.h +++ b/backends/graphics/gph/gph-graphics.h @@ -35,26 +35,23 @@ class GPHGraphicsManager : public SurfaceSdlGraphicsManager { public: GPHGraphicsManager(SdlEventSource *boss, SdlWindow *window); - bool hasFeature(OSystem::Feature f); - void setFeatureState(OSystem::Feature f, bool enable); - bool getFeatureState(OSystem::Feature f); - int getDefaultGraphicsMode() const; - - void initSize(uint w, uint h, const Graphics::PixelFormat *format = NULL); - const OSystem::GraphicsMode *getSupportedGraphicsModes() const; - bool setGraphicsMode(const char *name); - bool setGraphicsMode(int mode); - void setGraphicsModeIntern(); - void internUpdateScreen(); - void showOverlay(); - void hideOverlay(); - bool loadGFXMode(); - void drawMouse(); - void undrawMouse(); - virtual void warpMouse(int x, int y); - - SurfaceSdlGraphicsManager::MousePos *getMouseCurState(); - SurfaceSdlGraphicsManager::VideoState *getVideoMode(); + bool hasFeature(OSystem::Feature f) const override; + void setFeatureState(OSystem::Feature f, bool enable) override; + bool getFeatureState(OSystem::Feature f) const; + int getDefaultGraphicsMode() const override; + + void initSize(uint w, uint h, const Graphics::PixelFormat *format = NULL) override; + const OSystem::GraphicsMode *getSupportedGraphicsModes() const override; + bool setGraphicsMode(const char *name) override; + bool setGraphicsMode(int mode) override; + void setGraphicsModeIntern() override; + void internUpdateScreen() override; + void showOverlay() override; + void hideOverlay() override; + bool loadGFXMode() override; + void drawMouse() override; + void undrawMouse() override; + void warpMouse(int x, int y) override; virtual void transformMouseCoordinates(Common::Point &point); }; diff --git a/backends/graphics/graphics.h b/backends/graphics/graphics.h index bcd659ac11..cf33803cf5 100644 --- a/backends/graphics/graphics.h +++ b/backends/graphics/graphics.h @@ -38,9 +38,9 @@ class GraphicsManager : public PaletteManager { public: virtual ~GraphicsManager() {} - virtual bool hasFeature(OSystem::Feature f) = 0; + virtual bool hasFeature(OSystem::Feature f) const = 0; virtual void setFeatureState(OSystem::Feature f, bool enable) = 0; - virtual bool getFeatureState(OSystem::Feature f) = 0; + virtual bool getFeatureState(OSystem::Feature f) const = 0; virtual const OSystem::GraphicsMode *getSupportedGraphicsModes() const = 0; virtual int getDefaultGraphicsMode() const = 0; @@ -65,10 +65,10 @@ public: virtual void beginGFXTransaction() = 0; virtual OSystem::TransactionError endGFXTransaction() = 0; - virtual int16 getHeight() = 0; - virtual int16 getWidth() = 0; + virtual int16 getHeight() const = 0; + virtual int16 getWidth() const = 0; virtual void setPalette(const byte *colors, uint start, uint num) = 0; - virtual void grabPalette(byte *colors, uint start, uint num) = 0; + virtual void grabPalette(byte *colors, uint start, uint num) const = 0; virtual void copyRectToScreen(const void *buf, int pitch, int x, int y, int w, int h) = 0; virtual Graphics::Surface *lockScreen() = 0; virtual void unlockScreen() = 0; @@ -82,10 +82,10 @@ public: virtual void hideOverlay() = 0; virtual Graphics::PixelFormat getOverlayFormat() const = 0; virtual void clearOverlay() = 0; - virtual void grabOverlay(void *buf, int pitch) = 0; - virtual void copyRectToOverlay(const void *buf, int pitch, int x, int y, int w, int h)= 0; - virtual int16 getOverlayHeight() = 0; - virtual int16 getOverlayWidth() = 0; + virtual void grabOverlay(void *buf, int pitch) const = 0; + virtual void copyRectToOverlay(const void *buf, int pitch, int x, int y, int w, int h) = 0; + virtual int16 getOverlayHeight() const = 0; + virtual int16 getOverlayWidth() const = 0; virtual bool showMouse(bool visible) = 0; virtual void warpMouse(int x, int y) = 0; diff --git a/backends/graphics/linuxmotosdl/linuxmotosdl-graphics.h b/backends/graphics/linuxmotosdl/linuxmotosdl-graphics.h index d7a13b1cb4..e7f96e877c 100644 --- a/backends/graphics/linuxmotosdl/linuxmotosdl-graphics.h +++ b/backends/graphics/linuxmotosdl/linuxmotosdl-graphics.h @@ -29,18 +29,18 @@ class LinuxmotoSdlGraphicsManager : public SurfaceSdlGraphicsManager { public: LinuxmotoSdlGraphicsManager(SdlEventSource *sdlEventSource, SdlWindow *window); - virtual void initSize(uint w, uint h); - virtual void setGraphicsModeIntern(); - virtual bool setGraphicsMode(int mode); - virtual void internUpdateScreen(); - virtual const OSystem::GraphicsMode *getSupportedGraphicsModes() const; - virtual int getDefaultGraphicsMode() const; - virtual bool loadGFXMode(); - virtual void drawMouse(); - virtual void undrawMouse(); - virtual void showOverlay(); - virtual void hideOverlay(); - virtual void warpMouse(int x, int y); + virtual void initSize(uint w, uint h) override; + virtual void setGraphicsModeIntern() override; + virtual bool setGraphicsMode(int mode) override; + virtual void internUpdateScreen() override; + virtual const OSystem::GraphicsMode *getSupportedGraphicsModes() const override; + virtual int getDefaultGraphicsMode() const override; + virtual bool loadGFXMode() override; + virtual void drawMouse() override; + virtual void undrawMouse() override; + virtual void showOverlay() override; + virtual void hideOverlay() override; + virtual void warpMouse(int x, int y) override; virtual void transformMouseCoordinates(Common::Point &point); }; diff --git a/backends/graphics/maemosdl/maemosdl-graphics.h b/backends/graphics/maemosdl/maemosdl-graphics.h index 4cb84c81ee..ff4278b48c 100644 --- a/backends/graphics/maemosdl/maemosdl-graphics.h +++ b/backends/graphics/maemosdl/maemosdl-graphics.h @@ -32,7 +32,7 @@ public: MaemoSdlGraphicsManager(SdlEventSource *sdlEventSource, SdlWindow *window); protected: - virtual bool loadGFXMode(); + virtual bool loadGFXMode() override; }; #endif diff --git a/backends/graphics/null/null-graphics.h b/backends/graphics/null/null-graphics.h index 67306c29f3..4c628568ff 100644 --- a/backends/graphics/null/null-graphics.h +++ b/backends/graphics/null/null-graphics.h @@ -31,55 +31,55 @@ class NullGraphicsManager : public GraphicsManager { public: virtual ~NullGraphicsManager() {} - bool hasFeature(OSystem::Feature f) { return false; } - void setFeatureState(OSystem::Feature f, bool enable) {} - bool getFeatureState(OSystem::Feature f) { return false; } + bool hasFeature(OSystem::Feature f) const override { return false; } + void setFeatureState(OSystem::Feature f, bool enable) override {} + bool getFeatureState(OSystem::Feature f) const override { return false; } - const OSystem::GraphicsMode *getSupportedGraphicsModes() const { return s_noGraphicsModes; } - int getDefaultGraphicsMode() const { return 0; } - bool setGraphicsMode(int mode) { return true; } - void resetGraphicsScale(){} - int getGraphicsMode() const { return 0; } - inline Graphics::PixelFormat getScreenFormat() const { + const OSystem::GraphicsMode *getSupportedGraphicsModes() const override { return s_noGraphicsModes; } + int getDefaultGraphicsMode() const override { return 0; } + bool setGraphicsMode(int mode) override { return true; } + void resetGraphicsScale() override {} + int getGraphicsMode() const override { return 0; } + inline Graphics::PixelFormat getScreenFormat() const override { return Graphics::PixelFormat::createFormatCLUT8(); } - inline Common::List<Graphics::PixelFormat> getSupportedFormats() const { + inline Common::List<Graphics::PixelFormat> getSupportedFormats() const override { Common::List<Graphics::PixelFormat> list; list.push_back(Graphics::PixelFormat::createFormatCLUT8()); return list; } - void initSize(uint width, uint height, const Graphics::PixelFormat *format = NULL) {} - virtual int getScreenChangeID() const { return 0; } + void initSize(uint width, uint height, const Graphics::PixelFormat *format = NULL) override {} + virtual int getScreenChangeID() const override { return 0; } - void beginGFXTransaction() {} - OSystem::TransactionError endGFXTransaction() { return OSystem::kTransactionSuccess; } + void beginGFXTransaction() override {} + OSystem::TransactionError endGFXTransaction() override { return OSystem::kTransactionSuccess; } - int16 getHeight() { return 0; } - int16 getWidth() { return 0; } - void setPalette(const byte *colors, uint start, uint num) {} - void grabPalette(byte *colors, uint start, uint num) {} - void copyRectToScreen(const void *buf, int pitch, int x, int y, int w, int h) {} - Graphics::Surface *lockScreen() { return NULL; } - void unlockScreen() {} - void fillScreen(uint32 col) {} - void updateScreen() {} - void setShakePos(int shakeOffset) {} - void setFocusRectangle(const Common::Rect& rect) {} - void clearFocusRectangle() {} + int16 getHeight() const override { return 0; } + int16 getWidth() const override { return 0; } + void setPalette(const byte *colors, uint start, uint num) override {} + void grabPalette(byte *colors, uint start, uint num) const override {} + void copyRectToScreen(const void *buf, int pitch, int x, int y, int w, int h) override {} + Graphics::Surface *lockScreen() override { return NULL; } + void unlockScreen() override {} + void fillScreen(uint32 col) override {} + void updateScreen() override {} + void setShakePos(int shakeOffset) override {} + void setFocusRectangle(const Common::Rect& rect) override {} + void clearFocusRectangle() override {} - void showOverlay() {} - void hideOverlay() {} - Graphics::PixelFormat getOverlayFormat() const { return Graphics::PixelFormat(); } - void clearOverlay() {} - void grabOverlay(void *buf, int pitch) {} - void copyRectToOverlay(const void *buf, int pitch, int x, int y, int w, int h) {} - int16 getOverlayHeight() { return 0; } - int16 getOverlayWidth() { return 0; } + void showOverlay() override {} + void hideOverlay() override {} + Graphics::PixelFormat getOverlayFormat() const override { return Graphics::PixelFormat(); } + void clearOverlay() override {} + void grabOverlay(void *buf, int pitch) const override {} + void copyRectToOverlay(const void *buf, int pitch, int x, int y, int w, int h) override {} + int16 getOverlayHeight() const override { return 0; } + int16 getOverlayWidth() const override { return 0; } - bool showMouse(bool visible) { return !visible; } - void warpMouse(int x, int y) {} - void setMouseCursor(const void *buf, uint w, uint h, int hotspotX, int hotspotY, uint32 keycolor, bool dontScale = false, const Graphics::PixelFormat *format = NULL) {} - void setCursorPalette(const byte *colors, uint start, uint num) {} + bool showMouse(bool visible) override { return !visible; } + void warpMouse(int x, int y) override {} + void setMouseCursor(const void *buf, uint w, uint h, int hotspotX, int hotspotY, uint32 keycolor, bool dontScale = false, const Graphics::PixelFormat *format = NULL) override {} + void setCursorPalette(const byte *colors, uint start, uint num) override {} }; #endif 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. diff --git a/backends/graphics/opengl/opengl-graphics.h b/backends/graphics/opengl/opengl-graphics.h index e02137bba7..df968aa67e 100644 --- a/backends/graphics/opengl/opengl-graphics.h +++ b/backends/graphics/opengl/opengl-graphics.h @@ -25,7 +25,7 @@ #include "backends/graphics/opengl/opengl-sys.h" #include "backends/graphics/opengl/framebuffer.h" -#include "backends/graphics/graphics.h" +#include "backends/graphics/windowed.h" #include "common/frac.h" #include "common/mutex.h" @@ -53,74 +53,69 @@ enum { GFX_OPENGL = 0 }; -class OpenGLGraphicsManager : virtual public GraphicsManager { +class OpenGLGraphicsManager : virtual public WindowedGraphicsManager { public: OpenGLGraphicsManager(); virtual ~OpenGLGraphicsManager(); // GraphicsManager API - virtual bool hasFeature(OSystem::Feature f); - virtual void setFeatureState(OSystem::Feature f, bool enable); - virtual bool getFeatureState(OSystem::Feature f); + 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; - virtual const OSystem::GraphicsMode *getSupportedGraphicsModes() const; - virtual int getDefaultGraphicsMode() const; - virtual bool setGraphicsMode(int mode); - virtual int getGraphicsMode() const; + virtual const OSystem::GraphicsMode *getSupportedGraphicsModes() const override; + virtual int getDefaultGraphicsMode() const override; + virtual bool setGraphicsMode(int mode) override; + virtual int getGraphicsMode() const override; - virtual void resetGraphicsScale() {} + virtual void resetGraphicsScale() override {} #ifdef USE_RGB_COLOR - virtual Graphics::PixelFormat getScreenFormat() const; - virtual Common::List<Graphics::PixelFormat> getSupportedFormats() const = 0; + virtual Graphics::PixelFormat getScreenFormat() const override; + virtual Common::List<Graphics::PixelFormat> getSupportedFormats() const override = 0; #endif - virtual void beginGFXTransaction(); - virtual OSystem::TransactionError endGFXTransaction(); + virtual void beginGFXTransaction() override; + virtual OSystem::TransactionError endGFXTransaction() override; - virtual int getScreenChangeID() const; + virtual int getScreenChangeID() const override; - virtual void initSize(uint width, uint height, const Graphics::PixelFormat *format); + virtual void initSize(uint width, uint height, const Graphics::PixelFormat *format) override; - virtual int16 getWidth(); - virtual int16 getHeight(); + virtual int16 getWidth() const override; + virtual int16 getHeight() const override; - virtual void copyRectToScreen(const void *buf, int pitch, int x, int y, int w, int h); - virtual void fillScreen(uint32 col); + virtual void copyRectToScreen(const void *buf, int pitch, int x, int y, int w, int h) override; + virtual void fillScreen(uint32 col) override; - virtual void setShakePos(int shakeOffset); + virtual void setShakePos(int shakeOffset) override; - virtual void updateScreen(); + virtual void updateScreen() override; - virtual Graphics::Surface *lockScreen(); - virtual void unlockScreen(); + virtual Graphics::Surface *lockScreen() override; + virtual void unlockScreen() override; - virtual void setFocusRectangle(const Common::Rect& rect); - virtual void clearFocusRectangle(); + virtual void setFocusRectangle(const Common::Rect& rect) override; + virtual void clearFocusRectangle() override; - virtual int16 getOverlayWidth(); - virtual int16 getOverlayHeight(); + virtual int16 getOverlayWidth() const override; + virtual int16 getOverlayHeight() const override; - virtual void showOverlay(); - virtual void hideOverlay(); + virtual Graphics::PixelFormat getOverlayFormat() const override; - virtual Graphics::PixelFormat getOverlayFormat() const; + virtual void copyRectToOverlay(const void *buf, int pitch, int x, int y, int w, int h) override; + 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); - virtual void clearOverlay(); - virtual void grabOverlay(void *buf, int pitch); + virtual void setMouseCursor(const void *buf, uint w, uint h, int hotspotX, int hotspotY, uint32 keycolor, bool dontScale, const Graphics::PixelFormat *format) override; + virtual void setCursorPalette(const byte *colors, uint start, uint num) override; - virtual bool showMouse(bool visible); - virtual void warpMouse(int x, int y); - virtual void setMouseCursor(const void *buf, uint w, uint h, int hotspotX, int hotspotY, uint32 keycolor, bool dontScale, const Graphics::PixelFormat *format); - virtual void setCursorPalette(const byte *colors, uint start, uint num); - - virtual void displayMessageOnOSD(const char *msg); - virtual void displayActivityIconOnOSD(const Graphics::Surface *icon); + virtual void displayMessageOnOSD(const char *msg) override; + virtual void displayActivityIconOnOSD(const Graphics::Surface *icon) override; // PaletteManager interface - virtual void setPalette(const byte *colors, uint start, uint num); - virtual void grabPalette(byte *colors, uint start, uint num); + virtual void setPalette(const byte *colors, uint start, uint num) override; + virtual void grabPalette(byte *colors, uint start, uint num) const override; protected: /** @@ -129,15 +124,6 @@ protected: bool isGLESContext() const { return g_context.type == kContextGLES || g_context.type == kContextGLES2; } /** - * Set up the actual screen size available for the OpenGL code to do any - * drawing. - * - * @param width The width of the screen. - * @param height The height of the screen. - */ - void setActualScreenSize(uint width, uint height); - - /** * Sets the OpenGL (ES) type the graphics manager shall work with. * * This needs to be called at least once (and before ever calling @@ -167,33 +153,6 @@ protected: void notifyContextDestroy(); /** - * Adjust the physical mouse coordinates according to the currently visible screen. - */ - void adjustMousePosition(int16 &x, int16 &y); - - /** - * Set up the mouse position for graphics output. - * - * @param x X coordinate in physical coordinates. - * @param y Y coordinate in physical coordinates. - */ - void setMousePosition(int x, int y); - - /** - * Query the mouse position in physical coordinates. - */ - void getMousePosition(int16 &x, int16 &y) const { x = _cursorX; y = _cursorY; } - - /** - * Set up the mouse position for the (event) system. - * - * @param x X coordinate in physical coordinates. - * @param y Y coordinate in physical coordinates. - */ - virtual void setInternalMousePosition(int x, int y) = 0; - -private: - /** * Create a surface with the specified pixel format. * * @param format The pixel format the Surface object should accept as @@ -241,7 +200,7 @@ private: }; /** - * The currently setup video state. + * The currently set up video state. */ VideoState _currentState; @@ -292,8 +251,7 @@ protected: virtual void refreshScreen() = 0; /** - * Save a screenshot of the full display as BMP to the given file. This - * uses Common::DumpFile for writing the screenshot. + * Saves a screenshot of the entire window, excluding window decorations. * * @param filename The output filename. * @return true on success, false otherwise @@ -334,7 +292,6 @@ protected: */ virtual void *getProcAddress(const char *name) const = 0; -private: /** * Try to determine the internal parameters for a given pixel format. * @@ -342,49 +299,9 @@ private: */ bool getGLPixelFormat(const Graphics::PixelFormat &pixelFormat, GLenum &glIntFormat, GLenum &glFormat, GLenum &glType) const; - // - // Actual hardware screen - // - - /** - * The width of the physical output. - */ - uint _outputScreenWidth; - - /** - * The height of the physical output. - */ - uint _outputScreenHeight; - - /** - * @return The desired aspect of the game screen. - */ - frac_t getDesiredGameScreenAspect() const; - - /** - * Recalculates the area used to display the game screen. - */ - void recalculateDisplayArea(); - - /** - * The X coordinate of the game screen. - */ - uint _displayX; - - /** - * The Y coordinate of the game screen. - */ - uint _displayY; - - /** - * The width of the game screen in physical coordinates. - */ - uint _displayWidth; - - /** - * The height of the game screen in physical coordinates. - */ - uint _displayHeight; + virtual bool gameNeedsAspectRatioCorrection() const override; + virtual void recalculateDisplayAreas() override; + virtual void handleResizeImpl(const int width, const int height) override; /** * The default pixel format of the backend. @@ -396,12 +313,8 @@ private: */ Graphics::PixelFormat _defaultFormatAlpha; - // - // Game screen - // - /** - * The virtual game screen. + * The rendering surface for the virtual game screen. */ Surface *_gameScreen; @@ -420,15 +333,10 @@ private: // /** - * The overlay screen. + * The rendering surface for the overlay. */ Surface *_overlay; - /** - * Whether the overlay is visible or not. - */ - bool _overlayVisible; - // // Cursor // @@ -439,37 +347,17 @@ private: void updateCursorPalette(); /** - * The cursor image. + * The rendering surface for the mouse cursor. */ Surface *_cursor; /** - * X coordinate of the cursor in phyiscal coordinates. - */ - int _cursorX; - - /** - * Y coordinate of the cursor in physical coordinates. - */ - int _cursorY; - - /** - * X coordinate used for drawing the cursor. - */ - int _cursorDisplayX; - - /** - * Y coordinate used for drawing the cursor. - */ - int _cursorDisplayY; - - /** - * The X offset for the cursor hotspot in unscaled coordinates. + * The X offset for the cursor hotspot in unscaled game coordinates. */ int _cursorHotspotX; /** - * The Y offset for the cursor hotspot in unscaled coordinates. + * The Y offset for the cursor hotspot in unscaled game coordinates. */ int _cursorHotspotY; @@ -480,22 +368,24 @@ private: void recalculateCursorScaling(); /** - * The X offset for the cursor hotspot in scaled coordinates. + * The X offset for the cursor hotspot in scaled game display area + * coordinates. */ int _cursorHotspotXScaled; /** - * The Y offset for the cursor hotspot in scaled coordinates. + * The Y offset for the cursor hotspot in scaled game display area + * coordinates. */ int _cursorHotspotYScaled; /** - * The width of the cursor scaled coordinates. + * The width of the cursor in scaled game display area coordinates. */ uint _cursorWidthScaled; /** - * The height of the cursor scaled coordinates. + * The height of the cursor in scaled game display area coordinates. */ uint _cursorHeightScaled; @@ -505,11 +395,6 @@ private: uint32 _cursorKeyColor; /** - * Whether the cursor is actually visible. - */ - bool _cursorVisible; - - /** * Whether no cursor scaling should be applied. */ bool _cursorDontScale; @@ -524,15 +409,6 @@ private: */ byte _cursorPalette[3 * 256]; - // - // Misc - // - - /** - * Whether the screen contents shall be forced to redrawn. - */ - bool _forceRedraw; - #ifdef USE_OSD // // OSD @@ -541,7 +417,7 @@ protected: /** * Returns the font used for on screen display */ - virtual const Graphics::Font *getFontOSD(); + virtual const Graphics::Font *getFontOSD() const; private: /** diff --git a/backends/graphics/openglsdl/openglsdl-graphics.cpp b/backends/graphics/openglsdl/openglsdl-graphics.cpp index 73fc87a75f..c77e9dafc5 100644 --- a/backends/graphics/openglsdl/openglsdl-graphics.cpp +++ b/backends/graphics/openglsdl/openglsdl-graphics.cpp @@ -21,8 +21,10 @@ */ #include "backends/graphics/openglsdl/openglsdl-graphics.h" +#include "backends/graphics/opengl/texture.h" #include "backends/events/sdl/sdl-events.h" #include "backends/platform/sdl/sdl.h" +#include "graphics/scaler/aspect.h" #include "common/textconsole.h" #include "common/config-manager.h" @@ -35,7 +37,7 @@ OpenGLSdlGraphicsManager::OpenGLSdlGraphicsManager(uint desktopWidth, uint deskt #if SDL_VERSION_ATLEAST(2, 0, 0) _glContext(), #else - _lastVideoModeLoad(0), _hwScreen(nullptr), + _lastVideoModeLoad(0), #endif _graphicsScale(2), _ignoreLoadVideoMode(false), _gotResize(false), _wantsFullScreen(false), _ignoreResizeEvents(0), _desiredFullscreenWidth(0), _desiredFullscreenHeight(0) { @@ -46,20 +48,22 @@ OpenGLSdlGraphicsManager::OpenGLSdlGraphicsManager(uint desktopWidth, uint deskt SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 16); SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); - // Setup proper SDL OpenGL context creation. + // Set up proper SDL OpenGL context creation. #if SDL_VERSION_ATLEAST(2, 0, 0) OpenGL::ContextType glContextType; // Context version 1.4 is choosen arbitrarily based on what most shader // extensions were written against. -#define DEFAULT_GL_MAJOR 1 -#define DEFAULT_GL_MINOR 4 + enum { + DEFAULT_GL_MAJOR = 1, + DEFAULT_GL_MINOR = 4, -#define DEFAULT_GLES_MAJOR 1 -#define DEFAULT_GLES_MINOR 1 + DEFAULT_GLES_MAJOR = 1, + DEFAULT_GLES_MINOR = 1, -#define DEFAULT_GLES2_MAJOR 2 -#define DEFAULT_GLES2_MINOR 0 + DEFAULT_GLES2_MAJOR = 2, + DEFAULT_GLES2_MINOR = 0 + }; #if USE_FORCED_GL glContextType = OpenGL::kContextGL; @@ -127,12 +131,6 @@ OpenGLSdlGraphicsManager::OpenGLSdlGraphicsManager(uint desktopWidth, uint deskt } else { glContextType = OpenGL::kContextGL; } -#undef DEFAULT_GL_MAJOR -#undef DEFAULT_GL_MINOR -#undef DEFAULT_GLES_MAJOR -#undef DEFAULT_GLES_MINOR -#undef DEFAULT_GLES2_MAJOR -#undef DEFAULT_GLES2_MINOR #endif setContextType(glContextType); @@ -217,7 +215,7 @@ void OpenGLSdlGraphicsManager::deactivateManager() { SdlGraphicsManager::deactivateManager(); } -bool OpenGLSdlGraphicsManager::hasFeature(OSystem::Feature f) { +bool OpenGLSdlGraphicsManager::hasFeature(OSystem::Feature f) const { switch (f) { case OSystem::kFeatureFullscreenMode: case OSystem::kFeatureIconifyWindow: @@ -246,7 +244,7 @@ void OpenGLSdlGraphicsManager::setFeatureState(OSystem::Feature f, bool enable) } } -bool OpenGLSdlGraphicsManager::getFeatureState(OSystem::Feature f) { +bool OpenGLSdlGraphicsManager::getFeatureState(OSystem::Feature f) const { switch (f) { case OSystem::kFeatureFullscreenMode: #if SDL_VERSION_ATLEAST(2, 0, 0) @@ -344,7 +342,7 @@ void OpenGLSdlGraphicsManager::updateScreen() { void OpenGLSdlGraphicsManager::notifyVideoExpose() { } -void OpenGLSdlGraphicsManager::notifyResize(const uint width, const uint height) { +void OpenGLSdlGraphicsManager::notifyResize(const int width, const int height) { #if SDL_VERSION_ATLEAST(2, 0, 0) // We sometime get outdated resize events from SDL2. So check that the size we get // is the actual current window size. If not ignore the resize. @@ -354,11 +352,10 @@ void OpenGLSdlGraphicsManager::notifyResize(const uint width, const uint height) // causes a SDL_WINDOWEVENT_RESIZED event with the old resolution to be sent, and this // event is processed after recreating the window at the new resolution. int currentWidth, currentHeight; - getWindowDimensions(¤tWidth, ¤tHeight); - if (width != (uint)currentWidth || height != (uint)currentHeight) + getWindowSizeFromSdl(¤tWidth, ¤tHeight); + if (width != currentWidth || height != currentHeight) return; - setActualScreenSize(width, height); - _eventSource->resetKeyboardEmulation(width - 1, height - 1); + handleResize(width, height); #else if (!_ignoreResizeEvents && _hwScreen && !(_hwScreen->flags & SDL_FULLSCREEN)) { // We save that we handled a resize event here. We need to know this @@ -373,18 +370,6 @@ void OpenGLSdlGraphicsManager::notifyResize(const uint width, const uint height) #endif } -void OpenGLSdlGraphicsManager::transformMouseCoordinates(Common::Point &point) { - adjustMousePosition(point.x, point.y); -} - -void OpenGLSdlGraphicsManager::notifyMousePos(Common::Point mouse) { - setMousePosition(mouse.x, mouse.y); -} - -void OpenGLSdlGraphicsManager::setInternalMousePosition(int x, int y) { - _window->warpMouseInWindow(x, y); -} - bool OpenGLSdlGraphicsManager::loadVideoMode(uint requestedWidth, uint requestedHeight, const Graphics::PixelFormat &format) { // In some cases we might not want to load the requested video mode. This // will assure that the window size is not altered. @@ -422,6 +407,11 @@ void *OpenGLSdlGraphicsManager::getProcAddress(const char *name) const { return SDL_GL_GetProcAddress(name); } +void OpenGLSdlGraphicsManager::handleResizeImpl(const int width, const int height) { + OpenGLGraphicsManager::handleResizeImpl(width, height); + SdlGraphicsManager::handleResizeImpl(width, height); +} + bool OpenGLSdlGraphicsManager::setupMode(uint width, uint height) { // In case we request a fullscreen mode we will use the mode the user // has chosen last time or the biggest mode available. @@ -517,9 +507,8 @@ bool OpenGLSdlGraphicsManager::setupMode(uint width, uint height) { notifyContextCreate(rgba8888, rgba8888); int actualWidth, actualHeight; - getWindowDimensions(&actualWidth, &actualHeight); - setActualScreenSize(actualWidth, actualHeight); - _eventSource->resetKeyboardEmulation(actualWidth - 1, actualHeight - 1); + getWindowSizeFromSdl(&actualWidth, &actualHeight); + handleResize(actualWidth, actualHeight); return true; #else // WORKAROUND: Working around infamous SDL bugs when switching @@ -566,8 +555,7 @@ bool OpenGLSdlGraphicsManager::setupMode(uint width, uint height) { if (_hwScreen) { notifyContextCreate(rgba8888, rgba8888); - setActualScreenSize(_hwScreen->w, _hwScreen->h); - _eventSource->resetKeyboardEmulation(_hwScreen->w - 1, _hwScreen->h - 1); + handleResize(_hwScreen->w, _hwScreen->h); } // Ignore resize events (from SDL) for a few frames, if this isn't @@ -580,20 +568,6 @@ bool OpenGLSdlGraphicsManager::setupMode(uint width, uint height) { #endif } -void OpenGLSdlGraphicsManager::getWindowDimensions(int *width, int *height) { -#if SDL_VERSION_ATLEAST(2, 0, 0) - SDL_GetWindowSize(_window->getSDLWindow(), width, height); -#else - if (width) { - *width = _hwScreen->w; - } - - if (height) { - *height = _hwScreen->h; - } -#endif -} - bool OpenGLSdlGraphicsManager::notifyEvent(const Common::Event &event) { switch (event.type) { case Common::EVENT_KEYUP: @@ -707,7 +681,7 @@ bool OpenGLSdlGraphicsManager::notifyEvent(const Common::Event &event) { // current scale setting in case the user resized the // window. Then we apply the direction change. int windowWidth = 0, windowHeight = 0; - getWindowDimensions(&windowWidth, &windowHeight); + getWindowSizeFromSdl(&windowWidth, &windowHeight); _graphicsScale = MAX<int>(windowWidth / _lastRequestedWidth, windowHeight / _lastRequestedHeight); _graphicsScale = MAX<int>(_graphicsScale + direction, 1); @@ -725,7 +699,7 @@ bool OpenGLSdlGraphicsManager::notifyEvent(const Common::Event &event) { #ifdef USE_OSD int windowWidth = 0, windowHeight = 0; - getWindowDimensions(&windowWidth, &windowHeight); + getWindowSizeFromSdl(&windowWidth, &windowHeight); const Common::String osdMsg = Common::String::format(_("Resolution: %dx%d"), windowWidth, windowHeight); displayMessageOnOSD(osdMsg.c_str()); #endif @@ -785,7 +759,7 @@ bool OpenGLSdlGraphicsManager::notifyEvent(const Common::Event &event) { } } -bool OpenGLSdlGraphicsManager::isHotkey(const Common::Event &event) { +bool OpenGLSdlGraphicsManager::isHotkey(const Common::Event &event) const { if (event.kbd.hasFlags(Common::KBD_ALT)) { return event.kbd.keycode == Common::KEYCODE_RETURN || event.kbd.keycode == (Common::KeyCode)SDLK_KP_ENTER diff --git a/backends/graphics/openglsdl/openglsdl-graphics.h b/backends/graphics/openglsdl/openglsdl-graphics.h index c5003d867b..954c7215a4 100644 --- a/backends/graphics/openglsdl/openglsdl-graphics.h +++ b/backends/graphics/openglsdl/openglsdl-graphics.h @@ -36,38 +36,37 @@ public: virtual ~OpenGLSdlGraphicsManager(); // GraphicsManager API - virtual void activateManager(); - virtual void deactivateManager(); + virtual void activateManager() override; + virtual void deactivateManager() override; - virtual bool hasFeature(OSystem::Feature f); - virtual void setFeatureState(OSystem::Feature f, bool enable); - virtual bool getFeatureState(OSystem::Feature f); + 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; virtual void initSize(uint w, uint h, const Graphics::PixelFormat *format) override; #ifdef USE_RGB_COLOR - virtual Common::List<Graphics::PixelFormat> getSupportedFormats() const; + virtual Common::List<Graphics::PixelFormat> getSupportedFormats() const override; #endif - virtual void updateScreen(); + virtual void updateScreen() override; // EventObserver API - virtual bool notifyEvent(const Common::Event &event); + virtual bool notifyEvent(const Common::Event &event) override; // SdlGraphicsManager API - virtual void notifyVideoExpose(); - virtual void notifyResize(const uint width, const uint height); - virtual void transformMouseCoordinates(Common::Point &point); - virtual void notifyMousePos(Common::Point mouse); + virtual void notifyVideoExpose() override; + virtual void notifyResize(const int width, const int height) override; protected: - virtual void setInternalMousePosition(int x, int y); + virtual bool loadVideoMode(uint requestedWidth, uint requestedHeight, const Graphics::PixelFormat &format) override; - virtual bool loadVideoMode(uint requestedWidth, uint requestedHeight, const Graphics::PixelFormat &format); + virtual void refreshScreen() override; - virtual void refreshScreen(); + virtual void *getProcAddress(const char *name) const override; + + virtual void handleResizeImpl(const int width, const int height) override; - virtual void *getProcAddress(const char *name) const; virtual int getGraphicsModeScale(int mode) const override { return 1; } private: @@ -78,11 +77,8 @@ private: SDL_GLContext _glContext; #else uint32 _lastVideoModeLoad; - SDL_Surface *_hwScreen; #endif - void getWindowDimensions(int *width, int *height); - uint _lastRequestedWidth; uint _lastRequestedHeight; uint _graphicsScale; @@ -122,7 +118,7 @@ private: uint _desiredFullscreenWidth; uint _desiredFullscreenHeight; - virtual bool isHotkey(const Common::Event &event); + bool isHotkey(const Common::Event &event) const; }; #endif diff --git a/backends/graphics/openpandora/op-graphics.h b/backends/graphics/openpandora/op-graphics.h index 50994072bb..56777dc892 100644 --- a/backends/graphics/openpandora/op-graphics.h +++ b/backends/graphics/openpandora/op-graphics.h @@ -34,8 +34,8 @@ class OPGraphicsManager : public SurfaceSdlGraphicsManager { public: OPGraphicsManager(SdlEventSource *sdlEventSource, SdlWindow *window); - bool loadGFXMode(); - void unloadGFXMode(); + bool loadGFXMode() override; + void unloadGFXMode() override; }; #endif /* BACKENDS_GRAPHICS_OP_H */ diff --git a/backends/graphics/psp2sdl/psp2sdl-graphics.h b/backends/graphics/psp2sdl/psp2sdl-graphics.h index 638437c9a6..0cabeb094d 100644 --- a/backends/graphics/psp2sdl/psp2sdl-graphics.h +++ b/backends/graphics/psp2sdl/psp2sdl-graphics.h @@ -30,19 +30,19 @@ class PSP2SdlGraphicsManager : public SurfaceSdlGraphicsManager { public: PSP2SdlGraphicsManager(SdlEventSource *sdlEventSource, SdlWindow *window); virtual ~PSP2SdlGraphicsManager(); - - virtual OSystem::TransactionError endGFXTransaction(); - virtual const OSystem::GraphicsMode *getSupportedShaders() const; + + virtual OSystem::TransactionError endGFXTransaction() override; + virtual const OSystem::GraphicsMode *getSupportedShaders() const override; protected: - virtual void setGraphicsModeIntern(); - virtual void unloadGFXMode(); - virtual bool hotswapGFXMode(); - - virtual void internUpdateScreen(); - virtual void updateShader(); - virtual void setAspectRatioCorrection(bool enable); - virtual SDL_Surface *SDL_SetVideoMode(int width, int height, int bpp, Uint32 flags); + virtual void setGraphicsModeIntern() override; + virtual void unloadGFXMode() override; + virtual bool hotswapGFXMode() override; + + virtual void internUpdateScreen() override; + virtual void updateShader() override; + virtual void setAspectRatioCorrection(bool enable) override; + virtual SDL_Surface *SDL_SetVideoMode(int width, int height, int bpp, Uint32 flags) override; void PSP2_UpdateRects(SDL_Surface *screen, int numrects, SDL_Rect *rects); void PSP2_UpdateFiltering(); diff --git a/backends/graphics/samsungtvsdl/samsungtvsdl-graphics.cpp b/backends/graphics/samsungtvsdl/samsungtvsdl-graphics.cpp index 0c98462891..befa793263 100644 --- a/backends/graphics/samsungtvsdl/samsungtvsdl-graphics.cpp +++ b/backends/graphics/samsungtvsdl/samsungtvsdl-graphics.cpp @@ -32,7 +32,7 @@ SamsungTVSdlGraphicsManager::SamsungTVSdlGraphicsManager(SdlEventSource *sdlEven : SurfaceSdlGraphicsManager(sdlEventSource, window) { } -bool SamsungTVSdlGraphicsManager::hasFeature(OSystem::Feature f) { +bool SamsungTVSdlGraphicsManager::hasFeature(OSystem::Feature f) const { return (f == OSystem::kFeatureAspectRatioCorrection) || (f == OSystem::kFeatureCursorPalette); @@ -48,7 +48,7 @@ void SamsungTVSdlGraphicsManager::setFeatureState(OSystem::Feature f, bool enabl } } -bool SamsungTVSdlGraphicsManager::getFeatureState(OSystem::Feature f) { +bool SamsungTVSdlGraphicsManager::getFeatureState(OSystem::Feature f) const { switch (f) { case OSystem::kFeatureAspectRatioCorrection: return SurfaceSdlGraphicsManager::getFeatureState(f); diff --git a/backends/graphics/samsungtvsdl/samsungtvsdl-graphics.h b/backends/graphics/samsungtvsdl/samsungtvsdl-graphics.h index 8699d77bc8..b86ebe2c45 100644 --- a/backends/graphics/samsungtvsdl/samsungtvsdl-graphics.h +++ b/backends/graphics/samsungtvsdl/samsungtvsdl-graphics.h @@ -31,9 +31,9 @@ class SamsungTVSdlGraphicsManager : public SurfaceSdlGraphicsManager { public: SamsungTVSdlGraphicsManager(SdlEventSource *sdlEventSource, SdlWindow *window); - bool hasFeature(OSystem::Feature f); - void setFeatureState(OSystem::Feature f, bool enable); - bool getFeatureState(OSystem::Feature f); + bool hasFeature(OSystem::Feature f) const override; + void setFeatureState(OSystem::Feature f, bool enable) override; + bool getFeatureState(OSystem::Feature f) const override; }; #endif diff --git a/backends/graphics/sdl/sdl-graphics.cpp b/backends/graphics/sdl/sdl-graphics.cpp index a181582235..0e0a45a38f 100644 --- a/backends/graphics/sdl/sdl-graphics.cpp +++ b/backends/graphics/sdl/sdl-graphics.cpp @@ -28,15 +28,11 @@ #include "graphics/scaler/aspect.h" SdlGraphicsManager::SdlGraphicsManager(SdlEventSource *source, SdlWindow *window) - : _eventSource(source), _window(window) + : _eventSource(source), _window(window), _hwScreen(nullptr) #if SDL_VERSION_ATLEAST(2, 0, 0) , _allowWindowSizeReset(false), _hintedWidth(0), _hintedHeight(0), _lastFlags(0) #endif - { -} - -SdlGraphicsManager::~SdlGraphicsManager() { -} +{} void SdlGraphicsManager::activateManager() { _eventSource->setGraphicsManager(this); @@ -46,7 +42,7 @@ void SdlGraphicsManager::deactivateManager() { _eventSource->setGraphicsManager(0); } -SdlGraphicsManager::State SdlGraphicsManager::getState() { +SdlGraphicsManager::State SdlGraphicsManager::getState() const { State state; state.screenWidth = getWidth(); @@ -152,6 +148,82 @@ void SdlGraphicsManager::initSizeHint(const Graphics::ModeList &modes) { #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<int>(mouse.x, _activeArea.drawRect.left, _activeArea.drawRect.right - 1); + mouse.y = CLIP<int>(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)) { + _eventSource->fakeWarpMouse(x, y); + } +} + +void SdlGraphicsManager::handleResizeImpl(const int width, const int height) { + _eventSource->resetKeyboardEmulation(width - 1, height - 1); + _forceRedraw = true; +} + #if SDL_VERSION_ATLEAST(2, 0, 0) bool SdlGraphicsManager::createOrUpdateWindow(int width, int height, const Uint32 flags) { if (!_window) { @@ -159,11 +231,12 @@ bool SdlGraphicsManager::createOrUpdateWindow(int width, int height, const Uint3 } // We only update the actual window when flags change (which usually means - // fullscreen mode is entered/exited) or when updates are forced so that we + // 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) - if (!_window->getSDLWindow() || _lastFlags != flags || _allowWindowSizeReset) { + // 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) { if (_hintedWidth) { width = _hintedWidth; } diff --git a/backends/graphics/sdl/sdl-graphics.h b/backends/graphics/sdl/sdl-graphics.h index 74ee2838ea..526306270b 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/windowed.h" #include "backends/platform/sdl/sdl-window.h" #include "common/rect.h" @@ -32,13 +32,11 @@ class SdlEventSource; /** * 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 { +class SdlGraphicsManager : virtual public WindowedGraphicsManager { public: SdlGraphicsManager(SdlEventSource *source, SdlWindow *window); - virtual ~SdlGraphicsManager(); + virtual ~SdlGraphicsManager() {} /** * Makes this graphics manager active. That means it should be ready to @@ -62,10 +60,10 @@ public: virtual void notifyVideoExpose() = 0; /** - * Notify the graphics manager about an resize event. + * Notify the graphics manager about a resize event. * * It is noteworthy that the requested width/height should actually be set - * up as is and not changed by the graphics manager, since else it might + * up as is and not changed by the graphics manager, since otherwise it may * lead to odd behavior for certain window managers. * * It is only required to overwrite this method in case you want a @@ -74,27 +72,28 @@ public: * @param width Requested window width. * @param height Requested window height. */ - virtual void notifyResize(const uint width, const uint height) {} + virtual void notifyResize(const int width, const int height) {} /** - * Transforms real screen coordinates into the current active screen - * coordinates (may be either game screen or overlay). + * Notifies the graphics manager about a mouse position change. * - * @param point Mouse coordinates to transform. - */ - virtual void transformMouseCoordinates(Common::Point &point) = 0; - - /** - * Notifies the graphics manager about a position change according to the - * real screen coordinates. + * The passed point *must* be converted from window coordinates to virtual + * coordinates in order for the event to be processed correctly by the game + * engine. Just use `convertWindowToVirtual` for this unless you need to do + * something special. * - * @param mouse Mouse position. + * @param mouse The mouse position in window coordinates, which must be + * converted synchronously to virtual coordinates. + * @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 void notifyMousePos(Common::Point mouse) = 0; + virtual bool notifyMousePosition(Common::Point &mouse); + + virtual bool showMouse(const bool visible) override; /** * A (subset) of the graphic manager's state. This is used when switching - * between different SDL graphic managers on runtime. + * between different SDL graphic managers at runtime. */ struct State { int screenWidth, screenHeight; @@ -108,17 +107,17 @@ public: }; /** - * Queries the current state of the graphic manager. + * Gets the current state of the graphics manager. */ - State getState(); + 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; } @@ -130,6 +129,31 @@ protected: 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) override; + #if SDL_VERSION_ATLEAST(2, 0, 0) public: void unlockWindowSize() { @@ -146,6 +170,7 @@ protected: bool createOrUpdateWindow(const int width, const int height, const Uint32 flags); #endif + SDL_Surface *_hwScreen; SdlEventSource *_eventSource; SdlWindow *_window; }; diff --git a/backends/graphics/surfacesdl/surfacesdl-graphics.cpp b/backends/graphics/surfacesdl/surfacesdl-graphics.cpp index 897cdcb352..f025cfa7e5 100644 --- a/backends/graphics/surfacesdl/surfacesdl-graphics.cpp +++ b/backends/graphics/surfacesdl/surfacesdl-graphics.cpp @@ -23,7 +23,6 @@ #include "common/scummsys.h" #if defined(SDL_BACKEND) - #include "backends/graphics/surfacesdl/surfacesdl-graphics.h" #include "backends/events/sdl/sdl-events.h" #include "backends/platform/sdl/sdl.h" @@ -133,24 +132,19 @@ SurfaceSdlGraphicsManager::SurfaceSdlGraphicsManager(SdlEventSource *sdlEventSou _osdMessageSurface(nullptr), _osdMessageAlpha(SDL_ALPHA_TRANSPARENT), _osdMessageFadeStartTime(0), _osdIconSurface(nullptr), #endif - _hwscreen(0), #if SDL_VERSION_ATLEAST(2, 0, 0) _renderer(nullptr), _screenTexture(nullptr), - _viewport(), _windowWidth(1), _windowHeight(1), #endif #if defined(WIN32) && !SDL_VERSION_ATLEAST(2, 0, 0) _originalBitsPerPixel(0), #endif _screen(0), _tmpscreen(0), -#ifdef USE_RGB_COLOR _screenFormat(Graphics::PixelFormat::createFormatCLUT8()), _cursorFormat(Graphics::PixelFormat::createFormatCLUT8()), -#endif - _overlayVisible(false), _overlayscreen(0), _tmpscreen2(0), _scalerProc(0), _screenChangeCount(0), - _mouseVisible(false), _mouseNeedsRedraw(false), _mouseData(0), _mouseSurface(0), - _mouseOrigSurface(0), _cursorDontScale(false), _cursorPaletteDisabled(true), + _mouseData(nullptr), _mouseSurface(nullptr), + _mouseOrigSurface(nullptr), _cursorDontScale(false), _cursorPaletteDisabled(true), _currentShakePos(0), _newShakePos(0), _paletteDirtyStart(0), _paletteDirtyEnd(0), _screenIsLocked(false), @@ -214,21 +208,19 @@ SurfaceSdlGraphicsManager::SurfaceSdlGraphicsManager(SdlEventSource *sdlEventSou SurfaceSdlGraphicsManager::~SurfaceSdlGraphicsManager() { unloadGFXMode(); -#if SDL_VERSION_ATLEAST(2, 0, 0) - if (_window) - _window->destroyWindow(); -#endif - if (_mouseSurface) - SDL_FreeSurface(_mouseSurface); - _mouseSurface = 0; - if (_mouseOrigSurface) + if (_mouseOrigSurface) { SDL_FreeSurface(_mouseOrigSurface); - _mouseOrigSurface = 0; + if (_mouseOrigSurface == _mouseSurface) { + _mouseSurface = nullptr; + } + } + if (_mouseSurface) { + SDL_FreeSurface(_mouseSurface); + } g_system->deleteMutex(_graphicsMutex); - free(_currentPalette); free(_cursorPalette); - free(_mouseData); + delete[] _mouseData; } void SurfaceSdlGraphicsManager::activateManager() { @@ -247,7 +239,7 @@ void SurfaceSdlGraphicsManager::deactivateManager() { SdlGraphicsManager::deactivateManager(); } -bool SurfaceSdlGraphicsManager::hasFeature(OSystem::Feature f) { +bool SurfaceSdlGraphicsManager::hasFeature(OSystem::Feature f) const { return (f == OSystem::kFeatureFullscreenMode) || (f == OSystem::kFeatureAspectRatioCorrection) || @@ -284,7 +276,7 @@ void SurfaceSdlGraphicsManager::setFeatureState(OSystem::Feature f, bool enable) } } -bool SurfaceSdlGraphicsManager::getFeatureState(OSystem::Feature f) { +bool SurfaceSdlGraphicsManager::getFeatureState(OSystem::Feature f) const { // 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. @@ -555,16 +547,16 @@ void SurfaceSdlGraphicsManager::detectSupportedFormats() { Graphics::PixelFormat(2, 4, 4, 4, 4, 4, 8, 12, 0) }; - if (_hwscreen) { + if (_hwScreen) { // Get our currently set hardware format - Graphics::PixelFormat hwFormat(_hwscreen->format->BytesPerPixel, - 8 - _hwscreen->format->Rloss, 8 - _hwscreen->format->Gloss, - 8 - _hwscreen->format->Bloss, 8 - _hwscreen->format->Aloss, - _hwscreen->format->Rshift, _hwscreen->format->Gshift, - _hwscreen->format->Bshift, _hwscreen->format->Ashift); + Graphics::PixelFormat hwFormat(_hwScreen->format->BytesPerPixel, + 8 - _hwScreen->format->Rloss, 8 - _hwScreen->format->Gloss, + 8 - _hwScreen->format->Bloss, 8 - _hwScreen->format->Aloss, + _hwScreen->format->Rshift, _hwScreen->format->Gshift, + _hwScreen->format->Bshift, _hwScreen->format->Ashift); // Workaround to SDL not providing an accurate Aloss value on Mac OS X. - if (_hwscreen->format->Amask == 0) + if (_hwScreen->format->Amask == 0) hwFormat.aLoss = 8; _supportedFormats.push_back(hwFormat); @@ -579,7 +571,7 @@ void SurfaceSdlGraphicsManager::detectSupportedFormats() { // Push some RGB formats for (i = 0; i < ARRAYSIZE(RGBList); i++) { - if (_hwscreen && (RGBList[i].bytesPerPixel > format.bytesPerPixel)) + if (_hwScreen && (RGBList[i].bytesPerPixel > format.bytesPerPixel)) continue; if (RGBList[i] != format) _supportedFormats.push_back(RGBList[i]); @@ -587,7 +579,7 @@ void SurfaceSdlGraphicsManager::detectSupportedFormats() { // Push some BGR formats for (i = 0; i < ARRAYSIZE(BGRList); i++) { - if (_hwscreen && (BGRList[i].bytesPerPixel > format.bytesPerPixel)) + if (_hwScreen && (BGRList[i].bytesPerPixel > format.bytesPerPixel)) continue; if (BGRList[i] != format) _supportedFormats.push_back(BGRList[i]); @@ -722,11 +714,11 @@ void SurfaceSdlGraphicsManager::setGraphicsModeIntern() { } } - if (!_screen || !_hwscreen) + if (!_screen || !_hwScreen) return; // Blit everything to the screen - _forceFull = true; + _forceRedraw = true; // Even if the old and new scale factors are the same, we may have a // different scaler for the cursor now. @@ -797,13 +789,6 @@ void SurfaceSdlGraphicsManager::initSize(uint w, uint h, const Graphics::PixelFo _transactionDetails.sizeChanged = true; } -int SurfaceSdlGraphicsManager::effectiveScreenHeight() const { - return _videoMode.scaleFactor * - (_videoMode.aspectRatioCorrection - ? real2Aspect(_videoMode.screenHeight) - : _videoMode.screenHeight); -} - static void fixupResolutionForAspectRatio(AspectRatio desiredAspectRatio, int &width, int &height) { assert(&width != &height); @@ -864,7 +849,7 @@ static void fixupResolutionForAspectRatio(AspectRatio desiredAspectRatio, int &w } bool SurfaceSdlGraphicsManager::loadGFXMode() { - _forceFull = true; + _forceRedraw = true; #if !defined(__MAEMO__) && !defined(DINGUX) && !defined(GPH_DEVICE) && !defined(LINUXMOTO) && !defined(OPENPANDORA) _videoMode.overlayWidth = _videoMode.screenWidth * _videoMode.scaleFactor; @@ -873,11 +858,14 @@ bool SurfaceSdlGraphicsManager::loadGFXMode() { if (_videoMode.screenHeight != 200 && _videoMode.screenHeight != 400) _videoMode.aspectRatioCorrection = false; - if (_videoMode.aspectRatioCorrection) + _videoMode.hardwareWidth = _videoMode.screenWidth * _videoMode.scaleFactor; + _videoMode.hardwareHeight = _videoMode.screenHeight * _videoMode.scaleFactor; + + if (_videoMode.aspectRatioCorrection) { _videoMode.overlayHeight = real2Aspect(_videoMode.overlayHeight); + _videoMode.hardwareHeight = real2Aspect(_videoMode.hardwareHeight); + } - _videoMode.hardwareWidth = _videoMode.screenWidth * _videoMode.scaleFactor; - _videoMode.hardwareHeight = effectiveScreenHeight(); // On GPH devices ALL the _videoMode.hardware... are setup in GPHGraphicsManager::loadGFXMode() #elif !defined(GPH_DEVICE) _videoMode.hardwareWidth = _videoMode.overlayWidth; @@ -887,22 +875,20 @@ bool SurfaceSdlGraphicsManager::loadGFXMode() { // // Create the surface that contains the 8 bit game data // -#ifdef USE_RGB_COLOR + + const Graphics::PixelFormat &format = _screenFormat; + const Uint32 rMask = ((0xFF >> format.rLoss) << format.rShift); + const Uint32 gMask = ((0xFF >> format.gLoss) << format.gShift); + const Uint32 bMask = ((0xFF >> format.bLoss) << format.bShift); + const Uint32 aMask = ((0xFF >> format.aLoss) << format.aShift); _screen = SDL_CreateRGBSurface(SDL_SWSURFACE, _videoMode.screenWidth, _videoMode.screenHeight, - _screenFormat.bytesPerPixel << 3, - ((1 << _screenFormat.rBits()) - 1) << _screenFormat.rShift , - ((1 << _screenFormat.gBits()) - 1) << _screenFormat.gShift , - ((1 << _screenFormat.bBits()) - 1) << _screenFormat.bShift , - ((1 << _screenFormat.aBits()) - 1) << _screenFormat.aShift ); + _screenFormat.bytesPerPixel * 8, rMask, gMask, bMask, aMask); if (_screen == NULL) error("allocating _screen failed"); +#ifdef USE_RGB_COLOR // Avoid having SDL_SRCALPHA set even if we supplied an alpha-channel in the format. SDL_SetAlpha(_screen, 0, 255); -#else - _screen = SDL_CreateRGBSurface(SDL_SWSURFACE, _videoMode.screenWidth, _videoMode.screenHeight, 8, 0, 0, 0, 0); - if (_screen == NULL) - error("allocating _screen failed"); #endif // SDL 1.2 palettes default to all black, @@ -924,7 +910,7 @@ bool SurfaceSdlGraphicsManager::loadGFXMode() { _displayDisabled = ConfMan.getBool("disable_display"); if (_displayDisabled) { - _hwscreen = g_eventRec.getSurface(_videoMode.hardwareWidth, _videoMode.hardwareHeight); + _hwScreen = g_eventRec.getSurface(_videoMode.hardwareWidth, _videoMode.hardwareHeight); } else #endif { @@ -937,7 +923,7 @@ bool SurfaceSdlGraphicsManager::loadGFXMode() { } #endif - _hwscreen = SDL_SetVideoMode(_videoMode.hardwareWidth, _videoMode.hardwareHeight, 16, + _hwScreen = SDL_SetVideoMode(_videoMode.hardwareWidth, _videoMode.hardwareHeight, 16, _videoMode.fullscreen ? (SDL_FULLSCREEN|SDL_SWSURFACE) : SDL_SWSURFACE ); } @@ -946,9 +932,9 @@ bool SurfaceSdlGraphicsManager::loadGFXMode() { detectSupportedFormats(); #endif - if (_hwscreen == NULL) { + if (_hwScreen == NULL) { // DON'T use error(), as this tries to bring up the debug - // console, which WON'T WORK now that _hwscreen is hosed. + // console, which WON'T WORK now that _hwScreen is hosed. if (!_oldVideoMode.setup) { warning("SDL_SetVideoMode says we can't switch to that mode (%s)", SDL_GetError()); @@ -958,6 +944,10 @@ bool SurfaceSdlGraphicsManager::loadGFXMode() { } } +#if !SDL_VERSION_ATLEAST(2, 0, 0) + handleResize(_videoMode.hardwareWidth, _videoMode.hardwareHeight); +#endif + // // Create the surface used for the graphics in 16 bit before scaling, and also the overlay // @@ -965,20 +955,20 @@ bool SurfaceSdlGraphicsManager::loadGFXMode() { // Need some extra bytes around when using 2xSaI _tmpscreen = SDL_CreateRGBSurface(SDL_SWSURFACE, _videoMode.screenWidth + 3, _videoMode.screenHeight + 3, 16, - _hwscreen->format->Rmask, - _hwscreen->format->Gmask, - _hwscreen->format->Bmask, - _hwscreen->format->Amask); + _hwScreen->format->Rmask, + _hwScreen->format->Gmask, + _hwScreen->format->Bmask, + _hwScreen->format->Amask); if (_tmpscreen == NULL) error("allocating _tmpscreen failed"); _overlayscreen = SDL_CreateRGBSurface(SDL_SWSURFACE, _videoMode.overlayWidth, _videoMode.overlayHeight, 16, - _hwscreen->format->Rmask, - _hwscreen->format->Gmask, - _hwscreen->format->Bmask, - _hwscreen->format->Amask); + _hwScreen->format->Rmask, + _hwScreen->format->Gmask, + _hwScreen->format->Bmask, + _hwScreen->format->Amask); if (_overlayscreen == NULL) error("allocating _overlayscreen failed"); @@ -997,25 +987,16 @@ bool SurfaceSdlGraphicsManager::loadGFXMode() { _tmpscreen2 = SDL_CreateRGBSurface(SDL_SWSURFACE, _videoMode.overlayWidth + 3, _videoMode.overlayHeight + 3, 16, - _hwscreen->format->Rmask, - _hwscreen->format->Gmask, - _hwscreen->format->Bmask, - _hwscreen->format->Amask); + _hwScreen->format->Rmask, + _hwScreen->format->Gmask, + _hwScreen->format->Bmask, + _hwScreen->format->Amask); if (_tmpscreen2 == NULL) error("allocating _tmpscreen2 failed"); -#if !SDL_VERSION_ATLEAST(2, 0, 0) - // For SDL2 the output resolution might differ from the requested - // resolution. We handle resetting the keyboard emulation properly inside - // our SDL_SetVideoMode wrapper for SDL2. - _eventSource->resetKeyboardEmulation( - _videoMode.screenWidth * _videoMode.scaleFactor - 1, - effectiveScreenHeight() - 1); -#endif - // Distinguish 555 and 565 mode - if (_hwscreen->format->Rmask == 0x7C00) + if (_hwScreen->format->Rmask == 0x7C00) InitScalers(555); else InitScalers(565); @@ -1033,9 +1014,9 @@ void SurfaceSdlGraphicsManager::unloadGFXMode() { deinitializeRenderer(); #endif - if (_hwscreen) { - SDL_FreeSurface(_hwscreen); - _hwscreen = NULL; + if (_hwScreen) { + SDL_FreeSurface(_hwScreen); + _hwScreen = NULL; } if (_tmpscreen) { @@ -1087,9 +1068,9 @@ bool SurfaceSdlGraphicsManager::hotswapGFXMode() { _overlayscreen = NULL; // Release the HW screen surface - if (_hwscreen) { - SDL_FreeSurface(_hwscreen); - _hwscreen = NULL; + if (_hwScreen) { + SDL_FreeSurface(_hwScreen); + _hwScreen = NULL; } if (_tmpscreen) { SDL_FreeSurface(_tmpscreen); @@ -1139,14 +1120,14 @@ void SurfaceSdlGraphicsManager::updateScreen() { } void SurfaceSdlGraphicsManager::updateShader() { -// shader init code goes here -// currently only used on Vita port -// the user-selected shaderID should be obtained via ConfMan.getInt("shader") -// and the corresponding shader should then be activated here -// this way the user can combine any software scaling (scalers) -// with any hardware shading (shaders). The shaders could provide -// scanline masks, overlays, but could also serve for -// hardware-based up-scaling (sharp-bilinear-simple, etc.) + // shader init code goes here + // currently only used on Vita port + // the user-selected shaderID should be obtained via ConfMan.getInt("shader") + // and the corresponding shader should then be activated here + // this way the user can combine any software scaling (scalers) + // with any hardware shading (shaders). The shaders could provide + // scanline masks, overlays, but could also serve for + // hardware-based up-scaling (sharp-bilinear-simple, etc.) } void SurfaceSdlGraphicsManager::internUpdateScreen() { @@ -1155,25 +1136,19 @@ void SurfaceSdlGraphicsManager::internUpdateScreen() { ScalerProc *scalerProc; int scale1; - // definitions not available for non-DEBUG here. (needed this to compile in SYMBIAN32 & linux?) -#if defined(DEBUG) && !defined(WIN32) && !defined(_WIN32_WCE) - assert(_hwscreen != NULL); - assert(_hwscreen->map->sw_data != NULL); -#endif - // If the shake position changed, fill the dirty area with blackness if (_currentShakePos != _newShakePos || - (_mouseNeedsRedraw && _mouseBackup.y <= _currentShakePos)) { + (_cursorNeedsRedraw && _mouseBackup.y <= _currentShakePos)) { SDL_Rect blackrect = {0, 0, (Uint16)(_videoMode.screenWidth * _videoMode.scaleFactor), (Uint16)(_newShakePos * _videoMode.scaleFactor)}; if (_videoMode.aspectRatioCorrection && !_overlayVisible) blackrect.h = real2Aspect(blackrect.h - 1) + 1; - SDL_FillRect(_hwscreen, &blackrect, 0); + SDL_FillRect(_hwScreen, &blackrect, 0); _currentShakePos = _newShakePos; - _forceFull = true; + _forceRedraw = true; } // Check whether the palette was changed in the meantime and update the @@ -1185,7 +1160,7 @@ void SurfaceSdlGraphicsManager::internUpdateScreen() { _paletteDirtyEnd = 0; - _forceFull = true; + _forceRedraw = true; } if (!_overlayVisible) { @@ -1207,7 +1182,7 @@ void SurfaceSdlGraphicsManager::internUpdateScreen() { // Add the area covered by the mouse cursor to the list of dirty rects if // we have to redraw the mouse. - if (_mouseNeedsRedraw) + if (_cursorNeedsRedraw) undrawMouse(); #ifdef USE_OSD @@ -1215,7 +1190,7 @@ void SurfaceSdlGraphicsManager::internUpdateScreen() { #endif // Force a full redraw if requested - if (_forceFull) { + if (_forceRedraw) { _numDirtyRects = 1; _dirtyRectList[0].x = 0; _dirtyRectList[0].y = 0; @@ -1224,7 +1199,7 @@ void SurfaceSdlGraphicsManager::internUpdateScreen() { } // Only draw anything if necessary - if (_numDirtyRects > 0 || _mouseNeedsRedraw) { + if (_numDirtyRects > 0 || _cursorNeedsRedraw) { SDL_Rect *r; SDL_Rect dst; uint32 srcPitch, dstPitch; @@ -1240,10 +1215,10 @@ void SurfaceSdlGraphicsManager::internUpdateScreen() { } SDL_LockSurface(srcSurf); - SDL_LockSurface(_hwscreen); + SDL_LockSurface(_hwScreen); srcPitch = srcSurf->pitch; - dstPitch = _hwscreen->pitch; + dstPitch = _hwScreen->pitch; for (r = _dirtyRectList; r != lastRect; ++r) { register int dst_y = r->y + _currentShakePos; @@ -1268,7 +1243,7 @@ void SurfaceSdlGraphicsManager::internUpdateScreen() { assert(scalerProc != NULL); scalerProc((byte *)srcSurf->pixels + (r->x * 2 + 2) + (r->y + 1) * srcPitch, srcPitch, - (byte *)_hwscreen->pixels + rx1 * 2 + dst_y * dstPitch, dstPitch, r->w, dst_h); + (byte *)_hwScreen->pixels + rx1 * 2 + dst_y * dstPitch, dstPitch, r->w, dst_h); } r->x = rx1; @@ -1278,17 +1253,17 @@ void SurfaceSdlGraphicsManager::internUpdateScreen() { #ifdef USE_SCALERS if (_videoMode.aspectRatioCorrection && orig_dst_y < height && !_overlayVisible) - r->h = stretch200To240((uint8 *) _hwscreen->pixels, dstPitch, r->w, r->h, r->x, r->y, orig_dst_y * scale1); + r->h = stretch200To240((uint8 *) _hwScreen->pixels, dstPitch, r->w, r->h, r->x, r->y, orig_dst_y * scale1); #endif } SDL_UnlockSurface(srcSurf); - SDL_UnlockSurface(_hwscreen); + SDL_UnlockSurface(_hwScreen); // Readjust the dirty rect list in case we are doing a full update. // This is necessary if shaking is active. - if (_forceFull) { + if (_forceRedraw) { _dirtyRectList[0].y = 0; - _dirtyRectList[0].h = effectiveScreenHeight(); + _dirtyRectList[0].h = _videoMode.hardwareHeight; } drawMouse(); @@ -1318,18 +1293,18 @@ void SurfaceSdlGraphicsManager::internUpdateScreen() { y = real2Aspect(y); if (h > 0 && w > 0) { - SDL_LockSurface(_hwscreen); + SDL_LockSurface(_hwScreen); // Use white as color for now. - Uint32 rectColor = SDL_MapRGB(_hwscreen->format, 0xFF, 0xFF, 0xFF); + Uint32 rectColor = SDL_MapRGB(_hwScreen->format, 0xFF, 0xFF, 0xFF); // First draw the top and bottom lines // then draw the left and right lines - if (_hwscreen->format->BytesPerPixel == 2) { - uint16 *top = (uint16 *)((byte *)_hwscreen->pixels + y * _hwscreen->pitch + x * 2); - uint16 *bottom = (uint16 *)((byte *)_hwscreen->pixels + (y + h) * _hwscreen->pitch + x * 2); - byte *left = ((byte *)_hwscreen->pixels + y * _hwscreen->pitch + x * 2); - byte *right = ((byte *)_hwscreen->pixels + y * _hwscreen->pitch + (x + w - 1) * 2); + if (_hwScreen->format->BytesPerPixel == 2) { + uint16 *top = (uint16 *)((byte *)_hwScreen->pixels + y * _hwScreen->pitch + x * 2); + uint16 *bottom = (uint16 *)((byte *)_hwScreen->pixels + (y + h) * _hwScreen->pitch + x * 2); + byte *left = ((byte *)_hwScreen->pixels + y * _hwScreen->pitch + x * 2); + byte *right = ((byte *)_hwScreen->pixels + y * _hwScreen->pitch + (x + w - 1) * 2); while (w--) { *top++ = rectColor; @@ -1340,14 +1315,14 @@ void SurfaceSdlGraphicsManager::internUpdateScreen() { *(uint16 *)left = rectColor; *(uint16 *)right = rectColor; - left += _hwscreen->pitch; - right += _hwscreen->pitch; + left += _hwScreen->pitch; + right += _hwScreen->pitch; } - } else if (_hwscreen->format->BytesPerPixel == 4) { - uint32 *top = (uint32 *)((byte *)_hwscreen->pixels + y * _hwscreen->pitch + x * 4); - uint32 *bottom = (uint32 *)((byte *)_hwscreen->pixels + (y + h) * _hwscreen->pitch + x * 4); - byte *left = ((byte *)_hwscreen->pixels + y * _hwscreen->pitch + x * 4); - byte *right = ((byte *)_hwscreen->pixels + y * _hwscreen->pitch + (x + w - 1) * 4); + } else if (_hwScreen->format->BytesPerPixel == 4) { + uint32 *top = (uint32 *)((byte *)_hwScreen->pixels + y * _hwScreen->pitch + x * 4); + uint32 *bottom = (uint32 *)((byte *)_hwScreen->pixels + (y + h) * _hwScreen->pitch + x * 4); + byte *left = ((byte *)_hwScreen->pixels + y * _hwScreen->pitch + x * 4); + byte *right = ((byte *)_hwScreen->pixels + y * _hwScreen->pitch + (x + w - 1) * 4); while (w--) { *top++ = rectColor; @@ -1358,12 +1333,12 @@ void SurfaceSdlGraphicsManager::internUpdateScreen() { *(uint32 *)left = rectColor; *(uint32 *)right = rectColor; - left += _hwscreen->pitch; - right += _hwscreen->pitch; + left += _hwScreen->pitch; + right += _hwScreen->pitch; } } - SDL_UnlockSurface(_hwscreen); + SDL_UnlockSurface(_hwScreen); } } } @@ -1371,17 +1346,17 @@ void SurfaceSdlGraphicsManager::internUpdateScreen() { // Finally, blit all our changes to the screen if (!_displayDisabled) { - SDL_UpdateRects(_hwscreen, _numDirtyRects, _dirtyRectList); + SDL_UpdateRects(_hwScreen, _numDirtyRects, _dirtyRectList); } } _numDirtyRects = 0; - _forceFull = false; - _mouseNeedsRedraw = false; + _forceRedraw = false; + _cursorNeedsRedraw = false; } bool SurfaceSdlGraphicsManager::saveScreenshot(const char *filename) { - assert(_hwscreen != NULL); + assert(_hwScreen != NULL); Common::StackLock lock(_graphicsMutex); #ifdef USE_PNG @@ -1391,12 +1366,12 @@ bool SurfaceSdlGraphicsManager::saveScreenshot(const char *filename) { } #if SDL_VERSION_ATLEAST(2, 0, 0) - SDL_Surface *rgbScreen = SDL_ConvertSurfaceFormat(_hwscreen, SDL_PIXELFORMAT_RGB24, 0); + SDL_Surface *rgbScreen = SDL_ConvertSurfaceFormat(_hwScreen, SDL_PIXELFORMAT_RGB24, 0); #else // This block of code was taken mostly as-is from SDL 1.2's SDL_SaveBMP_RW SDL_Surface *rgbScreen = SDL_CreateRGBSurface(SDL_SWSURFACE, - _hwscreen->w, - _hwscreen->h, + _hwScreen->w, + _hwScreen->h, 24, #ifdef SCUMM_LITTLE_ENDIAN 0x0000FF, 0x00FF00, 0xFF0000, @@ -1411,9 +1386,9 @@ bool SurfaceSdlGraphicsManager::saveScreenshot(const char *filename) { SDL_Rect bounds; bounds.x = bounds.y = 0; - bounds.w = _hwscreen->w; - bounds.h = _hwscreen->h; - if (SDL_LowerBlit(_hwscreen, &bounds, rgbScreen, &bounds) < 0) { + bounds.w = _hwScreen->w; + bounds.h = _hwScreen->h; + if (SDL_LowerBlit(_hwScreen, &bounds, rgbScreen, &bounds) < 0) { SDL_FreeSurface(rgbScreen); rgbScreen = nullptr; } @@ -1441,7 +1416,7 @@ bool SurfaceSdlGraphicsManager::saveScreenshot(const char *filename) { return success; #else - return SDL_SaveBMP(_hwscreen, filename) == 0; + return SDL_SaveBMP(_hwScreen, filename) == 0; #endif } @@ -1505,7 +1480,6 @@ void SurfaceSdlGraphicsManager::copyRectToScreen(const void *buf, int pitch, int if (SDL_LockSurface(_screen) == -1) error("SDL_LockSurface failed: %s", SDL_GetError()); -#ifdef USE_RGB_COLOR byte *dst = (byte *)_screen->pixels + y * _screen->pitch + x * _screenFormat.bytesPerPixel; if (_videoMode.screenWidth == w && pitch == _screen->pitch) { memcpy(dst, buf, h*pitch); @@ -1517,19 +1491,6 @@ void SurfaceSdlGraphicsManager::copyRectToScreen(const void *buf, int pitch, int dst += _screen->pitch; } while (--h); } -#else - byte *dst = (byte *)_screen->pixels + y * _screen->pitch + x; - if (_screen->pitch == pitch && pitch == w) { - memcpy(dst, buf, h*w); - } else { - const byte *src = (const byte *)buf; - do { - memcpy(dst, src, w); - src += pitch; - dst += _screen->pitch; - } while (--h); - } -#endif // Unlock the screen surface SDL_UnlockSurface(_screen); @@ -1549,13 +1510,7 @@ Graphics::Surface *SurfaceSdlGraphicsManager::lockScreen() { if (SDL_LockSurface(_screen) == -1) error("SDL_LockSurface failed: %s", SDL_GetError()); - _framebuffer.init(_screen->w, _screen->h, _screen->pitch, _screen->pixels, -#ifdef USE_RGB_COLOR - _screenFormat -#else - Graphics::PixelFormat::createFormatCLUT8() -#endif - ); + _framebuffer.init(_screen->w, _screen->h, _screen->pitch, _screen->pixels, _screenFormat); return &_framebuffer; } @@ -1571,7 +1526,7 @@ void SurfaceSdlGraphicsManager::unlockScreen() { SDL_UnlockSurface(_screen); // Trigger a full screen update - _forceFull = true; + _forceRedraw = true; // Finally unlock the graphics mutex g_system->unlockMutex(_graphicsMutex); @@ -1585,11 +1540,11 @@ void SurfaceSdlGraphicsManager::fillScreen(uint32 col) { } void SurfaceSdlGraphicsManager::addDirtyRect(int x, int y, int w, int h, bool realCoordinates) { - if (_forceFull) + if (_forceRedraw) return; if (_numDirtyRects == NUM_DIRTY_RECT) { - _forceFull = true; + _forceRedraw = true; return; } @@ -1608,8 +1563,8 @@ void SurfaceSdlGraphicsManager::addDirtyRect(int x, int y, int w, int h, bool re if (!realCoordinates) { x--; y--; - w+=2; - h+=2; + w += 2; + h += 2; } // clip @@ -1620,7 +1575,7 @@ void SurfaceSdlGraphicsManager::addDirtyRect(int x, int y, int w, int h, bool re if (y < 0) { h += y; - y=0; + y = 0; } if (w > width - x) { @@ -1638,7 +1593,7 @@ void SurfaceSdlGraphicsManager::addDirtyRect(int x, int y, int w, int h, bool re #endif if (w == width && h == height) { - _forceFull = true; + _forceRedraw = true; return; } @@ -1652,20 +1607,17 @@ void SurfaceSdlGraphicsManager::addDirtyRect(int x, int y, int w, int h, bool re } } -int16 SurfaceSdlGraphicsManager::getHeight() { +int16 SurfaceSdlGraphicsManager::getHeight() const { return _videoMode.screenHeight; } -int16 SurfaceSdlGraphicsManager::getWidth() { +int16 SurfaceSdlGraphicsManager::getWidth() const { return _videoMode.screenWidth; } void SurfaceSdlGraphicsManager::setPalette(const byte *colors, uint start, uint num) { assert(colors); - -#ifdef USE_RGB_COLOR assert(_screenFormat.bytesPerPixel == 1); -#endif // Setting the palette before _screen is created is allowed - for now - // since we don't actually set the palette until the screen is updated. @@ -1697,12 +1649,9 @@ void SurfaceSdlGraphicsManager::setPalette(const byte *colors, uint start, uint blitCursor(); } -void SurfaceSdlGraphicsManager::grabPalette(byte *colors, uint start, uint num) { +void SurfaceSdlGraphicsManager::grabPalette(byte *colors, uint start, uint num) const { assert(colors); - -#ifdef USE_RGB_COLOR assert(_screenFormat.bytesPerPixel == 1); -#endif const SDL_Color *base = _currentPalette + start; @@ -1777,56 +1726,7 @@ void SurfaceSdlGraphicsManager::clearFocusRectangle() { #pragma mark --- Overlays --- #pragma mark - -void SurfaceSdlGraphicsManager::showOverlay() { - assert(_transactionMode == kTransactionNone); - - int x, y; - - if (_overlayVisible) - return; - - _overlayVisible = true; - - // Since resolution could change, put mouse to adjusted position - // Fixes bug #1349059 - x = _mouseCurState.x * _videoMode.scaleFactor; - if (_videoMode.aspectRatioCorrection) - y = real2Aspect(_mouseCurState.y) * _videoMode.scaleFactor; - else - y = _mouseCurState.y * _videoMode.scaleFactor; - - warpMouse(x, y); - - clearOverlay(); -} - -void SurfaceSdlGraphicsManager::hideOverlay() { - assert(_transactionMode == kTransactionNone); - - if (!_overlayVisible) - return; - - int x, y; - - _overlayVisible = false; - - // Since resolution could change, put mouse to adjusted position - // Fixes bug #1349059 - x = _mouseCurState.x / _videoMode.scaleFactor; - y = _mouseCurState.y / _videoMode.scaleFactor; - if (_videoMode.aspectRatioCorrection) - y = aspect2Real(y); - - warpMouse(x, y); - - clearOverlay(); - - _forceFull = true; -} - void SurfaceSdlGraphicsManager::clearOverlay() { - //assert(_transactionMode == kTransactionNone); - Common::StackLock lock(_graphicsMutex); // Lock the mutex until this function ends if (!_overlayVisible) @@ -1854,10 +1754,10 @@ void SurfaceSdlGraphicsManager::clearOverlay() { SDL_UnlockSurface(_tmpscreen); SDL_UnlockSurface(_overlayscreen); - _forceFull = true; + _forceRedraw = true; } -void SurfaceSdlGraphicsManager::grabOverlay(void *buf, int pitch) { +void SurfaceSdlGraphicsManager::grabOverlay(void *buf, int pitch) const { assert(_transactionMode == kTransactionNone); if (_overlayscreen == NULL) @@ -1931,143 +1831,159 @@ void SurfaceSdlGraphicsManager::copyRectToOverlay(const void *buf, int pitch, in #pragma mark --- Mouse --- #pragma mark - -bool SurfaceSdlGraphicsManager::showMouse(bool visible) { - if (_mouseVisible == visible) - return visible; +void SurfaceSdlGraphicsManager::setMouseCursor(const void *buf, uint w, uint h, int hotspotX, int hotspotY, uint32 keyColor, bool dontScale, const Graphics::PixelFormat *format) { + if (format) { +#ifndef USE_RGB_COLOR + assert(format->bytesPerPixel == 1); +#endif + _cursorFormat = *format; + } else { + _cursorFormat = Graphics::PixelFormat::createFormatCLUT8(); + } - bool last = _mouseVisible; - _mouseVisible = visible; - _mouseNeedsRedraw = true; + if (_cursorFormat.bytesPerPixel == 4) { + assert(keyColor == 0); + dontScale = true; + } else { + assert(keyColor < 1U << (_cursorFormat.bytesPerPixel * 8)); + } - return last; -} + _mouseCurState.hotX = hotspotX; + _mouseCurState.hotY = hotspotY; -void SurfaceSdlGraphicsManager::setMousePos(int x, int y) { - if (x != _mouseCurState.x || y != _mouseCurState.y) { - _mouseNeedsRedraw = true; - _mouseCurState.x = x; - _mouseCurState.y = y; - } -} + _mouseKeyColor = keyColor; -void SurfaceSdlGraphicsManager::warpMouse(int x, int y) { - // Don't change actual mouse position, when mouse is outside of our window (in case of windowed mode) - if (!_window->hasMouseFocus()) { - setMousePos(x, y); // but change game cursor position - return; - } + _cursorDontScale = dontScale; - int x1 = x, y1 = y; - if (_videoMode.aspectRatioCorrection && !_overlayVisible) - y1 = real2Aspect(y1); + if (_mouseCurState.w != (int)w || _mouseCurState.h != (int)h) { + _mouseCurState.w = w; + _mouseCurState.h = h; - if (_mouseCurState.x != x || _mouseCurState.y != y) { - if (!_overlayVisible) { - x1 *= _videoMode.scaleFactor; - y1 *= _videoMode.scaleFactor; + if (!w || !h) { + return; } -#if SDL_VERSION_ATLEAST(2, 0, 0) - // Transform our coordinates in "virtual" output coordinate space into - // actual output coordinate space. - x1 = x1 * _windowWidth / _videoMode.hardwareWidth; - y1 = y1 * _windowHeight / _videoMode.hardwareHeight; -#endif + if (_mouseOrigSurface) { + SDL_FreeSurface(_mouseOrigSurface); + + if (_mouseSurface == _mouseOrigSurface) { + _mouseSurface = nullptr; + } + } + + if (_cursorFormat.bytesPerPixel == 4) { + if (_mouseSurface != _mouseOrigSurface) { + SDL_FreeSurface(_mouseSurface); + } - _window->warpMouseInWindow(x1, y1); + const Uint32 rMask = ((0xFF >> format->rLoss) << format->rShift); + const Uint32 gMask = ((0xFF >> format->gLoss) << format->gShift); + const Uint32 bMask = ((0xFF >> format->bLoss) << format->bShift); + const Uint32 aMask = ((0xFF >> format->aLoss) << format->aShift); + _mouseSurface = _mouseOrigSurface = SDL_CreateRGBSurfaceFrom(const_cast<void *>(buf), w, h, format->bytesPerPixel * 8, w * format->bytesPerPixel, rMask, gMask, bMask, aMask); + } else { + // Allocate bigger surface because AdvMame2x adds black pixel at [0,0] + _mouseOrigSurface = SDL_CreateRGBSurface(SDL_SWSURFACE | SDL_RLEACCEL | SDL_SRCCOLORKEY | SDL_SRCALPHA, + _mouseCurState.w + 2, + _mouseCurState.h + 2, + 16, + _hwScreen->format->Rmask, + _hwScreen->format->Gmask, + _hwScreen->format->Bmask, + _hwScreen->format->Amask); + } - // SDL_WarpMouse() generates a mouse movement event, so - // setMousePos() would be called eventually. However, the - // cannon script in CoMI calls this function twice each time - // the cannon is reloaded. Unless we update the mouse position - // immediately the second call is ignored, causing the cannon - // to change its aim. + if (_mouseOrigSurface == nullptr) { + error("Allocating _mouseOrigSurface failed"); + } - setMousePos(x, y); + if (_cursorFormat.bytesPerPixel < 4) { + SDL_SetColorKey(_mouseOrigSurface, SDL_RLEACCEL | SDL_SRCCOLORKEY | SDL_SRCALPHA, kMouseColorKey); + } } -} -void SurfaceSdlGraphicsManager::setMouseCursor(const void *buf, uint w, uint h, int hotspot_x, int hotspot_y, uint32 keycolor, bool dontScale, const Graphics::PixelFormat *format) { -#ifdef USE_RGB_COLOR - if (!format) - _cursorFormat = Graphics::PixelFormat::createFormatCLUT8(); - else if (format->bytesPerPixel <= _screenFormat.bytesPerPixel) - _cursorFormat = *format; + delete[] _mouseData; + if (_cursorFormat.bytesPerPixel == 4) { + _mouseData = nullptr; + } else { + _mouseData = new byte[w * h * _cursorFormat.bytesPerPixel]; + assert(_mouseData); + memcpy(_mouseData, buf, w * h * _cursorFormat.bytesPerPixel); + } - if (_cursorFormat.bytesPerPixel < 4) - assert(keycolor < (uint)(1 << (_cursorFormat.bytesPerPixel << 3))); -#else - assert(keycolor <= 0xFF); -#endif + blitCursor(); +} - if (w == 0 || h == 0) +void SurfaceSdlGraphicsManager::blitCursor() { + const int w = _mouseCurState.w; + const int h = _mouseCurState.h; + + if (!w || !h || !_mouseOrigSurface) { return; + } - _mouseCurState.hotX = hotspot_x; - _mouseCurState.hotY = hotspot_y; + if (_cursorFormat.bytesPerPixel != 4 && !_mouseData) { + return; + } - _mouseKeyColor = keycolor; + _cursorNeedsRedraw = true; - _cursorDontScale = dontScale; + int cursorScale; + if (_cursorDontScale) { + // Don't scale the cursor at all if the user requests this behavior. + cursorScale = 1; + } else { + // Scale the cursor with the game screen scale factor. + cursorScale = _videoMode.scaleFactor; + } - if (_mouseCurState.w != (int)w || _mouseCurState.h != (int)h) { - _mouseCurState.w = w; - _mouseCurState.h = h; + assert(_cursorFormat.bytesPerPixel != 4 || cursorScale == 1); - if (_mouseOrigSurface) - SDL_FreeSurface(_mouseOrigSurface); + // Adapt the real hotspot according to the scale factor. + int rW = w * cursorScale; + int rH = h * cursorScale; + _mouseCurState.rHotX = _mouseCurState.hotX * cursorScale; + _mouseCurState.rHotY = _mouseCurState.hotY * cursorScale; - // Allocate bigger surface because AdvMame2x adds black pixel at [0,0] - _mouseOrigSurface = SDL_CreateRGBSurface(SDL_SWSURFACE | SDL_RLEACCEL | SDL_SRCCOLORKEY | SDL_SRCALPHA, - _mouseCurState.w + 2, - _mouseCurState.h + 2, - 16, - _hwscreen->format->Rmask, - _hwscreen->format->Gmask, - _hwscreen->format->Bmask, - _hwscreen->format->Amask); + // The virtual dimensions will be the same as the original. - if (_mouseOrigSurface == NULL) - error("allocating _mouseOrigSurface failed"); - SDL_SetColorKey(_mouseOrigSurface, SDL_RLEACCEL | SDL_SRCCOLORKEY | SDL_SRCALPHA, kMouseColorKey); - } + _mouseCurState.vW = w; + _mouseCurState.vH = h; + _mouseCurState.vHotX = _mouseCurState.hotX; + _mouseCurState.vHotY = _mouseCurState.hotY; - free(_mouseData); -#ifdef USE_RGB_COLOR - _mouseData = (byte *)malloc(w * h * _cursorFormat.bytesPerPixel); - memcpy(_mouseData, buf, w * h * _cursorFormat.bytesPerPixel); -#else - _mouseData = (byte *)malloc(w * h); - memcpy(_mouseData, buf, w * h); +#ifdef USE_SCALERS + // store original to pass to aspect-correction function later + const int rH1 = rH; #endif - blitCursor(); -} + if (!_cursorDontScale && _videoMode.aspectRatioCorrection) { + rH = real2Aspect(rH - 1) + 1; + _mouseCurState.rHotY = real2Aspect(_mouseCurState.rHotY); + } -void SurfaceSdlGraphicsManager::blitCursor() { - byte *dstPtr; - const byte *srcPtr = _mouseData; -#ifdef USE_RGB_COLOR - uint32 color; -#else - byte color; -#endif - int w, h, i, j; + bool sizeChanged = false; + if (_mouseCurState.rW != rW || _mouseCurState.rH != rH) { + _mouseCurState.rW = rW; + _mouseCurState.rH = rH; + sizeChanged = true; + } - if (!_mouseOrigSurface || !_mouseData) + // 32bpp always blits directly, so no need to do any more work here + if (_cursorFormat.bytesPerPixel == 4) { return; - - _mouseNeedsRedraw = true; - - w = _mouseCurState.w; - h = _mouseCurState.h; + } SDL_LockSurface(_mouseOrigSurface); + byte *dstPtr; + const byte *srcPtr = _mouseData; + uint32 color; + // Make whole surface transparent - for (i = 0; i < h + 2; i++) { + for (int i = 0; i < h + 2; i++) { dstPtr = (byte *)_mouseOrigSurface->pixels + _mouseOrigSurface->pitch * i; - for (j = 0; j < w + 2; j++) { + for (int j = 0; j < w + 2; j++) { *(uint16 *)dstPtr = kMouseColorKey; dstPtr += 2; } @@ -2083,75 +1999,31 @@ void SurfaceSdlGraphicsManager::blitCursor() { else palette = _cursorPalette; - for (i = 0; i < h; i++) { - for (j = 0; j < w; j++) { -#ifdef USE_RGB_COLOR - if (_cursorFormat.bytesPerPixel > 1) { - if (_cursorFormat.bytesPerPixel == 2) - color = *(const uint16 *)srcPtr; - else - color = *(const uint32 *)srcPtr; - if (color != _mouseKeyColor) { // transparent, don't draw + for (int i = 0; i < h; i++) { + for (int j = 0; j < w; j++) { + if (_cursorFormat.bytesPerPixel == 2) { + color = *(const uint16 *)srcPtr; + if (color != _mouseKeyColor) { uint8 r, g, b; _cursorFormat.colorToRGB(color, r, g, b); - *(uint16 *)dstPtr = SDL_MapRGB(_mouseOrigSurface->format, - r, g, b); + *(uint16 *)dstPtr = SDL_MapRGB(_mouseOrigSurface->format, r, g, b); } dstPtr += 2; srcPtr += _cursorFormat.bytesPerPixel; } else { -#endif color = *srcPtr; - if (color != _mouseKeyColor) { // transparent, don't draw + if (color != _mouseKeyColor) { *(uint16 *)dstPtr = SDL_MapRGB(_mouseOrigSurface->format, palette[color].r, palette[color].g, palette[color].b); } dstPtr += 2; srcPtr++; -#ifdef USE_RGB_COLOR } -#endif } dstPtr += _mouseOrigSurface->pitch - w * 2; } - int rW, rH; - int cursorScale; - - if (_cursorDontScale) { - // Don't scale the cursor at all if the user requests this behavior. - cursorScale = 1; - } else { - // Scale the cursor with the game screen scale factor. - cursorScale = _videoMode.scaleFactor; - } - - // Adapt the real hotspot according to the scale factor. - rW = w * cursorScale; - rH = h * cursorScale; - _mouseCurState.rHotX = _mouseCurState.hotX * cursorScale; - _mouseCurState.rHotY = _mouseCurState.hotY * cursorScale; - - // The virtual dimensions will be the same as the original. - - _mouseCurState.vW = w; - _mouseCurState.vH = h; - _mouseCurState.vHotX = _mouseCurState.hotX; - _mouseCurState.vHotY = _mouseCurState.hotY; - -#ifdef USE_SCALERS - int rH1 = rH; // store original to pass to aspect-correction function later -#endif - - if (!_cursorDontScale && _videoMode.aspectRatioCorrection) { - rH = real2Aspect(rH - 1) + 1; - _mouseCurState.rHotY = real2Aspect(_mouseCurState.rHotY); - } - - if (_mouseCurState.rW != rW || _mouseCurState.rH != rH) { - _mouseCurState.rW = rW; - _mouseCurState.rH = rH; - + if (sizeChanged) { if (_mouseSurface) SDL_FreeSurface(_mouseSurface); @@ -2159,13 +2031,13 @@ void SurfaceSdlGraphicsManager::blitCursor() { _mouseCurState.rW, _mouseCurState.rH, 16, - _hwscreen->format->Rmask, - _hwscreen->format->Gmask, - _hwscreen->format->Bmask, - _hwscreen->format->Amask); + _hwScreen->format->Rmask, + _hwScreen->format->Gmask, + _hwScreen->format->Bmask, + _hwScreen->format->Amask); - if (_mouseSurface == NULL) - error("allocating _mouseSurface failed"); + if (_mouseSurface == nullptr) + error("Allocating _mouseSurface failed"); SDL_SetColorKey(_mouseSurface, SDL_RLEACCEL | SDL_SRCCOLORKEY | SDL_SRCALPHA, kMouseColorKey); } @@ -2236,7 +2108,7 @@ void SurfaceSdlGraphicsManager::undrawMouse() { } void SurfaceSdlGraphicsManager::drawMouse() { - if (!_mouseVisible || !_mouseSurface) { + if (!_cursorVisible || !_mouseSurface || !_mouseCurState.w || !_mouseCurState.h) { _mouseBackup.x = _mouseBackup.y = _mouseBackup.w = _mouseBackup.h = 0; return; } @@ -2245,8 +2117,10 @@ void SurfaceSdlGraphicsManager::drawMouse() { int scale; int hotX, hotY; - dst.x = _mouseCurState.x; - dst.y = _mouseCurState.y; + const Common::Point virtualCursor = convertWindowToVirtual(_cursorX, _cursorY); + + dst.x = virtualCursor.x; + dst.y = virtualCursor.y; if (!_overlayVisible) { scale = _videoMode.scaleFactor; @@ -2283,10 +2157,17 @@ void SurfaceSdlGraphicsManager::drawMouse() { dst.w = _mouseCurState.rW; dst.h = _mouseCurState.rH; + // Alpha-blended cursors will happily blend into themselves if the hardware + // surface under the cursor is not reset first + if (!_forceRedraw && _cursorFormat.bytesPerPixel == 4) { + if (SDL_BlitSurface(_screen, &dst, _hwScreen, &dst) != 0) + error("SD_BlitSurface failed: %s", SDL_GetError()); + } + // Note that SDL_BlitSurface() and addDirtyRect() will both perform any // clipping necessary - if (SDL_BlitSurface(_mouseSurface, NULL, _hwscreen, &dst) != 0) + if (SDL_BlitSurface(_mouseSurface, nullptr, _hwScreen, &dst) != 0) error("SDL_BlitSurface failed: %s", SDL_GetError()); // The screen will be updated using real surface coordinates, i.e. @@ -2335,14 +2216,14 @@ void SurfaceSdlGraphicsManager::displayMessageOnOSD(const char *msg) { } // Clip the rect - if (width > _hwscreen->w) - width = _hwscreen->w; - if (height > _hwscreen->h) - height = _hwscreen->h; + if (width > _hwScreen->w) + width = _hwScreen->w; + if (height > _hwScreen->h) + height = _hwScreen->h; _osdMessageSurface = SDL_CreateRGBSurface( SDL_SWSURFACE | SDL_RLEACCEL | SDL_SRCALPHA, - width, height, 16, _hwscreen->format->Rmask, _hwscreen->format->Gmask, _hwscreen->format->Bmask, _hwscreen->format->Amask + width, height, 16, _hwScreen->format->Rmask, _hwScreen->format->Gmask, _hwScreen->format->Bmask, _hwScreen->format->Amask ); // Lock the surface @@ -2379,8 +2260,8 @@ void SurfaceSdlGraphicsManager::displayMessageOnOSD(const char *msg) { SDL_Rect SurfaceSdlGraphicsManager::getOSDMessageRect() const { SDL_Rect rect; - rect.x = (_hwscreen->w - _osdMessageSurface->w) / 2; - rect.y = (_hwscreen->h - _osdMessageSurface->h) / 2; + rect.x = (_hwScreen->w - _osdMessageSurface->w) / 2; + rect.y = (_hwScreen->h - _osdMessageSurface->h) / 2; rect.w = _osdMessageSurface->w; rect.h = _osdMessageSurface->h; return rect; @@ -2393,7 +2274,7 @@ void SurfaceSdlGraphicsManager::displayActivityIconOnOSD(const Graphics::Surface if (_osdIconSurface && !icon) { // Force a redraw to clear the icon on the next update - _forceFull = true; + _forceRedraw = true; } if (_osdIconSurface) { @@ -2432,7 +2313,7 @@ void SurfaceSdlGraphicsManager::displayActivityIconOnOSD(const Graphics::Surface SDL_Rect SurfaceSdlGraphicsManager::getOSDIconRect() const { SDL_Rect dstRect; - dstRect.x = _hwscreen->w - _osdIconSurface->w - 10; + dstRect.x = _hwScreen->w - _osdIconSurface->w - 10; dstRect.y = 10; dstRect.w = _osdIconSurface->w; dstRect.h = _osdIconSurface->h; @@ -2464,7 +2345,7 @@ void SurfaceSdlGraphicsManager::updateOSD() { _osdMessageAlpha = startAlpha + diff * (SDL_ALPHA_TRANSPARENT - startAlpha) / kOSDFadeOutDuration; } SDL_SetAlpha(_osdMessageSurface, SDL_RLEACCEL | SDL_SRCCOLORKEY | SDL_SRCALPHA, _osdMessageAlpha); - _forceFull = true; + _forceRedraw = true; } if (_osdMessageAlpha == SDL_ALPHA_TRANSPARENT) { @@ -2474,26 +2355,30 @@ void SurfaceSdlGraphicsManager::updateOSD() { if (_osdIconSurface) { // Redraw the area below the icon for the transparent blit to give correct results. - _forceFull = true; + _forceRedraw = true; } } void SurfaceSdlGraphicsManager::drawOSD() { if (_osdMessageSurface) { SDL_Rect dstRect = getOSDMessageRect(); - SDL_BlitSurface(_osdMessageSurface, 0, _hwscreen, &dstRect); + SDL_BlitSurface(_osdMessageSurface, 0, _hwScreen, &dstRect); } if (_osdIconSurface) { SDL_Rect dstRect = getOSDIconRect(); - SDL_BlitSurface(_osdIconSurface, 0, _hwscreen, &dstRect); + SDL_BlitSurface(_osdIconSurface, 0, _hwScreen, &dstRect); } } #endif -bool SurfaceSdlGraphicsManager::handleScalerHotkeys(Common::KeyCode key) { +void SurfaceSdlGraphicsManager::handleResizeImpl(const int width, const int height) { + SdlGraphicsManager::handleResizeImpl(width, height); + recalculateDisplayAreas(); +} +bool SurfaceSdlGraphicsManager::handleScalerHotkeys(Common::KeyCode key) { // Ctrl-Alt-a toggles aspect ratio correction if (key == 'a') { beginGFXTransaction(); @@ -2505,13 +2390,13 @@ bool SurfaceSdlGraphicsManager::handleScalerHotkeys(Common::KeyCode key) { message = Common::String::format("%s\n%d x %d -> %d x %d", _("Enabled aspect ratio correction"), _videoMode.screenWidth, _videoMode.screenHeight, - _hwscreen->w, _hwscreen->h + _hwScreen->w, _hwScreen->h ); else message = Common::String::format("%s\n%d x %d -> %d x %d", _("Disabled aspect ratio correction"), _videoMode.screenWidth, _videoMode.screenHeight, - _hwscreen->w, _hwscreen->h + _hwScreen->w, _hwScreen->h ); displayMessageOnOSD(message.c_str()); #endif @@ -2532,7 +2417,7 @@ bool SurfaceSdlGraphicsManager::handleScalerHotkeys(Common::KeyCode key) { displayMessageOnOSD(_("Filtering disabled")); } #endif - _forceFull = true; + _forceRedraw = true; internUpdateScreen(); return true; } @@ -2542,12 +2427,19 @@ bool SurfaceSdlGraphicsManager::handleScalerHotkeys(Common::KeyCode key) { int factor = _videoMode.scaleFactor - 1; SDLKey sdlKey = (SDLKey)key; +#if SDL_VERSION_ATLEAST(2, 0, 0) + bool sizeChanged = false; +#endif + // Increase/decrease the scale factor if (sdlKey == SDLK_EQUALS || sdlKey == SDLK_PLUS || sdlKey == SDLK_MINUS || sdlKey == SDLK_KP_PLUS || sdlKey == SDLK_KP_MINUS) { factor += (sdlKey == SDLK_MINUS || sdlKey == SDLK_KP_MINUS) ? -1 : +1; if (0 <= factor && factor <= 3) { newMode = s_gfxModeSwitchTable[_scalerType][factor]; +#if SDL_VERSION_ATLEAST(2, 0, 0) + sizeChanged = true; +#endif } } @@ -2585,10 +2477,19 @@ bool SurfaceSdlGraphicsManager::handleScalerHotkeys(Common::KeyCode key) { _("Active graphics filter:"), newScalerName, _videoMode.screenWidth, _videoMode.screenHeight, - _hwscreen->w, _hwscreen->h); + _hwScreen->w, _hwScreen->h); displayMessageOnOSD(message.c_str()); } #endif + +#if SDL_VERSION_ATLEAST(2, 0, 0) + if (sizeChanged) { + // Forcibly resizing the window here since a user switching scaler + // size will not normally cause the window to update + _window->createOrUpdateWindow(_hwScreen->w, _hwScreen->h, _lastFlags); + } +#endif + internUpdateScreen(); return true; @@ -2700,37 +2601,11 @@ bool SurfaceSdlGraphicsManager::notifyEvent(const Common::Event &event) { } void SurfaceSdlGraphicsManager::notifyVideoExpose() { - _forceFull = true; + _forceRedraw = true; } -void SurfaceSdlGraphicsManager::notifyResize(const uint width, const uint height) { -#if SDL_VERSION_ATLEAST(2, 0, 0) - setWindowResolution(width, height); -#endif -} - -void SurfaceSdlGraphicsManager::transformMouseCoordinates(Common::Point &point) { -#if SDL_VERSION_ATLEAST(2, 0, 0) - // In SDL2 the actual output resolution might be different from what we - // requested. Thus, we transform the coordinates from actual output - // coordinate space into the "virtual" output coordinate space. - // Please note that we ignore the possible existence of black bars here, - // this avoids the feeling of stickyness to black bars. - point.x = point.x * _videoMode.hardwareWidth / _windowWidth; - point.y = point.y * _videoMode.hardwareHeight / _windowHeight; -#endif - - if (!_overlayVisible) { - point.x /= _videoMode.scaleFactor; - point.y /= _videoMode.scaleFactor; - if (_videoMode.aspectRatioCorrection) - point.y = aspect2Real(point.y); - } -} - -void SurfaceSdlGraphicsManager::notifyMousePos(Common::Point mouse) { - transformMouseCoordinates(mouse); - setMousePos(mouse.x, mouse.y); +void SurfaceSdlGraphicsManager::notifyResize(const int width, const int height) { + handleResize(width, height); } #if SDL_VERSION_ATLEAST(2, 0, 0) @@ -2742,39 +2617,6 @@ void SurfaceSdlGraphicsManager::deinitializeRenderer() { _renderer = nullptr; } -void SurfaceSdlGraphicsManager::setWindowResolution(int width, int height) { - _windowWidth = width; - _windowHeight = height; - - // We expect full screen resolution as inputs coming from the event system. - _eventSource->resetKeyboardEmulation(_windowWidth - 1, _windowHeight - 1); - - // Calculate the "viewport" for the actual area we draw in. In fullscreen - // we can easily get a different resolution than what we requested. In - // this case, we add black bars if necessary to assure the aspect ratio - // is preserved. - const frac_t outputAspect = intToFrac(_windowWidth) / _windowHeight; - const frac_t desiredAspect = intToFrac(_videoMode.hardwareWidth) / _videoMode.hardwareHeight; - - _viewport.w = _windowWidth; - _viewport.h = _windowHeight; - - // Adjust one dimension for mantaining the aspect ratio. - if (abs(outputAspect - desiredAspect) >= (int)(FRAC_ONE / 1000)) { - if (outputAspect < desiredAspect) { - _viewport.h = _videoMode.hardwareHeight * _windowWidth / _videoMode.hardwareWidth; - } else if (outputAspect > desiredAspect) { - _viewport.w = _videoMode.hardwareWidth * _windowHeight / _videoMode.hardwareHeight; - } - } - - _viewport.x = (_windowWidth - _viewport.w) / 2; - _viewport.y = (_windowHeight - _viewport.h) / 2; - - // Force a full redraw because we changed the viewport. - _forceFull = true; -} - void SurfaceSdlGraphicsManager::recreateScreenTexture() { if (!_renderer) return; @@ -2792,10 +2634,7 @@ void SurfaceSdlGraphicsManager::recreateScreenTexture() { SDL_Surface *SurfaceSdlGraphicsManager::SDL_SetVideoMode(int width, int height, int bpp, Uint32 flags) { deinitializeRenderer(); - uint32 createWindowFlags = 0; -#ifdef USE_SDL_RESIZABLE_WINDOW - createWindowFlags |= SDL_WINDOW_RESIZABLE; -#endif + uint32 createWindowFlags = SDL_WINDOW_RESIZABLE; if ((flags & SDL_FULLSCREEN) != 0) { createWindowFlags |= SDL_WINDOW_FULLSCREEN_DESKTOP; } @@ -2810,8 +2649,8 @@ SDL_Surface *SurfaceSdlGraphicsManager::SDL_SetVideoMode(int width, int height, return nullptr; } - SDL_GetWindowSize(_window->getSDLWindow(), &_windowWidth, &_windowHeight); - setWindowResolution(_windowWidth, _windowHeight); + getWindowSizeFromSdl(&_windowWidth, &_windowHeight); + handleResize(_windowWidth, _windowHeight); SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, _videoMode.filtering ? "linear" : "nearest"); @@ -2833,8 +2672,14 @@ SDL_Surface *SurfaceSdlGraphicsManager::SDL_SetVideoMode(int width, int height, void SurfaceSdlGraphicsManager::SDL_UpdateRects(SDL_Surface *screen, int numrects, SDL_Rect *rects) { SDL_UpdateTexture(_screenTexture, nullptr, screen->pixels, screen->pitch); + SDL_Rect viewport; + viewport.x = _activeArea.drawRect.left; + viewport.y = _activeArea.drawRect.top; + viewport.w = _activeArea.drawRect.width(); + viewport.h = _activeArea.drawRect.height(); + SDL_RenderClear(_renderer); - SDL_RenderCopy(_renderer, _screenTexture, NULL, &_viewport); + SDL_RenderCopy(_renderer, _screenTexture, NULL, &viewport); SDL_RenderPresent(_renderer); } #endif // SDL_VERSION_ATLEAST(2, 0, 0) diff --git a/backends/graphics/surfacesdl/surfacesdl-graphics.h b/backends/graphics/surfacesdl/surfacesdl-graphics.h index 62a4a38d3e..60f5d29f55 100644 --- a/backends/graphics/surfacesdl/surfacesdl-graphics.h +++ b/backends/graphics/surfacesdl/surfacesdl-graphics.h @@ -39,17 +39,7 @@ #define USE_SDL_DEBUG_FOCUSRECT #endif -// We have (some) support for resizable windows when SDL2 is used. However -// the overlay still uses the resolution setup with SDL_SetVideoMode. This -// makes the GUI look subpar when the user resizes the window. In addition -// we do not adapt the scale factor right now. Thus, we disable this code -// path for now. -#if SDL_VERSION_ATLEAST(2, 0, 0) && 0 -#define USE_SDL_RESIZABLE_WINDOW -#endif - #if !defined(_WIN32_WCE) && !defined(__SYMBIAN32__) -// Uncomment this to enable the 'on screen display' code. #define USE_OSD 1 #endif @@ -89,76 +79,70 @@ public: SurfaceSdlGraphicsManager(SdlEventSource *sdlEventSource, SdlWindow *window); virtual ~SurfaceSdlGraphicsManager(); - virtual void activateManager(); - virtual void deactivateManager(); + virtual void activateManager() override; + virtual void deactivateManager() override; - virtual bool hasFeature(OSystem::Feature f); - virtual void setFeatureState(OSystem::Feature f, bool enable); - virtual bool getFeatureState(OSystem::Feature f); + 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; - virtual const OSystem::GraphicsMode *getSupportedGraphicsModes() const; - virtual int getDefaultGraphicsMode() const; - virtual bool setGraphicsMode(int mode); - virtual int getGraphicsMode() const; - virtual void resetGraphicsScale(); + virtual const OSystem::GraphicsMode *getSupportedGraphicsModes() const override; + virtual int getDefaultGraphicsMode() const override; + virtual bool setGraphicsMode(int mode) override; + virtual int getGraphicsMode() const override; + virtual void resetGraphicsScale() override; #ifdef USE_RGB_COLOR - virtual Graphics::PixelFormat getScreenFormat() const { return _screenFormat; } - virtual Common::List<Graphics::PixelFormat> getSupportedFormats() const; + virtual Graphics::PixelFormat getScreenFormat() const override { return _screenFormat; } + virtual Common::List<Graphics::PixelFormat> getSupportedFormats() const override; #endif - virtual const OSystem::GraphicsMode *getSupportedShaders() const; - virtual int getShader() const; - virtual bool setShader(int id); - virtual void initSize(uint w, uint h, const Graphics::PixelFormat *format = NULL); - virtual int getScreenChangeID() const { return _screenChangeCount; } + virtual const OSystem::GraphicsMode *getSupportedShaders() const override; + virtual int getShader() const override; + virtual bool setShader(int id) override; + virtual void initSize(uint w, uint h, const Graphics::PixelFormat *format = NULL) override; + virtual int getScreenChangeID() const override { return _screenChangeCount; } - virtual void beginGFXTransaction(); - virtual OSystem::TransactionError endGFXTransaction(); + virtual void beginGFXTransaction() override; + virtual OSystem::TransactionError endGFXTransaction() override; - virtual int16 getHeight(); - virtual int16 getWidth(); + virtual int16 getHeight() const override; + virtual int16 getWidth() const override; protected: // PaletteManager API - virtual void setPalette(const byte *colors, uint start, uint num); - virtual void grabPalette(byte *colors, uint start, uint num); + virtual void setPalette(const byte *colors, uint start, uint num) override; + virtual void grabPalette(byte *colors, uint start, uint num) const override; public: - virtual void copyRectToScreen(const void *buf, int pitch, int x, int y, int w, int h); - virtual Graphics::Surface *lockScreen(); - virtual void unlockScreen(); - virtual void fillScreen(uint32 col); - virtual void updateScreen(); - virtual void setShakePos(int shakeOffset); - virtual void setFocusRectangle(const Common::Rect& rect); - virtual void clearFocusRectangle(); - - virtual void showOverlay(); - virtual void hideOverlay(); - virtual Graphics::PixelFormat getOverlayFormat() const { return _overlayFormat; } - virtual void clearOverlay(); - virtual void grabOverlay(void *buf, int pitch); - virtual void copyRectToOverlay(const void *buf, int pitch, int x, int y, int w, int h); - virtual int16 getOverlayHeight() { return _videoMode.overlayHeight; } - virtual int16 getOverlayWidth() { return _videoMode.overlayWidth; } - - virtual bool showMouse(bool visible); - virtual void warpMouse(int x, int y); - 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); + virtual void copyRectToScreen(const void *buf, int pitch, int x, int y, int w, int h) override; + virtual Graphics::Surface *lockScreen() override; + virtual void unlockScreen() override; + virtual void fillScreen(uint32 col) override; + virtual void updateScreen() override; + virtual void setShakePos(int shakeOffset) override; + virtual void setFocusRectangle(const Common::Rect& rect) override; + virtual void clearFocusRectangle() 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; + virtual int16 getOverlayHeight() const override { return _videoMode.overlayHeight; } + virtual int16 getOverlayWidth() const override { return _videoMode.overlayWidth; } + + virtual void setMouseCursor(const void *buf, uint w, uint h, int hotspotX, int hotspotY, uint32 keycolor, bool dontScale = false, const Graphics::PixelFormat *format = NULL) override; + virtual void setCursorPalette(const byte *colors, uint start, uint num) override; #ifdef USE_OSD - virtual void displayMessageOnOSD(const char *msg); - virtual void displayActivityIconOnOSD(const Graphics::Surface *icon); + virtual void displayMessageOnOSD(const char *msg) override; + virtual void displayActivityIconOnOSD(const Graphics::Surface *icon) override; #endif // Override from Common::EventObserver - bool notifyEvent(const Common::Event &event); + virtual bool notifyEvent(const Common::Event &event) override; // SdlGraphicsManager interface - virtual void notifyVideoExpose(); - virtual void notifyResize(const uint width, const uint height); - virtual void transformMouseCoordinates(Common::Point &point); - virtual void notifyMousePos(Common::Point mouse); + virtual void notifyVideoExpose() override; + virtual void notifyResize(const int width, const int height) override; protected: #ifdef USE_OSD @@ -187,8 +171,11 @@ protected: void drawOSD(); #endif - /** Hardware screen */ - SDL_Surface *_hwscreen; + virtual bool gameNeedsAspectRatioCorrection() const override { + return _videoMode.aspectRatioCorrection; + } + + virtual void handleResizeImpl(const int width, const int height) override; virtual int getGraphicsModeScale(int mode) const override; @@ -197,10 +184,7 @@ protected: * around this API to keep the code paths as close as possible. */ SDL_Renderer *_renderer; SDL_Texture *_screenTexture; - SDL_Rect _viewport; - int _windowWidth, _windowHeight; void deinitializeRenderer(); - void setWindowResolution(int width, int height); void recreateScreenTexture(); virtual SDL_Surface *SDL_SetVideoMode(int width, int height, int bpp, Uint32 flags); @@ -209,9 +193,9 @@ protected: /** Unseen game screen */ SDL_Surface *_screen; -#ifdef USE_RGB_COLOR Graphics::PixelFormat _screenFormat; Graphics::PixelFormat _cursorFormat; +#ifdef USE_RGB_COLOR Common::List<Graphics::PixelFormat> _supportedFormats; /** @@ -227,7 +211,6 @@ protected: SDL_Surface *_tmpscreen2; SDL_Surface *_overlayscreen; - bool _overlayVisible; Graphics::PixelFormat _overlayFormat; enum { @@ -289,14 +272,11 @@ protected: uint8 _originalBitsPerPixel; #endif - /** Force full redraw on next updateScreen */ - bool _forceFull; - ScalerProc *_scalerProc; int _scalerType; int _transactionMode; - // Indicates whether it is needed to free _hwsurface in destructor + // Indicates whether it is needed to free _hwSurface in destructor bool _displayDisabled; bool _screenIsLocked; @@ -317,10 +297,6 @@ protected: int _numDirtyRects; struct MousePos { - // The mouse position, using either virtual (game) or real - // (overlay) coordinates. - int16 x, y; - // The size and hotspot of the original cursor image. int16 w, h; int16 hotX, hotY; @@ -335,14 +311,12 @@ protected: int16 vW, vH; int16 vHotX, vHotY; - MousePos() : x(0), y(0), w(0), h(0), hotX(0), hotY(0), + MousePos() : w(0), h(0), hotX(0), hotY(0), rW(0), rH(0), rHotX(0), rHotY(0), vW(0), vH(0), vHotX(0), vHotY(0) { } }; - bool _mouseVisible; - bool _mouseNeedsRedraw; byte *_mouseData; SDL_Rect _mouseBackup; MousePos _mouseCurState; @@ -395,21 +369,45 @@ protected: virtual void unloadGFXMode(); virtual bool hotswapGFXMode(); - virtual void setFullscreenMode(bool enable); virtual void setAspectRatioCorrection(bool enable); #if SDL_VERSION_ATLEAST(2, 0, 0) - virtual void setFilteringMode(bool enable); + void setFilteringMode(bool enable); #endif - virtual int effectiveScreenHeight() const; - + virtual bool saveScreenshot(const char *filename); virtual void setGraphicsModeIntern(); - virtual bool handleScalerHotkeys(Common::KeyCode key); - virtual bool isScalerHotkey(const Common::Event &event); - virtual void setMousePos(int x, int y); - virtual void toggleFullScreen(); - virtual bool saveScreenshot(const char *filename); +private: + void setFullscreenMode(bool enable); + bool handleScalerHotkeys(Common::KeyCode key); + bool isScalerHotkey(const Common::Event &event); + void toggleFullScreen(); + + /** + * Converts the given point from the overlay's coordinate space to the + * game's coordinate space. + */ + Common::Point convertOverlayToGame(const int x, const int y) const { + if (getOverlayWidth() == 0 || getOverlayHeight() == 0) { + error("convertOverlayToGame called without a valid overlay"); + } + + return Common::Point(x * getWidth() / getOverlayWidth(), + y * getHeight() / getOverlayHeight()); + } + + /** + * Converts the given point from the game's coordinate space to the + * overlay's coordinate space. + */ + Common::Point convertGameToOverlay(const int x, const int y) const { + if (getWidth() == 0 || getHeight() == 0) { + error("convertGameToOverlay called without a valid overlay"); + } + + return Common::Point(x * getOverlayWidth() / getWidth(), + y * getOverlayHeight() / getHeight()); + } }; #endif diff --git a/backends/graphics/symbiansdl/symbiansdl-graphics.cpp b/backends/graphics/symbiansdl/symbiansdl-graphics.cpp index c17cfd5efa..227674f811 100644 --- a/backends/graphics/symbiansdl/symbiansdl-graphics.cpp +++ b/backends/graphics/symbiansdl/symbiansdl-graphics.cpp @@ -50,7 +50,7 @@ bool SymbianSdlGraphicsManager::setGraphicsMode(int /*name*/) { return SurfaceSdlGraphicsManager::setGraphicsMode(getDefaultGraphicsMode()); } -bool SymbianSdlGraphicsManager::hasFeature(OSystem::Feature f) { +bool SymbianSdlGraphicsManager::hasFeature(OSystem::Feature f) const { switch (f) { case OSystem::kFeatureFullscreenMode: case OSystem::kFeatureAspectRatioCorrection: diff --git a/backends/graphics/symbiansdl/symbiansdl-graphics.h b/backends/graphics/symbiansdl/symbiansdl-graphics.h index fb9a49a834..0fcfb70f24 100644 --- a/backends/graphics/symbiansdl/symbiansdl-graphics.h +++ b/backends/graphics/symbiansdl/symbiansdl-graphics.h @@ -30,12 +30,12 @@ public: SymbianSdlGraphicsManager(SdlEventSource *sdlEventSource, SdlWindow *window); public: - virtual bool hasFeature(OSystem::Feature f); - virtual void setFeatureState(OSystem::Feature f, bool enable); + virtual bool hasFeature(OSystem::Feature f) const override; + virtual void setFeatureState(OSystem::Feature f, bool enable) override; - virtual const OSystem::GraphicsMode *getSupportedGraphicsModes() const; - virtual int getDefaultGraphicsMode() const; - virtual bool setGraphicsMode(int mode); + virtual const OSystem::GraphicsMode *getSupportedGraphicsModes() const override; + virtual int getDefaultGraphicsMode() const override; + virtual bool setGraphicsMode(int mode) override; }; #endif diff --git a/backends/graphics/wincesdl/wincesdl-graphics.cpp b/backends/graphics/wincesdl/wincesdl-graphics.cpp index 44a1214a44..1677ecac06 100644 --- a/backends/graphics/wincesdl/wincesdl-graphics.cpp +++ b/backends/graphics/wincesdl/wincesdl-graphics.cpp @@ -115,7 +115,7 @@ const OSystem::GraphicsMode *WINCESdlGraphicsManager::getSupportedGraphicsModes( return s_supportedGraphicsModesLow; } -bool WINCESdlGraphicsManager::hasFeature(OSystem::Feature f) { +bool WINCESdlGraphicsManager::hasFeature(OSystem::Feature f) const { return (f == OSystem::kFeatureVirtualKeyboard); } @@ -153,7 +153,7 @@ void WINCESdlGraphicsManager::setFeatureState(OSystem::Feature f, bool enable) { } } -bool WINCESdlGraphicsManager::getFeatureState(OSystem::Feature f) { +bool WINCESdlGraphicsManager::getFeatureState(OSystem::Feature f) const { switch (f) { case OSystem::kFeatureFullscreenMode: return false; diff --git a/backends/graphics/wincesdl/wincesdl-graphics.h b/backends/graphics/wincesdl/wincesdl-graphics.h index 9316c69e44..4842d49023 100644 --- a/backends/graphics/wincesdl/wincesdl-graphics.h +++ b/backends/graphics/wincesdl/wincesdl-graphics.h @@ -46,9 +46,9 @@ public: const OSystem::GraphicsMode *getSupportedGraphicsModes() const; void initSize(uint w, uint h, const Graphics::PixelFormat *format = NULL); - bool hasFeature(OSystem::Feature f); + bool hasFeature(OSystem::Feature f) const; void setFeatureState(OSystem::Feature f, bool enable); - bool getFeatureState(OSystem::Feature f); + bool getFeatureState(OSystem::Feature f) const; int getDefaultGraphicsMode() const; bool setGraphicsMode(int mode); diff --git a/backends/graphics/windowed.h b/backends/graphics/windowed.h new file mode 100644 index 0000000000..1d4958c9d6 --- /dev/null +++ b/backends/graphics/windowed.h @@ -0,0 +1,337 @@ +/* ScummVM - Graphic Adventure Engine + * + * 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. + * + * 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_WINDOWED_H +#define BACKENDS_GRAPHICS_WINDOWED_H + +#include "backends/graphics/graphics.h" +#include "common/frac.h" +#include "common/rect.h" +#include "common/textconsole.h" +#include "graphics/scaler/aspect.h" + +class WindowedGraphicsManager : virtual public GraphicsManager { +public: + WindowedGraphicsManager() : + _windowWidth(0), + _windowHeight(0), + _overlayVisible(false), + _forceRedraw(false), + _cursorVisible(false), + _cursorX(0), + _cursorY(0), + _cursorNeedsRedraw(false), + _cursorLastInActiveArea(true) {} + + virtual void showOverlay() override { + if (_overlayVisible) + return; + + _activeArea.drawRect = _overlayDrawRect; + _activeArea.width = getOverlayWidth(); + _activeArea.height = getOverlayHeight(); + _overlayVisible = true; + _forceRedraw = true; + } + + virtual void hideOverlay() override { + if (!_overlayVisible) + return; + + _activeArea.drawRect = _gameDrawRect; + _activeArea.width = getWidth(); + _activeArea.height = getHeight(); + _overlayVisible = false; + _forceRedraw = true; + } + +protected: + /** + * @returns whether or not the game screen must have aspect ratio correction + * applied for correct rendering. + */ + virtual bool gameNeedsAspectRatioCorrection() const = 0; + + /** + * Backend-specific implementation for updating internal surfaces that need + * to reflect the new window size. + */ + virtual void handleResizeImpl(const int width, const int height) = 0; + + /** + * Converts the given point from the active virtual screen's coordinate + * space to the window's coordinate space (i.e. game-to-window or + * overlay-to-window). + */ + Common::Point convertVirtualToWindow(const int x, const int y) const { + const int targetX = _activeArea.drawRect.left; + const int targetY = _activeArea.drawRect.top; + const int targetWidth = _activeArea.drawRect.width(); + const int targetHeight = _activeArea.drawRect.height(); + const int sourceWidth = _activeArea.width; + const int sourceHeight = _activeArea.height; + + if (sourceWidth == 0 || sourceHeight == 0) { + error("convertVirtualToWindow called without a valid draw rect"); + } + + return Common::Point(targetX + x * targetWidth / sourceWidth, + targetY + y * targetHeight / sourceHeight); + } + + /** + * Converts the given point from the window's coordinate space to the + * active virtual screen's coordinate space (i.e. window-to-game or + * window-to-overlay). + */ + Common::Point convertWindowToVirtual(int x, int y) const { + const int sourceX = _activeArea.drawRect.left; + const int sourceY = _activeArea.drawRect.top; + const int sourceMaxX = _activeArea.drawRect.right - 1; + const int sourceMaxY = _activeArea.drawRect.bottom - 1; + const int sourceWidth = _activeArea.drawRect.width(); + const int sourceHeight = _activeArea.drawRect.height(); + const int targetWidth = _activeArea.width; + const int targetHeight = _activeArea.height; + + if (sourceWidth == 0 || sourceHeight == 0) { + error("convertWindowToVirtual called without a valid draw rect"); + } + + x = CLIP<int>(x, sourceX, sourceMaxX); + y = CLIP<int>(y, sourceY, sourceMaxY); + + return Common::Point(((x - sourceX) * targetWidth) / sourceWidth, + ((y - sourceY) * targetHeight) / sourceHeight); + } + + /** + * @returns the desired aspect ratio of the game surface. + */ + frac_t getDesiredGameAspectRatio() const { + if (getHeight() == 0 || gameNeedsAspectRatioCorrection()) { + return intToFrac(4) / 3; + } + + return intToFrac(getWidth()) / getHeight(); + } + + /** + * Called after the window has been updated with new dimensions. + * + * @param width The new width of the window, excluding window decoration. + * @param height The new height of the window, excluding window decoration. + */ + void handleResize(const int width, const int height) { + _windowWidth = width; + _windowHeight = height; + handleResizeImpl(width, height); + } + + /** + * Recalculates the display areas for the game and overlay surfaces within + * the window. + */ + virtual void recalculateDisplayAreas() { + if (_windowHeight == 0) { + return; + } + + const frac_t outputAspect = intToFrac(_windowWidth) / _windowHeight; + + populateDisplayAreaDrawRect(getDesiredGameAspectRatio(), outputAspect, _gameDrawRect); + + if (getOverlayHeight()) { + const frac_t overlayAspect = intToFrac(getOverlayWidth()) / getOverlayHeight(); + populateDisplayAreaDrawRect(overlayAspect, outputAspect, _overlayDrawRect); + } + + if (_overlayVisible) { + _activeArea.drawRect = _overlayDrawRect; + _activeArea.width = getOverlayWidth(); + _activeArea.height = getOverlayHeight(); + } else { + _activeArea.drawRect = _gameDrawRect; + _activeArea.width = getWidth(); + _activeArea.height = getHeight(); + } + } + /** + * Sets the position of the hardware mouse cursor in the host system, + * relative to the window. + * + * @param x X coordinate in window coordinates. + * @param y Y coordinate in window coordinates. + */ + virtual void setSystemMousePosition(const int x, const int y) = 0; + + virtual bool showMouse(const bool visible) override { + if (_cursorVisible == visible) { + return visible; + } + + const bool last = _cursorVisible; + _cursorVisible = visible; + _cursorNeedsRedraw = true; + return last; + } + + /** + * Move ("warp") the mouse cursor to the specified position. + * + * @param x The new X position of the mouse in virtual screen coordinates. + * @param y The new Y position of the mouse in virtual screen coordinates. + */ + void warpMouse(const int x, const int y) { + // Check active coordinate instead of window coordinate to avoid warping + // the mouse if it is still within the same virtual pixel + const Common::Point virtualCursor = convertWindowToVirtual(_cursorX, _cursorY); + if (virtualCursor.x != x || virtualCursor.y != y) { + // Warping the mouse in SDL generates a mouse movement event, so + // `setMousePosition` would be called eventually through the + // `notifyMousePosition` callback if we *only* set the system mouse + // position here. However, this can cause problems with some games. + // For example, the cannon script in CoMI calls to warp the mouse + // twice each time the cannon is reloaded, and unless we update the + // mouse position immediately, the second call is ignored, which + // causes the cannon to change its aim. + const Common::Point windowCursor = convertVirtualToWindow(x, y); + setMousePosition(windowCursor.x, windowCursor.y); + setSystemMousePosition(windowCursor.x, windowCursor.y); + } + } + + /** + * Sets the position of the rendered mouse cursor in the window. + * + * @param x X coordinate in window coordinates. + * @param y Y coordinate in window coordinates. + */ + void setMousePosition(int x, int y) { + if (_cursorX != x || _cursorY != y) { + _cursorNeedsRedraw = true; + } + + _cursorX = x; + _cursorY = y; + } + + /** + * The width of the window, excluding window decoration. + */ + int _windowWidth; + + /** + * The height of the window, excluding window decoration. + */ + int _windowHeight; + + /** + * Whether the overlay (i.e. launcher, including the out-of-game launcher) + * is visible or not. + */ + bool _overlayVisible; + + /** + * The scaled draw rectangle for the game surface within the window. + */ + Common::Rect _gameDrawRect; + + /** + * The scaled draw rectangle for the overlay (launcher) surface within the + * window. + */ + Common::Rect _overlayDrawRect; + + /** + * Data about the display area of a virtual screen. + */ + struct DisplayArea { + /** + * The scaled area where the virtual screen is drawn within the window. + */ + Common::Rect drawRect; + + /** + * The width of the virtual screen's unscaled coordinate space. + */ + int width; + + /** + * The height of the virtual screen's unscaled coordinate space. + */ + int height; + }; + + /** + * Display area information about the currently active virtual screen. This + * will be the overlay screen when the overlay is active, and the game + * screen otherwise. + */ + DisplayArea _activeArea; + + /** + * Whether the screen must be redrawn on the next frame. + */ + bool _forceRedraw; + + /** + * Whether the cursor is actually visible. + */ + bool _cursorVisible; + + /** + * Whether the mouse cursor needs to be redrawn on the next frame. + */ + bool _cursorNeedsRedraw; + + /** + * Whether the last position of the system cursor was within the active area + * of the window. + */ + bool _cursorLastInActiveArea; + + /** + * The position of the mouse cursor, in window coordinates. + */ + int _cursorX, _cursorY; + +private: + void populateDisplayAreaDrawRect(const frac_t inputAspect, const frac_t outputAspect, Common::Rect &drawRect) const { + int width = _windowWidth; + int height = _windowHeight; + + // Maintain aspect ratios + if (outputAspect < inputAspect) { + height = intToFrac(width) / inputAspect; + } else if (outputAspect > inputAspect) { + width = fracToInt(height * inputAspect); + } + + drawRect.left = (_windowWidth - width) / 2; + drawRect.top = (_windowHeight - height) / 2; + drawRect.setWidth(width); + drawRect.setHeight(height); + } +}; + +#endif diff --git a/backends/modular-backend.cpp b/backends/modular-backend.cpp index c9adbd3100..944ddd5a47 100644 --- a/backends/modular-backend.cpp +++ b/backends/modular-backend.cpp @@ -217,6 +217,7 @@ bool ModularBackend::showMouse(bool visible) { } void ModularBackend::warpMouse(int x, int y) { + _eventManager->purgeMouseEvents(); _graphicsManager->warpMouse(x, y); } diff --git a/backends/platform/sdl/sdl-window.cpp b/backends/platform/sdl/sdl-window.cpp index 75cf813638..fe27d84de2 100644 --- a/backends/platform/sdl/sdl-window.cpp +++ b/backends/platform/sdl/sdl-window.cpp @@ -135,8 +135,10 @@ void SdlWindow::toggleMouseGrab() { #else if (SDL_WM_GrabInput(SDL_GRAB_QUERY) == SDL_GRAB_OFF) { SDL_WM_GrabInput(SDL_GRAB_ON); + _inputGrabState = true; } else { SDL_WM_GrabInput(SDL_GRAB_OFF); + _inputGrabState = false; } #endif } @@ -153,14 +155,20 @@ bool SdlWindow::hasMouseFocus() const { #endif } -void SdlWindow::warpMouseInWindow(uint x, uint y) { +bool SdlWindow::warpMouseInWindow(int x, int y) { + if (hasMouseFocus()) { #if SDL_VERSION_ATLEAST(2, 0, 0) - if (_window && hasMouseFocus()) { - SDL_WarpMouseInWindow(_window, x, y); - } + if (_window) { + SDL_WarpMouseInWindow(_window, x, y); + return true; + } #else - SDL_WarpMouse(x, y); + SDL_WarpMouse(x, y); + return true; #endif + } + + return false; } void SdlWindow::iconifyWindow() { diff --git a/backends/platform/sdl/sdl-window.h b/backends/platform/sdl/sdl-window.h index d75e811f56..e1a3499d19 100644 --- a/backends/platform/sdl/sdl-window.h +++ b/backends/platform/sdl/sdl-window.h @@ -56,9 +56,12 @@ public: bool hasMouseFocus() const; /** - * Warp the mouse to the specified position in window coordinates. + * Warp the mouse to the specified position in window coordinates. The mouse + * will only be warped if the window is focused in the window manager. + * + * @returns true if the system cursor was warped. */ - void warpMouseInWindow(uint x, uint y); + bool warpMouseInWindow(int x, int y); /** * Iconifies the window. @@ -73,6 +76,11 @@ public: */ bool getSDLWMInformation(SDL_SysWMinfo *info) const; + bool mouseIsGrabbed() const { return _inputGrabState; } + +private: + bool _inputGrabState; + #if SDL_VERSION_ATLEAST(2, 0, 0) public: /** @@ -108,7 +116,6 @@ private: */ int _lastX, _lastY; - bool _inputGrabState; Common::String _windowCaption; #endif }; diff --git a/common/events.h b/common/events.h index 21a65a642b..e5bb8cab50 100644 --- a/common/events.h +++ b/common/events.h @@ -395,6 +395,11 @@ public: */ virtual void pushEvent(const Event &event) = 0; + /** + * Purges all unprocessed mouse events already in the event queue. + */ + virtual void purgeMouseEvents() = 0; + /** Return the current mouse position */ virtual Point getMousePos() const = 0; diff --git a/graphics/cursorman.cpp b/graphics/cursorman.cpp index 5fcd2a3602..678b074360 100644 --- a/graphics/cursorman.cpp +++ b/graphics/cursorman.cpp @@ -65,9 +65,7 @@ void CursorManager::pushCursor(const void *buf, uint w, uint h, int hotspotX, in cur->_visible = isVisible(); _cursorStack.push(cur); - if (buf) { - g_system->setMouseCursor(cur->_data, w, h, hotspotX, hotspotY, keycolor, dontScale, format); - } + g_system->setMouseCursor(cur->_data, w, h, hotspotX, hotspotY, keycolor, dontScale, format); } void CursorManager::popCursor() { @@ -80,6 +78,8 @@ void CursorManager::popCursor() { if (!_cursorStack.empty()) { cur = _cursorStack.top(); g_system->setMouseCursor(cur->_data, cur->_width, cur->_height, cur->_hotspotX, cur->_hotspotY, cur->_keycolor, cur->_dontScale, &cur->_format); + } else { + g_system->setMouseCursor(nullptr, 0, 0, 0, 0, 0); } g_system->showMouse(isVisible()); @@ -99,6 +99,7 @@ void CursorManager::popAllCursors() { } } + g_system->setMouseCursor(nullptr, 0, 0, 0, 0, 0); g_system->showMouse(isVisible()); } diff --git a/graphics/palette.h b/graphics/palette.h index 2884bef7f4..0b9b861aa9 100644 --- a/graphics/palette.h +++ b/graphics/palette.h @@ -96,7 +96,7 @@ public: * * @see getScreenFormat */ - virtual void grabPalette(byte *colors, uint start, uint num) = 0; + virtual void grabPalette(byte *colors, uint start, uint num) const = 0; }; #endif |