diff options
Diffstat (limited to 'backends')
78 files changed, 2370 insertions, 1517 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/fs/riscos/riscos-fs-factory.cpp b/backends/fs/riscos/riscos-fs-factory.cpp new file mode 100644 index 0000000000..b698bcb908 --- /dev/null +++ b/backends/fs/riscos/riscos-fs-factory.cpp @@ -0,0 +1,46 @@ +/* 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. + * + */ + +#if defined(RISCOS) + +// Re-enable some forbidden symbols to avoid clashes with stat.h and unistd.h. +#define FORBIDDEN_SYMBOL_EXCEPTION_unistd_h + +#include "backends/fs/riscos/riscos-fs-factory.h" +#include "backends/fs/riscos/riscos-fs.h" + +#include <unistd.h> + +AbstractFSNode *RISCOSFilesystemFactory::makeRootFileNode() const { + return new RISCOSFilesystemNode("/"); +} + +AbstractFSNode *RISCOSFilesystemFactory::makeCurrentDirectoryFileNode() const { + char buf[MAXPATHLEN]; + return getcwd(buf, MAXPATHLEN) ? new RISCOSFilesystemNode(buf) : NULL; +} + +AbstractFSNode *RISCOSFilesystemFactory::makeFileNodePath(const Common::String &path) const { + assert(!path.empty()); + return new RISCOSFilesystemNode(path); +} +#endif diff --git a/backends/fs/riscos/riscos-fs-factory.h b/backends/fs/riscos/riscos-fs-factory.h new file mode 100644 index 0000000000..4bed2b5f08 --- /dev/null +++ b/backends/fs/riscos/riscos-fs-factory.h @@ -0,0 +1,40 @@ +/* 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 RISCOS_FILESYSTEM_FACTORY_H +#define RISCOS_FILESYSTEM_FACTORY_H + +#include "backends/fs/fs-factory.h" + +/** + * Creates RISCOSFilesystemNode objects. + * + * Parts of this class are documented in the base interface class, FilesystemFactory. + */ +class RISCOSFilesystemFactory : public FilesystemFactory { +protected: + virtual AbstractFSNode *makeRootFileNode() const; + virtual AbstractFSNode *makeCurrentDirectoryFileNode() const; + virtual AbstractFSNode *makeFileNodePath(const Common::String &path) const; +}; + +#endif /*RISCOS_FILESYSTEM_FACTORY_H*/ diff --git a/backends/fs/riscos/riscos-fs.cpp b/backends/fs/riscos/riscos-fs.cpp new file mode 100644 index 0000000000..38d150e572 --- /dev/null +++ b/backends/fs/riscos/riscos-fs.cpp @@ -0,0 +1,323 @@ +/* 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. + * + */ + +#if defined(RISCOS) + +// Re-enable some forbidden symbols to avoid clashes with stat.h and unistd.h. +#define FORBIDDEN_SYMBOL_EXCEPTION_unistd_h +#define FORBIDDEN_SYMBOL_EXCEPTION_mkdir + +#include "backends/fs/riscos/riscos-fs.h" +#include "backends/fs/stdiostream.h" +#include "common/algorithm.h" + +#include <limits.h> +#include <stdio.h> +#include <unistd.h> +#include <fcntl.h> + +#include <unixlib/local.h> +#include <kernel.h> +#include <swis.h> + +bool RISCOSFilesystemNode::exists() const { + return access(_path.c_str(), F_OK) == 0; +} + +bool RISCOSFilesystemNode::isReadable() const { + return access(_path.c_str(), R_OK) == 0; +} + +bool RISCOSFilesystemNode::isWritable() const { + return access(_path.c_str(), W_OK) == 0; +} + +RISCOSFilesystemNode::RISCOSFilesystemNode(const Common::String &p) { + _path = p; + if (p == "/") { + _isDirectory = true; + _isValid = true; + } else { + int type = _swi(OS_File, _INR(0,1)|_RETURN(0), 20, toRISCOS(_path).c_str()); + if (type == 0) { + _isDirectory = false; + _isValid = false; + } else if (type == 2) { + _isDirectory = true; + _isValid = true; + } else { + _isDirectory = false; + _isValid = true; + } + } +} + +Common::String RISCOSFilesystemNode::toRISCOS(Common::String &path) { + char start[PATH_MAX]; + char *end = __riscosify_std(path.c_str(), 0, start, PATH_MAX, 0); + return Common::String(start, end); +} + +Common::String RISCOSFilesystemNode::toUnix(Common::String &path) { + Common::String out = Common::String(path); + uint32 start = 0; + if (out.contains("$")) { + char *x = strstr(out.c_str(), "$"); + start = x ? x - out.c_str() : -1; + } + + for (uint32 ptr = start; ptr < out.size(); ptr += 1) { + switch (out.c_str()[ptr]) { + case '.': + out.setChar('/', ptr); + break; + case '/': + out.setChar('.', ptr); + break; + default: + break; + } + } + + if (out.contains("$")) + out = "/" + out; + + return out; +} + +AbstractFSNode *RISCOSFilesystemNode::getChild(const Common::String &n) const { + assert(!_path.empty()); + assert(_isDirectory); + + // Make sure the string contains no slashes + assert(!n.contains('/')); + + // We assume here that _path is already normalized (hence don't bother to call + // Common::normalizePath on the final path). + Common::String newPath(_path); + if (_path.lastChar() != '/') + newPath += '/'; + newPath += n; + + return makeNode(newPath); +} + +bool RISCOSFilesystemNode::getChildren(AbstractFSList &myList, ListMode mode, bool hidden) const { + assert(_isDirectory); + + if (_path == "/") { + // Special case for the root dir: List all drives + char fsname[PATH_MAX] = ""; + for (int fsNum = 0; fsNum < 256; fsNum += 1) { + _swi(OS_FSControl, _INR(0,3), 33, fsNum, fsname, sizeof(fsname)); + if (strcmp(fsname, "") != 0) { + if (!(fsNum == 46 || fsNum == 53 || fsNum == 99)) { + int drives = 9; + if (fsNum == 193) + drives = 23; + + for (int discnum = 0; discnum <= drives; discnum += 1) { + const Common::String path = Common::String::format("%s::%d.$", fsname, discnum); + char outpath[PATH_MAX] = ""; + if(_swix(OS_FSControl, _INR(0,2)|_IN(5), 37, path.c_str(), outpath, sizeof(outpath)) == NULL) { + int exist; + if (_swix(OS_File, _INR(0,1)|_OUT(0), 23, outpath, &exist) != NULL || exist != 2) + continue; + + RISCOSFilesystemNode *entry = new RISCOSFilesystemNode(); + entry->_isDirectory = true; + entry->_isValid = true; + entry->_path = Common::String::format("/%s", outpath); + entry->_displayName = outpath; + myList.push_back(entry); + } + } + } + } + } + return true; + } + + int count = 0; + int read = 0; + char file[PATH_MAX]; + Common::String dir = _path; + + while (count != -1) { + _swix(OS_GBPB, _INR(0,5)|_OUTR(3,4), 9, toRISCOS(dir).c_str(), file, 1, count, sizeof(file), &read, &count); + + if (count == -1) + continue; + + // Start with a clone of this node, with the correct path set + RISCOSFilesystemNode entry(*this); + entry._displayName = file; + entry._displayName = toUnix(entry._displayName); + if (_path.lastChar() != '/') + entry._path += '/'; + entry._path += entry._displayName; + + int type = _swi(OS_File, _INR(0,1)|_RETURN(0), 20, toRISCOS(entry._path).c_str()); + if (type == 0) { + continue; + } else if (type == 2) { + entry._isDirectory = true; + } else { + entry._isDirectory = false; + } + + // Honor the chosen mode + if ((mode == Common::FSNode::kListFilesOnly && entry._isDirectory) || + (mode == Common::FSNode::kListDirectoriesOnly && !entry._isDirectory)) + continue; + + myList.push_back(new RISCOSFilesystemNode(entry)); + } + + return true; +} + +AbstractFSNode *RISCOSFilesystemNode::getParent() const { + if (_path == "/") + return 0; // The filesystem root has no parent + + const char *start = _path.c_str(); + const char *end = start + _path.size(); + + // Strip of the last component. We make use of the fact that at this + // point, _path is guaranteed to be normalized + while (end > start && *(end-1) != '/') + end--; + + if (end == start) { + // This only happens if we were called with a relative path, for which + // there simply is no parent. + // TODO: We could also resolve this by assuming that the parent is the + // current working directory, and returning a node referring to that. + return 0; + } + + if (*(end-1) == '/' && end != start + 1) + end--; + + return makeNode(Common::String(start, end)); +} + +Common::SeekableReadStream *RISCOSFilesystemNode::createReadStream() { + return StdioStream::makeFromPath(getPath(), false); +} + +Common::WriteStream *RISCOSFilesystemNode::createWriteStream() { + return StdioStream::makeFromPath(getPath(), true); +} + +bool RISCOSFilesystemNode::create(bool isDirectoryFlag) { + bool success; + + if (isDirectoryFlag) { + success = _swix(OS_File, _INR(0,1), 8, toRISCOS(_path).c_str()) == NULL; + } else { + int fd = open(_path.c_str(), O_WRONLY | O_CREAT | O_TRUNC, 0755); + success = fd >= 0; + + if (fd >= 0) { + close(fd); + } + } + + if (success) { + if (exists()) { + _isDirectory = _swi(OS_File, _INR(0,1)|_RETURN(0), 20, toRISCOS(_path).c_str()) == 2; + if (_isDirectory != isDirectoryFlag) warning("failed to create %s: got %s", isDirectoryFlag ? "directory" : "file", _isDirectory ? "directory" : "file"); + return _isDirectory == isDirectoryFlag; + } + + warning("RISCOSFilesystemNode: Attempting to create a %s was a success, but access indicates there is no such %s", + isDirectoryFlag ? "directory" : "file", isDirectoryFlag ? "directory" : "file"); + return false; + } + + return false; +} + +namespace Riscos { + +bool assureDirectoryExists(const Common::String &dir, const char *prefix) { + AbstractFSNode *node; + + // Check whether the prefix exists if one is supplied. + if (prefix) { + node = new RISCOSFilesystemNode(prefix); + if (!node->isDirectory()) { + return false; + } + } + + // Obtain absolute path. + Common::String path; + if (prefix) { + path = prefix; + path += '/'; + path += dir; + } else { + path = dir; + } + + path = Common::normalizePath(path, '/'); + + const Common::String::iterator end = path.end(); + Common::String::iterator cur = path.begin(); + if (*cur == '/') + ++cur; + + do { + if (cur + 1 != end) { + if (*cur != '/') { + continue; + } + + // It is kind of ugly and against the purpose of Common::String to + // insert 0s inside, but this is just for a local string and + // simplifies the code a lot. + *cur = '\0'; + } + + node = new RISCOSFilesystemNode(path); + if (!node->create(true)) { + if (node->exists()) { + if (!node->isDirectory()) { + return false; + } + } else { + return false; + } + } + + *cur = '/'; + } while (cur++ != end); + + return true; +} + +} // End of namespace RISCOS + +#endif //#if defined(RISCOS) diff --git a/backends/fs/riscos/riscos-fs.h b/backends/fs/riscos/riscos-fs.h new file mode 100644 index 0000000000..b02f30bce7 --- /dev/null +++ b/backends/fs/riscos/riscos-fs.h @@ -0,0 +1,105 @@ +/* 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 RISCOS_FILESYSTEM_H +#define RISCOS_FILESYSTEM_H + +#include "backends/fs/abstract-fs.h" + +/** + * Implementation of the ScummVM file system API. + * + * Parts of this class are documented in the base interface class, AbstractFSNode. + */ +class RISCOSFilesystemNode : public AbstractFSNode { +protected: + Common::String _displayName; + Common::String _path; + bool _isDirectory; + bool _isValid; + + virtual AbstractFSNode *makeNode(const Common::String &path) const { + return new RISCOSFilesystemNode(path); + } + + /** + * Plain constructor, for internal use only (hence protected). + */ + RISCOSFilesystemNode() : _isDirectory(false), _isValid(false) {} +public: + /** + * Creates a RISCOSFilesystemNode for a given path. + * + * @param path the path the new node should point to. + */ + RISCOSFilesystemNode(const Common::String &path); + + virtual bool exists() const; + virtual Common::String getDisplayName() const { return _displayName; } + virtual Common::String getName() const { return _displayName; } + virtual Common::String getPath() const { return _path; } + virtual bool isDirectory() const { return _isDirectory; } + virtual bool isReadable() const; + virtual bool isWritable() const; + + virtual AbstractFSNode *getChild(const Common::String &n) const; + virtual bool getChildren(AbstractFSList &list, ListMode mode, bool hidden) const; + virtual AbstractFSNode *getParent() const; + + virtual Common::SeekableReadStream *createReadStream(); + virtual Common::WriteStream *createWriteStream(); + virtual bool create(bool isDirectoryFlag); + +private: + /** + * Converts a Unix style path to a RISC OS style path. + * + * @param str Unix style path to convert. + * @return RISC OS style path. + */ + static Common::String toRISCOS(Common::String &path); + + /** + * Converts a RISC OS style path to a Unix style path. + * + * @param str RISC OS style path to convert. + * @return Unix style path. + */ + static Common::String toUnix(Common::String &path); + +}; + +namespace Riscos { + +/** + * Assure that a directory path exists. + * + * @param dir The path which is required to exist. + * @param prefix An (optional) prefix which should not be created if non existent. + * prefix is prepended to dir if supplied. + * @return true in case the directoy exists (or was created), false otherwise. + */ +bool assureDirectoryExists(const Common::String &dir, const char *prefix = nullptr); + +} // End of namespace RISCOS + +#endif diff --git a/backends/graphics/default-palette.h b/backends/graphics/default-palette.h index a66e1862b7..e1b4c5cb22 100644 --- a/backends/graphics/default-palette.h +++ b/backends/graphics/default-palette.h @@ -51,7 +51,7 @@ public: memcpy(_palette + 3 * start, colors, 3 * num); setPaletteIntern(colors, start, num); } - void grabPalette(byte *colors, uint start, uint num) { + void grabPalette(byte *colors, uint start, uint num) const { assert(start + num <= 256); memcpy(colors, _palette + 3 * start, 3 * num); } diff --git a/backends/graphics/dinguxsdl/dinguxsdl-graphics.cpp b/backends/graphics/dinguxsdl/dinguxsdl-graphics.cpp index 9e75dd10f4..7d5f542ac0 100644 --- a/backends/graphics/dinguxsdl/dinguxsdl-graphics.cpp +++ b/backends/graphics/dinguxsdl/dinguxsdl-graphics.cpp @@ -75,7 +75,6 @@ bool DINGUXSdlGraphicsManager::setGraphicsMode(int mode) { return false; } - _transactionDetails.normal1xScaler = (mode == GFX_NORMAL); if (_oldVideoMode.setup && _oldVideoMode.scaleFactor != newScaleFactor) _transactionDetails.needHotswap = true; @@ -107,11 +106,11 @@ void DINGUXSdlGraphicsManager::setGraphicsModeIntern() { _scalerProc = newScalerProc; - 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. @@ -137,7 +136,7 @@ void DINGUXSdlGraphicsManager::initSize(uint w, uint h) { } void DINGUXSdlGraphicsManager::drawMouse() { - if (!_mouseVisible || !_mouseSurface) { + if (!_cursorVisible || !_mouseSurface) { _mouseBackup.x = _mouseBackup.y = _mouseBackup.w = _mouseBackup.h = 0; return; } @@ -147,11 +146,11 @@ void DINGUXSdlGraphicsManager::drawMouse() { int hotX, hotY; if (_videoMode.mode == GFX_HALF && !_overlayVisible) { - dst.x = _mouseCurState.x / 2; - dst.y = _mouseCurState.y / 2; + dst.x = _cursorX / 2; + dst.y = _cursorY / 2; } else { - dst.x = _mouseCurState.x; - dst.y = _mouseCurState.y; + dst.x = _cursorX; + dst.y = _cursorY; } if (!_overlayVisible) { @@ -194,7 +193,7 @@ void DINGUXSdlGraphicsManager::drawMouse() { // Note that SDL_BlitSurface() and addDirtyRect() will both perform any // clipping necessary - if (SDL_BlitSurface(_mouseSurface, NULL, _hwscreen, &dst) != 0) + if (SDL_BlitSurface(_mouseSurface, NULL, _hwScreen, &dst) != 0) error("SDL_BlitSurface failed: %s", SDL_GetError()); // The screen will be updated using real surface coordinates, i.e. @@ -227,8 +226,8 @@ void DINGUXSdlGraphicsManager::internUpdateScreen() { int scale1; #if defined(DEBUG) && ! defined(_WIN32_WCE) // definitions not available for non-DEBUG here. (needed this to compile in SYMBIAN32 & linux?) - assert(_hwscreen != NULL); - assert(_hwscreen->map->sw_data != NULL); + assert(_hwScreen != NULL); + assert(_hwScreen->map->sw_data != NULL); #endif // If the shake position changed, fill the dirty area with blackness @@ -238,11 +237,11 @@ void DINGUXSdlGraphicsManager::internUpdateScreen() { 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 @@ -254,7 +253,7 @@ void DINGUXSdlGraphicsManager::internUpdateScreen() { _paletteDirtyEnd = 0; - _forceFull = true; + _forceRedraw = true; } if (!_overlayVisible) { @@ -275,7 +274,7 @@ void DINGUXSdlGraphicsManager::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 @@ -283,7 +282,7 @@ void DINGUXSdlGraphicsManager::internUpdateScreen() { #endif // Force a full redraw if requested - if (_forceFull) { + if (_forceRedraw) { _numDirtyRects = 1; _dirtyRectList[0].x = 0; _dirtyRectList[0].y = 0; @@ -292,7 +291,7 @@ void DINGUXSdlGraphicsManager::internUpdateScreen() { } // Only draw anything if necessary - if (_numDirtyRects > 0 || _mouseNeedsRedraw) { + if (_numDirtyRects > 0 || _cursorNeedsRedraw) { SDL_Rect *r; SDL_Rect dst; uint32 srcPitch, dstPitch; @@ -308,10 +307,10 @@ void DINGUXSdlGraphicsManager::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; @@ -351,11 +350,11 @@ void DINGUXSdlGraphicsManager::internUpdateScreen() { dst_y = dst_y / 2; scalerProc((byte *)srcSurf->pixels + (src_x * 2 + 2) + (src_y + 1) * srcPitch, srcPitch, - (byte *)_hwscreen->pixels + dst_x * 2 + dst_y * dstPitch, dstPitch, dst_w, dst_h); + (byte *)_hwScreen->pixels + dst_x * 2 + dst_y * dstPitch, dstPitch, dst_w, dst_h); } else { scalerProc((byte *)srcSurf->pixels + (r->x * 2 + 2) + (r->y + 1) * srcPitch, srcPitch, - (byte *)_hwscreen->pixels + r->x * 2 + dst_y * dstPitch, dstPitch, r->w, dst_h); + (byte *)_hwScreen->pixels + r->x * 2 + dst_y * dstPitch, dstPitch, r->w, dst_h); } } @@ -373,17 +372,17 @@ void DINGUXSdlGraphicsManager::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 = (_videoMode.mode == GFX_HALF) ? effectiveScreenHeight() / 2 : effectiveScreenHeight(); + _dirtyRectList[0].h = (_videoMode.mode == GFX_HALF) ? _videoMode.hardwareHeight / 2 : _videoMode.hardwareHeight; } drawMouse(); @@ -392,26 +391,26 @@ void DINGUXSdlGraphicsManager::internUpdateScreen() { drawOSD(); #endif // Finally, blit all our changes to the screen - SDL_UpdateRects(_hwscreen, _numDirtyRects, _dirtyRectList); + SDL_UpdateRects(_hwScreen, _numDirtyRects, _dirtyRectList); } _numDirtyRects = 0; - _forceFull = false; - _mouseNeedsRedraw = false; + _forceRedraw = false; + _cursorNeedsRedraw = false; } void DINGUXSdlGraphicsManager::showOverlay() { if (_videoMode.mode == GFX_HALF) { - _mouseCurState.x = _mouseCurState.x / 2; - _mouseCurState.y = _mouseCurState.y / 2; + _cursorX = _cursorX / 2; + _cursorY = _cursorY / 2; } SurfaceSdlGraphicsManager::showOverlay(); } void DINGUXSdlGraphicsManager::hideOverlay() { if (_videoMode.mode == GFX_HALF) { - _mouseCurState.x = _mouseCurState.x * 2; - _mouseCurState.y = _mouseCurState.y * 2; + _cursorX = _cursorX * 2; + _cursorY = _cursorY * 2; } SurfaceSdlGraphicsManager::hideOverlay(); } @@ -440,22 +439,25 @@ bool DINGUXSdlGraphicsManager::loadGFXMode() { _videoMode.overlayHeight = _videoMode.screenHeight / 2; _videoMode.fullscreen = true; } else { - _videoMode.overlayWidth = _videoMode.screenWidth * _videoMode.scaleFactor; _videoMode.overlayHeight = _videoMode.screenHeight * _videoMode.scaleFactor; - if (_videoMode.aspectRatioCorrection) - _videoMode.overlayHeight = real2Aspect(_videoMode.overlayHeight); + if (_videoMode.screenHeight != 200 && _videoMode.screenHeight != 400) + _videoMode.aspectRatioCorrection = false; _videoMode.hardwareWidth = _videoMode.screenWidth * _videoMode.scaleFactor; - _videoMode.hardwareHeight = effectiveScreenHeight(); - } + _videoMode.hardwareHeight = _videoMode.screenHeight * _videoMode.scaleFactor; + if (_videoMode.aspectRatioCorrection) { + _videoMode.overlayHeight = real2Aspect(_videoMode.overlayHeight); + _videoMode.hardwareHeight = real2Aspect(_videoMode.hardwareHeight); + } + } return SurfaceSdlGraphicsManager::loadGFXMode(); } -bool DINGUXSdlGraphicsManager::hasFeature(OSystem::Feature f) { +bool DINGUXSdlGraphicsManager::hasFeature(OSystem::Feature f) const { return (f == OSystem::kFeatureAspectRatioCorrection) || (f == OSystem::kFeatureCursorPalette); @@ -475,7 +477,7 @@ void DINGUXSdlGraphicsManager::setFeatureState(OSystem::Feature f, bool enable) } } -bool DINGUXSdlGraphicsManager::getFeatureState(OSystem::Feature f) { +bool DINGUXSdlGraphicsManager::getFeatureState(OSystem::Feature f) const { assert(_transactionMode == kTransactionNone); switch (f) { @@ -488,16 +490,8 @@ 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 (_cursorX != x || _cursorY != y) { if (_videoMode.mode == GFX_HALF && !_overlayVisible) { x = x / 2; y = y / 2; diff --git a/backends/graphics/dinguxsdl/dinguxsdl-graphics.h b/backends/graphics/dinguxsdl/dinguxsdl-graphics.h index 8a356106ad..3a2a299a2f 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) const 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 a19512110f..9a97e97aa5 100644 --- a/backends/graphics/gph/gph-graphics.cpp +++ b/backends/graphics/gph/gph-graphics.cpp @@ -69,7 +69,6 @@ bool GPHGraphicsManager::setGraphicsMode(int mode) { return false; } - _transactionDetails.normal1xScaler = (mode == GFX_NORMAL); if (_oldVideoMode.setup && _oldVideoMode.scaleFactor != newScaleFactor) _transactionDetails.needHotswap = true; @@ -99,11 +98,11 @@ void GPHGraphicsManager::setGraphicsModeIntern() { _scalerProc = newScalerProc; - 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. @@ -151,7 +150,7 @@ void GPHGraphicsManager::initSize(uint w, uint h, const Graphics::PixelFormat *f } void GPHGraphicsManager::drawMouse() { - if (!_mouseVisible || !_mouseSurface) { + if (!_cursorVisible || !_mouseSurface) { _mouseBackup.x = _mouseBackup.y = _mouseBackup.w = _mouseBackup.h = 0; return; } @@ -162,11 +161,11 @@ void GPHGraphicsManager::drawMouse() { int hotX, hotY; if (_videoMode.mode == GFX_HALF && !_overlayVisible) { - dst.x = _mouseCurState.x / 2; - dst.y = _mouseCurState.y / 2; + dst.x = _cursorX / 2; + dst.y = _cursorY / 2; } else { - dst.x = _mouseCurState.x; - dst.y = _mouseCurState.y; + dst.x = _cursorX; + dst.y = _cursorY; } if (!_overlayVisible) { @@ -213,7 +212,7 @@ void GPHGraphicsManager::drawMouse() { // Note that SDL_BlitSurface() and addDirtyRect() will both perform any // clipping necessary - if (SDL_BlitSurface(_mouseSurface, NULL, _hwscreen, &dst) != 0) + if (SDL_BlitSurface(_mouseSurface, NULL, _hwScreen, &dst) != 0) error("SDL_BlitSurface failed: %s", SDL_GetError()); // The screen will be updated using real surface coordinates, i.e. @@ -246,23 +245,23 @@ void GPHGraphicsManager::internUpdateScreen() { int scale1; #if defined(DEBUG) - assert(_hwscreen != NULL); - assert(_hwscreen->map->sw_data != NULL); + 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, _videoMode.screenWidth *_videoMode.scaleFactor, _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 @@ -274,7 +273,7 @@ void GPHGraphicsManager::internUpdateScreen() { _paletteDirtyEnd = 0; - _forceFull = true; + _forceRedraw = true; } if (!_overlayVisible) { @@ -296,7 +295,7 @@ void GPHGraphicsManager::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 @@ -304,7 +303,7 @@ void GPHGraphicsManager::internUpdateScreen() { #endif // Force a full redraw if requested - if (_forceFull) { + if (_forceRedraw) { _numDirtyRects = 1; _dirtyRectList[0].x = 0; _dirtyRectList[0].y = 0; @@ -312,11 +311,11 @@ void GPHGraphicsManager::internUpdateScreen() { _dirtyRectList[0].h = height; // HACK: Make sure the full hardware screen is wiped clean. - SDL_FillRect(_hwscreen, NULL, 0); + SDL_FillRect(_hwScreen, NULL, 0); } // Only draw anything if necessary - if (_numDirtyRects > 0 || _mouseNeedsRedraw) { + if (_numDirtyRects > 0 || _cursorNeedsRedraw) { SDL_Rect *r; SDL_Rect dst; uint32 srcPitch, dstPitch; @@ -332,10 +331,10 @@ void GPHGraphicsManager::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; @@ -375,10 +374,10 @@ void GPHGraphicsManager::internUpdateScreen() { dst_y = dst_y / 2; scalerProc((byte *)srcSurf->pixels + (src_x * 2 + 2) + (src_y + 1) * srcPitch, srcPitch, - (byte *)_hwscreen->pixels + dst_x * 2 + dst_y * dstPitch, dstPitch, dst_w, dst_h); + (byte *)_hwScreen->pixels + dst_x * 2 + dst_y * dstPitch, dstPitch, dst_w, dst_h); } else { scalerProc((byte *)srcSurf->pixels + (r->x * 2 + 2) + (r->y + 1) * srcPitch, srcPitch, - (byte *)_hwscreen->pixels + r->x * 2 + dst_y * dstPitch, dstPitch, r->w, dst_h); + (byte *)_hwScreen->pixels + r->x * 2 + dst_y * dstPitch, dstPitch, r->w, dst_h); } } @@ -396,17 +395,17 @@ void GPHGraphicsManager::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 = (_videoMode.mode == GFX_HALF) ? effectiveScreenHeight() / 2 : effectiveScreenHeight(); + _dirtyRectList[0].h = (_videoMode.mode == GFX_HALF) ? _videoMode.hardwareHeight / 2 : _videoMode.hardwareHeight; } drawMouse(); @@ -416,26 +415,26 @@ void GPHGraphicsManager::internUpdateScreen() { #endif // Finally, blit all our changes to the screen - SDL_UpdateRects(_hwscreen, _numDirtyRects, _dirtyRectList); + SDL_UpdateRects(_hwScreen, _numDirtyRects, _dirtyRectList); } _numDirtyRects = 0; - _forceFull = false; - _mouseNeedsRedraw = false; + _forceRedraw = false; + _cursorNeedsRedraw = false; } void GPHGraphicsManager::showOverlay() { if (_videoMode.mode == GFX_HALF) { - _mouseCurState.x = _mouseCurState.x / 2; - _mouseCurState.y = _mouseCurState.y / 2; + _cursorX = _cursorX / 2; + _cursorY = _cursorY / 2; } SurfaceSdlGraphicsManager::showOverlay(); } void GPHGraphicsManager::hideOverlay() { if (_videoMode.mode == GFX_HALF) { - _mouseCurState.x = _mouseCurState.x * 2; - _mouseCurState.y = _mouseCurState.y * 2; + _cursorX = _cursorX * 2; + _cursorY = _cursorY * 2; } SurfaceSdlGraphicsManager::hideOverlay(); } @@ -478,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); @@ -498,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) { @@ -511,16 +510,8 @@ 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 (_cursorX != x || _cursorY != y) { if (_videoMode.mode == GFX_HALF && !_overlayVisible) { x = x / 2; y = y / 2; 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 35f2fa1cb6..d5c36c13c4 100644 --- a/backends/graphics/graphics.h +++ b/backends/graphics/graphics.h @@ -27,6 +27,7 @@ #include "common/noncopyable.h" #include "common/keyboard.h" +#include "graphics/mode.h" #include "graphics/palette.h" /** @@ -37,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; @@ -58,15 +59,16 @@ public: virtual Common::List<Graphics::PixelFormat> getSupportedFormats() const = 0; #endif virtual void initSize(uint width, uint height, const Graphics::PixelFormat *format = NULL) = 0; + virtual void initSizeHint(const Graphics::ModeList &modes) {} virtual int getScreenChangeID() const = 0; 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; @@ -80,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; @@ -96,7 +98,7 @@ public: // Graphics::PaletteManager interface //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; }; #endif diff --git a/backends/graphics/linuxmotosdl/linuxmotosdl-graphics.cpp b/backends/graphics/linuxmotosdl/linuxmotosdl-graphics.cpp index 6a920e9eae..b61ee690bb 100644 --- a/backends/graphics/linuxmotosdl/linuxmotosdl-graphics.cpp +++ b/backends/graphics/linuxmotosdl/linuxmotosdl-graphics.cpp @@ -79,7 +79,6 @@ bool LinuxmotoSdlGraphicsManager::setGraphicsMode(int mode) { return false; } - _transactionDetails.normal1xScaler = (mode == GFX_NORMAL); if (_oldVideoMode.setup && _oldVideoMode.scaleFactor != newScaleFactor) _transactionDetails.needHotswap = true; 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 f664314862..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) @@ -268,22 +266,19 @@ bool OpenGLSdlGraphicsManager::getFeatureState(OSystem::Feature f) { } } -bool OpenGLSdlGraphicsManager::setGraphicsMode(int mode) { +void OpenGLSdlGraphicsManager::initSize(uint w, uint h, const Graphics::PixelFormat *format) { // HACK: This is stupid but the SurfaceSDL backend defaults to 2x. This // assures that the launcher (which requests 320x200) has a reasonable // size. It also makes small games have a reasonable size (i.e. at least // 640x400). We follow the same logic here until we have a better way to // give hints to our backend for that. - _graphicsScale = 2; - - return OpenGLGraphicsManager::setGraphicsMode(mode); -} - -void OpenGLSdlGraphicsManager::resetGraphicsScale() { - OpenGLGraphicsManager::resetGraphicsScale(); + if (w > 320) { + _graphicsScale = 1; + } else { + _graphicsScale = 2; + } - // HACK: See OpenGLSdlGraphicsManager::setGraphicsMode. - _graphicsScale = 1; + return OpenGLGraphicsManager::initSize(w, h, format); } #ifdef USE_RGB_COLOR @@ -347,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. @@ -357,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 @@ -376,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. @@ -425,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. @@ -509,16 +496,8 @@ bool OpenGLSdlGraphicsManager::setupMode(uint width, uint height) { SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, _glContextMajor); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, _glContextMinor); - if (!_window->createOrUpdateWindow(width, height, flags)) { - // We treat fullscreen requests as a "hint" for now. This means in - // case it is not available we simply ignore it. - if (_wantsFullScreen) { - _window->createOrUpdateWindow(width, height, SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE); - } - - if (!_window->getSDLWindow()) { - return false; - } + if (!createOrUpdateWindow(width, height, flags)) { + return false; } _glContext = SDL_GL_CreateContext(_window->getSDLWindow()); @@ -528,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 @@ -577,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 @@ -591,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: @@ -718,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); @@ -736,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 @@ -796,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 51edcb4363..954c7215a4 100644 --- a/backends/graphics/openglsdl/openglsdl-graphics.h +++ b/backends/graphics/openglsdl/openglsdl-graphics.h @@ -36,39 +36,39 @@ 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 bool setGraphicsMode(int mode); - virtual void resetGraphicsScale(); + 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 int getGraphicsModeScale(int mode) const override { return 1; } - virtual void *getProcAddress(const char *name) const; private: bool setupMode(uint width, uint height); @@ -77,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; @@ -121,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.cpp b/backends/graphics/openpandora/op-graphics.cpp index f4c9dc16cc..d6c16462e8 100644 --- a/backends/graphics/openpandora/op-graphics.cpp +++ b/backends/graphics/openpandora/op-graphics.cpp @@ -54,19 +54,6 @@ bool OPGraphicsManager::loadGFXMode() { SDL_SetCursor(hiddenCursor); _videoMode.fullscreen = true; - - _videoMode.overlayWidth = _videoMode.screenWidth * _videoMode.scaleFactor; - _videoMode.overlayHeight = _videoMode.screenHeight * _videoMode.scaleFactor; - - if (_videoMode.screenHeight != 200 && _videoMode.screenHeight != 400) - _videoMode.aspectRatioCorrection = false; - - if (_videoMode.aspectRatioCorrection) - _videoMode.overlayHeight = real2Aspect(_videoMode.overlayHeight); - - _videoMode.hardwareWidth = _videoMode.screenWidth * _videoMode.scaleFactor; - _videoMode.hardwareHeight = effectiveScreenHeight(); - return SurfaceSdlGraphicsManager::loadGFXMode(); } 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.cpp b/backends/graphics/psp2sdl/psp2sdl-graphics.cpp index b56f13e27a..affcf9d8f5 100644 --- a/backends/graphics/psp2sdl/psp2sdl-graphics.cpp +++ b/backends/graphics/psp2sdl/psp2sdl-graphics.cpp @@ -111,8 +111,8 @@ PSP2SdlGraphicsManager::~PSP2SdlGraphicsManager() { } _vitatex_hwscreen = NULL; } - if (_hwscreen) { - _hwscreen->pixels = _sdlpixels_hwscreen; + if (_hwScreen) { + _hwScreen->pixels = _sdlpixels_hwscreen; } _sdlpixels_hwscreen = nullptr; } @@ -153,7 +153,7 @@ void PSP2SdlGraphicsManager::unloadGFXMode() { deinitializeRenderer(); - if (_hwscreen) { + if (_hwScreen) { if (_vitatex_hwscreen) { vita2d_free_texture(_vitatex_hwscreen); for (int i = 0; i < 6; i++) { @@ -162,7 +162,7 @@ void PSP2SdlGraphicsManager::unloadGFXMode() { } _vitatex_hwscreen = NULL; } - _hwscreen->pixels = _sdlpixels_hwscreen; + _hwScreen->pixels = _sdlpixels_hwscreen; } SurfaceSdlGraphicsManager::unloadGFXMode(); } @@ -172,7 +172,7 @@ bool PSP2SdlGraphicsManager::hotswapGFXMode() { return false; // Release the HW screen surface - if (_hwscreen) { + if (_hwScreen) { if (_vitatex_hwscreen) { vita2d_free_texture(_vitatex_hwscreen); for (int i = 0; i < 6; i++) { @@ -181,7 +181,7 @@ bool PSP2SdlGraphicsManager::hotswapGFXMode() { } _vitatex_hwscreen = NULL; } - _hwscreen->pixels = _sdlpixels_hwscreen; + _hwScreen->pixels = _sdlpixels_hwscreen; } return SurfaceSdlGraphicsManager::hotswapGFXMode(); } @@ -222,23 +222,23 @@ void PSP2SdlGraphicsManager::internUpdateScreen() { // definitions not available for non-DEBUG here. (needed this to compile in SYMBIAN32 & linux?) #if defined(DEBUG) - assert(_hwscreen != NULL); - assert(_hwscreen->map->sw_data != NULL); + 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 @@ -250,7 +250,7 @@ void PSP2SdlGraphicsManager::internUpdateScreen() { _paletteDirtyEnd = 0; - _forceFull = true; + _forceRedraw = true; } if (!_overlayVisible) { @@ -272,7 +272,7 @@ void PSP2SdlGraphicsManager::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 @@ -280,7 +280,7 @@ void PSP2SdlGraphicsManager::internUpdateScreen() { #endif // Force a full redraw if requested - if (_forceFull) { + if (_forceRedraw) { _numDirtyRects = 1; _dirtyRectList[0].x = 0; _dirtyRectList[0].y = 0; @@ -289,7 +289,7 @@ void PSP2SdlGraphicsManager::internUpdateScreen() { } // Only draw anything if necessary - if (_numDirtyRects > 0 || _mouseNeedsRedraw) { + if (_numDirtyRects > 0 || _cursorNeedsRedraw) { SDL_Rect *r; SDL_Rect dst; uint32 srcPitch, dstPitch; @@ -306,7 +306,7 @@ void PSP2SdlGraphicsManager::internUpdateScreen() { SDL_LockSurface(srcSurf); srcPitch = srcSurf->pitch; - dstPitch = _hwscreen->pitch; + dstPitch = _hwScreen->pitch; for (r = _dirtyRectList; r != lastRect; ++r) { register int dst_y = r->y + _currentShakePos; @@ -331,7 +331,7 @@ void PSP2SdlGraphicsManager::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; @@ -341,15 +341,15 @@ void PSP2SdlGraphicsManager::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); // 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(); @@ -380,15 +380,15 @@ void PSP2SdlGraphicsManager::internUpdateScreen() { if (h > 0 && w > 0) { // 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; @@ -399,14 +399,14 @@ void PSP2SdlGraphicsManager::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; @@ -417,8 +417,8 @@ void PSP2SdlGraphicsManager::internUpdateScreen() { *(uint32 *)left = rectColor; *(uint32 *)right = rectColor; - left += _hwscreen->pitch; - right += _hwscreen->pitch; + left += _hwScreen->pitch; + right += _hwScreen->pitch; } } } @@ -428,13 +428,13 @@ void PSP2SdlGraphicsManager::internUpdateScreen() { // Finally, blit all our changes to the screen if (!_displayDisabled) { - PSP2_UpdateRects(_hwscreen, _numDirtyRects, _dirtyRectList); + PSP2_UpdateRects(_hwScreen, _numDirtyRects, _dirtyRectList); } } _numDirtyRects = 0; - _forceFull = false; - _mouseNeedsRedraw = false; + _forceRedraw = false; + _cursorNeedsRedraw = false; } void PSP2SdlGraphicsManager::setAspectRatioCorrection(bool enable) { 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 a13ca45477..0e0a45a38f 100644 --- a/backends/graphics/sdl/sdl-graphics.cpp +++ b/backends/graphics/sdl/sdl-graphics.cpp @@ -21,17 +21,18 @@ */ #include "backends/graphics/sdl/sdl-graphics.h" - #include "backends/platform/sdl/sdl-sys.h" #include "backends/events/sdl/sdl-events.h" +#include "common/config-manager.h" #include "common/textconsole.h" +#include "graphics/scaler/aspect.h" SdlGraphicsManager::SdlGraphicsManager(SdlEventSource *source, SdlWindow *window) - : _eventSource(source), _window(window) { -} - -SdlGraphicsManager::~SdlGraphicsManager() { -} + : _eventSource(source), _window(window), _hwScreen(nullptr) +#if SDL_VERSION_ATLEAST(2, 0, 0) + , _allowWindowSizeReset(false), _hintedWidth(0), _hintedHeight(0), _lastFlags(0) +#endif +{} void SdlGraphicsManager::activateManager() { _eventSource->setGraphicsManager(this); @@ -41,7 +42,7 @@ void SdlGraphicsManager::deactivateManager() { _eventSource->setGraphicsManager(0); } -SdlGraphicsManager::State SdlGraphicsManager::getState() { +SdlGraphicsManager::State SdlGraphicsManager::getState() const { State state; state.screenWidth = getWidth(); @@ -60,7 +61,7 @@ bool SdlGraphicsManager::setState(const State &state) { #ifdef USE_RGB_COLOR initSize(state.screenWidth, state.screenHeight, &state.pixelFormat); #else - initSize(state.screenWidth, state.screenHeight, 0); + initSize(state.screenWidth, state.screenHeight, nullptr); #endif setFeatureState(OSystem::kFeatureAspectRatioCorrection, state.aspectRatio); setFeatureState(OSystem::kFeatureFullscreenMode, state.fullscreen); @@ -73,3 +74,184 @@ bool SdlGraphicsManager::setState(const State &state) { } } +bool SdlGraphicsManager::defaultGraphicsModeConfig() const { + const Common::ConfigManager::Domain *transientDomain = ConfMan.getDomain(Common::ConfigManager::kTransientDomain); + if (transientDomain && transientDomain->contains("gfx_mode")) { + const Common::String &mode = transientDomain->getVal("gfx_mode"); + if (!mode.equalsIgnoreCase("normal") && !mode.equalsIgnoreCase("default")) { + return false; + } + } + + const Common::ConfigManager::Domain *gameDomain = ConfMan.getActiveDomain(); + if (gameDomain && gameDomain->contains("gfx_mode")) { + const Common::String &mode = gameDomain->getVal("gfx_mode"); + if (!mode.equalsIgnoreCase("normal") && !mode.equalsIgnoreCase("default")) { + return false; + } + } + + return true; +} + +int SdlGraphicsManager::getGraphicsModeIdByName(const Common::String &name) const { + const OSystem::GraphicsMode *mode = getSupportedGraphicsModes(); + while (mode && mode->name != nullptr) { + if (name.equalsIgnoreCase(mode->name)) { + return mode->id; + } + ++mode; + } + return -1; +} + +void SdlGraphicsManager::initSizeHint(const Graphics::ModeList &modes) { +#if SDL_VERSION_ATLEAST(2, 0, 0) + const bool useDefault = defaultGraphicsModeConfig(); + + int scale = getGraphicsModeScale(getGraphicsModeIdByName(ConfMan.get("gfx_mode"))); + if (scale == -1) { + warning("Unknown scaler; defaulting to 1"); + scale = 1; + } + + int16 bestWidth = 0, bestHeight = 0; + const Graphics::ModeList::const_iterator end = modes.end(); + for (Graphics::ModeList::const_iterator it = modes.begin(); it != end; ++it) { + int16 width = it->width, height = it->height; + + // TODO: Normalize AR correction by passing a PAR in the mode list + // instead of checking the dimensions here like this, since not all + // 320x200/640x400 uses are with non-square pixels (e.g. DreamWeb). + if (ConfMan.getBool("aspect_ratio")) { + if ((width == 320 && height == 200) || (width == 640 && height == 400)) { + height = real2Aspect(height); + } + } + + if (!useDefault || width <= 320) { + width *= scale; + height *= scale; + } + + if (bestWidth < width) { + bestWidth = width; + } + + if (bestHeight < height) { + bestHeight = height; + } + } + + _hintedWidth = bestWidth; + _hintedHeight = bestHeight; +#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) { + return false; + } + + // We only update the actual window when flags change (which usually means + // 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), 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; + } + if (_hintedHeight) { + height = _hintedHeight; + } + + if (!_window->createOrUpdateWindow(width, height, flags)) { + return false; + } + + _lastFlags = flags; + _allowWindowSizeReset = false; + } + + return true; +} +#endif diff --git a/backends/graphics/sdl/sdl-graphics.h b/backends/graphics/sdl/sdl-graphics.h index 7f8790a9b4..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,21 +107,70 @@ 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; } + virtual void initSizeHint(const Graphics::ModeList &modes) override; + +protected: + virtual int getGraphicsModeScale(int mode) const = 0; + + 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() { + _allowWindowSizeReset = true; + _hintedWidth = 0; + _hintedHeight = 0; + } + protected: + Uint32 _lastFlags; + bool _allowWindowSizeReset; + int _hintedWidth, _hintedHeight; + + 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 983b71ab28..262ea84096 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. @@ -332,7 +324,6 @@ void SurfaceSdlGraphicsManager::beginGFXTransaction() { _transactionDetails.needHotswap = false; _transactionDetails.needUpdatescreen = false; - _transactionDetails.normal1xScaler = false; #if SDL_VERSION_ATLEAST(2, 0, 0) _transactionDetails.needTextureUpdate = false; #endif @@ -556,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); @@ -580,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]); @@ -588,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]); @@ -599,65 +590,55 @@ void SurfaceSdlGraphicsManager::detectSupportedFormats() { } #endif -bool SurfaceSdlGraphicsManager::setGraphicsMode(int mode) { - Common::StackLock lock(_graphicsMutex); - - assert(_transactionMode == kTransactionActive); - - if (_oldVideoMode.setup && _oldVideoMode.mode == mode) - return true; - - int newScaleFactor = 1; - +int SurfaceSdlGraphicsManager::getGraphicsModeScale(int mode) const { + int scale; switch (mode) { case GFX_NORMAL: - newScaleFactor = 1; + scale = 1; break; #ifdef USE_SCALERS case GFX_DOUBLESIZE: - newScaleFactor = 2; - break; - case GFX_TRIPLESIZE: - newScaleFactor = 3; - break; - case GFX_2XSAI: - newScaleFactor = 2; - break; case GFX_SUPER2XSAI: - newScaleFactor = 2; - break; case GFX_SUPEREAGLE: - newScaleFactor = 2; - break; case GFX_ADVMAME2X: - newScaleFactor = 2; - break; - case GFX_ADVMAME3X: - newScaleFactor = 3; - break; + case GFX_TV2X: + case GFX_DOTMATRIX: #ifdef USE_HQ_SCALERS case GFX_HQ2X: - newScaleFactor = 2; +#endif + scale = 2; break; + case GFX_TRIPLESIZE: + case GFX_ADVMAME3X: +#ifdef USE_HQ_SCALERS case GFX_HQ3X: - newScaleFactor = 3; - break; #endif - case GFX_TV2X: - newScaleFactor = 2; - break; - case GFX_DOTMATRIX: - newScaleFactor = 2; + scale = 3; break; -#endif // USE_SCALERS - +#endif default: + scale = -1; + } + + return scale; +} + +bool SurfaceSdlGraphicsManager::setGraphicsMode(int mode) { + Common::StackLock lock(_graphicsMutex); + + assert(_transactionMode == kTransactionActive); + + if (_oldVideoMode.setup && _oldVideoMode.mode == mode) + return true; + + int newScaleFactor = getGraphicsModeScale(mode); + + if (newScaleFactor == -1) { warning("unknown gfx mode %d", mode); return false; } - _transactionDetails.normal1xScaler = (mode == GFX_NORMAL); if (_oldVideoMode.setup && _oldVideoMode.scaleFactor != newScaleFactor) _transactionDetails.needHotswap = true; @@ -733,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. @@ -784,9 +765,23 @@ void SurfaceSdlGraphicsManager::initSize(uint w, uint h, const Graphics::PixelFo } #endif - // Avoid redundant res changes +#if !SDL_VERSION_ATLEAST(2, 0, 0) + // Avoid redundant res changes, only in SDL1. In SDL2, redundancies may not + // actually be redundant if ScummVM is switching between game engines and + // the screen dimensions are being reinitialized, since window resizing is + // supposed to reset when this happens if ((int)w == _videoMode.screenWidth && (int)h == _videoMode.screenHeight) return; +#endif + + if ((int)w != _videoMode.screenWidth || (int)h != _videoMode.screenHeight) { + const bool useDefault = defaultGraphicsModeConfig(); + if (useDefault && w > 320) { + resetGraphicsScale(); + } else { + setGraphicsMode(getGraphicsModeIdByName(ConfMan.get("gfx_mode"))); + } + } _videoMode.screenWidth = w; _videoMode.screenHeight = h; @@ -794,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); @@ -861,20 +849,23 @@ 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) +#if !defined(__MAEMO__) && !defined(DINGUX) && !defined(GPH_DEVICE) && !defined(LINUXMOTO) _videoMode.overlayWidth = _videoMode.screenWidth * _videoMode.scaleFactor; _videoMode.overlayHeight = _videoMode.screenHeight * _videoMode.scaleFactor; 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; @@ -884,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, @@ -921,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 { @@ -934,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 ); } @@ -943,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()); @@ -955,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 // @@ -962,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"); @@ -994,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); @@ -1030,9 +1014,9 @@ void SurfaceSdlGraphicsManager::unloadGFXMode() { deinitializeRenderer(); #endif - if (_hwscreen) { - SDL_FreeSurface(_hwscreen); - _hwscreen = NULL; + if (_hwScreen) { + SDL_FreeSurface(_hwScreen); + _hwScreen = NULL; } if (_tmpscreen) { @@ -1084,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); @@ -1136,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() { @@ -1152,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 @@ -1182,7 +1160,7 @@ void SurfaceSdlGraphicsManager::internUpdateScreen() { _paletteDirtyEnd = 0; - _forceFull = true; + _forceRedraw = true; } if (!_overlayVisible) { @@ -1203,8 +1181,10 @@ 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) + // we have to redraw the mouse, or if the cursor is alpha-blended since + // alpha-blended cursors will happily blend into themselves if the surface + // under the cursor is not reset first + if (_cursorNeedsRedraw || _cursorFormat.bytesPerPixel == 4) undrawMouse(); #ifdef USE_OSD @@ -1212,7 +1192,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; @@ -1221,7 +1201,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; @@ -1237,10 +1217,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; @@ -1265,7 +1245,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; @@ -1275,17 +1255,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(); @@ -1315,18 +1295,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; @@ -1337,14 +1317,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; @@ -1355,12 +1335,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); } } } @@ -1368,17 +1348,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 @@ -1388,12 +1368,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, @@ -1408,9 +1388,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; } @@ -1438,7 +1418,7 @@ bool SurfaceSdlGraphicsManager::saveScreenshot(const char *filename) { return success; #else - return SDL_SaveBMP(_hwscreen, filename) == 0; + return SDL_SaveBMP(_hwScreen, filename) == 0; #endif } @@ -1502,7 +1482,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); @@ -1514,19 +1493,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); @@ -1546,13 +1512,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; } @@ -1568,7 +1528,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); @@ -1582,11 +1542,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; } @@ -1605,8 +1565,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 @@ -1617,7 +1577,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) { @@ -1635,7 +1595,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; } @@ -1649,20 +1609,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. @@ -1694,12 +1651,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; @@ -1774,56 +1728,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) @@ -1851,10 +1756,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) @@ -1928,143 +1833,201 @@ 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); + } 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); - _window->warpMouseInWindow(x1, y1); + if (_mouseSurface == _mouseOrigSurface) { + _mouseSurface = nullptr; + } + } - // 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 (_cursorFormat.bytesPerPixel == 4) { + if (_mouseSurface != _mouseOrigSurface) { + SDL_FreeSurface(_mouseSurface); + } - setMousePos(x, y); + 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); + } + + if (_mouseOrigSurface == nullptr) { + error("Allocating _mouseOrigSurface failed"); + } + + if (_cursorFormat.bytesPerPixel < 4) { + SDL_SetColorKey(_mouseOrigSurface, SDL_RLEACCEL | SDL_SRCCOLORKEY | SDL_SRCALPHA, kMouseColorKey); + } } + + 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); + } + + blitCursor(); } -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; +void SurfaceSdlGraphicsManager::blitCursor() { + const int w = _mouseCurState.w; + const int h = _mouseCurState.h; - if (_cursorFormat.bytesPerPixel < 4) - assert(keycolor < (uint)(1 << (_cursorFormat.bytesPerPixel << 3))); -#else - assert(keycolor <= 0xFF); -#endif + if (!w || !h || !_mouseOrigSurface) { + return; + } - if (w == 0 || h == 0) + if (_cursorFormat.bytesPerPixel != 4 && !_mouseData) { return; + } - _mouseCurState.hotX = hotspot_x; - _mouseCurState.hotY = hotspot_y; + _cursorNeedsRedraw = true; - _mouseKeyColor = keycolor; + 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; + } - _cursorDontScale = dontScale; + // 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; - if (_mouseCurState.w != (int)w || _mouseCurState.h != (int)h) { - _mouseCurState.w = w; - _mouseCurState.h = h; + // The virtual dimensions will be the same as the original. - if (_mouseOrigSurface) - SDL_FreeSurface(_mouseOrigSurface); + _mouseCurState.vW = w; + _mouseCurState.vH = h; + _mouseCurState.vHotX = _mouseCurState.hotX; + _mouseCurState.vHotY = _mouseCurState.hotY; - // 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); +#ifdef USE_SCALERS + // store original to pass to aspect-correction function later + const int rH1 = rH; +#endif - if (_mouseOrigSurface == NULL) - error("allocating _mouseOrigSurface failed"); - SDL_SetColorKey(_mouseOrigSurface, SDL_RLEACCEL | SDL_SRCCOLORKEY | SDL_SRCALPHA, kMouseColorKey); + if (!_cursorDontScale && _videoMode.aspectRatioCorrection) { + rH = real2Aspect(rH - 1) + 1; + _mouseCurState.rHotY = real2Aspect(_mouseCurState.rHotY); } - 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); -#endif - - blitCursor(); -} + bool sizeChanged = false; + if (_mouseCurState.rW != rW || _mouseCurState.rH != rH) { + _mouseCurState.rW = rW; + _mouseCurState.rH = rH; + sizeChanged = true; + } -void SurfaceSdlGraphicsManager::blitCursor() { - byte *dstPtr; - const byte *srcPtr = _mouseData; -#ifdef USE_RGB_COLOR - uint32 color; -#else - byte color; -#endif - int w, h, i, j; + if (_cursorFormat.bytesPerPixel == 4) { + if (_mouseSurface != _mouseOrigSurface) { + SDL_FreeSurface(_mouseSurface); + } - if (!_mouseOrigSurface || !_mouseData) - return; + if (cursorScale == 1) { + _mouseSurface = _mouseOrigSurface; + return; + } - _mouseNeedsRedraw = true; + SDL_PixelFormat *format = _mouseOrigSurface->format; + _mouseSurface = SDL_CreateRGBSurface(SDL_SWSURFACE | SDL_SRCALPHA, + rW, rH, + format->BitsPerPixel, + format->Rmask, + format->Gmask, + format->Bmask, + format->Amask); + + // At least SDL 2.0.4 on Windows apparently has a broken SDL_BlitScaled + // implementation, and SDL 1 has no such API at all, and our other + // scalers operate exclusively at 16bpp, so here is a scrappy 32bpp + // point scaler + SDL_LockSurface(_mouseOrigSurface); + SDL_LockSurface(_mouseSurface); + + const byte *src = (const byte *)_mouseOrigSurface->pixels; + byte *dst = (byte *)_mouseSurface->pixels; + for (int y = 0; y < _mouseOrigSurface->h; ++y) { + uint32 *rowDst = (uint32 *)dst; + const uint32 *rowSrc = (const uint32 *)src; + for (int x = 0; x < _mouseOrigSurface->w; ++x) { + for (int scaleX = 0; scaleX < cursorScale; ++scaleX) { + *rowDst++ = *rowSrc; + } + ++rowSrc; + } + for (int scaleY = 0; scaleY < cursorScale - 1; ++scaleY) { + memcpy(dst + _mouseSurface->pitch, dst, _mouseSurface->pitch); + dst += _mouseSurface->pitch; + } + dst += _mouseSurface->pitch; + src += _mouseOrigSurface->pitch; + } - w = _mouseCurState.w; - h = _mouseCurState.h; + SDL_UnlockSurface(_mouseSurface); + SDL_UnlockSurface(_mouseOrigSurface); + return; + } 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; } @@ -2080,75 +2043,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); @@ -2156,13 +2075,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); } @@ -2233,7 +2152,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; } @@ -2242,8 +2161,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,7 +2204,7 @@ void SurfaceSdlGraphicsManager::drawMouse() { // 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. @@ -2332,14 +2253,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 @@ -2376,8 +2297,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; @@ -2390,7 +2311,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) { @@ -2429,7 +2350,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; @@ -2461,7 +2382,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) { @@ -2471,26 +2392,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(); @@ -2502,13 +2427,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 @@ -2529,7 +2454,7 @@ bool SurfaceSdlGraphicsManager::handleScalerHotkeys(Common::KeyCode key) { displayMessageOnOSD(_("Filtering disabled")); } #endif - _forceFull = true; + _forceRedraw = true; internUpdateScreen(); return true; } @@ -2539,12 +2464,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 } } @@ -2582,10 +2514,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; @@ -2697,37 +2638,13 @@ bool SurfaceSdlGraphicsManager::notifyEvent(const Common::Event &event) { } void SurfaceSdlGraphicsManager::notifyVideoExpose() { - _forceFull = true; -} - -void SurfaceSdlGraphicsManager::notifyResize(const uint width, const uint height) { -#if SDL_VERSION_ATLEAST(2, 0, 0) - setWindowResolution(width, height); -#endif + _forceRedraw = true; } -void SurfaceSdlGraphicsManager::transformMouseCoordinates(Common::Point &point) { +void SurfaceSdlGraphicsManager::notifyResize(const int width, const int height) { #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; + handleResize(width, height); #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); } #if SDL_VERSION_ATLEAST(2, 0, 0) @@ -2739,39 +2656,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; @@ -2789,15 +2673,12 @@ 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; } - if (!_window->createOrUpdateWindow(width, height, createWindowFlags)) { + if (!createOrUpdateWindow(width, height, createWindowFlags)) { return nullptr; } @@ -2807,8 +2688,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"); @@ -2830,8 +2711,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 532399ed66..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,18 +171,20 @@ 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; #if SDL_VERSION_ATLEAST(2, 0, 0) /* SDL2 features a different API for 2D graphics. We create a wrapper * 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); @@ -207,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; /** @@ -225,7 +211,6 @@ protected: SDL_Surface *_tmpscreen2; SDL_Surface *_overlayscreen; - bool _overlayVisible; Graphics::PixelFormat _overlayFormat; enum { @@ -238,7 +223,6 @@ protected: bool sizeChanged; bool needHotswap; bool needUpdatescreen; - bool normal1xScaler; #if SDL_VERSION_ATLEAST(2, 0, 0) bool needTextureUpdate; #endif @@ -288,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; @@ -316,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; @@ -334,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; @@ -394,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/midi/coreaudio.cpp b/backends/midi/coreaudio.cpp index 74c590c654..140771960b 100644 --- a/backends/midi/coreaudio.cpp +++ b/backends/midi/coreaudio.cpp @@ -308,7 +308,7 @@ void MidiDriver_CORE::sysEx(const byte *msg, uint16 length) { class CoreAudioMusicPlugin : public MusicPluginObject { public: const char *getName() const { - return "CoreAudio"; + return "Apple DLS Software Synthesizer"; } const char *getId() const { @@ -321,8 +321,6 @@ public: MusicDevices CoreAudioMusicPlugin::getDevices() const { MusicDevices devices; - // TODO: Return a different music type depending on the configuration - // TODO: List the available devices devices.push_back(MusicDevice(this, "", MT_GM)); return devices; } diff --git a/backends/midi/coremidi.cpp b/backends/midi/coremidi.cpp index e2ec8405e9..37d58c5cbd 100644 --- a/backends/midi/coremidi.cpp +++ b/backends/midi/coremidi.cpp @@ -53,7 +53,7 @@ http://lists.apple.com/archives/coreaudio-api/2003/Jul/msg00137.html */ class MidiDriver_CoreMIDI : public MidiDriver_MPU401 { public: - MidiDriver_CoreMIDI(); + MidiDriver_CoreMIDI(ItemCount device); ~MidiDriver_CoreMIDI(); int open(); bool isOpen() const { return mOutPort != 0 && mDest != 0; } @@ -62,13 +62,14 @@ public: void sysEx(const byte *msg, uint16 length); private: + ItemCount mDevice; MIDIClientRef mClient; MIDIPortRef mOutPort; MIDIEndpointRef mDest; }; -MidiDriver_CoreMIDI::MidiDriver_CoreMIDI() - : mClient(0), mOutPort(0), mDest(0) { +MidiDriver_CoreMIDI::MidiDriver_CoreMIDI(ItemCount device) + : mDevice(device), mClient(0), mOutPort(0), mDest(0) { OSStatus err; err = MIDIClientCreate(CFSTR("ScummVM MIDI Driver for OS X"), NULL, NULL, &mClient); @@ -88,9 +89,9 @@ int MidiDriver_CoreMIDI::open() { mOutPort = 0; - int dests = MIDIGetNumberOfDestinations(); - if (dests > 0 && mClient) { - mDest = MIDIGetDestination(0); + ItemCount dests = MIDIGetNumberOfDestinations(); + if (mDevice < dests && mClient) { + mDest = MIDIGetDestination(mDevice); err = MIDIOutputPortCreate( mClient, CFSTR("scummvm_output_port"), &mOutPort); @@ -195,20 +196,59 @@ public: MusicDevices getDevices() const; Common::Error createInstance(MidiDriver **mididriver, MidiDriver::DeviceHandle = 0) const; + +private: + bool getDeviceName(ItemCount deviceIndex, Common::String &outName) const; }; MusicDevices CoreMIDIMusicPlugin::getDevices() const { + // TODO: Is it possible to get the music type for each device? + // Maybe look at the kMIDIPropertyModel property? + MusicDevices devices; - // TODO: Return a different music type depending on the configuration - // TODO: List the available devices - devices.push_back(MusicDevice(this, "", MT_GM)); + ItemCount deviceCount = MIDIGetNumberOfDestinations(); + for (ItemCount i = 0 ; i < deviceCount ; ++i) { + Common::String name; + if (getDeviceName(i, name)) + devices.push_back(MusicDevice(this, name, MT_GM)); + } return devices; } -Common::Error CoreMIDIMusicPlugin::createInstance(MidiDriver **mididriver, MidiDriver::DeviceHandle) const { - *mididriver = new MidiDriver_CoreMIDI(); +Common::Error CoreMIDIMusicPlugin::createInstance(MidiDriver **mididriver, MidiDriver::DeviceHandle device) const { + ItemCount deviceCount = MIDIGetNumberOfDestinations(); + for (ItemCount i = 0 ; i < deviceCount ; ++i) { + Common::String name; + if (getDeviceName(i, name)) { + MusicDevice md(this, name, MT_GM); + if (md.getHandle() == device) { + *mididriver = new MidiDriver_CoreMIDI(i); + return Common::kNoError; + } + } + } + + return Common::kUnknownError; +} - return Common::kNoError; +bool CoreMIDIMusicPlugin::getDeviceName(ItemCount deviceIndex, Common::String &outName) const { + MIDIEndpointRef dest = MIDIGetDestination(deviceIndex); + if (!dest) + return false; + CFStringRef name = nil; + if (MIDIObjectGetStringProperty(dest, kMIDIPropertyDisplayName, &name) == noErr) { + char buffer[128]; + if (CFStringGetCString(name, buffer, sizeof(buffer), kCFStringEncodingASCII)) { + outName = buffer; + CFRelease(name); + return true; + } + CFRelease(name); + } + // Rather than fail use a default name + warning("Failed to get name for CoreMIDi device %lu", deviceIndex); + outName = Common::String::format("Unknown Device %lu", deviceIndex); + return true; } //#if PLUGIN_ENABLED_DYNAMIC(COREMIDI) diff --git a/backends/modular-backend.cpp b/backends/modular-backend.cpp index 1dab18d54e..944ddd5a47 100644 --- a/backends/modular-backend.cpp +++ b/backends/modular-backend.cpp @@ -113,6 +113,10 @@ void ModularBackend::initSize(uint w, uint h, const Graphics::PixelFormat *forma _graphicsManager->initSize(w, h, format); } +void ModularBackend::initSizeHint(const Graphics::ModeList &modes) { + _graphicsManager->initSizeHint(modes); +} + int ModularBackend::getScreenChangeID() const { return _graphicsManager->getScreenChangeID(); } @@ -213,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/modular-backend.h b/backends/modular-backend.h index d828c2dde6..982dbbfb02 100644 --- a/backends/modular-backend.h +++ b/backends/modular-backend.h @@ -75,6 +75,7 @@ public: virtual Common::List<Graphics::PixelFormat> getSupportedFormats() const; #endif virtual void initSize(uint width, uint height, const Graphics::PixelFormat *format = NULL); + virtual void initSizeHint(const Graphics::ModeList &modes) override; virtual int getScreenChangeID() const; virtual void beginGFXTransaction(); diff --git a/backends/module.mk b/backends/module.mk index 5d8c91253f..f7d6ad21dc 100644 --- a/backends/module.mk +++ b/backends/module.mk @@ -210,6 +210,12 @@ MODULE_OBJS += \ midi/camd.o endif +ifdef RISCOS +MODULE_OBJS += \ + fs/riscos/riscos-fs.o \ + fs/riscos/riscos-fs-factory.o +endif + ifdef PLAYSTATION3 MODULE_OBJS += \ fs/posix/posix-fs.o \ diff --git a/backends/platform/3ds/osystem-graphics.cpp b/backends/platform/3ds/osystem-graphics.cpp index 78b7907fe6..e791dd4c21 100644 --- a/backends/platform/3ds/osystem-graphics.cpp +++ b/backends/platform/3ds/osystem-graphics.cpp @@ -230,7 +230,7 @@ void OSystem_3DS::setPalette(const byte *colors, uint start, uint num) { flushGameScreen(); } } -void OSystem_3DS::grabPalette(byte *colors, uint start, uint num) { +void OSystem_3DS::grabPalette(byte *colors, uint start, uint num) const { assert(start + num <= 256); memcpy(colors, _palette + 3 * start, 3 * num); } diff --git a/backends/platform/3ds/osystem.h b/backends/platform/3ds/osystem.h index 5df49fe593..cad46a18dc 100644 --- a/backends/platform/3ds/osystem.h +++ b/backends/platform/3ds/osystem.h @@ -105,7 +105,7 @@ public: int16 getHeight(){ return _gameHeight; } int16 getWidth(){ return _gameWidth; } void setPalette(const byte *colors, uint start, uint num); - void grabPalette(byte *colors, uint start, uint num); + void grabPalette(byte *colors, uint start, uint num) const; void copyRectToScreen(const void *buf, int pitch, int x, int y, int w, int h); Graphics::Surface *lockScreen(); diff --git a/backends/platform/android/android.h b/backends/platform/android/android.h index 2935d96381..c261f85325 100644 --- a/backends/platform/android/android.h +++ b/backends/platform/android/android.h @@ -234,7 +234,7 @@ private: protected: // PaletteManager API virtual void setPalette(const byte *colors, uint start, uint num); - virtual void grabPalette(byte *colors, uint start, uint num); + virtual void grabPalette(byte *colors, uint start, uint num) const; public: virtual void copyRectToScreen(const void *buf, int pitch, int x, int y, diff --git a/backends/platform/android/gfx.cpp b/backends/platform/android/gfx.cpp index f847296892..a4f1746cb7 100644 --- a/backends/platform/android/gfx.cpp +++ b/backends/platform/android/gfx.cpp @@ -408,7 +408,7 @@ void OSystem_Android::setPalette(const byte *colors, uint start, uint num) { WRITE_UINT16(p, pf.RGBToColor(colors[0], colors[1], colors[2])); } -void OSystem_Android::grabPalette(byte *colors, uint start, uint num) { +void OSystem_Android::grabPalette(byte *colors, uint start, uint num) const { ENTER("%p, %u, %u", colors, start, num); #ifdef USE_RGB_COLOR diff --git a/backends/platform/dc/dc.h b/backends/platform/dc/dc.h index 6cd938ec9c..34e8014ed9 100644 --- a/backends/platform/dc/dc.h +++ b/backends/platform/dc/dc.h @@ -106,7 +106,7 @@ class OSystem_Dreamcast : private DCHardware, public EventsBaseBackend, public P protected: // PaletteManager API void setPalette(const byte *colors, uint start, uint num); - void grabPalette(byte *colors, uint start, uint num); + void grabPalette(byte *colors, uint start, uint num) const; public: diff --git a/backends/platform/dc/display.cpp b/backends/platform/dc/display.cpp index 1785c3c416..2547605398 100644 --- a/backends/platform/dc/display.cpp +++ b/backends/platform/dc/display.cpp @@ -171,7 +171,7 @@ void OSystem_Dreamcast::setCursorPalette(const byte *colors, uint start, uint nu _enable_cursor_palette = true; } -void OSystem_Dreamcast::grabPalette(byte *colors, uint start, uint num) +void OSystem_Dreamcast::grabPalette(byte *colors, uint start, uint num) const { const unsigned short *src = palette + start; if (num>0) diff --git a/backends/platform/ds/arm9/source/osystem_ds.cpp b/backends/platform/ds/arm9/source/osystem_ds.cpp index f23192cd9d..861ee2e0c5 100644 --- a/backends/platform/ds/arm9/source/osystem_ds.cpp +++ b/backends/platform/ds/arm9/source/osystem_ds.cpp @@ -268,7 +268,7 @@ void OSystem_DS::setCursorPalette(const byte *colors, uint start, uint num) { refreshCursor(); } -void OSystem_DS::grabPalette(unsigned char *colors, uint start, uint num) { +void OSystem_DS::grabPalette(unsigned char *colors, uint start, uint num) const { // consolePrintf("Grabpalette"); for (unsigned int r = start; r < start + num; r++) { diff --git a/backends/platform/ds/arm9/source/osystem_ds.h b/backends/platform/ds/arm9/source/osystem_ds.h index 9f73e125c2..f883bd14d1 100644 --- a/backends/platform/ds/arm9/source/osystem_ds.h +++ b/backends/platform/ds/arm9/source/osystem_ds.h @@ -93,7 +93,7 @@ public: protected: // PaletteManager API virtual void setPalette(const byte *colors, uint start, uint num); - virtual void grabPalette(byte *colors, uint start, uint num); + virtual void grabPalette(byte *colors, uint start, uint num) const; public: void restoreHardwarePalette(); diff --git a/backends/platform/ios7/ios7_app_delegate.mm b/backends/platform/ios7/ios7_app_delegate.mm index 88d0a8925e..014275d116 100644 --- a/backends/platform/ios7/ios7_app_delegate.mm +++ b/backends/platform/ios7/ios7_app_delegate.mm @@ -39,14 +39,6 @@ return self; } -- (void)mainLoop:(id)param { - @autoreleasepool { - iOS7_main(iOS7_argc, iOS7_argv); - } - - exit(0); -} - - (void)applicationDidFinishLaunching:(UIApplication *)application { CGRect rect = [[UIScreen mainScreen] bounds]; @@ -78,7 +70,12 @@ name:@"UIDeviceOrientationDidChangeNotification" object:nil]; - [NSThread detachNewThreadSelector:@selector(mainLoop:) toTarget:self withObject:nil]; + // Force creation of the shared instance on the main thread + iOS7_buildSharedOSystemInstance(); + + dispatch_async(dispatch_get_global_queue(0, 0), ^{ + iOS7_main(iOS7_argc, iOS7_argv); + }); } - (void)applicationWillResignActive:(UIApplication *)application { diff --git a/backends/platform/ios7/ios7_common.h b/backends/platform/ios7/ios7_common.h index 3609387efd..d5c1135564 100644 --- a/backends/platform/ios7/ios7_common.h +++ b/backends/platform/ios7/ios7_common.h @@ -122,6 +122,7 @@ void iOS7_updateScreen(); bool iOS7_fetchEvent(InternalEvent *event); bool iOS7_isBigDevice(); +void iOS7_buildSharedOSystemInstance(); void iOS7_main(int argc, char **argv); const char *iOS7_getDocumentsDir(); bool iOS7_touchpadModeEnabled(); diff --git a/backends/platform/ios7/ios7_osys_main.cpp b/backends/platform/ios7/ios7_osys_main.cpp index 3a627478f9..90c294a7d5 100644 --- a/backends/platform/ios7/ios7_osys_main.cpp +++ b/backends/platform/ios7/ios7_osys_main.cpp @@ -365,6 +365,10 @@ bool iOS7_touchpadModeEnabled() { return sys && sys->touchpadModeEnabled(); } +void iOS7_buildSharedOSystemInstance() { + OSystem_iOS7::sharedInstance(); +} + void iOS7_main(int argc, char **argv) { //OSystem_iOS7::migrateApp(); diff --git a/backends/platform/ios7/ios7_osys_main.h b/backends/platform/ios7/ios7_osys_main.h index 0f89cf7aa5..e0ac599b1d 100644 --- a/backends/platform/ios7/ios7_osys_main.h +++ b/backends/platform/ios7/ios7_osys_main.h @@ -153,7 +153,7 @@ public: protected: // PaletteManager API virtual void setPalette(const byte *colors, uint start, uint num); - virtual void grabPalette(byte *colors, uint start, uint num); + virtual void grabPalette(byte *colors, uint start, uint num) const; public: virtual void copyRectToScreen(const void *buf, int pitch, int x, int y, int w, int h); diff --git a/backends/platform/ios7/ios7_osys_video.mm b/backends/platform/ios7/ios7_osys_video.mm index 1ec0defd7e..30f8950ec6 100644 --- a/backends/platform/ios7/ios7_osys_video.mm +++ b/backends/platform/ios7/ios7_osys_video.mm @@ -120,6 +120,15 @@ Common::List<Graphics::PixelFormat> OSystem_iOS7::getSupportedFormats() const { } #endif +static inline void execute_on_main_thread(void (^block)(void)) { + if ([NSThread currentThread] == [NSThread mainThread]) { + block(); + } + else { + dispatch_sync(dispatch_get_main_queue(), block); + } +} + void OSystem_iOS7::initSize(uint width, uint height, const Graphics::PixelFormat *format) { //printf("initSize(%u, %u, %p)\n", width, height, (const void *)format); @@ -135,7 +144,9 @@ void OSystem_iOS7::initSize(uint width, uint height, const Graphics::PixelFormat // Create the screen texture right here. We need to do this here, since // when a game requests hi-color mode, we actually set the framebuffer // to the texture buffer to avoid an additional copy step. - [[iOS7AppDelegate iPhoneView] performSelectorOnMainThread:@selector(createScreenTexture) withObject:nil waitUntilDone: YES]; + execute_on_main_thread(^ { + [[iOS7AppDelegate iPhoneView] createScreenTexture]; + }); // In case the client code tries to set up a non supported mode, we will // fall back to CLUT8 and set the transaction error accordingly. @@ -172,13 +183,17 @@ void OSystem_iOS7::beginGFXTransaction() { OSystem::TransactionError OSystem_iOS7::endGFXTransaction() { _screenChangeCount++; updateOutputSurface(); - [[iOS7AppDelegate iPhoneView] performSelectorOnMainThread:@selector(setGraphicsMode) withObject:nil waitUntilDone: YES]; + execute_on_main_thread(^ { + [[iOS7AppDelegate iPhoneView] setGraphicsMode]; + }); return _gfxTransactionError; } void OSystem_iOS7::updateOutputSurface() { - [[iOS7AppDelegate iPhoneView] performSelectorOnMainThread:@selector(initSurface) withObject:nil waitUntilDone: YES]; + execute_on_main_thread(^ { + [[iOS7AppDelegate iPhoneView] initSurface]; + }); } int16 OSystem_iOS7::getHeight() { @@ -208,7 +223,7 @@ void OSystem_iOS7::setPalette(const byte *colors, uint start, uint num) { _mouseDirty = _mouseNeedTextureUpdate = true; } -void OSystem_iOS7::grabPalette(byte *colors, uint start, uint num) { +void OSystem_iOS7::grabPalette(byte *colors, uint start, uint num) const { //printf("grabPalette(%p, %u, %u)\n", colors, start, num); assert(start + num <= 256); byte *b = colors; @@ -338,7 +353,9 @@ void OSystem_iOS7::unlockScreen() { void OSystem_iOS7::setShakePos(int shakeOffset) { //printf("setShakePos(%i)\n", shakeOffset); _videoContext->shakeOffsetY = shakeOffset; - [[iOS7AppDelegate iPhoneView] performSelectorOnMainThread:@selector(setViewTransformation) withObject:nil waitUntilDone: YES]; + execute_on_main_thread(^ { + [[iOS7AppDelegate iPhoneView] setViewTransformation]; + }); // HACK: We use this to force a redraw. _mouseDirty = true; } @@ -348,8 +365,10 @@ void OSystem_iOS7::showOverlay() { _videoContext->overlayVisible = true; dirtyFullOverlayScreen(); updateScreen(); - [[iOS7AppDelegate iPhoneView] performSelectorOnMainThread:@selector(updateMouseCursorScaling) withObject:nil waitUntilDone: YES]; - [[iOS7AppDelegate iPhoneView] performSelectorOnMainThread:@selector(clearColorBuffer) withObject:nil waitUntilDone: YES]; + execute_on_main_thread(^ { + [[iOS7AppDelegate iPhoneView] updateMouseCursorScaling]; + [[iOS7AppDelegate iPhoneView] clearColorBuffer]; + }); } void OSystem_iOS7::hideOverlay() { @@ -357,8 +376,10 @@ void OSystem_iOS7::hideOverlay() { _videoContext->overlayVisible = false; _dirtyOverlayRects.clear(); dirtyFullScreen(); - [[iOS7AppDelegate iPhoneView] performSelectorOnMainThread:@selector(updateMouseCursorScaling) withObject:nil waitUntilDone: YES]; - [[iOS7AppDelegate iPhoneView] performSelectorOnMainThread:@selector(clearColorBuffer) withObject:nil waitUntilDone: YES]; + execute_on_main_thread(^ { + [[iOS7AppDelegate iPhoneView] updateMouseCursorScaling]; + [[iOS7AppDelegate iPhoneView] clearColorBuffer]; + }); } void OSystem_iOS7::clearOverlay() { @@ -439,7 +460,9 @@ void OSystem_iOS7::warpMouse(int x, int y) { //printf("warpMouse(%d, %d)\n", x, y); _videoContext->mouseX = x; _videoContext->mouseY = y; - [[iOS7AppDelegate iPhoneView] performSelectorOnMainThread:@selector(notifyMouseMove) withObject:nil waitUntilDone: YES]; + execute_on_main_thread(^ { + [[iOS7AppDelegate iPhoneView] notifyMouseMove]; + }); _mouseDirty = true; } @@ -552,5 +575,7 @@ void OSystem_iOS7::updateMouseTexture() { } } - [[iOS7AppDelegate iPhoneView] performSelectorOnMainThread:@selector(updateMouseCursor) withObject:nil waitUntilDone: YES]; + execute_on_main_thread(^ { + [[iOS7AppDelegate iPhoneView] updateMouseCursor]; + }); } diff --git a/backends/platform/ios7/ios7_video.mm b/backends/platform/ios7/ios7_video.mm index 5baa83e8e8..85a4dc91d8 100644 --- a/backends/platform/ios7/ios7_video.mm +++ b/backends/platform/ios7/ios7_video.mm @@ -55,16 +55,31 @@ bool iOS7_isBigDevice() { return UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad; } +static inline void execute_on_main_thread(void (^block)(void)) { + if ([NSThread currentThread] == [NSThread mainThread]) { + block(); + } + else { + dispatch_sync(dispatch_get_main_queue(), block); + } +} + void iOS7_updateScreen() { //printf("Mouse: (%i, %i)\n", mouseX, mouseY); if (!g_needsScreenUpdate) { g_needsScreenUpdate = 1; - [[iOS7AppDelegate iPhoneView] performSelectorOnMainThread:@selector(updateSurface) withObject:nil waitUntilDone: NO]; + execute_on_main_thread(^{ + [[iOS7AppDelegate iPhoneView] updateSurface]; + }); } } bool iOS7_fetchEvent(InternalEvent *event) { - return [[iOS7AppDelegate iPhoneView] fetchEvent:event]; + __block bool fetched; + execute_on_main_thread(^{ + fetched = [[iOS7AppDelegate iPhoneView] fetchEvent:event]; + }); + return fetched; } uint getSizeNextPOT(uint size) { diff --git a/backends/platform/iphone/osys_main.h b/backends/platform/iphone/osys_main.h index 390566322c..6aa77e291d 100644 --- a/backends/platform/iphone/osys_main.h +++ b/backends/platform/iphone/osys_main.h @@ -140,7 +140,7 @@ public: protected: // PaletteManager API virtual void setPalette(const byte *colors, uint start, uint num); - virtual void grabPalette(byte *colors, uint start, uint num); + virtual void grabPalette(byte *colors, uint start, uint num) const; public: virtual void copyRectToScreen(const void *buf, int pitch, int x, int y, int w, int h); diff --git a/backends/platform/iphone/osys_video.mm b/backends/platform/iphone/osys_video.mm index fa5c729a1c..f07160d350 100644 --- a/backends/platform/iphone/osys_video.mm +++ b/backends/platform/iphone/osys_video.mm @@ -155,7 +155,7 @@ void OSystem_IPHONE::setPalette(const byte *colors, uint start, uint num) { _mouseDirty = _mouseNeedTextureUpdate = true; } -void OSystem_IPHONE::grabPalette(byte *colors, uint start, uint num) { +void OSystem_IPHONE::grabPalette(byte *colors, uint start, uint num) const { //printf("grabPalette(%p, %u, %u)\n", colors, start, num); assert(start + num <= 256); byte *b = colors; diff --git a/backends/platform/n64/osys_n64.h b/backends/platform/n64/osys_n64.h index ad49c2981f..80bedbb5ab 100644 --- a/backends/platform/n64/osys_n64.h +++ b/backends/platform/n64/osys_n64.h @@ -157,7 +157,7 @@ public: protected: // PaletteManager API virtual void setPalette(const byte *colors, uint start, uint num); - virtual void grabPalette(byte *colors, uint start, uint num); + virtual void grabPalette(byte *colors, uint start, uint num) const; public: virtual void copyRectToScreen(const void *buf, int pitch, int x, int y, int w, int h); diff --git a/backends/platform/n64/osys_n64_base.cpp b/backends/platform/n64/osys_n64_base.cpp index 16eeae5b7e..1282b16d47 100644 --- a/backends/platform/n64/osys_n64_base.cpp +++ b/backends/platform/n64/osys_n64_base.cpp @@ -408,7 +408,7 @@ void OSystem_N64::rebuildOffscreenMouseBuffer(void) { } } -void OSystem_N64::grabPalette(byte *colors, uint start, uint num) { +void OSystem_N64::grabPalette(byte *colors, uint start, uint num) const { #ifdef N64_EXTREME_MEMORY_SAVING // This way loses precisions uint32 i; uint16 color; diff --git a/backends/platform/ps2/Gs2dScreen.cpp b/backends/platform/ps2/Gs2dScreen.cpp index a4ec23329a..823defe8b4 100644 --- a/backends/platform/ps2/Gs2dScreen.cpp +++ b/backends/platform/ps2/Gs2dScreen.cpp @@ -556,7 +556,7 @@ void Gs2dScreen::setPalette(const uint8 *pal, uint8 start, uint16 num) { SignalSema(g_DmacSema); } -void Gs2dScreen::grabPalette(uint8 *pal, uint8 start, uint16 num) { +void Gs2dScreen::grabPalette(uint8 *pal, uint8 start, uint16 num) const { assert(start + num <= 256); for (uint16 cnt = 0; cnt < num; cnt++) { uint16 src = start + cnt; diff --git a/backends/platform/ps2/Gs2dScreen.h b/backends/platform/ps2/Gs2dScreen.h index ea2b1e5f78..9ed62da2d0 100644 --- a/backends/platform/ps2/Gs2dScreen.h +++ b/backends/platform/ps2/Gs2dScreen.h @@ -61,7 +61,7 @@ public: void copyScreenRect(const uint8 *buf, int pitch, int x, int y, int w, int h); void setPalette(const uint8 *pal, uint8 start, uint16 num); void updateScreen(void); - void grabPalette(uint8 *pal, uint8 start, uint16 num); + void grabPalette(uint8 *pal, uint8 start, uint16 num) const; //- overlay routines void copyOverlayRect(const byte *buf, uint16 pitch, uint16 x, uint16 y, uint16 w, uint16 h); void grabOverlay(byte *buf, uint16 pitch); diff --git a/backends/platform/ps2/systemps2.cpp b/backends/platform/ps2/systemps2.cpp index e914cdb9c9..f76e26a543 100644 --- a/backends/platform/ps2/systemps2.cpp +++ b/backends/platform/ps2/systemps2.cpp @@ -678,7 +678,7 @@ void OSystem_PS2::setPalette(const byte *colors, uint start, uint num) { _screen->setPalette(colors, (uint8)start, (uint16)num); } -void OSystem_PS2::grabPalette(byte *colors, uint start, uint num) { +void OSystem_PS2::grabPalette(byte *colors, uint start, uint num) const { _screen->grabPalette(colors, (uint8)start, (uint16)num); } diff --git a/backends/platform/ps2/systemps2.h b/backends/platform/ps2/systemps2.h index 45b7dfae36..019c3634a0 100644 --- a/backends/platform/ps2/systemps2.h +++ b/backends/platform/ps2/systemps2.h @@ -61,7 +61,7 @@ public: protected: // PaletteManager API virtual void setPalette(const byte *colors, uint start, uint num); - virtual void grabPalette(byte *colors, uint start, uint num); + virtual void grabPalette(byte *colors, uint start, uint num) const; public: virtual void copyRectToScreen(const void *buf, int pitch, int x, int y, int w, int h); diff --git a/backends/platform/psp/default_display_client.h b/backends/platform/psp/default_display_client.h index d46b7f1a8a..f2972e0b49 100644 --- a/backends/platform/psp/default_display_client.h +++ b/backends/platform/psp/default_display_client.h @@ -40,10 +40,10 @@ public: void clearBuffer(); void clearPalette(); void render() { _renderer.render(); } - uint32 getWidth() { return _buffer.getSourceWidth(); } - uint32 getHeight() { return _buffer.getSourceHeight(); } + uint32 getWidth() const { return _buffer.getSourceWidth(); } + uint32 getHeight() const { return _buffer.getSourceHeight(); } void setPartialPalette(const byte *colors, uint start, uint num) { setDirty(); return _palette.setPartial(colors, start, num); } - void getPartialPalette(byte *colors, uint start, uint num) { + void getPartialPalette(byte *colors, uint start, uint num) const { return _palette.getPartial(colors, start, num); } void copyFromRect(const byte *buf, int pitch, int destX, int destY, int recWidth, int recHeight); diff --git a/backends/platform/psp/display_client.cpp b/backends/platform/psp/display_client.cpp index b238631e62..6e1ae9a10a 100644 --- a/backends/platform/psp/display_client.cpp +++ b/backends/platform/psp/display_client.cpp @@ -204,7 +204,7 @@ void Palette::deallocate() { // Copy some of the palette to an array of colors // -void Palette::getPartial(byte *colors, uint start, uint num) { +void Palette::getPartial(byte *colors, uint start, uint num) const { DEBUG_ENTER_FUNC(); assert(_values); @@ -286,13 +286,13 @@ void Palette::print(uint32 numToPrint /* = 0 */) { } } -uint32 Palette::getRawColorAt(uint32 position) { +uint32 Palette::getRawColorAt(uint32 position) const { byte *pcolor = &_values[_pixelFormat.pixelsToBytes(position)]; uint32 color = _pixelFormat.getColorValueAt(pcolor); return color; } -uint32 Palette::getRGBAColorAt(uint32 position) { +uint32 Palette::getRGBAColorAt(uint32 position) const { uint32 color = getRawColorAt(position); uint32 r, g, b, a; _pixelFormat.colorToRgba(color, r, g, b, a); diff --git a/backends/platform/psp/display_client.h b/backends/platform/psp/display_client.h index 5e81947e20..a25d9f9ecc 100644 --- a/backends/platform/psp/display_client.h +++ b/backends/platform/psp/display_client.h @@ -85,18 +85,19 @@ public: void clear(); void setPixelFormats(PSPPixelFormat::Type paletteType, PSPPixelFormat::Type bufferType, bool swapRedBlue = false); void setNumOfEntries(uint32 num) { _numOfEntries = num; } - uint32 getNumOfEntries() { return _numOfEntries; } - uint32 getSizeInBytes() { return _pixelFormat.pixelsToBytes(_numOfEntries); } + uint32 getNumOfEntries() const { return _numOfEntries; } + uint32 getSizeInBytes() const { return _pixelFormat.pixelsToBytes(_numOfEntries); } void set(byte *values) { setPartial(values, 0, _numOfEntries); } void setPartial(const byte *colors, uint start, uint num, bool supportsAlpha = false); - void getPartial(byte *colors, uint start, uint num); - uint32 getRawColorAt(uint32 position); - uint32 getRGBAColorAt(uint32 position); + void getPartial(byte *colors, uint start, uint num) const; + uint32 getRawColorAt(uint32 position) const; + uint32 getRGBAColorAt(uint32 position) const; void setSingleColorRGBA(uint32 num, byte r, byte g, byte b, byte a); void setColorPositionAlpha(uint32 position, bool alpha); + const byte *getRawValues() const { return _values; } byte *getRawValues() { return _values; } - bool isAllocated() { return (_values != 0); } - PSPPixelFormat::Type getPixelFormat() { return _pixelFormat.format; } + bool isAllocated() const { return (_values != 0); } + PSPPixelFormat::Type getPixelFormat() const { return _pixelFormat.format; } void print(uint32 numToPrint = 0); // print to screen protected: @@ -127,19 +128,20 @@ public: void setPixelFormat(PSPPixelFormat::Type type, bool swapRedBlue = false); // getters - uint32 getWidth() { return _width; } - uint32 getWidthInBytes() { return _pixelFormat.pixelsToBytes(getWidth()); } - uint32 getHeight() { return _height; } - uint32 getSourceWidth() { return _sourceSize.width; } - uint32 getSourceWidthInBytes() { return _pixelFormat.pixelsToBytes(_sourceSize.width); } - uint32 getSourceHeight() { return _sourceSize.height; } - uint32 getTextureWidth() { return _textureSize.width; } - uint32 getTextureHeight() { return _textureSize.height; } - PSPPixelFormat::Type getPixelFormat() { return _pixelFormat.format; } - uint32 getBitsPerPixel() { return _pixelFormat.bitsPerPixel; } - uint32 getBytesPerPixel() { return getBitsPerPixel() >> 3; } /* won't work for 4-bit */ + uint32 getWidth() const { return _width; } + uint32 getWidthInBytes() const { return _pixelFormat.pixelsToBytes(getWidth()); } + uint32 getHeight() const { return _height; } + uint32 getSourceWidth() const { return _sourceSize.width; } + uint32 getSourceWidthInBytes() const { return _pixelFormat.pixelsToBytes(_sourceSize.width); } + uint32 getSourceHeight() const { return _sourceSize.height; } + uint32 getTextureWidth() const { return _textureSize.width; } + uint32 getTextureHeight() const { return _textureSize.height; } + PSPPixelFormat::Type getPixelFormat() const { return _pixelFormat.format; } + uint32 getBitsPerPixel() const { return _pixelFormat.bitsPerPixel; } + uint32 getBytesPerPixel() const { return getBitsPerPixel() >> 3; } /* won't work for 4-bit */ + const byte *getPixels() const { return _pixels; } byte *getPixels() { return _pixels; } - uint32 getSizeInBytes() { return _pixelFormat.pixelsToBytes(_width * _height); } + uint32 getSizeInBytes() const { return _pixelFormat.pixelsToBytes(_width * _height); } bool hasPalette(); void copyFromArray(const byte *buffer, int pitch); @@ -147,7 +149,7 @@ public: void copyToArray(byte *dst, int pitch); bool allocate(bool inVram = false); void deallocate(); - bool isAllocated() { return (_pixels != 0) ; } + bool isAllocated() const { return (_pixels != 0) ; } void clear(); void flipNibbles(); // To handle peculiarities of PSP's 4 bit textures static uint32 scaleUpToPowerOfTwo(uint32 size); diff --git a/backends/platform/psp/osys_psp.cpp b/backends/platform/psp/osys_psp.cpp index 67cb72d9d4..e31456fb70 100644 --- a/backends/platform/psp/osys_psp.cpp +++ b/backends/platform/psp/osys_psp.cpp @@ -280,7 +280,7 @@ int16 OSystem_PSP::getOverlayHeight() { return (int16)_overlay.getHeight(); } -void OSystem_PSP::grabPalette(byte *colors, uint start, uint num) { +void OSystem_PSP::grabPalette(byte *colors, uint start, uint num) const { DEBUG_ENTER_FUNC(); _screen.getPartialPalette(colors, start, num); } diff --git a/backends/platform/psp/osys_psp.h b/backends/platform/psp/osys_psp.h index 6f9238b84e..304c724aaa 100644 --- a/backends/platform/psp/osys_psp.h +++ b/backends/platform/psp/osys_psp.h @@ -94,7 +94,7 @@ public: protected: // PaletteManager API void setPalette(const byte *colors, uint start, uint num); - void grabPalette(byte *colors, uint start, uint num); + void grabPalette(byte *colors, uint start, uint num) const; public: void setCursorPalette(const byte *colors, uint start, uint num); diff --git a/backends/platform/psp/psppixelformat.cpp b/backends/platform/psp/psppixelformat.cpp index 2d7d524b45..83f5935eee 100644 --- a/backends/platform/psp/psppixelformat.cpp +++ b/backends/platform/psp/psppixelformat.cpp @@ -173,7 +173,7 @@ Graphics::PixelFormat PSPPixelFormat::convertToScummvmPixelFormat(PSPPixelFormat return pf; } -uint32 PSPPixelFormat::convertTo32BitColor(uint32 color) { +uint32 PSPPixelFormat::convertTo32BitColor(uint32 color) const { DEBUG_ENTER_FUNC(); uint32 r, g, b, a, output; diff --git a/backends/platform/psp/psppixelformat.h b/backends/platform/psp/psppixelformat.h index ede5a97d6f..3cb3b8fcae 100644 --- a/backends/platform/psp/psppixelformat.h +++ b/backends/platform/psp/psppixelformat.h @@ -55,9 +55,9 @@ struct PSPPixelFormat { PSPPixelFormat::Type &paletteType, bool &swapRedBlue); static Graphics::PixelFormat convertToScummvmPixelFormat(PSPPixelFormat::Type type); - uint32 convertTo32BitColor(uint32 color); + uint32 convertTo32BitColor(uint32 color) const; - inline uint32 rgbaToColor(uint32 r, uint32 g, uint32 b, uint32 a) { + inline uint32 rgbaToColor(uint32 r, uint32 g, uint32 b, uint32 a) const { uint32 color; switch (format) { @@ -80,7 +80,7 @@ struct PSPPixelFormat { return color; } - inline void colorToRgba(uint32 color, uint32 &r, uint32 &g, uint32 &b, uint32 &a) { + inline void colorToRgba(uint32 color, uint32 &r, uint32 &g, uint32 &b, uint32 &a) const { switch (format) { case Type_4444: a = (color >> 12) & 0xF; // Interpolate to get true colors @@ -140,7 +140,7 @@ struct PSPPixelFormat { return color; } - inline uint32 pixelsToBytes(uint32 pixels) { + inline uint32 pixelsToBytes(uint32 pixels) const { switch (bitsPerPixel) { case 4: pixels >>= 1; @@ -160,7 +160,7 @@ struct PSPPixelFormat { return pixels; } - inline uint16 swapRedBlue16(uint16 color) { + inline uint16 swapRedBlue16(uint16 color) const { uint16 output; switch (format) { @@ -181,7 +181,7 @@ struct PSPPixelFormat { return output; } - inline uint32 swapRedBlue32(uint32 color) { + inline uint32 swapRedBlue32(uint32 color) const { uint32 output; switch (format) { @@ -211,7 +211,7 @@ struct PSPPixelFormat { } // Return whatever color we point at - inline uint32 getColorValueAt(byte *pointer) { + inline uint32 getColorValueAt(byte *pointer) const { uint32 result; switch (bitsPerPixel) { diff --git a/backends/platform/sdl/riscos/riscos.cpp b/backends/platform/sdl/riscos/riscos.cpp index 08609396f1..0cdbceb902 100644 --- a/backends/platform/sdl/riscos/riscos.cpp +++ b/backends/platform/sdl/riscos/riscos.cpp @@ -20,16 +20,14 @@ * */ -#define FORBIDDEN_SYMBOL_EXCEPTION_unistd_h - #include "common/scummsys.h" #ifdef RISCOS #include "backends/platform/sdl/riscos/riscos.h" #include "backends/saves/default/default-saves.h" -#include "backends/fs/posix/posix-fs-factory.h" -#include "backends/fs/posix/posix-fs.h" +#include "backends/fs/riscos/riscos-fs-factory.h" +#include "backends/fs/riscos/riscos-fs.h" #include <kernel.h> #include <swis.h> @@ -40,7 +38,7 @@ void OSystem_RISCOS::init() { // Initialze File System Factory - _fsFactory = new POSIXFilesystemFactory(); + _fsFactory = new RISCOSFilesystemFactory(); // Invoke parent implementation of this method OSystem_SDL::init(); @@ -50,7 +48,7 @@ void OSystem_RISCOS::initBackend() { // Create the savefile manager if (_savefileManager == 0) { Common::String savePath = "/<Choices$Write>/ScummVM/Saves"; - if (Posix::assureDirectoryExists(savePath)) + if (Riscos::assureDirectoryExists(savePath)) _savefileManager = new DefaultSaveFileManager(savePath); } @@ -89,7 +87,7 @@ Common::WriteStream *OSystem_RISCOS::createLogFile() { Common::String logFile = "/<Choices$Write>/ScummVM/Logs"; - if (!Posix::assureDirectoryExists(logFile)) { + if (!Riscos::assureDirectoryExists(logFile)) { return 0; } diff --git a/backends/platform/sdl/sdl-window.cpp b/backends/platform/sdl/sdl-window.cpp index 07ddc998ba..b38a97c5ef 100644 --- a/backends/platform/sdl/sdl-window.cpp +++ b/backends/platform/sdl/sdl-window.cpp @@ -129,14 +129,16 @@ void SdlWindow::setWindowCaption(const Common::String &caption) { void SdlWindow::toggleMouseGrab() { #if SDL_VERSION_ATLEAST(2, 0, 0) if (_window) { - _inputGrabState = !(SDL_GetWindowGrab(_window) == SDL_TRUE); + _inputGrabState = SDL_GetWindowGrab(_window) == SDL_FALSE; SDL_SetWindowGrab(_window, _inputGrabState ? SDL_TRUE : SDL_FALSE); } #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() { @@ -223,6 +231,33 @@ bool SdlWindow::createOrUpdateWindow(int width, int height, uint32 flags) { const uint32 oldNonUpdateableFlags = _lastFlags & ~updateableFlagsMask; const uint32 newNonUpdateableFlags = flags & ~updateableFlagsMask; + const uint32 fullscreenFlags = flags & fullscreenMask; + + // This is terrible, but there is no way in SDL to get information on the + // maximum bounds of a window with decoration, and SDL is too dumb to make + // sure the window's surface doesn't grow beyond the display bounds, which + // can easily happen with 3x scalers. There is a function in SDL to get the + // window decoration size, but it only exists starting in SDL 2.0.5, which + // is a buggy release on some platforms so we can't safely use 2.0.5+ + // features since some users replace the SDL dynamic library with 2.0.4, and + // the documentation says it only works on X11 anyway, which means it is + // basically worthless. So we'll just try to keep things closeish to the + // maximum for now. + SDL_DisplayMode displayMode; + SDL_GetDesktopDisplayMode(0, &displayMode); + if (!fullscreenFlags) { + displayMode.w -= 20; + displayMode.h -= 30; + } + + if (width > displayMode.w) { + width = displayMode.w; + } + + if (height > displayMode.h) { + height = displayMode.h; + } + if (!_window || oldNonUpdateableFlags != newNonUpdateableFlags) { destroyWindow(); _window = SDL_CreateWindow(_windowCaption.c_str(), _lastX, @@ -231,8 +266,6 @@ bool SdlWindow::createOrUpdateWindow(int width, int height, uint32 flags) { setupIcon(); } } else { - const uint32 fullscreenFlags = flags & fullscreenMask; - if (fullscreenFlags) { SDL_DisplayMode fullscreenMode; fullscreenMode.w = width; @@ -246,7 +279,8 @@ bool SdlWindow::createOrUpdateWindow(int width, int height, uint32 flags) { } SDL_SetWindowFullscreen(_window, fullscreenFlags); - SDL_SetWindowGrab(_window, (flags & SDL_WINDOW_INPUT_GRABBED) ? SDL_TRUE : SDL_FALSE); + const bool shouldGrab = (flags & SDL_WINDOW_INPUT_GRABBED) | fullscreenFlags; + SDL_SetWindowGrab(_window, shouldGrab ? SDL_TRUE : SDL_FALSE); } if (!_window) { diff --git a/backends/platform/sdl/sdl-window.h b/backends/platform/sdl/sdl-window.h index d75e811f56..05893c47d3 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,18 @@ public: */ bool getSDLWMInformation(SDL_SysWMinfo *info) const; + bool mouseIsGrabbed() const { +#if SDL_VERSION_ATLEAST(2, 0, 0) + if (_window) { + return SDL_GetWindowGrab(_window) == SDL_TRUE; + } +#endif + return _inputGrabState; + } + +private: + bool _inputGrabState; + #if SDL_VERSION_ATLEAST(2, 0, 0) public: /** @@ -108,7 +123,6 @@ private: */ int _lastX, _lastY; - bool _inputGrabState; Common::String _windowCaption; #endif }; diff --git a/backends/platform/sdl/sdl.cpp b/backends/platform/sdl/sdl.cpp index bbd5c89f80..f44d87666a 100644 --- a/backends/platform/sdl/sdl.cpp +++ b/backends/platform/sdl/sdl.cpp @@ -297,20 +297,28 @@ void OSystem_SDL::initBackend() { dynamic_cast<SdlGraphicsManager *>(_graphicsManager)->activateManager(); } -#if defined(USE_TASKBAR) void OSystem_SDL::engineInit() { +#if SDL_VERSION_ATLEAST(2, 0, 0) + dynamic_cast<SdlGraphicsManager *>(_graphicsManager)->unlockWindowSize(); +#endif +#ifdef USE_TASKBAR // Add the started engine to the list of recent tasks _taskbarManager->addRecent(ConfMan.getActiveDomainName(), ConfMan.get("description")); // Set the overlay icon the current running engine _taskbarManager->setOverlayIcon(ConfMan.getActiveDomainName(), ConfMan.get("description")); +#endif } void OSystem_SDL::engineDone() { +#if SDL_VERSION_ATLEAST(2, 0, 0) + dynamic_cast<SdlGraphicsManager *>(_graphicsManager)->unlockWindowSize(); +#endif +#ifdef USE_TASKBAR // Remove overlay icon _taskbarManager->setOverlayIcon("", ""); -} #endif +} void OSystem_SDL::initSDL() { // Check if SDL has not been initialized diff --git a/backends/platform/sdl/sdl.h b/backends/platform/sdl/sdl.h index bc4292be0b..61513fa65f 100644 --- a/backends/platform/sdl/sdl.h +++ b/backends/platform/sdl/sdl.h @@ -59,10 +59,8 @@ public: // Override functions from ModularBackend and OSystem virtual void initBackend(); -#if defined(USE_TASKBAR) virtual void engineInit(); virtual void engineDone(); -#endif virtual void quit(); virtual void fatalError(); diff --git a/backends/platform/wii/osystem.h b/backends/platform/wii/osystem.h index f1591614bf..5482eb7d49 100644 --- a/backends/platform/wii/osystem.h +++ b/backends/platform/wii/osystem.h @@ -165,7 +165,7 @@ public: virtual PaletteManager *getPaletteManager() { return this; } protected: virtual void setPalette(const byte *colors, uint start, uint num); - virtual void grabPalette(byte *colors, uint start, uint num); + virtual void grabPalette(byte *colors, uint start, uint num) const; public: virtual void setCursorPalette(const byte *colors, uint start, uint num); virtual void copyRectToScreen(const void *buf, int pitch, int x, int y, diff --git a/backends/platform/wii/osystem_gfx.cpp b/backends/platform/wii/osystem_gfx.cpp index c7989e95ad..932ca3814c 100644 --- a/backends/platform/wii/osystem_gfx.cpp +++ b/backends/platform/wii/osystem_gfx.cpp @@ -352,7 +352,7 @@ void OSystem_Wii::setPalette(const byte *colors, uint start, uint num) { } } -void OSystem_Wii::grabPalette(byte *colors, uint start, uint num) { +void OSystem_Wii::grabPalette(byte *colors, uint start, uint num) const { #ifdef USE_RGB_COLOR assert(_pfGame.bytesPerPixel == 1); #endif |
