aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorsylvaintv2011-03-08 00:51:21 +0100
committersylvaintv2011-03-08 00:51:21 +0100
commit53d6a4f831c9e7c7de594cdaed3c8546b41ea2e2 (patch)
tree4b89d219842fad3a6ff00778e175c3868b4fe628
parent7d36aabd4271212e2c0b741172a40d07871e5b4c (diff)
downloadscummvm-rg350-53d6a4f831c9e7c7de594cdaed3c8546b41ea2e2.tar.gz
scummvm-rg350-53d6a4f831c9e7c7de594cdaed3c8546b41ea2e2.tar.bz2
scummvm-rg350-53d6a4f831c9e7c7de594cdaed3c8546b41ea2e2.zip
TOON: Decrease CPU usage
Added dirty rects Reduced the max FPS from 60 to 30
-rw-r--r--engines/toon/anim.cpp6
-rw-r--r--engines/toon/font.cpp6
-rw-r--r--engines/toon/movie.cpp2
-rw-r--r--engines/toon/picture.cpp38
-rw-r--r--engines/toon/picture.h1
-rw-r--r--engines/toon/script_func.cpp2
-rw-r--r--engines/toon/toon.cpp136
-rw-r--r--engines/toon/toon.h9
8 files changed, 190 insertions, 10 deletions
diff --git a/engines/toon/anim.cpp b/engines/toon/anim.cpp
index 2e63d89f37..6d0d75f077 100644
--- a/engines/toon/anim.cpp
+++ b/engines/toon/anim.cpp
@@ -151,6 +151,8 @@ void Animation::drawFrame(Graphics::Surface &surface, int32 frame, int32 xx, int
int32 offsX = 0;
int32 offsY = 0;
+ _vm->addDirtyRect(xx + _x1 + _frames[frame]._x1, yy + _y1 + _frames[frame]._y1, xx + rectX + _x1 + _frames[frame]._x1 , yy + rectY + _y1 + _frames[frame]._y1);
+
if (xx + _x1 + _frames[frame]._x1 < 0) {
offsX = -(xx + _x1 + _frames[frame]._x1);
}
@@ -212,6 +214,7 @@ void Animation::drawFrameWithMaskAndScale(Graphics::Surface &surface, int32 fram
int32 finalWidth = rectX * scale / 1024;
int32 finalHeight = rectY * scale / 1024;
+
// compute final x1,y1,x2,y2
int32 xx1 = xx + _x1 + _frames[frame]._x1 * scale / 1024;
int32 yy1 = yy + _y1 + _frames[frame]._y1 * scale / 1024;
@@ -221,6 +224,9 @@ void Animation::drawFrameWithMaskAndScale(Graphics::Surface &surface, int32 fram
// Strangerke - Commented (not used)
// int32 h = _frames[frame]._y2 - _frames[frame]._y1;
+ _vm->addDirtyRect(xx1,yy1,xx2,yy2);
+
+
int32 destPitch = surface.pitch;
int32 destPitchMask = mask->getWidth();
uint8 *c = _frames[frame]._data;
diff --git a/engines/toon/font.cpp b/engines/toon/font.cpp
index 8455ca7b61..53786f8617 100644
--- a/engines/toon/font.cpp
+++ b/engines/toon/font.cpp
@@ -81,6 +81,8 @@ void FontRenderer::renderText(int32 x, int32 y, Common::String origText, int32 m
x -= xx / 2;
}
+ _vm->addDirtyRect(x,y,x+xx,y+yy);
+
int32 curX = x;
int32 curY = y;
int32 height = 0;
@@ -270,9 +272,13 @@ void FontRenderer::renderMultiLineText(int32 x, int32 y, Common::String origText
int32 curX = x;
int32 curY = y;
+
+
for (int32 i = 0; i < numLines; i++) {
const byte *line = lines[i];
curX = x - lineSize[i] / 2;
+ _vm->addDirtyRect(curX + _vm->state()->_currentScrollValue, y, curX + lineSize[i] + _vm->state()->_currentScrollValue, curY + height);
+
while (*line) {
byte curChar = textToFont(*line);
if (curChar != 32) _currentFont->drawFontFrame(_vm->getMainSurface(), curChar, curX + _vm->state()->_currentScrollValue, curY, _currentFontColor);
diff --git a/engines/toon/movie.cpp b/engines/toon/movie.cpp
index bf4b6639fa..68c09fb586 100644
--- a/engines/toon/movie.cpp
+++ b/engines/toon/movie.cpp
@@ -135,11 +135,13 @@ bool Movie::playVideo(bool isFirstIntroVideo) {
Common::Event event;
while (_vm->getSystem()->getEventManager()->pollEvent(event))
if ((event.type == Common::EVENT_KEYDOWN && event.kbd.keycode == Common::KEYCODE_ESCAPE)) {
+ _vm->dirtyAllScreen();
return false;
}
_vm->getSystem()->delayMillis(10);
}
+ _vm->dirtyAllScreen();
return !_vm->shouldQuit();
}
diff --git a/engines/toon/picture.cpp b/engines/toon/picture.cpp
index 18e6a8cf7f..fce711717a 100644
--- a/engines/toon/picture.cpp
+++ b/engines/toon/picture.cpp
@@ -187,6 +187,44 @@ void Picture::drawMask(Graphics::Surface &surface, int32 x, int32 y, int32 dx, i
}
}
+void Picture::drawWithRectList(Graphics::Surface& surface, int32 x, int32 y, int32 dx, int32 dy, Common::Array<Common::Rect>& rectArray) {
+
+ int32 rx = MIN(_width, surface.w - x);
+ int32 ry = MIN(_height, surface.h - y);
+
+ if (rx < 0 || ry < 0)
+ return;
+
+ int32 destPitch = surface.pitch;
+ int32 srcPitch = _width;
+
+ for (uint32 i = 0; i < rectArray.size(); i++) {
+
+ Common::Rect rect = rectArray[i];
+
+ int32 fillRx = MIN<int32>(rx, rect.right - rect.left);
+ int32 fillRy = MIN<int32>(ry, rect.bottom - rect.top);
+
+ uint8 *c = _data + _width * (dy + rect.top) + (dx + rect.left);
+ uint8 *curRow = (uint8 *)surface.pixels + (y + rect.top) * destPitch + (x + rect.left);
+
+ for (int32 yy = 0; yy < fillRy; yy++) {
+ uint8 *curSrc = c;
+ uint8 *cur = curRow;
+ for (int32 xx = 0; xx < fillRx; xx++) {
+ *cur = *curSrc;
+ curSrc++;
+ cur++;
+ }
+ curRow += destPitch;
+ c += srcPitch;
+ }
+
+ }
+
+
+}
+
void Picture::draw(Graphics::Surface &surface, int32 x, int32 y, int32 dx, int32 dy) {
debugC(6, kDebugPicture, "draw(surface, %d, %d, %d, %d)", x, y, dx, dy);
diff --git a/engines/toon/picture.h b/engines/toon/picture.h
index 1b0fd7f550..6aca408364 100644
--- a/engines/toon/picture.h
+++ b/engines/toon/picture.h
@@ -44,6 +44,7 @@ public:
bool loadPicture(Common::String file, bool totalPalette = false);
void setupPalette();
void draw(Graphics::Surface &surface, int32 x, int32 y, int32 dx, int32 dy);
+ void drawWithRectList(Graphics::Surface& surface, int32 x, int32 y, int32 dx, int32 dy, Common::Array<Common::Rect>& rectArray);
void drawMask(Graphics::Surface &surface, int32 x, int32 y, int32 dx, int32 dy);
void drawLineOnMask(int32 x, int32 y, int32 x2, int32 y2, bool walkable);
void floodFillNotWalkableOnMask(int32 x, int32 y);
diff --git a/engines/toon/script_func.cpp b/engines/toon/script_func.cpp
index adf3a1c9cc..84225ec76b 100644
--- a/engines/toon/script_func.cpp
+++ b/engines/toon/script_func.cpp
@@ -1028,7 +1028,7 @@ int32 ScriptFunc::sys_Cmd_Draw_Scene_Anim_WSA_Frame(EMCState *state) {
else if (animId == 20 || animId == 15 || animId == 21 || animId == 16 || animId == 17 || animId == 18)
_vm->pauseSceneAnimationScript(_vm->getCurrentUpdatingSceneAnimation(), 1);
else if (animId == 9) {
- _vm->pauseSceneAnimationScript(_vm->getCurrentUpdatingSceneAnimation(), 6);
+ _vm->pauseSceneAnimationScript(_vm->getCurrentUpdatingSceneAnimation(), 3);
}
}
diff --git a/engines/toon/toon.cpp b/engines/toon/toon.cpp
index cc694cbe74..b4335d7afd 100644
--- a/engines/toon/toon.cpp
+++ b/engines/toon/toon.cpp
@@ -378,10 +378,21 @@ void ToonEngine::updateTimer(int32 timeIncrement) {
}
void ToonEngine::render() {
- if (_gameState->_inCutaway)
- _currentCutaway->draw(*_mainSurface, 0, 0, 0, 0);
- else
- _currentPicture->draw(*_mainSurface, 0, 0, 0, 0);
+
+ if (_dirtyAll) {
+ if (_gameState->_inCutaway)
+ _currentCutaway->draw(*_mainSurface, 0, 0, 0, 0);
+ else
+ _currentPicture->draw(*_mainSurface, 0, 0, 0, 0);
+ _dirtyRects.push_back(Common::Rect(0, 0, 1280, 400));
+ } else {
+ if (_gameState->_inCutaway)
+ _currentCutaway->drawWithRectList(*_mainSurface, 0, 0, 0, 0, _dirtyRects);
+ else
+ _currentPicture->drawWithRectList(*_mainSurface, 0, 0, 0, 0, _dirtyRects);
+ }
+
+ clearDirtyRects();
//_currentMask->drawMask(*_mainSurface,0,0,0,0);
_animationManager->render();
@@ -422,8 +433,8 @@ void ToonEngine::render() {
// add a little sleep here
int32 newMillis = (int32)_system->getMillis();
int32 sleepMs = 1; // Minimum delay to allow thread scheduling
- if ((newMillis - _lastRenderTime) < _tickLength)
- sleepMs = _tickLength - (newMillis - _lastRenderTime);
+ if ((newMillis - _lastRenderTime) < _tickLength * 2)
+ sleepMs = _tickLength * 2 - (newMillis - _lastRenderTime);
assert(sleepMs >= 0);
_system->delayMillis(sleepMs);
_lastRenderTime = _system->getMillis();
@@ -484,7 +495,51 @@ void ToonEngine::copyToVirtualScreen(bool updateScreen) {
_cursorAnimationInstance->setPosition(_mouseX - 40 + state()->_currentScrollValue - _cursorOffsetX, _mouseY - 40 - _cursorOffsetY, 0, false);
_cursorAnimationInstance->render();
}
- _system->copyRectToScreen((byte *)_mainSurface->pixels + state()->_currentScrollValue, 1280, 0, 0, 640, 400);
+
+
+ // Handle dirty rects here
+ static int32 lastScroll = 0;
+
+ if (_dirtyAll || _gameState->_currentScrollValue != lastScroll) {
+ // we have to refresh everything in case of scrolling.
+ _system->copyRectToScreen((byte *)_mainSurface->pixels + state()->_currentScrollValue, 1280, 0, 0, 640, 400);
+ } else {
+
+ int32 offX = 0;
+ for (uint i = 0; i < _oldDirtyRects.size(); i++) {
+ Common::Rect rect = _oldDirtyRects[i];
+ rect.translate(-state()->_currentScrollValue,0);
+ offX = 0;
+ if(rect.right <= 0)
+ continue;
+ if (rect.left < 0) {
+ offX = -rect.left;
+ rect.left = 0;
+ }
+ rect.clip(640, 400);
+ if (rect.left >= 0 && rect.top >= 0 && rect.right - rect.left > 0 && rect.bottom - rect.top > 0) {
+ _system->copyRectToScreen((byte *)_mainSurface->pixels + _oldDirtyRects[i].left + offX + _oldDirtyRects[i].top * 1280, 1280, rect.left , rect.top, rect.right - rect.left, rect.bottom - rect.top);
+ }
+ }
+
+ for (uint i = 0; i < _dirtyRects.size(); i++) {
+ Common::Rect rect = _dirtyRects[i];
+ rect.translate(-state()->_currentScrollValue,0);
+ offX = 0;
+ if (rect.right <= 0)
+ continue;
+ if (rect.left < 0) {
+ offX = -rect.left;
+ rect.left = 0;
+ }
+ rect.clip(640, 400);
+ if (rect.left >= 0 && rect.top >= 0 && rect.right - rect.left > 0 && rect.bottom - rect.top > 0) {
+ _system->copyRectToScreen((byte *)_mainSurface->pixels + _dirtyRects[i].left + offX + _dirtyRects[i].top * 1280, 1280, rect.left , rect.top, rect.right - rect.left, rect.bottom - rect.top);
+ }
+ }
+ }
+ lastScroll = _gameState->_currentScrollValue;
+
if (updateScreen) {
_system->updateScreen();
_shouldQuit = shouldQuit(); // update game quit flag - this shouldn't be called all the time, as it's a virtual function
@@ -589,6 +644,7 @@ bool ToonEngine::showMainmenu(bool &loadedGame) {
bool musicPlaying = false;
_gameState->_inMenu = true;
+ dirtyAllScreen();
while (!doExit) {
clickingOn = MAINMENUHOTSPOT_NONE;
@@ -607,7 +663,15 @@ bool ToonEngine::showMainmenu(bool &loadedGame) {
}
while (!clickRelease) {
- mainmenuPicture->draw(*_mainSurface, 0, 0, 0, 0);
+
+ if(_dirtyAll) {
+ mainmenuPicture->draw(*_mainSurface, 0, 0, 0, 0);
+ addDirtyRect(0,0,640,400);
+ } else {
+ mainmenuPicture->drawWithRectList(*_mainSurface, 0, 0, 0, 0, _dirtyRects);
+ }
+
+ clearDirtyRects();
for (int entryNr = 0; entryNr < MAINMENU_ENTRYCOUNT; entryNr++) {
if (entries[entryNr].menuMask & menuMask) {
@@ -1211,6 +1275,9 @@ void ToonEngine::loadScene(int32 SceneId, bool forGameLoad) {
state()->_mouseHidden = false;
+ clearDirtyRects();
+ dirtyAllScreen();
+
if (!forGameLoad) {
_script->start(&_scriptState[0], 0);
@@ -2562,7 +2629,13 @@ void ToonEngine::renderInventory() {
if (!_gameState->_inInventory)
return;
- _inventoryPicture->draw(*_mainSurface, 0, 0, 0, 0);
+ if (!_dirtyAll) {
+ _inventoryPicture->drawWithRectList(*_mainSurface, 0, 0, 0, 0, _dirtyRects);
+ } else {
+ _inventoryPicture->draw(*_mainSurface, 0, 0, 0, 0);
+ _dirtyRects.push_back(Common::Rect(0,0,640,400));
+ }
+ clearDirtyRects();
// draw items on screen
for (int32 i = 0; i < _gameState->_numInventoryItems; i++) {
@@ -2597,6 +2670,7 @@ int32 ToonEngine::showInventory() {
fadeOut(5);
_inventoryPicture->loadPicture("SACK128.CPS", true);
_inventoryPicture->setupPalette();
+ dirtyAllScreen();
if (_gameState->_mouseState >= 0) {
setCursor(_gameState->_mouseState, true, -18, -14);
@@ -2710,6 +2784,7 @@ int32 ToonEngine::showInventory() {
setupGeneralPalette();
}
flushPalette();
+ dirtyAllScreen();
_firstFrame = true;
return 0;
@@ -2784,6 +2859,7 @@ void ToonEngine::showCutaway(Common::String cutawayPicture) {
_currentCutaway->setupPalette();
_oldScrollValue = _gameState->_currentScrollValue;
_gameState->_currentScrollValue = 0;
+ dirtyAllScreen();
flushPalette();
}
@@ -2794,6 +2870,7 @@ void ToonEngine::hideCutaway() {
_gameState->_currentScrollValue = _oldScrollValue;
_currentCutaway = 0;
_currentPicture->setupPalette();
+ dirtyAllScreen();
flushPalette();
}
@@ -4673,6 +4750,47 @@ void ToonEngine::playRoomMusic() {
_audioManager->playMusic(_gameState->_locations[_gameState->_currentScene]._name, _gameState->_locations[_gameState->_currentScene]._music);
}
+void ToonEngine::dirtyAllScreen()
+{
+ _dirtyRects.clear();
+ _dirtyAll = true;
+}
+
+void ToonEngine::addDirtyRect( int32 left, int32 top, int32 right, int32 bottom ) {
+ left = MAX<int32>(left, 0);
+ right = MIN<int32>(right, 1280);
+ top = MAX<int32>(top, 0);
+ bottom = MIN<int32>(bottom, 400);
+
+ Common::Rect rect(left,top,right,bottom);
+
+ if (bottom - top <= 0 || right - left <= 0)
+ return;
+
+ for (uint32 i = 0; i < _dirtyRects.size(); i++) {
+ if (_dirtyRects[i].contains(rect))
+ return;
+ if (rect.contains(_dirtyRects[i])) {
+ _dirtyRects.remove_at(i);
+ i--;
+ }
+ }
+
+ // check also in the old rect (of the old frame)
+ for (int32 i = _oldDirtyRects.size() - 1 ; i >= 0; i--) {
+ if (rect.contains(_oldDirtyRects[i])) {
+ _oldDirtyRects.remove_at(i);
+ }
+ }
+
+ _dirtyRects.push_back(rect);
+}
+
+void ToonEngine::clearDirtyRects() {
+ _oldDirtyRects = _dirtyRects;
+ _dirtyRects.clear();
+ _dirtyAll = false;
+}
void SceneAnimation::save(ToonEngine *vm, Common::WriteStream *stream) {
stream->writeByte(_active);
stream->writeSint32BE(_id);
diff --git a/engines/toon/toon.h b/engines/toon/toon.h
index f3370aed5e..dca6bfe78e 100644
--- a/engines/toon/toon.h
+++ b/engines/toon/toon.h
@@ -334,6 +334,10 @@ public:
(f == kSupportsSavingDuringRuntime);
}
+ void dirtyAllScreen();
+ void addDirtyRect(int32 left, int32 top, int32 right, int32 bottom);
+ void clearDirtyRects();
+
protected:
OSystem *_system;
int32 _tickLength;
@@ -371,6 +375,11 @@ protected:
bool _updatingSceneScriptRunFlag;
Graphics::Surface *_mainSurface;
+ Common::Array<Common::Rect> _dirtyRects;
+ Common::Array<Common::Rect> _oldDirtyRects;
+
+ bool _dirtyAll;
+
AnimationInstance *_cursorAnimationInstance;
Animation *_cursorAnimation;