SHERLOCK: Add dirty rect handling

This commit is contained in:
Paul Gilbert 2015-03-17 00:01:12 -04:00
parent 4b5cbc5897
commit 59c124aa60
2 changed files with 75 additions and 1 deletions

View File

@ -44,8 +44,21 @@ void Screen::setFont(int fontNumber) {
}
void Screen::update() {
g_system->copyRectToScreen(getPixels(), this->w, 0, 0, this->w, this->h);
// Merge the dirty rects
mergeDirtyRects();
// Loop through copying dirty areas to the physical screen
Common::List<Common::Rect>::iterator i;
for (i = _dirtyRects.begin(); i != _dirtyRects.end(); ++i) {
const Common::Rect &r = *i;
const byte *srcP = (const byte *)getBasePtr(r.left, r.top);
g_system->copyRectToScreen(srcP, this->pitch, r.left, r.top,
r.width(), r.height());
}
// Signal the physical screen to update
g_system->updateScreen();
_dirtyRects.clear();
}
void Screen::getPalette(byte palette[PALETTE_SIZE]) {
@ -104,4 +117,57 @@ void Screen::fadeToBlack() {
} while (repeatFlag && !_vm->shouldQuit());
}
/**
* Adds a rectangle to the list of modified areas of the screen during the
* current frame
*/
void Screen::addDirtyRect(const Common::Rect &r) {
_dirtyRects.push_back(r);
assert(r.isValidRect() && r.width() > 0 && r.height() > 0);
}
/**
* Merges together overlapping dirty areas of the screen
*/
void Screen::mergeDirtyRects() {
Common::List<Common::Rect>::iterator rOuter, rInner;
// Ensure dirty rect list has at least two entries
rOuter = _dirtyRects.begin();
for (int i = 0; i < 2; ++i, ++rOuter) {
if (rOuter == _dirtyRects.end())
return;
}
// Process the dirty rect list to find any rects to merge
for (rOuter = _dirtyRects.begin(); rOuter != _dirtyRects.end(); ++rOuter) {
rInner = rOuter;
while (++rInner != _dirtyRects.end()) {
if ((*rOuter).intersects(*rInner)) {
// these two rectangles overlap or
// are next to each other - merge them
unionRectangle(*rOuter, *rOuter, *rInner);
// remove the inner rect from the list
_dirtyRects.erase(rInner);
// move back to beginning of list
rInner = rOuter;
}
}
}
}
/**
* Returns the union of two dirty area rectangles
*/
bool Screen::unionRectangle(Common::Rect &destRect, const Common::Rect &src1, const Common::Rect &src2) {
destRect = src1;
destRect.extend(src2);
return !destRect.isEmpty();
}
} // End of namespace Sherlock

View File

@ -23,6 +23,7 @@
#ifndef SHERLOCK_SCREEN_H
#define SHERLOCK_SCREEN_H
#include "common/list.h"
#include "common/rect.h"
#include "graphics/surface.h"
@ -40,6 +41,13 @@ private:
SherlockEngine *_vm;
int _fontNumber;
Surface _backBuffer1, _backBuffer2;
Common::List<Common::Rect> _dirtyRects;
void mergeDirtyRects();
bool unionRectangle(Common::Rect &destRect, const Common::Rect &src1, const Common::Rect &src2);
protected:
virtual void addDirtyRect(const Common::Rect &r);
public:
Screen(SherlockEngine *vm);