tightens memory use

This commit is contained in:
tosh 2013-04-04 11:59:16 +02:00
parent de4734d6fb
commit 284530f7d6
2 changed files with 52 additions and 13 deletions

View file

@ -96,10 +96,14 @@ namespace starfield {
Tiling tiling(k); Tiling tiling(k);
size_t nTiles = tiling.getTileCount(); size_t nTiles = tiling.getTileCount();
// REVISIT: could coalesce allocation for faster rebuild
// REVISIT: batch arrays are probably oversized, but - hey - they
// are not very large (unless for insane tiling) and we're better
// off safe than sorry
_arrData = new GpuVertex[n]; _arrData = new GpuVertex[n];
_arrTile = new Tile[nTiles + 1]; _arrTile = new Tile[nTiles + 1];
_arrBatchOffs = new GLint[nTiles]; _arrBatchOffs = new GLint[nTiles * 2];
_arrBatchCount = new GLsizei[nTiles]; _arrBatchCount = new GLsizei[nTiles * 2];
prepareVertexData(src, n, tiling, b, bMin); prepareVertexData(src, n, tiling, b, bMin);
@ -290,21 +294,31 @@ namespace starfield {
bool select(Tile* t) { bool select(Tile* t) {
if (t < _arrTile || t >= _itrTilesEnd || if (t < _arrTile || t >= _itrTilesEnd ||
!! (t->flags & Tile::visited)) { !! (t->flags & Tile::checked)) {
return false; // out of bounds or been here already
return false;
} }
if (! (t->flags & Tile::checked)) {
if (_refRenderer.visitTile(t)) // will check now and never again
t->flags |= Tile::render; t->flags |= Tile::checked;
if (_refRenderer.visitTile(t)) {
// good one -> remember (for batching) and propagate
t->flags |= Tile::render;
return true;
} }
return !! (t->flags & Tile::render); return false;
} }
void process(Tile* t) { bool process(Tile* t) {
t->flags |= Tile::visited; if (! (t->flags & Tile::visited)) {
t->flags |= Tile::visited;
return true;
}
return false;
} }
void right(Tile*& cursor) const { cursor += 1; } void right(Tile*& cursor) const { cursor += 1; }

View file

@ -11,6 +11,29 @@
/** /**
* Line scanning, iterative flood fill algorithm. * Line scanning, iterative flood fill algorithm.
*
* The strategy must obey the following contract:
*
* There is an associated cursor that represents a position on the image.
* The member functions 'left(C&)', 'right(C&)', 'up(C&)', and 'down(C&)'
* move it.
* The state of a cursor can be deferred to temporary storage (typically a
* stack or a queue) using the 'defer(C const&)' member function.
* Calling 'deferred(C&)' restores a cursor's state from temporary storage
* and removes it there.
* The 'select(C const&)' and 'process(C const&)' functions control the
* algorithm. The former is called to determine where to go. It may be
* called multiple times but does not have to (and should not) return
* 'true' more than once for a pixel to be selected (will cause memory
* overuse, otherwise). The latter will never be called for a given pixel
* unless previously selected. It may be called multiple times, in which
* case it should return 'true' upon successful processing and 'false'
* when an already processed pixel has been visited.
*
* Note: The terms "image" and "pixel" are used for illustratory purposes
* and mean "undirected graph with 4-connected 2D grid topology" and "node",
* respectively.
*
*/ */
template< class Strategy, typename Cursor > template< class Strategy, typename Cursor >
void floodFill(Cursor const& position, void floodFill(Cursor const& position,
@ -35,16 +58,18 @@ struct floodFill_impl : Strategy {
void go(Cursor position) { void go(Cursor position) {
if (! select(position)) {
return;
}
Cursor higher, lower, h,l, i; Cursor higher, lower, h,l, i;
bool higherFound, lowerFound, hf, lf; bool higherFound, lowerFound, hf, lf;
do { do {
if (! select(position)) { if (! process(position)) {
continue; continue;
} }
process(position);
higher = position; higherFound = false; higher = position; higherFound = false;
up(higher); yTest(higher, higherFound); up(higher); yTest(higher, higherFound);
lower = position; lowerFound = false; lower = position; lowerFound = false;