Bug 1289525 - Shrink the TextureClientPool to maximum size after a short delay, and clear the pool after a longer delay r=jrmuizel

This commit is contained in:
George Wright 2016-07-29 14:14:09 -04:00
parent dfa9fefa78
commit 617f4761d4
4 changed files with 66 additions and 6 deletions

View File

@ -19,11 +19,30 @@
namespace mozilla {
namespace layers {
// We want to shrink to our maximum size of N unused tiles
// after a timeout to allow for short-term budget requirements
static void
ShrinkCallback(nsITimer *aTimer, void *aClosure)
{
static_cast<TextureClientPool*>(aClosure)->ShrinkToMaximumSize();
}
// After a certain amount of inactivity, let's clear the pool so that
// we don't hold onto tiles needlessly. In general, allocations are
// cheap enough that re-allocating isn't an issue unless we're allocating
// at an inopportune time (e.g. mid-animation).
static void
ClearCallback(nsITimer *aTimer, void *aClosure)
{
static_cast<TextureClientPool*>(aClosure)->Clear();
}
TextureClientPool::TextureClientPool(LayersBackend aLayersBackend,
gfx::SurfaceFormat aFormat,
gfx::IntSize aSize,
TextureFlags aFlags,
uint32_t aShrinkTimeoutMsec,
uint32_t aClearTimeoutMsec,
uint32_t aInitialPoolSize,
uint32_t aPoolUnusedSize,
TextureForwarder* aAllocator)
@ -31,6 +50,8 @@ TextureClientPool::TextureClientPool(LayersBackend aLayersBackend,
, mFormat(aFormat)
, mSize(aSize)
, mFlags(aFlags)
, mShrinkTimeoutMsec(aShrinkTimeoutMsec)
, mClearTimeoutMsec(aClearTimeoutMsec)
, mInitialPoolSize(aInitialPoolSize)
, mPoolUnusedSize(aPoolUnusedSize)
, mOutstandingClients(0)
@ -39,7 +60,8 @@ TextureClientPool::TextureClientPool(LayersBackend aLayersBackend,
{
TCP_LOG("TexturePool %p created with maximum unused texture clients %u\n",
this, mInitialPoolSize);
mTimer = do_CreateInstance("@mozilla.org/timer;1");
mShrinkTimer = do_CreateInstance("@mozilla.org/timer;1");
mClearTimer = do_CreateInstance("@mozilla.org/timer;1");
if (aFormat == gfx::SurfaceFormat::UNKNOWN) {
gfxWarning() << "Creating texture pool for SurfaceFormat::UNKNOWN format";
}
@ -47,7 +69,8 @@ TextureClientPool::TextureClientPool(LayersBackend aLayersBackend,
TextureClientPool::~TextureClientPool()
{
mTimer->Cancel();
mShrinkTimer->Cancel();
mClearTimer->Cancel();
}
#ifdef GFX_DEBUG_TRACK_CLIENTS_IN_POOL
@ -145,6 +168,25 @@ TextureClientPool::AllocateTextureClient()
}
}
void
TextureClientPool::ResetTimers()
{
// Shrink down if we're beyond our maximum size
if (mShrinkTimeoutMsec &&
mTextureClients.size() + mTextureClientsDeferred.size() > mPoolUnusedSize) {
TCP_LOG("TexturePool %p scheduling a shrink-to-max-size\n", this);
mShrinkTimer->InitWithFuncCallback(ShrinkCallback, this, mShrinkTimeoutMsec,
nsITimer::TYPE_ONE_SHOT);
}
// Clear pool after a period of inactivity to reduce memory consumption
if (mClearTimeoutMsec) {
TCP_LOG("TexturePool %p scheduling a clear\n", this);
mClearTimer->InitWithFuncCallback(ClearCallback, this, mClearTimeoutMsec,
nsITimer::TYPE_ONE_SHOT);
}
}
void
TextureClientPool::ReturnTextureClient(TextureClient *aClient)
{
@ -162,8 +204,7 @@ TextureClientPool::ReturnTextureClient(TextureClient *aClient)
TCP_LOG("TexturePool %p had client %p returned; size %u outstanding %u\n",
this, aClient, mTextureClients.size(), mOutstandingClients);
// Shrink down if we're beyond our maximum size
ShrinkToMaximumSize();
ResetTimers();
}
void
@ -180,7 +221,8 @@ TextureClientPool::ReturnTextureClientDeferred(TextureClient* aClient)
mTextureClientsDeferred.push_back(aClient);
TCP_LOG("TexturePool %p had client %p defer-returned, size %u outstanding %u\n",
this, aClient, mTextureClientsDeferred.size(), mOutstandingClients);
ShrinkToMaximumSize();
ResetTimers();
}
void

View File

@ -48,6 +48,8 @@ public:
gfx::SurfaceFormat aFormat,
gfx::IntSize aSize,
TextureFlags aFlags,
uint32_t aShrinkTimeoutMsec,
uint32_t aClearTimeoutMsec,
uint32_t aInitialPoolSize,
uint32_t aPoolUnusedSize,
TextureForwarder* aAllocator);
@ -114,6 +116,9 @@ private:
/// Allocate a single TextureClient to be returned from the pool.
void AllocateTextureClient();
/// Reset and/or initialise timers for shrinking/clearing the pool.
void ResetTimers();
/// Backend passed to the TextureClient for buffer creation.
LayersBackend mBackend;
@ -126,6 +131,14 @@ private:
/// Flags passed to the TextureClient for buffer creation.
const TextureFlags mFlags;
/// How long to wait after a TextureClient is returned before trying
/// to shrink the pool to its maximum size of mPoolUnusedSize.
uint32_t mShrinkTimeoutMsec;
/// How long to wait after a TextureClient is returned before trying
/// to clear the pool.
uint32_t mClearTimeoutMsec;
// The initial number of unused texture clients to seed the pool with
// on construction
uint32_t mInitialPoolSize;
@ -145,7 +158,8 @@ private:
std::stack<RefPtr<TextureClient> > mTextureClients;
std::list<RefPtr<TextureClient>> mTextureClientsDeferred;
RefPtr<nsITimer> mTimer;
RefPtr<nsITimer> mShrinkTimer;
RefPtr<nsITimer> mClearTimer;
// This mSurfaceAllocator owns us, so no need to hold a ref to it
TextureForwarder* mSurfaceAllocator;

View File

@ -932,6 +932,8 @@ CompositorBridgeChild::GetTexturePool(LayersBackend aBackend,
new TextureClientPool(aBackend, aFormat,
gfx::gfxVars::TileSize(),
aFlags,
gfxPrefs::LayersTilePoolShrinkTimeout(),
gfxPrefs::LayersTilePoolClearTimeout(),
gfxPrefs::LayersTileInitialPoolSize(),
gfxPrefs::LayersTilePoolUnusedSize(),
this));

View File

@ -505,6 +505,8 @@ private:
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(Once, "layers.tiles.edge-padding", TileEdgePaddingEnabled, bool, true);
DECL_GFX_PREF(Live, "layers.tiles.fade-in.enabled", LayerTileFadeInEnabled, bool, false);