Bug 749143 - Don't draw retained tiles outside of layer bounds. r=bgirard

It is possible for the content that layers represent to change size, causing
tiles to be reused where they shouldn't. Make sure that tiles that are outside
of content bounds are not drawn, and that they get evicted when harvesting
tiles.
This commit is contained in:
Chris Lord 2012-04-26 12:53:14 -04:00
parent 5c8f163884
commit a7e24267f0
3 changed files with 32 additions and 4 deletions

View File

@ -20,6 +20,7 @@ ReusableTileStoreOGL::~ReusableTileStoreOGL()
void
ReusableTileStoreOGL::HarvestTiles(TiledLayerBufferOGL* aVideoMemoryTiledBuffer,
const nsIntSize& aContentSize,
const nsIntRegion& aOldValidRegion,
const nsIntRegion& aNewValidRegion,
const gfxSize& aOldResolution,
@ -33,21 +34,33 @@ ReusableTileStoreOGL::HarvestTiles(TiledLayerBufferOGL* aVideoMemoryTiledBuffer,
#endif
// Iterate over existing harvested tiles and release any that are contained
// within the new valid region.
// within the new valid region, or that fall outside of the layer.
mContext->MakeCurrent();
for (int i = 0; i < mTiles.Length();) {
ReusableTiledTextureOGL* tile = mTiles[i];
nsIntRect tileRect;
bool release = false;
if (tile->mResolution == aNewResolution) {
if (aNewValidRegion.Contains(tile->mTileRegion))
if (aNewValidRegion.Contains(tile->mTileRegion)) {
release = true;
} else {
tileRect = tile->mTileRegion.GetBounds();
}
} else {
nsIntRegion transformedTileRegion(tile->mTileRegion);
transformedTileRegion.ScaleRoundOut(tile->mResolution.width / aNewResolution.width,
tile->mResolution.height / aNewResolution.height);
if (aNewValidRegion.Contains(transformedTileRegion))
release = true;
else
tileRect = transformedTileRegion.GetBounds();
}
if (!release) {
if (tileRect.width > aContentSize.width ||
tileRect.height > aContentSize.height)
release = true;
}
if (release) {
@ -143,6 +156,7 @@ ReusableTileStoreOGL::HarvestTiles(TiledLayerBufferOGL* aVideoMemoryTiledBuffer,
void
ReusableTileStoreOGL::DrawTiles(TiledThebesLayerOGL* aLayer,
const nsIntSize& aContentSize,
const nsIntRegion& aValidRegion,
const gfxSize& aResolution,
const gfx3DMatrix& aTransform,
@ -165,6 +179,13 @@ ReusableTileStoreOGL::DrawTiles(TiledThebesLayerOGL* aLayer,
if (aValidRegion.Contains(transformedTileRegion))
continue;
// Skip drawing tiles that have fallen outside of the layer area (these
// will be discarded next time tiles are harvested).
nsIntRect transformedTileRect = transformedTileRegion.GetBounds();
if (transformedTileRect.XMost() > aContentSize.width ||
transformedTileRect.YMost() > aContentSize.height)
continue;
// Reconcile the resolution difference by adjusting the transform.
gfx3DMatrix transform = aTransform;
if (aResolution != tile->mResolution)

View File

@ -62,6 +62,7 @@ public:
// aNewValidRegion and aNewResolution should be the valid region and
// resolution of the data that is about to update aVideoMemoryTiledBuffer.
void HarvestTiles(TiledLayerBufferOGL* aVideoMemoryTiledBuffer,
const nsIntSize& aContentSize,
const nsIntRegion& aOldValidRegion,
const nsIntRegion& aNewValidRegion,
const gfxSize& aOldResolution,
@ -71,6 +72,7 @@ public:
// Differences in resolution will be reconciled via altering the given
// transformation.
void DrawTiles(TiledThebesLayerOGL* aLayer,
const nsIntSize& aContentSize,
const nsIntRegion& aValidRegion,
const gfxSize& aResolution,
const gfx3DMatrix& aTransform,

View File

@ -155,7 +155,9 @@ TiledThebesLayerOGL::ProcessUploadQueue()
resolution.height *= metrics.mResolution.height;
}
const FrameMetrics& metrics = GetParent()->GetFrameMetrics();
mReusableTileStore->HarvestTiles(&mVideoMemoryTiledBuffer,
metrics.mContentSize,
mVideoMemoryTiledBuffer.GetValidRegion(),
mMainMemoryTiledBuffer.GetValidRegion(),
mVideoMemoryTiledBuffer.GetResolution(),
@ -212,10 +214,13 @@ TiledThebesLayerOGL::RenderLayer(int aPreviousFrameBuffer, const nsIntPoint& aOf
ProcessUploadQueue();
// Render old tiles to fill in gaps we haven't had the time to render yet.
if (mReusableTileStore)
mReusableTileStore->DrawTiles(this, mVideoMemoryTiledBuffer.GetValidRegion(),
if (mReusableTileStore) {
const FrameMetrics& metrics = GetParent()->GetFrameMetrics();
mReusableTileStore->DrawTiles(this, metrics.mContentSize,
mVideoMemoryTiledBuffer.GetValidRegion(),
mVideoMemoryTiledBuffer.GetResolution(),
GetEffectiveTransform(), aOffset);
}
// Render valid tiles.
const nsIntRegion& visibleRegion = GetEffectiveVisibleRegion();