mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-26 22:32:46 +00:00
Bug 737434 - Reuse tiles when resizing tiled textures. r=bgirard
Instead of scrapping all tiles when a tiled texture is resized, reuse as many tiles as possible. Strictly speaking, more tiles could be reused, but the selected reuse strategy maintains the spacial structure of the texture, and we don't often resize in such a way as to make this inefficient.
This commit is contained in:
parent
92ca2da37c
commit
7c32133736
@ -866,6 +866,8 @@ TiledTextureImage::TiledTextureImage(GLContext* aGL,
|
||||
: TextureImage(aSize, LOCAL_GL_CLAMP_TO_EDGE, aContentType, aUseNearestFilter)
|
||||
, mCurrentImage(0)
|
||||
, mInUpdate(false)
|
||||
, mRows(0)
|
||||
, mColumns(0)
|
||||
, mGL(aGL)
|
||||
, mUseNearestFilter(aUseNearestFilter)
|
||||
, mTextureState(Created)
|
||||
@ -1114,30 +1116,98 @@ TiledTextureImage::ApplyFilter()
|
||||
}
|
||||
|
||||
/*
|
||||
* simple resize, just discards everything. we can be more clever just
|
||||
* adding or discarding tiles, but do we want this?
|
||||
* Resize, trying to reuse tiles. The reuse strategy is to decide on reuse per
|
||||
* column. A tile on a column is reused if it hasn't changed size, otherwise it
|
||||
* is discarded/replaced. Extra tiles on a column are pruned after iterating
|
||||
* each column, and extra rows are pruned after iteration over the entire image
|
||||
* finishes.
|
||||
*/
|
||||
void TiledTextureImage::Resize(const nsIntSize& aSize)
|
||||
{
|
||||
if (mSize == aSize && mTextureState != Created) {
|
||||
return;
|
||||
}
|
||||
mSize = aSize;
|
||||
mImages.Clear();
|
||||
// calculate rows and columns, rounding up
|
||||
mColumns = (aSize.width + mTileSize - 1) / mTileSize;
|
||||
mRows = (aSize.height + mTileSize - 1) / mTileSize;
|
||||
|
||||
for (unsigned int row = 0; row < mRows; row++) {
|
||||
for (unsigned int col = 0; col < mColumns; col++) {
|
||||
nsIntSize size( // use tilesize first, then the remainder
|
||||
(col+1) * mTileSize > (unsigned int)aSize.width ? aSize.width % mTileSize : mTileSize,
|
||||
(row+1) * mTileSize > (unsigned int)aSize.height ? aSize.height % mTileSize : mTileSize);
|
||||
nsRefPtr<TextureImage> teximg =
|
||||
mGL->TileGenFunc(size, mContentType, mUseNearestFilter);
|
||||
mImages.AppendElement(teximg.forget());
|
||||
}
|
||||
// calculate rows and columns, rounding up
|
||||
unsigned int columns = (aSize.width + mTileSize - 1) / mTileSize;
|
||||
unsigned int rows = (aSize.height + mTileSize - 1) / mTileSize;
|
||||
|
||||
// Iterate over old tile-store and insert/remove tiles as necessary
|
||||
int row;
|
||||
unsigned int i = 0;
|
||||
for (row = 0; row < (int)rows; row++) {
|
||||
// If we've gone beyond how many rows there were before, set mColumns to
|
||||
// zero so that we only create new tiles.
|
||||
if (row >= (int)mRows)
|
||||
mColumns = 0;
|
||||
|
||||
// Similarly, if we're on the last row of old tiles and the height has
|
||||
// changed, discard all tiles in that row.
|
||||
// This will cause the pruning of columns not to work, but we don't need
|
||||
// to worry about that, as no more tiles will be reused past this point
|
||||
// anyway.
|
||||
if ((row == (int)mRows - 1) && (aSize.height != mSize.height))
|
||||
mColumns = 0;
|
||||
|
||||
int col;
|
||||
for (col = 0; col < (int)columns; col++) {
|
||||
nsIntSize size( // use tilesize first, then the remainder
|
||||
(col+1) * mTileSize > (unsigned int)aSize.width ? aSize.width % mTileSize : mTileSize,
|
||||
(row+1) * mTileSize > (unsigned int)aSize.height ? aSize.height % mTileSize : mTileSize);
|
||||
|
||||
bool replace = false;
|
||||
|
||||
// Check if we can re-use old tiles.
|
||||
if (col < (int)mColumns) {
|
||||
// Reuse an existing tile. If the tile is an end-tile and the
|
||||
// width differs, replace it instead.
|
||||
if (mSize.width != aSize.width) {
|
||||
if (col == (int)mColumns - 1) {
|
||||
// Tile at the end of the old column, replace it with
|
||||
// a new one.
|
||||
replace = true;
|
||||
} else if (col == (int)columns - 1) {
|
||||
// Tile at the end of the new column, create a new one.
|
||||
} else {
|
||||
// Before the last column on both the old and new sizes,
|
||||
// reuse existing tile.
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
// Width hasn't changed, reuse existing tile.
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// Create a new tile.
|
||||
nsRefPtr<TextureImage> teximg =
|
||||
mGL->TileGenFunc(size, mContentType, mUseNearestFilter);
|
||||
if (replace)
|
||||
mImages.ReplaceElementAt(i, &teximg.forget());
|
||||
else
|
||||
mImages.InsertElementAt(i, teximg.forget());
|
||||
i++;
|
||||
}
|
||||
|
||||
// Prune any unused tiles on the end of the column.
|
||||
if (row < (int)mRows) {
|
||||
for (col = (int)mColumns - col; col > 0; col--) {
|
||||
mImages.RemoveElementAt(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Prune any unused tiles at the end of the store.
|
||||
unsigned int length = mImages.Length();
|
||||
for (; i < length; i++)
|
||||
mImages.RemoveElementAt(mImages.Length()-1);
|
||||
|
||||
// Reset tile-store properties.
|
||||
mRows = rows;
|
||||
mColumns = columns;
|
||||
mSize = aSize;
|
||||
mTextureState = Allocated;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user