From dba6881f180a44cfdbe4862ab0733147ebb811b9 Mon Sep 17 00:00:00 2001 From: Benoit Girard Date: Mon, 15 Oct 2012 15:08:45 -0400 Subject: [PATCH] Bug 796117 - Keep tiles cached when changing resolution. r=Cwiiis --HG-- extra : rebase_source : fdc4bb831c367d2d33dadb75c6d1f9784b97d44d --- gfx/layers/basic/BasicTiledThebesLayer.cpp | 6 +++ gfx/layers/opengl/ReusableTileStoreOGL.cpp | 54 +++++++++++----------- 2 files changed, 34 insertions(+), 26 deletions(-) diff --git a/gfx/layers/basic/BasicTiledThebesLayer.cpp b/gfx/layers/basic/BasicTiledThebesLayer.cpp index f33266f61b6a..21dd7276ad90 100644 --- a/gfx/layers/basic/BasicTiledThebesLayer.cpp +++ b/gfx/layers/basic/BasicTiledThebesLayer.cpp @@ -263,6 +263,12 @@ BasicTiledThebesLayer::PaintThebes(gfxContext* aContext, resolution.height *= metrics.mResolution.height; } + // If the resolution has changed, discard all the old tiles. + // They will end up being retained on the shadow side by ReusableTileStoreOGL + if (mTiledBuffer.GetResolution() != resolution) { + mValidRegion = nsIntRegion(); + } + // Calculate the scroll offset since the last transaction. Progressive tile // painting is only used when scrolling. gfx::Point scrollOffset(0, 0); diff --git a/gfx/layers/opengl/ReusableTileStoreOGL.cpp b/gfx/layers/opengl/ReusableTileStoreOGL.cpp index baa7c8858125..cc5a4a46c59d 100644 --- a/gfx/layers/opengl/ReusableTileStoreOGL.cpp +++ b/gfx/layers/opengl/ReusableTileStoreOGL.cpp @@ -59,33 +59,19 @@ ReusableTileStoreOGL::InvalidateTiles(TiledThebesLayerOGL* aLayer, mContext->MakeCurrent(); for (uint32_t i = 0; i < mTiles.Length();) { ReusableTiledTextureOGL* tile = mTiles[i]; - - // Check if the tile region is contained within the new valid region. - nsIntRect tileRect; bool release = false; - if (tile->mResolution == aResolution) { - if (aValidRegion.Contains(tile->mTileRegion)) { - release = true; - } else { - tileRect = tile->mTileRegion.GetBounds(); - } - } else { + + nsIntRect tileRect = tile->mTileRegion.GetBounds(); + if (tile->mResolution != aResolution) { nsIntRegion transformedTileRegion(tile->mTileRegion); transformedTileRegion.ScaleRoundOut(tile->mResolution.width / aResolution.width, tile->mResolution.height / aResolution.height); - if (aValidRegion.Contains(transformedTileRegion)) - release = true; - else - tileRect = transformedTileRegion.GetBounds(); + tileRect = transformedTileRegion.GetBounds(); } - // If the tile region wasn't contained within the valid region, check if - // it intersects with the currently rendered region. - if (!release) { - // Transform the tile region to see if it falls inside the rendered bounds - gfxRect tileBounds = aLayer->GetEffectiveTransform().TransformBounds(gfxRect(tileRect)); - if (renderBounds.Contains(tileBounds)) - release = true; + // Check if the tile region is contained within the new valid region. + if (aValidRegion.Contains(tileRect)) { + release = true; } if (release) { @@ -134,16 +120,20 @@ ReusableTileStoreOGL::HarvestTiles(TiledThebesLayerOGL* aLayer, // A tile will consume 256^2 of memory, don't retain small tile trims. // This works around the display port sometimes creating a small 1 pixel wide // tile because of rounding error. - if (w < 16) + if (w < 16) { + x += w; continue; + } for (int y = validBounds.y; y < validBounds.YMost();) { int h = tileSize - aVideoMemoryTiledBuffer->GetTileStart(y); if (y + h > validBounds.y + validBounds.height) h = validBounds.y + validBounds.height - y; - if (h < 16) + if (h < 16) { + y += h; continue; + } // If the new valid region doesn't contain this tile region, // harvest the tile. @@ -166,9 +156,6 @@ ReusableTileStoreOGL::HarvestTiles(TiledThebesLayerOGL* aLayer, } if (retainTile) { -#ifdef GFX_TILEDLAYER_PREF_WARNINGS - printf_stderr("Retaining tile at %d,%d, x%f for reuse\n", x, y, aOldResolution.width); -#endif TiledTexture removedTile; if (aVideoMemoryTiledBuffer->RemoveTile(nsIntPoint(x, y), removedTile)) { ReusableTiledTextureOGL* reusedTile = @@ -176,6 +163,9 @@ ReusableTileStoreOGL::HarvestTiles(TiledThebesLayerOGL* aLayer, tileSize, aOldResolution); mTiles.AppendElement(reusedTile); +#ifdef GFX_TILEDLAYER_PREF_WARNINGS + bool replacedATile = false; +#endif // Remove any tile that is superseded by this new tile. // (same resolution, same area) for (int i = 0; i < mTiles.Length() - 1; i++) { @@ -186,10 +176,20 @@ ReusableTileStoreOGL::HarvestTiles(TiledThebesLayerOGL* aLayer, mTiles[i]->mResolution == aOldResolution) { mContext->fDeleteTextures(1, &mTiles[i]->mTexture.mTextureHandle); mTiles.RemoveElementAt(i); +#ifdef GFX_TILEDLAYER_PREF_WARNINGS + replacedATile = true; +#endif // There should only be one similar tile break; } } +#ifdef GFX_TILEDLAYER_PREF_WARNINGS + if (replacedATile) { + printf_stderr("Replaced tile at %d,%d, x%f for reuse\n", x, y, aOldResolution.width); + } else { + printf_stderr("New tile at %d,%d, x%f for reuse\n", x, y, aOldResolution.width); + } +#endif } #ifdef GFX_TILEDLAYER_PREF_WARNINGS else @@ -218,6 +218,7 @@ ReusableTileStoreOGL::HarvestTiles(TiledThebesLayerOGL* aLayer, } #ifdef GFX_TILEDLAYER_PREF_WARNINGS + printf_stderr("Retained tile limit: %f\n", aVideoMemoryTiledBuffer->GetTileCount() * mSizeLimit); printf_stderr("Retained %d tiles\n", mTiles.Length()); #endif } @@ -274,6 +275,7 @@ ReusableTileStoreOGL::DrawTiles(TiledThebesLayerOGL* aLayer, transform.Scale(scaleFactor.width, scaleFactor.height, 1); // Subtract the layer's valid region from the tile region. + // This region will be drawn by the layer itself. nsIntRegion transformedValidRegion(aValidRegion); if (aResolution != tile->mResolution) transformedValidRegion.ScaleRoundOut(1.0f/scaleFactor.width,