mirror of
https://github.com/libretro/scummvm.git
synced 2025-03-01 15:55:45 +00:00
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
@ -52,6 +52,10 @@ public:
|
||||
MacMenu(int id, const Common::Rect &bounds, MacWindowManager *wm);
|
||||
~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 MacMenu *createMenuFromPEexe(Common::PEResources *exe, MacWindowManager *wm);
|
||||
|
||||
|
@ -191,7 +191,7 @@ void MacWindow::center(bool toCenter) {
|
||||
if (!_wm)
|
||||
return;
|
||||
|
||||
Common::Rect screen = _wm->_screen->getBounds();
|
||||
Common::Rect screen = _wm->getScreenBounds();
|
||||
|
||||
if (toCenter) {
|
||||
move((screen.width() - _dims.width()) / 2, (screen.height() - _dims.height()) / 2);
|
||||
|
@ -115,6 +115,28 @@ public:
|
||||
*/
|
||||
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.
|
||||
* This method is most often called by the WM, and relies on
|
||||
@ -133,6 +155,11 @@ public:
|
||||
*/
|
||||
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.
|
||||
* @param callback A function pointer to a function that accepts:
|
||||
@ -196,15 +223,6 @@ public:
|
||||
*/
|
||||
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.
|
||||
* @param pattern
|
||||
@ -221,6 +239,9 @@ public:
|
||||
virtual bool draw(bool forceRedraw = false) 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
|
||||
* nothing if WM is null.
|
||||
@ -307,6 +328,8 @@ public:
|
||||
void markAllDirty();
|
||||
void mergeDirtyRects();
|
||||
|
||||
virtual bool isDirty() override { return _borderIsDirty || _contentIsDirty; }
|
||||
|
||||
private:
|
||||
void prepareBorderSurface(ManagedSurface *g);
|
||||
void drawSimpleBorder(ManagedSurface *g);
|
||||
|
@ -156,7 +156,7 @@ static const byte macCursorCrossBar[] = {
|
||||
static void menuTimerHandler(void *refCon);
|
||||
|
||||
MacWindowManager::MacWindowManager(uint32 mode, MacPatterns *patterns) {
|
||||
_screen = 0;
|
||||
_screen = nullptr;
|
||||
_screenCopy = nullptr;
|
||||
_desktopBmp = nullptr;
|
||||
_desktop = nullptr;
|
||||
@ -243,6 +243,17 @@ void MacWindowManager::setScreen(ManagedSurface *screen) {
|
||||
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) {
|
||||
_mode = mode;
|
||||
|
||||
@ -300,7 +311,7 @@ MacMenu *MacWindowManager::addMenu() {
|
||||
delete _menu;
|
||||
}
|
||||
|
||||
_menu = new MacMenu(getNextId(), _screen->getBounds(), this);
|
||||
_menu = new MacMenu(getNextId(), getScreenBounds(), this);
|
||||
|
||||
_windows[_menu->getId()] = _menu;
|
||||
|
||||
@ -327,6 +338,9 @@ void MacWindowManager::activateMenu() {
|
||||
}
|
||||
|
||||
void MacWindowManager::activateScreenCopy() {
|
||||
if (!_screen)
|
||||
return;
|
||||
|
||||
if (!_screenCopy)
|
||||
_screenCopy = new ManagedSurface(*_screen); // Create a copy
|
||||
else
|
||||
@ -463,19 +477,22 @@ void MacWindowManager::drawDesktop() {
|
||||
}
|
||||
|
||||
void MacWindowManager::draw() {
|
||||
assert(_screen);
|
||||
|
||||
removeMarked();
|
||||
|
||||
if (_fullRefresh) {
|
||||
if (!(_mode & kWMModeNoDesktop)) {
|
||||
if (_desktop->w != _screen->w || _desktop->h != _screen->h) {
|
||||
_desktop->free();
|
||||
_desktop->create(_screen->w, _screen->h, PixelFormat::createFormatCLUT8());
|
||||
drawDesktop();
|
||||
}
|
||||
Common::Rect screen = getScreenBounds();
|
||||
if (_desktop->w != screen.width() || _desktop->h != screen.height()) {
|
||||
_desktop->free();
|
||||
_desktop->create(screen.width(), screen.height(), PixelFormat::createFormatCLUT8());
|
||||
drawDesktop();
|
||||
}
|
||||
|
||||
if (_screen) {
|
||||
_screen->blitFrom(*_desktop, Common::Point(0, 0));
|
||||
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)
|
||||
@ -489,7 +506,7 @@ void MacWindowManager::draw() {
|
||||
continue;
|
||||
|
||||
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));
|
||||
|
||||
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);
|
||||
g_system->copyRectToScreen(_screen->getBasePtr(clip.left, clip.top), _screen->pitch, clip.left, clip.top, clip.width(), clip.height());
|
||||
dirtyRects.push_back(clip);
|
||||
@ -513,8 +549,13 @@ void MacWindowManager::draw() {
|
||||
}
|
||||
|
||||
// Menu is drawn on top of everything and always
|
||||
if (_menu && !(_mode & kWMModeFullscreen))
|
||||
_menu->draw(_screen, _fullRefresh);
|
||||
if (_menu && !(_mode & kWMModeFullscreen)) {
|
||||
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;
|
||||
}
|
||||
|
@ -147,6 +147,14 @@ public:
|
||||
* @param screen Surface on which the desktop will be drawn.
|
||||
*/
|
||||
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.
|
||||
* Note that this method allocates the necessary memory for the window.
|
||||
@ -258,6 +266,8 @@ public:
|
||||
|
||||
MacWidget *getActiveWidget() { return _activeWidget; }
|
||||
|
||||
Common::Rect getScreenBounds() { return _screen ? _screen->getBounds() : _screenDims; }
|
||||
|
||||
void clearWidgetRefs(MacWidget *widget);
|
||||
|
||||
void pushCursor(MacCursorType type, Cursor *cursor = nullptr);
|
||||
@ -325,6 +335,7 @@ public:
|
||||
|
||||
ManagedSurface *_screen;
|
||||
ManagedSurface *_screenCopy;
|
||||
Common::Rect _screenDims;
|
||||
|
||||
private:
|
||||
Common::List<BaseMacWindow *> _windowStack;
|
||||
|
Loading…
x
Reference in New Issue
Block a user