Okay, today’s entry is about optimizing tiled surfaces by caching them.
Here’s the deal – we have tiled surfaces, surfaces where a little square is repeated all over.
It’s great for backgrounds, as people who had a Geocities page in 1999 know (if you did not: http://wonder-tonic.com/geocitiesizer/index.php)
An example of a tiled image is the default system menu:
Another is dialogue balloons in Rosemary:
Each tile is handled more or less as a stand alone surface at every redraw, which means: huge overhead.
The fix is: cache them.
This involves hacking the renderer a bit so that it draws to a “dummy” surface and changing the UITIledImage code accordingly:
bool BaseRenderOSystem::startSpriteBatch(bool swap, int width, int height) {
if (swap) {
_swapped = true;
_auxSurface = _renderSurface;
_renderSurface = new
Graphics::Surface();
_renderSurface->create(width, height, _auxSurface->format);
}
_spriteBatch = true;
_batchNum = 1;
return STATUS_OK;
}
bool BaseRenderOSystem::endSpriteBatch(bool swap) {
if (_swapped) {
_swapped = false;
Graphics::Surface *temp;
temp = _renderSurface;
_renderSurface = _auxSurface;
_auxSurface = temp;
}
_spriteBatch = false;
_batchNum = 0;
return STATUS_OK;
}
// ....
bool UITiledImage::display(int x, int y, int width, int height) {
int tileWidth = _middleMiddle.right - _middleMiddle.left;
int tileHeight = _middleMiddle.bottom - _middleMiddle.top;
int nuColumns = (width - (_middleLeft.right - _middleLeft.left) - (_middleRight.right - _middleRight.left)) / tileWidth;
int nuRows = (height - (_upMiddle.bottom - _upMiddle.top) - (_downMiddle.bottom - _downMiddle.top)) / tileHeight;
int col, row;
assert (width != 0);
assert (height != 0);
// Below is the new if block, which is executed only once:
if (_cache == nullptr || width != _width || height != _height) {
// This as a side effect enables the special "dummy" rendering mode
_gameRef->_renderer->startSpriteBatch(true, width, height);
int x = 0;
int y = 0;
_width = width;
_height = height;
// top left/right
_image->_surface->displayTrans(x, y, _upLeft);
_image->_surface->displayTrans(x + (_upLeft.right - _upLeft.left) + nuColumns * tileWidth, y, _upRight);
// Etc, same for SW, NW, NE tiles
// tiles
if (nuRows > 0 && nuColumns > 0) {
yyy = y + (_upMiddle.bottom - _upMiddle.top);
xxx = x + (_upLeft.right - _upLeft.left);
_image->_surface->displayTrans(xxx, yyy, _middleMiddle);
_image->_surface->repeatLastDisplayOp(tileWidth, tileWidth, nuColumns, nuRows);
}
_gameRef->_renderer->endSpriteBatch(false);
// This is where we retrieve the complete image
_cache = _gameRef->_renderer->getAuxSurface();
}
Rect32 dst;
dst.top = 0;
dst.left = 0;
dst.setWidth(width);
dst.setHeight(height);
_cache->displayTrans(x, y, dst);
return STATUS_OK;
}
Then we store that surface and when we need to redraw the UITiledImage we simply use the cached version: single drawing call, less overhead.














