aboutsummaryrefslogtreecommitdiff
path: root/engines/tony
diff options
context:
space:
mode:
authorPaul Gilbert2012-06-23 00:57:21 +1000
committerPaul Gilbert2012-06-23 00:57:21 +1000
commit717756749df4a1effa2628d5a7c039401c1d1f47 (patch)
tree97a9a1b5796d2706ead5100e5d2fe6a2b296ec1c /engines/tony
parent2990482406710c77280c67f3b7672a569b9d5a92 (diff)
parenteef6b444df766b90d1323941c7ff9bd8355c111b (diff)
downloadscummvm-rg350-717756749df4a1effa2628d5a7c039401c1d1f47.tar.gz
scummvm-rg350-717756749df4a1effa2628d5a7c039401c1d1f47.tar.bz2
scummvm-rg350-717756749df4a1effa2628d5a7c039401c1d1f47.zip
TONY: Merge of dirty rect functionality
Diffstat (limited to 'engines/tony')
-rw-r--r--engines/tony/debugger.cpp14
-rw-r--r--engines/tony/debugger.h1
-rw-r--r--engines/tony/gfxcore.cpp83
-rw-r--r--engines/tony/gfxcore.h15
-rw-r--r--engines/tony/gfxengine.cpp2
-rw-r--r--engines/tony/gfxengine.h4
-rw-r--r--engines/tony/loc.cpp17
-rw-r--r--engines/tony/loc.h3
-rw-r--r--engines/tony/tony.cpp3
-rw-r--r--engines/tony/utils.cpp4
-rw-r--r--engines/tony/utils.h1
-rw-r--r--engines/tony/window.cpp43
-rw-r--r--engines/tony/window.h8
13 files changed, 186 insertions, 12 deletions
diff --git a/engines/tony/debugger.cpp b/engines/tony/debugger.cpp
index 8beb7285a4..75e58d68d4 100644
--- a/engines/tony/debugger.cpp
+++ b/engines/tony/debugger.cpp
@@ -30,6 +30,7 @@ namespace Tony {
Debugger::Debugger() : GUI::Debugger() {
DCmd_Register("continue", WRAP_METHOD(Debugger, Cmd_Exit));
DCmd_Register("scene", WRAP_METHOD(Debugger, Cmd_Scene));
+ DCmd_Register("dirty_rects", WRAP_METHOD(Debugger, Cmd_DirtyRects));
}
static int strToInt(const char *s) {
@@ -113,4 +114,17 @@ bool Debugger::Cmd_Scene(int argc, const char **argv) {
return false;
}
+/**
+ * Turns showing dirty rects on or off
+ */
+bool Debugger::Cmd_DirtyRects(int argc, const char **argv) {
+ if (argc != 2) {
+ DebugPrintf("Usage; %s [on | off]\n", argv[0]);
+ return true;
+ } else {
+ _vm->_window.showDirtyRects(strcmp(argv[1], "on") == 0);
+ return false;
+ }
+}
+
} // End of namespace Tony
diff --git a/engines/tony/debugger.h b/engines/tony/debugger.h
index c5ed5e417e..85ba9d75b6 100644
--- a/engines/tony/debugger.h
+++ b/engines/tony/debugger.h
@@ -35,6 +35,7 @@ public:
protected:
bool Cmd_Scene(int argc, const char **argv);
+ bool Cmd_DirtyRects(int argc, const char **argv);
};
} // End of namespace Tony
diff --git a/engines/tony/gfxcore.cpp b/engines/tony/gfxcore.cpp
index a4d8b9332b..d91f5bab4e 100644
--- a/engines/tony/gfxcore.cpp
+++ b/engines/tony/gfxcore.cpp
@@ -251,6 +251,7 @@ RMGfxWoodyBuffer::RMGfxWoodyBuffer(int dimx, int dimy, bool bUseDDraw)
RMGfxTargetBuffer::RMGfxTargetBuffer() {
_otlist = NULL;
_otSize = 0;
+ _trackDirtyRects = false;
// csModifyingOT = g_system->createMutex();
}
@@ -371,6 +372,67 @@ void RMGfxTargetBuffer::addPrim(RMGfxPrimitive *prim) {
// g_system->unlockMutex(csModifyingOT);
}
+void RMGfxTargetBuffer::addDirtyRect(const Common::Rect &r) {
+ assert(r.isValidRect());
+ if (_trackDirtyRects && r.width() > 0 && r.height() > 0)
+ _currentDirtyRects.push_back(r);
+}
+
+Common::List<Common::Rect> &RMGfxTargetBuffer::getDirtyRects() {
+ // Copy rects from both the current and previous frame into the output dirty rects list
+ Common::List<Common::Rect>::iterator i;
+ _dirtyRects.clear();
+ for (i = _previousDirtyRects.begin(); i != _previousDirtyRects.end(); ++i)
+ _dirtyRects.push_back(*i);
+ for (i = _currentDirtyRects.begin(); i != _currentDirtyRects.end(); ++i)
+ _dirtyRects.push_back(*i);
+
+ mergeDirtyRects();
+ return _dirtyRects;
+}
+
+/**
+ * Move the set of dirty rects from the finished current frame into the previous frame list.
+ */
+void RMGfxTargetBuffer::clearDirtyRects() {
+ Common::List<Common::Rect>::iterator i;
+ _previousDirtyRects.clear();
+ for (i = _currentDirtyRects.begin(); i != _currentDirtyRects.end(); ++i)
+ _previousDirtyRects.push_back(*i);
+
+ _currentDirtyRects.clear();
+}
+
+/**
+ * Merges any clipping rectangles that overlap to try and reduce
+ * the total number of clip rectangles.
+ */
+void RMGfxTargetBuffer::mergeDirtyRects() {
+ if (_dirtyRects.size() <= 1)
+ return;
+
+ Common::List<Common::Rect>::iterator rOuter, rInner;
+
+ 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
+
+ (*rOuter).extend(*rInner);
+
+ // remove the inner rect from the list
+ _dirtyRects.erase(rInner);
+
+ // move back to beginning of list
+ rInner = rOuter;
+ }
+ }
+ }
+}
+
/****************************************************************************\
* RMGfxSourceBufferPal Methods
\****************************************************************************/
@@ -539,6 +601,9 @@ void RMGfxSourceBuffer8::draw(CORO_PARAM, RMGfxTargetBuffer &bigBuf, RMGfxPrimit
buf += bufx - width;
}
}
+
+ // Specify the drawn area
+ bigBuf.addDirtyRect(Common::Rect(dst._x1, dst._y1, dst._x1 + width, dst._y1 + height));
}
RMGfxSourceBuffer8::RMGfxSourceBuffer8(int dimx, int dimy, bool bUseDDraw)
@@ -650,7 +715,8 @@ void RMGfxSourceBuffer8AB::draw(CORO_PARAM, RMGfxTargetBuffer &bigBuf, RMGfxPrim
}
}
- return;
+ // Specify the drawn area
+ bigBuf.addDirtyRect(Common::Rect(dst._x1, dst._y1, dst._x1 + width, dst._y1 + height));
}
@@ -826,6 +892,9 @@ void RMGfxSourceBuffer8RLE::draw(CORO_PARAM, RMGfxTargetBuffer &bigBuf, RMGfxPri
u = _dimx - (width + u);
x1 = (prim->getDst()._x1 + _dimx - 1) - u;
+ // Specify the drawn area
+ bigBuf.addDirtyRect(Common::Rect(x1 - width, y1, x1, y1 + height));
+
for (y = 0; y < height; y++) {
// Decompression
RLEDecompressLineFlipped(buf + x1, src + 2, u, width);
@@ -837,6 +906,9 @@ void RMGfxSourceBuffer8RLE::draw(CORO_PARAM, RMGfxTargetBuffer &bigBuf, RMGfxPri
buf += bigBuf.getDimx();
}
} else {
+ // Specify the drawn area
+ bigBuf.addDirtyRect(Common::Rect(x1, y1, x1 + width, y1 + height));
+
for (y = 0; y < height; y++) {
// Decompression
RLEDecompressLine(buf + x1, src + 2, u, width);
@@ -1697,6 +1769,9 @@ void RMGfxSourceBuffer8AA::drawAA(RMGfxTargetBuffer &bigBuf, RMGfxPrimitive *pri
// Skip to the next line
buf += bigBuf.getDimx();
}
+
+ // Specify the drawn area
+ bigBuf.addDirtyRect(Common::Rect(x1, y1, x1 + width, y1 + height));
}
@@ -1855,6 +1930,9 @@ void RMGfxSourceBuffer16::draw(CORO_PARAM, RMGfxTargetBuffer &bigBuf, RMGfxPrimi
raw += _dimx;
}
}
+
+ // Specify the drawn area
+ bigBuf.addDirtyRect(Common::Rect(x1, y1, x1 + dimx, y1 + dimy));
}
void RMGfxSourceBuffer16::prepareImage() {
@@ -1905,6 +1983,9 @@ void RMGfxBox::draw(CORO_PARAM, RMGfxTargetBuffer &bigBuf, RMGfxPrimitive *prim)
uint16 *buf = bigBuf;
RMRect rcDst;
+ // Specify the drawn area
+ bigBuf.addDirtyRect(rcDst);
+
// It takes the destination rectangle
rcDst = prim->getDst();
buf += rcDst._y1 * bigBuf.getDimx() + rcDst._x1;
diff --git a/engines/tony/gfxcore.h b/engines/tony/gfxcore.h
index be89c1713c..32e3c96881 100644
--- a/engines/tony/gfxcore.h
+++ b/engines/tony/gfxcore.h
@@ -558,6 +558,10 @@ private:
}
};
+ bool _trackDirtyRects;
+ Common::List<Common::Rect> _currentDirtyRects, _previousDirtyRects, _dirtyRects;
+
+ void mergeDirtyRects();
private:
// OSystem::MutexRef csModifyingOT;
@@ -589,6 +593,17 @@ public:
void offsetY(int nLines) {
RMGfxBuffer::offsetY(nLines, 16);
}
+
+ // Dirty rect methods
+ void addDirtyRect(const Common::Rect &r);
+ Common::List<Common::Rect> &getDirtyRects();
+ void clearDirtyRects();
+ void setTrackDirtyRects(bool v) {
+ _trackDirtyRects = v;
+ }
+ bool getTrackDirtyRects() const {
+ return _trackDirtyRects;
+ }
};
diff --git a/engines/tony/gfxengine.cpp b/engines/tony/gfxengine.cpp
index cc53a1d8e2..726ee07e28 100644
--- a/engines/tony/gfxengine.cpp
+++ b/engines/tony/gfxengine.cpp
@@ -63,6 +63,7 @@ RMGfxEngine::RMGfxEngine() {
// Create big buffer where the frame will be rendered
_bigBuf.create(RM_BBX, RM_BBY, 16);
_bigBuf.offsetY(RM_SKIPY);
+ _bigBuf.setTrackDirtyRects(true);
_csMainLoop = NULL;
_nCurLoc = 0;
@@ -473,6 +474,7 @@ void RMGfxEngine::init() {
delete load;
// Display 'Loading' screen
+ _bigBuf.addDirtyRect(Common::Rect(0, 0, RM_SX, RM_SY));
_vm->_window.getNewFrame(*this, NULL);
_vm->_window.repaint();
diff --git a/engines/tony/gfxengine.h b/engines/tony/gfxengine.h
index 74aafd15f6..2c48612c4d 100644
--- a/engines/tony/gfxengine.h
+++ b/engines/tony/gfxengine.h
@@ -109,8 +109,8 @@ public:
void enableMouse();
void disableMouse();
- operator byte *() {
- return (byte *)_bigBuf;
+ operator RMGfxTargetBuffer &() {
+ return _bigBuf;
}
RMInput &getInput() {
return _input;
diff --git a/engines/tony/loc.cpp b/engines/tony/loc.cpp
index e8dbb4fa69..d02bd9640f 100644
--- a/engines/tony/loc.cpp
+++ b/engines/tony/loc.cpp
@@ -1945,6 +1945,9 @@ RMLocation::RMLocation() {
_buf = NULL;
TEMPNumLoc = 0;
_cmode = CM_256;
+
+ _prevScroll.set(-1, -1);
+ _prevFixedScroll.set(-1, -1);
}
@@ -2135,6 +2138,8 @@ bool RMLocation::loadLOX(RMDataStream &ds) {
*/
void RMLocation::draw(CORO_PARAM, RMGfxTargetBuffer &bigBuf, RMGfxPrimitive *prim) {
CORO_BEGIN_CONTEXT;
+ bool priorTracking;
+ bool hasChanges;
CORO_END_CONTEXT(_ctx);
CORO_BEGIN_CODE(_ctx);
@@ -2146,9 +2151,21 @@ void RMLocation::draw(CORO_PARAM, RMGfxTargetBuffer &bigBuf, RMGfxPrimitive *pri
prim->setDst(_fixedScroll);
+ // Check whether dirty rects are being tracked, and if there are changes, leave tracking
+ // turned on so a dirty rect will be added for the entire background
+ _ctx->priorTracking = bigBuf.getTrackDirtyRects();
+ _ctx->hasChanges = (_prevScroll != _curScroll) || (_prevFixedScroll != _fixedScroll);
+ bigBuf.setTrackDirtyRects(_ctx->priorTracking && _ctx->hasChanges);
+
// Invoke the drawing method fo the image class, which will draw the location background
CORO_INVOKE_2(_buf->draw, bigBuf, prim);
+ if (_ctx->hasChanges) {
+ _prevScroll = _curScroll;
+ _prevFixedScroll = _fixedScroll;
+ }
+ bigBuf.setTrackDirtyRects(_ctx->priorTracking);
+
CORO_END_CODE;
}
diff --git a/engines/tony/loc.h b/engines/tony/loc.h
index 35674736dd..35f07fe637 100644
--- a/engines/tony/loc.h
+++ b/engines/tony/loc.h
@@ -539,6 +539,9 @@ private:
RMPoint _curScroll; // Current scroll position
RMPoint _fixedScroll;
+ RMPoint _prevScroll; // Previous scroll position
+ RMPoint _prevFixedScroll;
+
public:
// @@@@@@@@@@@@@@@@@@@@@@@
RMPoint TEMPTonyStart;
diff --git a/engines/tony/tony.cpp b/engines/tony/tony.cpp
index 475683d0f4..30ab716c20 100644
--- a/engines/tony/tony.cpp
+++ b/engines/tony/tony.cpp
@@ -634,8 +634,9 @@ Common::Error TonyEngine::saveGameState(int slot, const Common::String &desc) {
if (!GLOBALS._gfxEngine)
return Common::kUnknownError;
+ RMGfxTargetBuffer &bigBuf = *GLOBALS._gfxEngine;
RMSnapshot s;
- s.grabScreenshot(*GLOBALS._gfxEngine, 4, _curThumbnail);
+ s.grabScreenshot(bigBuf, 4, _curThumbnail);
GLOBALS._gfxEngine->saveState(getSaveStateFileName(slot), (byte *)_curThumbnail, desc);
return Common::kNoError;
diff --git a/engines/tony/utils.cpp b/engines/tony/utils.cpp
index 647ef0ed82..54a2209659 100644
--- a/engines/tony/utils.cpp
+++ b/engines/tony/utils.cpp
@@ -921,6 +921,10 @@ int RMRect::size() const {
return width() * height();
}
+RMRect::operator Common::Rect() const {
+ return Common::Rect(_x1, _y1, _x2, _y2);
+}
+
bool RMRect::isEmpty() const {
return (_x1 == 0 && _y1 == 0 && _x2 == 0 && _y2 == 0);
}
diff --git a/engines/tony/utils.h b/engines/tony/utils.h
index e7f943b231..f755a57c39 100644
--- a/engines/tony/utils.h
+++ b/engines/tony/utils.h
@@ -279,6 +279,7 @@ public:
int height() const;
bool isEmpty() const;
int size() const;
+ operator Common::Rect() const;
// Set
void setRect(int x1, int y1, int x2, int y2);
diff --git a/engines/tony/window.cpp b/engines/tony/window.cpp
index ba030e6a36..b8cd34d049 100644
--- a/engines/tony/window.cpp
+++ b/engines/tony/window.cpp
@@ -27,6 +27,7 @@
*/
#include "common/scummsys.h"
+#include "graphics/surface.h"
#include "util.h"
#include "tony/window.h"
#include "tony/game.h"
@@ -40,7 +41,7 @@ namespace Tony {
\****************************************************************************/
RMWindow::RMWindow() {
-
+ _showDirtyRects = false;
}
RMWindow::~RMWindow() {
@@ -61,6 +62,7 @@ void RMWindow::init() {
_bGrabScreenshot = false;
_bGrabThumbnail = false;
_bGrabMovie = false;
+ _wiping = false;
}
/**
@@ -108,13 +110,43 @@ void RMWindow::wipeEffect(Common::Rect &rcBoundEllipse) {
}
}
-void RMWindow::getNewFrame(byte *lpBuf, Common::Rect *rcBoundEllipse) {
+void RMWindow::getNewFrame(RMGfxTargetBuffer &bigBuf, Common::Rect *rcBoundEllipse) {
+ // Get a pointer to the bytes of the source buffer
+ byte *lpBuf = bigBuf;
+
if (rcBoundEllipse != NULL) {
// Circular wipe effect
getNewFrameWipe(lpBuf, *rcBoundEllipse);
- } else {
- // Standard screen copy
+ _wiping = true;
+ } else if (_wiping) {
+ // Just finished a wiping effect, so copy the full screen
g_system->copyRectToScreen(lpBuf, RM_SX * 2, 0, 0, RM_SX, RM_SY);
+ _wiping = false;
+
+ } else {
+ // Standard screen copy - iterate through the dirty rects
+ Common::List<Common::Rect> dirtyRects = bigBuf.getDirtyRects();
+ Common::List<Common::Rect>::iterator i;
+
+ // If showing dirty rects, copy the entire screen background and set up a surface pointer
+ Graphics::Surface *s = NULL;
+ if (_showDirtyRects) {
+ g_system->copyRectToScreen(lpBuf, RM_SX * 2, 0, 0, RM_SX, RM_SY);
+ s = g_system->lockScreen();
+ }
+
+ for (i = dirtyRects.begin(); i != dirtyRects.end(); ++i) {
+ Common::Rect &r = *i;
+ const byte *lpSrc = lpBuf + (RM_SX * 2) * r.top + (r.left * 2);
+ g_system->copyRectToScreen(lpSrc, RM_SX * 2, r.left, r.top, r.width(), r.height());
+
+ if (_showDirtyRects)
+ // Frame the copied area with a rectangle
+ s->frameRect(r, 0xffffff);
+ }
+
+ if (_showDirtyRects)
+ g_system->unlockScreen();
}
if (_bGrabThumbnail) {
@@ -124,6 +156,9 @@ void RMWindow::getNewFrame(byte *lpBuf, Common::Rect *rcBoundEllipse) {
s.grabScreenshot(lpBuf, 4, _wThumbBuf);
_bGrabThumbnail = false;
}
+
+ // Clear the dirty rect list
+ bigBuf.clearDirtyRects();
}
/**
diff --git a/engines/tony/window.h b/engines/tony/window.h
index 0d4c20b0fe..571a02829a 100644
--- a/engines/tony/window.h
+++ b/engines/tony/window.h
@@ -59,13 +59,12 @@ private:
void plotLines(const byte *lpBuf, const Common::Point &center, int x, int y);
protected:
-// void * /*LPDIRECTDRAWCLIPPER*/ _MainClipper;
-// void * /*LPDIRECTDRAWCLIPPER*/ _BackClipper;
-
int fps, fcount;
int lastsecond, lastfcount;
int mskRed, mskGreen, mskBlue;
+ bool _wiping;
+ bool _showDirtyRects;
bool _bGrabScreenshot;
bool _bGrabThumbnail;
@@ -100,7 +99,7 @@ public:
/**
* Reads the next frame
*/
- void getNewFrame(byte *lpBuf, Common::Rect *rcBoundEllipse);
+ void getNewFrame(RMGfxTargetBuffer &lpBuf, Common::Rect *rcBoundEllipse);
/**
* Request a thumbnail be grabbed during the next frame
@@ -110,6 +109,7 @@ public:
int getFps() const {
return fps;
}
+ void showDirtyRects(bool v) { _showDirtyRects = v; }
};
} // End of namespace Tony