GRAPHICS: MACGUI: Add WM direct copy mode
This does not keep the current screen state cached in a surface, but re-creates the screen from its various components each time something changes. This avoids an intermediate blitting. The mode is enabled just by not providing a surface to the WM, and instead providing a width and height.
This commit is contained in:
parent
59dd1716b1
commit
a639ae4002
5 changed files with 103 additions and 24 deletions
|
@ -52,6 +52,10 @@ public:
|
||||||
MacMenu(int id, const Common::Rect &bounds, MacWindowManager *wm);
|
MacMenu(int id, const Common::Rect &bounds, MacWindowManager *wm);
|
||||||
~MacMenu();
|
~MacMenu();
|
||||||
|
|
||||||
|
virtual ManagedSurface *getBorderSurface() override { return nullptr; }
|
||||||
|
virtual const Common::Rect &getInnerDimensions() override { return _dims; }
|
||||||
|
virtual bool isDirty() override { return _contentIsDirty || _dimensionsDirty; }
|
||||||
|
|
||||||
static Common::StringArray *readMenuFromResource(Common::SeekableReadStream *res);
|
static Common::StringArray *readMenuFromResource(Common::SeekableReadStream *res);
|
||||||
static MacMenu *createMenuFromPEexe(Common::PEResources *exe, MacWindowManager *wm);
|
static MacMenu *createMenuFromPEexe(Common::PEResources *exe, MacWindowManager *wm);
|
||||||
|
|
||||||
|
|
|
@ -191,7 +191,7 @@ void MacWindow::center(bool toCenter) {
|
||||||
if (!_wm)
|
if (!_wm)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Common::Rect screen = _wm->_screen->getBounds();
|
Common::Rect screen = _wm->getScreenBounds();
|
||||||
|
|
||||||
if (toCenter) {
|
if (toCenter) {
|
||||||
move((screen.width() - _dims.width()) / 2, (screen.height() - _dims.height()) / 2);
|
move((screen.width() - _dims.width()) / 2, (screen.height() - _dims.height()) / 2);
|
||||||
|
|
|
@ -115,6 +115,28 @@ public:
|
||||||
*/
|
*/
|
||||||
ManagedSurface *getWindowSurface() { return _composeSurface; }
|
ManagedSurface *getWindowSurface() { return _composeSurface; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Method to access the border surface of the window.
|
||||||
|
* @return A pointer to the border surface of the window.
|
||||||
|
*/
|
||||||
|
virtual ManagedSurface *getBorderSurface() = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Accessor to retrieve the dimensions of the inner surface of the window
|
||||||
|
* (i.e. without taking borders into account).
|
||||||
|
* Note that the returned dimensions' position is relative to the WM's
|
||||||
|
* screen, just like in getDimensions().
|
||||||
|
* @return The inner dimensions of the window.
|
||||||
|
*/
|
||||||
|
virtual const Common::Rect &getInnerDimensions() = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Method called to internally draw the window. This relies on the window
|
||||||
|
* being marked as dirty unless otherwise specified.
|
||||||
|
* @param forceRedraw Its behavior depends on the subclass.
|
||||||
|
*/
|
||||||
|
virtual bool draw(bool forceRedraw = false) = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Method called to draw the window into the target surface.
|
* Method called to draw the window into the target surface.
|
||||||
* This method is most often called by the WM, and relies on
|
* This method is most often called by the WM, and relies on
|
||||||
|
@ -133,6 +155,11 @@ public:
|
||||||
*/
|
*/
|
||||||
virtual bool processEvent(Common::Event &event) = 0;
|
virtual bool processEvent(Common::Event &event) = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Method that checks if the window is needs redrawing.
|
||||||
|
*/
|
||||||
|
virtual bool isDirty() = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the callback that will be used when an event needs to be processed.
|
* Set the callback that will be used when an event needs to be processed.
|
||||||
* @param callback A function pointer to a function that accepts:
|
* @param callback A function pointer to a function that accepts:
|
||||||
|
@ -196,15 +223,6 @@ public:
|
||||||
*/
|
*/
|
||||||
virtual void setDimensions(const Common::Rect &r) override;
|
virtual void setDimensions(const Common::Rect &r) override;
|
||||||
|
|
||||||
/**
|
|
||||||
* Accessor to retrieve the dimensions of the inner surface of the window
|
|
||||||
* (i.e. without taking borders into account).
|
|
||||||
* Note that the returned dimensions' position is relative to the WM's
|
|
||||||
* screen, just like in getDimensions().
|
|
||||||
* @return The inner dimensions of the window.
|
|
||||||
*/
|
|
||||||
const Common::Rect &getInnerDimensions() { return _innerDims; }
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set a background pattern for the window.
|
* Set a background pattern for the window.
|
||||||
* @param pattern
|
* @param pattern
|
||||||
|
@ -221,6 +239,9 @@ public:
|
||||||
virtual bool draw(bool forceRedraw = false) override;
|
virtual bool draw(bool forceRedraw = false) override;
|
||||||
virtual void blit(ManagedSurface *g, Common::Rect &dest) override;
|
virtual void blit(ManagedSurface *g, Common::Rect &dest) override;
|
||||||
|
|
||||||
|
virtual const Common::Rect &getInnerDimensions() override { return _innerDims; }
|
||||||
|
virtual ManagedSurface *getBorderSurface() override { return &_borderSurface; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Centers the window using the dimensions of the parent window manager, or undoes this; does
|
* Centers the window using the dimensions of the parent window manager, or undoes this; does
|
||||||
* nothing if WM is null.
|
* nothing if WM is null.
|
||||||
|
@ -307,6 +328,8 @@ public:
|
||||||
void markAllDirty();
|
void markAllDirty();
|
||||||
void mergeDirtyRects();
|
void mergeDirtyRects();
|
||||||
|
|
||||||
|
virtual bool isDirty() override { return _borderIsDirty || _contentIsDirty; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void prepareBorderSurface(ManagedSurface *g);
|
void prepareBorderSurface(ManagedSurface *g);
|
||||||
void drawSimpleBorder(ManagedSurface *g);
|
void drawSimpleBorder(ManagedSurface *g);
|
||||||
|
|
|
@ -156,7 +156,7 @@ static const byte macCursorCrossBar[] = {
|
||||||
static void menuTimerHandler(void *refCon);
|
static void menuTimerHandler(void *refCon);
|
||||||
|
|
||||||
MacWindowManager::MacWindowManager(uint32 mode, MacPatterns *patterns) {
|
MacWindowManager::MacWindowManager(uint32 mode, MacPatterns *patterns) {
|
||||||
_screen = 0;
|
_screen = nullptr;
|
||||||
_screenCopy = nullptr;
|
_screenCopy = nullptr;
|
||||||
_desktopBmp = nullptr;
|
_desktopBmp = nullptr;
|
||||||
_desktop = nullptr;
|
_desktop = nullptr;
|
||||||
|
@ -243,6 +243,17 @@ void MacWindowManager::setScreen(ManagedSurface *screen) {
|
||||||
drawDesktop();
|
drawDesktop();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MacWindowManager::setScreen(int w, int h) {
|
||||||
|
if (_desktop)
|
||||||
|
_desktop->free();
|
||||||
|
else
|
||||||
|
_desktop = new ManagedSurface();
|
||||||
|
|
||||||
|
_screenDims = Common::Rect(w, h);
|
||||||
|
_desktop->create(w, h, PixelFormat::createFormatCLUT8());
|
||||||
|
drawDesktop();
|
||||||
|
}
|
||||||
|
|
||||||
void MacWindowManager::setMode(uint32 mode) {
|
void MacWindowManager::setMode(uint32 mode) {
|
||||||
_mode = mode;
|
_mode = mode;
|
||||||
|
|
||||||
|
@ -300,7 +311,7 @@ MacMenu *MacWindowManager::addMenu() {
|
||||||
delete _menu;
|
delete _menu;
|
||||||
}
|
}
|
||||||
|
|
||||||
_menu = new MacMenu(getNextId(), _screen->getBounds(), this);
|
_menu = new MacMenu(getNextId(), getScreenBounds(), this);
|
||||||
|
|
||||||
_windows[_menu->getId()] = _menu;
|
_windows[_menu->getId()] = _menu;
|
||||||
|
|
||||||
|
@ -327,6 +338,9 @@ void MacWindowManager::activateMenu() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacWindowManager::activateScreenCopy() {
|
void MacWindowManager::activateScreenCopy() {
|
||||||
|
if (!_screen)
|
||||||
|
return;
|
||||||
|
|
||||||
if (!_screenCopy)
|
if (!_screenCopy)
|
||||||
_screenCopy = new ManagedSurface(*_screen); // Create a copy
|
_screenCopy = new ManagedSurface(*_screen); // Create a copy
|
||||||
else
|
else
|
||||||
|
@ -463,19 +477,22 @@ void MacWindowManager::drawDesktop() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacWindowManager::draw() {
|
void MacWindowManager::draw() {
|
||||||
assert(_screen);
|
|
||||||
|
|
||||||
removeMarked();
|
removeMarked();
|
||||||
|
|
||||||
if (_fullRefresh) {
|
if (_fullRefresh) {
|
||||||
if (!(_mode & kWMModeNoDesktop)) {
|
Common::Rect screen = getScreenBounds();
|
||||||
if (_desktop->w != _screen->w || _desktop->h != _screen->h) {
|
if (_desktop->w != screen.width() || _desktop->h != screen.height()) {
|
||||||
_desktop->free();
|
_desktop->free();
|
||||||
_desktop->create(_screen->w, _screen->h, PixelFormat::createFormatCLUT8());
|
_desktop->create(screen.width(), screen.height(), PixelFormat::createFormatCLUT8());
|
||||||
drawDesktop();
|
drawDesktop();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (_screen) {
|
||||||
_screen->blitFrom(*_desktop, Common::Point(0, 0));
|
_screen->blitFrom(*_desktop, Common::Point(0, 0));
|
||||||
g_system->copyRectToScreen(_screen->getPixels(), _screen->pitch, 0, 0, _screen->w, _screen->h);
|
g_system->copyRectToScreen(_screen->getPixels(), _screen->pitch, 0, 0, _screen->w, _screen->h);
|
||||||
|
} else {
|
||||||
|
_screenCopyPauseToken = new PauseToken(pauseEngine());
|
||||||
|
g_system->copyRectToScreen(_desktop->getPixels(), _desktop->pitch, 0, 0, _desktop->w, _desktop->h);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_redrawEngineCallback != nullptr)
|
if (_redrawEngineCallback != nullptr)
|
||||||
|
@ -489,7 +506,7 @@ void MacWindowManager::draw() {
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
Common::Rect clip = w->getDimensions();
|
Common::Rect clip = w->getDimensions();
|
||||||
clip.clip(_screen->getBounds());
|
clip.clip(getScreenBounds());
|
||||||
clip.clip(Common::Rect(0, 0, g_system->getWidth() - 1, g_system->getHeight() - 1));
|
clip.clip(Common::Rect(0, 0, g_system->getWidth() - 1, g_system->getHeight() - 1));
|
||||||
|
|
||||||
if (clip.isEmpty())
|
if (clip.isEmpty())
|
||||||
|
@ -505,7 +522,26 @@ void MacWindowManager::draw() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (w->draw(_screen, forceRedraw)) {
|
if (!_screen) {
|
||||||
|
if (w->isDirty() || forceRedraw) {
|
||||||
|
w->draw(forceRedraw);
|
||||||
|
|
||||||
|
Common::Rect dims = w->getDimensions();
|
||||||
|
Common::Rect innerDims = w->getInnerDimensions();
|
||||||
|
|
||||||
|
g_system->copyRectToScreen(w->getBorderSurface()->getBasePtr(0, 0), w->getBorderSurface()->pitch, clip.left, clip.top, dims.width(), dims.height());
|
||||||
|
|
||||||
|
g_system->copyRectToScreen(w->getWindowSurface()->getBasePtr(MAX(clip.left - innerDims.left, 0), MAX(clip.top - innerDims.top, 0)), w->getWindowSurface()->pitch, clip.left + (-dims.left + innerDims.left), clip.top + (-dims.top + innerDims.top), innerDims.width(), innerDims.height());
|
||||||
|
|
||||||
|
dirtyRects.push_back(clip);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_screenCopyPauseToken) {
|
||||||
|
_screenCopyPauseToken->clear();
|
||||||
|
delete _screenCopyPauseToken;
|
||||||
|
_screenCopyPauseToken = nullptr;
|
||||||
|
}
|
||||||
|
} else if (w->draw(_screen, forceRedraw)) {
|
||||||
w->setDirty(false);
|
w->setDirty(false);
|
||||||
g_system->copyRectToScreen(_screen->getBasePtr(clip.left, clip.top), _screen->pitch, clip.left, clip.top, clip.width(), clip.height());
|
g_system->copyRectToScreen(_screen->getBasePtr(clip.left, clip.top), _screen->pitch, clip.left, clip.top, clip.width(), clip.height());
|
||||||
dirtyRects.push_back(clip);
|
dirtyRects.push_back(clip);
|
||||||
|
@ -513,8 +549,13 @@ void MacWindowManager::draw() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Menu is drawn on top of everything and always
|
// Menu is drawn on top of everything and always
|
||||||
if (_menu && !(_mode & kWMModeFullscreen))
|
if (_menu && !(_mode & kWMModeFullscreen)) {
|
||||||
_menu->draw(_screen, _fullRefresh);
|
if (_screen) {
|
||||||
|
_menu->draw(_screen, _fullRefresh);
|
||||||
|
} else {
|
||||||
|
g_system->copyRectToScreen(_menu->getWindowSurface()->getBasePtr(_menu->_dims.left, _menu->_dims.top), _menu->getWindowSurface()->pitch, _menu->_dims.left, _menu->_dims.top, _menu->_dims.width(), _menu->_dims.height());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
_fullRefresh = false;
|
_fullRefresh = false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -147,6 +147,14 @@ public:
|
||||||
* @param screen Surface on which the desktop will be drawn.
|
* @param screen Surface on which the desktop will be drawn.
|
||||||
*/
|
*/
|
||||||
void setScreen(ManagedSurface *screen);
|
void setScreen(ManagedSurface *screen);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mutator to indicate the dimensions of the desktop, when a backing surface is not used.
|
||||||
|
* Note that this method should be called as soon as the WM is created.
|
||||||
|
* @param screen Surface on which the desktop will be drawn.
|
||||||
|
*/
|
||||||
|
void setScreen(int w, int h);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a window with the given parameters.
|
* Create a window with the given parameters.
|
||||||
* Note that this method allocates the necessary memory for the window.
|
* Note that this method allocates the necessary memory for the window.
|
||||||
|
@ -258,6 +266,8 @@ public:
|
||||||
|
|
||||||
MacWidget *getActiveWidget() { return _activeWidget; }
|
MacWidget *getActiveWidget() { return _activeWidget; }
|
||||||
|
|
||||||
|
Common::Rect getScreenBounds() { return _screen ? _screen->getBounds() : _screenDims; }
|
||||||
|
|
||||||
void clearWidgetRefs(MacWidget *widget);
|
void clearWidgetRefs(MacWidget *widget);
|
||||||
|
|
||||||
void pushCursor(MacCursorType type, Cursor *cursor = nullptr);
|
void pushCursor(MacCursorType type, Cursor *cursor = nullptr);
|
||||||
|
@ -325,6 +335,7 @@ public:
|
||||||
|
|
||||||
ManagedSurface *_screen;
|
ManagedSurface *_screen;
|
||||||
ManagedSurface *_screenCopy;
|
ManagedSurface *_screenCopy;
|
||||||
|
Common::Rect _screenDims;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Common::List<BaseMacWindow *> _windowStack;
|
Common::List<BaseMacWindow *> _windowStack;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue