[Scummvm-cvs-logs] CVS: scummvm/sword2/driver d_draw.cpp,1.51,1.52 d_draw.h,1.17,1.18 palette.cpp,1.26,1.27 rdwin.cpp,1.39,1.40 render.cpp,1.45,1.46 sprite.cpp,1.36,1.37
Torbj?rn Andersson
eriktorbjorn at users.sourceforge.net
Sun Jan 4 07:12:21 CET 2004
Update of /cvsroot/scummvm/scummvm/sword2/driver
In directory sc8-pr-cvs1:/tmp/cvs-serv17578/driver
Modified Files:
d_draw.cpp d_draw.h palette.cpp rdwin.cpp render.cpp
sprite.cpp
Log Message:
Adapted LavosSpawn's idea for more efficient screen updating. It still
renders the entire screen every frame, but it tries to update (i.e. copy to
the backend) only the parts of the screen that actually changed. At least
approximately so.
Index: d_draw.cpp
===================================================================
RCS file: /cvsroot/scummvm/scummvm/sword2/driver/d_draw.cpp,v
retrieving revision 1.51
retrieving revision 1.52
diff -u -d -r1.51 -r1.52
--- d_draw.cpp 28 Dec 2003 15:08:11 -0000 1.51
+++ d_draw.cpp 4 Jan 2004 15:11:30 -0000 1.52
@@ -32,12 +32,24 @@
int i, j;
+ _buffer = _dirtyGrid = NULL;
+
_buffer = (byte *) malloc(width * height);
if (!_buffer)
error("Could not initialise display");
_vm->_system->init_size(width, height);
+ _gridWide = width / CELLWIDE;
+ _gridDeep = height / CELLDEEP;
+
+ if ((width % CELLWIDE) || (height % CELLDEEP))
+ error("Bad cell size");
+
+ _dirtyGrid = (byte *) calloc(_gridWide, _gridDeep);
+ if (!_buffer)
+ error("Could not initialise dirty grid");
+
for (i = 0; i < ARRAYSIZE(_blockSurfaces); i++)
_blockSurfaces[i] = NULL;
@@ -51,6 +63,11 @@
}
}
+Graphics::~Graphics() {
+ free(_buffer);
+ free(_dirtyGrid);
+}
+
/**
* @return the graphics detail setting
*/
@@ -199,6 +216,7 @@
if (frameCounter == text[textCounter]->endFrame) {
closeTextObject(text[textCounter]);
_vm->_graphics->clearScene();
+ _vm->_graphics->setNeedFullRedraw();
textCounter++;
}
Index: d_draw.h
===================================================================
RCS file: /cvsroot/scummvm/scummvm/sword2/driver/d_draw.h,v
retrieving revision 1.17
retrieving revision 1.18
diff -u -d -r1.17 -r1.18
--- d_draw.h 28 Dec 2003 15:08:11 -0000 1.17
+++ d_draw.h 4 Jan 2004 15:11:30 -0000 1.18
@@ -41,6 +41,10 @@
#define SCALE_MAXWIDTH 512
#define SCALE_MAXHEIGHT 512
+// Dirty grid cell size
+#define CELLWIDE 10
+#define CELLDEEP 20
+
#if !defined(__GNUC__)
#pragma START_PACK_STRUCTS
#endif
@@ -85,6 +89,10 @@
Sword2Engine *_vm;
byte *_buffer;
+ byte *_dirtyGrid;
+
+ uint16 _gridWide;
+ uint16 _gridDeep;
int32 _renderCaps;
int8 _renderLevel;
@@ -179,6 +187,7 @@
public:
Graphics(Sword2Engine *vm, int16 width, int16 height);
+ ~Graphics();
// Game screen metrics
int16 _screenWide;
@@ -197,7 +206,7 @@
int32 setMenuIcon(uint8 menu, uint8 pocket, uint8 *icon);
void closeMenuImmediately(void);
- void updateDisplay(void);
+ void updateDisplay(bool redrawScene = true);
void setWindowName(const char *windowName);
void setNeedFullRedraw(void);
Index: palette.cpp
===================================================================
RCS file: /cvsroot/scummvm/scummvm/sword2/driver/palette.cpp,v
retrieving revision 1.26
retrieving revision 1.27
diff -u -d -r1.26 -r1.27
--- palette.cpp 16 Nov 2003 14:18:29 -0000 1.26
+++ palette.cpp 4 Jan 2004 15:11:30 -0000 1.27
@@ -113,10 +113,14 @@
void Graphics::setPalette(int16 startEntry, int16 noEntries, uint8 *colourTable, uint8 fadeNow) {
if (noEntries) {
memcpy(&_palCopy[startEntry][0], colourTable, noEntries * 4);
- if (fadeNow == RDPAL_INSTANT)
+ if (fadeNow == RDPAL_INSTANT) {
_vm->_system->set_palette((const byte *) _palCopy, startEntry, noEntries);
- } else
+ setNeedFullRedraw();
+ }
+ } else {
_vm->_system->set_palette((const byte *) _palCopy, 0, 256);
+ setNeedFullRedraw();
+ }
}
void Graphics::dimPalette(void) {
@@ -126,6 +130,7 @@
p[i] /= 2;
_vm->_system->set_palette(p, 0, 256);
+ setNeedFullRedraw();
}
/**
@@ -227,6 +232,7 @@
}
_vm->_system->set_palette(newPalette, 0, 256);
+ setNeedFullRedraw();
}
} // End of namespace Sword2
Index: rdwin.cpp
===================================================================
RCS file: /cvsroot/scummvm/scummvm/sword2/driver/rdwin.cpp,v
retrieving revision 1.39
retrieving revision 1.40
diff -u -d -r1.39 -r1.40
--- rdwin.cpp 19 Dec 2003 16:50:03 -0000 1.39
+++ rdwin.cpp 4 Jan 2004 15:11:30 -0000 1.40
@@ -66,28 +66,78 @@
}
}
-void Graphics::setNeedFullRedraw() {
+/**
+ * Tell updateDisplay() that the scene needs to be completely updated.
+ */
+
+void Graphics::setNeedFullRedraw(void) {
_needFullRedraw = true;
}
/**
- * This function should be called at a high rate (> 20 per second) to service
- * windows and the interface it provides.
+ * This function has two purposes: It redraws the scene, and it handles input
+ * events, palette fading, etc. It should be called at a high rate (> 20 per
+ * second), but the scene is usually only redrawn about 12 times per second,
+ * except when then screen is scrolling.
+ *
+ * @param redrawScene If true, redraw the scene.
*/
-void Graphics::updateDisplay(void) {
+void Graphics::updateDisplay(bool redrawScene) {
_vm->_input->parseEvents();
fadeServer();
- // FIXME: We re-render the entire picture area of the screen for each
- // frame, which is pretty horrible.
+ if (redrawScene) {
+ int i;
- if (_needFullRedraw) {
- _vm->_system->copy_rect(_buffer + MENUDEEP * _screenWide, _screenWide, 0, MENUDEEP, _screenWide, _screenDeep - 2 * MENUDEEP);
- _needFullRedraw = false;
+ // Note that the entire scene is always rendered, which is less
+ // than optimal, but at least we can try to be intelligent
+ // about updating the screen afterwards.
+
+ if (_needFullRedraw) {
+ // Update the entire screen. This is necessary when
+ // scrolling, fading, etc.
+
+ _vm->_system->copy_rect(_buffer + MENUDEEP * _screenWide, _screenWide, 0, MENUDEEP, _screenWide, _screenDeep - 2 * MENUDEEP);
+ _needFullRedraw = false;
+ } else {
+ // Update only the dirty areas of the screen
+
+ int j, x, y;
+ int stripWide;
+
+ for (i = 0; i < _gridDeep; i++) {
+ stripWide = 0;
+
+ for (j = 0; j < _gridWide; j++) {
+ if (_dirtyGrid[i * _gridWide + j]) {
+ stripWide++;
+ } else if (stripWide) {
+ x = CELLWIDE * (j - stripWide);
+ y = CELLDEEP * i;
+ _vm->_system->copy_rect(_buffer + y * _screenWide + x, _screenWide, x, y, stripWide * CELLWIDE, CELLDEEP);
+ stripWide = 0;
+ }
+ }
+
+ if (stripWide) {
+ x = CELLWIDE * (j - stripWide);
+ y = CELLDEEP * i;
+ _vm->_system->copy_rect(_buffer + y * _screenWide + x, _screenWide, x, y, stripWide * CELLWIDE, CELLDEEP);
+ stripWide = 0;
+ }
+ }
+ }
+
+ // Age the dirty cells one generation. This way we keep track
+ // of both the cells that were updated this time, and the ones
+ // that were updated the last time.
+
+ for (i = 0; i < _gridWide * _gridDeep; i++)
+ _dirtyGrid[i] >>= 1;
}
- // We still need to update because of fades, menu animations, etc.
+ // We always need to update because of fades, menu animations, etc.
_vm->_system->update_screen();
}
Index: render.cpp
===================================================================
RCS file: /cvsroot/scummvm/scummvm/sword2/driver/render.cpp,v
retrieving revision 1.45
retrieving revision 1.46
diff -u -d -r1.45 -r1.46
--- render.cpp 28 Dec 2003 15:08:12 -0000 1.45
+++ render.cpp 4 Jan 2004 15:11:30 -0000 1.46
@@ -75,7 +75,7 @@
}
// UploadRect(r);
- setNeedFullRedraw();
+ // setNeedFullRedraw();
}
// I've made the scaling two separate functions because there were cases from
@@ -519,6 +519,7 @@
void Graphics::setLocationMetrics(uint16 w, uint16 h) {
_locationWide = w;
_locationDeep = h;
+ setNeedFullRedraw();
}
/**
@@ -598,6 +599,9 @@
_renderTooSlow = false;
}
+ if (_scrollXOld != _scrollX || _scrollYOld != _scrollY)
+ setNeedFullRedraw();
+
_framesPerGameCycle = 0;
}
@@ -655,6 +659,9 @@
_scrollX = (int16) (_scrollXOld + ((_scrollXTarget - _scrollXOld) * (_startTime - _initialTime + _renderAverageTime)) / (_totalTime - _initialTime));
_scrollY = (int16) (_scrollYOld + ((_scrollYTarget - _scrollYOld) * (_startTime - _initialTime + _renderAverageTime)) / (_totalTime - _initialTime));
}
+
+ if (_scrollX != _scrollXOld || _scrollY != _scrollYOld)
+ setNeedFullRedraw();
return false;
}
Index: sprite.cpp
===================================================================
RCS file: /cvsroot/scummvm/scummvm/sword2/driver/sprite.cpp,v
retrieving revision 1.36
retrieving revision 1.37
diff -u -d -r1.36 -r1.37
--- sprite.cpp 28 Dec 2003 15:08:12 -0000 1.36
+++ sprite.cpp 4 Jan 2004 15:11:30 -0000 1.37
@@ -320,7 +320,6 @@
}
updateRect(&rd);
- setNeedFullRedraw();
}
/**
@@ -613,9 +612,17 @@
if (freeSprite)
free(sprite);
- // updateRect(&rd);
- setNeedFullRedraw();
+ // Mark the approximate area of the sprite as "dirty", first generation
+ int16 gridX1 = rd.left / CELLWIDE;
+ int16 gridY1 = rd.top / CELLDEEP;
+ int16 gridX2 = (rd.right - 1) / CELLWIDE;
+ int16 gridY2 = (rd.bottom - 1) / CELLDEEP;
+
+ for (i = gridY1; i <= gridY2; i++)
+ for (j = gridX1; j <= gridX2; j++)
+ _dirtyGrid[i * _gridWide + j] = 2;
+
return RD_OK;
}
More information about the Scummvm-git-logs
mailing list