Bug 1438551 - Don't discard the back buffer when we reuse the front buffer. r?nical
It can happen often where we reuse the front buffer for a long paint, and then
the next frame we see that it is still locked, and need to allocate a new buffer
from the texture pool. If this happens we don't need to repaint the new buffer
because the old buffer is still around, but we do need to copy it over and
upload it to texture sources. It seems better to just hold onto the back buffer
and let it accumulate more invalid regions.
MozReview-Commit-ID: 2DQjwAX7ZmM
--- a/gfx/layers/client/TiledContentClient.cpp
+++ b/gfx/layers/client/TiledContentClient.cpp
@@ -682,19 +682,25 @@ TileClient::GetBackBuffer(CompositableCl
}
// Try to re-use the front-buffer if possible
if (mFrontBuffer &&
mFrontBuffer->HasIntermediateBuffer() &&
!mFrontBuffer->IsReadLocked() &&
(aMode != SurfaceMode::SURFACE_COMPONENT_ALPHA || (
mFrontBufferOnWhite && !mFrontBufferOnWhite->IsReadLocked()))) {
- // If we had a backbuffer we no longer care about it since we'll
- // re-use the front buffer.
- DiscardBackBuffer();
+ // If we had a backbuffer we no longer need it since we can re-use the
+ // front buffer here. It can be worth it to hold on to the back buffer
+ // so we don't need to pay the cost of initializing a new back buffer
+ // later (copying pixels and texture upload). But this could increase
+ // our memory usage and lead to OOM more frequently from spikes in usage,
+ // so we have this behavior behind a pref.
+ if (!gfxPrefs::LayersTileRetainBackBuffer()) {
+ DiscardBackBuffer();
+ }
Flip();
} else {
if (!mBackBuffer || mBackBuffer->IsReadLocked()) {
mBackBuffer.Set(this,
CreateBackBufferTexture(mBackBuffer, aCompositable, mAllocator)
);
if (!mBackBuffer) {
DiscardBackBuffer();
--- a/gfx/thebes/gfxPrefs.h
+++ b/gfx/thebes/gfxPrefs.h
@@ -628,16 +628,17 @@ private:
// they are often the same size as the screen, especially for width.
DECL_GFX_PREF(Once, "layers.tile-width", LayersTileWidth, int32_t, 256);
DECL_GFX_PREF(Once, "layers.tile-height", LayersTileHeight, int32_t, 256);
DECL_GFX_PREF(Once, "layers.tile-initial-pool-size", LayersTileInitialPoolSize, uint32_t, (uint32_t)50);
DECL_GFX_PREF(Once, "layers.tile-pool-unused-size", LayersTilePoolUnusedSize, uint32_t, (uint32_t)10);
DECL_GFX_PREF(Once, "layers.tile-pool-shrink-timeout", LayersTilePoolShrinkTimeout, uint32_t, (uint32_t)50);
DECL_GFX_PREF(Once, "layers.tile-pool-clear-timeout", LayersTilePoolClearTimeout, uint32_t, (uint32_t)5000);
DECL_GFX_PREF(Once, "layers.tiles.adjust", LayersTilesAdjust, bool, true);
+ DECL_GFX_PREF(Live, "layers.tiles.retain-back-buffer", LayersTileRetainBackBuffer, bool, true);
DECL_GFX_PREF(Once, "layers.tiles.edge-padding", TileEdgePaddingEnabled, bool, true);
DECL_GFX_PREF(Live, "layers.tiles.fade-in.enabled", LayerTileFadeInEnabled, bool, false);
DECL_GFX_PREF(Live, "layers.tiles.fade-in.duration-ms", LayerTileFadeInDuration, uint32_t, 250);
DECL_GFX_PREF(Live, "layers.transaction.warning-ms", LayerTransactionWarning, uint32_t, 200);
DECL_GFX_PREF(Once, "layers.uniformity-info", UniformityInfo, bool, false);
DECL_GFX_PREF(Once, "layers.use-image-offscreen-surfaces", UseImageOffscreenSurfaces, bool, true);
DECL_GFX_PREF(Live, "layers.draw-mask-debug", DrawMaskLayer, bool, false);
--- a/modules/libpref/init/all.js
+++ b/modules/libpref/init/all.js
@@ -4830,16 +4830,17 @@ pref("layers.draw-borders", false);
pref("layers.draw-tile-borders", false);
pref("layers.draw-bigimage-borders", false);
pref("layers.enable-tiles", false);
pref("layers.single-tile.enabled", true);
pref("layers.low-precision-buffer", false);
pref("layers.progressive-paint", false);
pref("layers.tile-width", 256);
pref("layers.tile-height", 256);
+pref("layers.tiles.retain-back-buffer", true);
pref("layers.child-process-shutdown", true);
// Max number of layers per container. See Overwrite in mobile prefs.
pref("layers.max-active", -1);
// If this is set the tile size will only be treated as a suggestion.
// On B2G we will round this to the stride of the underlying allocation.
// On any platform we may later use the screen size and ignore
// tile-width/tile-height entirely. Its recommended to turn this off
// if you change the tile size.