mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-22 01:35:35 +00:00
Backed out changeset b0724a9e58bf (bug 1278341) for crashes in mozilla::layers::TextureClientPool::ReturnUnlockedClients
--HG-- extra : rebase_source : 0d2eedce1ee93725b3f77f64e15d7d74321bffbd
This commit is contained in:
parent
b1fa1b86ff
commit
730118cb62
@ -19,25 +19,30 @@
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
|
||||
static void
|
||||
ShrinkCallback(nsITimer *aTimer, void *aClosure)
|
||||
{
|
||||
static_cast<TextureClientPool*>(aClosure)->ShrinkToMinimumSize();
|
||||
}
|
||||
|
||||
TextureClientPool::TextureClientPool(LayersBackend aLayersBackend,
|
||||
gfx::SurfaceFormat aFormat,
|
||||
gfx::IntSize aSize,
|
||||
TextureFlags aFlags,
|
||||
uint32_t aInitialPoolSize,
|
||||
uint32_t aPoolIncrementSize,
|
||||
uint32_t aMaxTextureClients,
|
||||
uint32_t aShrinkTimeoutMsec,
|
||||
TextureForwarder* aAllocator)
|
||||
: mBackend(aLayersBackend)
|
||||
, mFormat(aFormat)
|
||||
, mSize(aSize)
|
||||
, mFlags(aFlags)
|
||||
, mInitialPoolSize(aInitialPoolSize)
|
||||
, mPoolIncrementSize(aPoolIncrementSize)
|
||||
, mMaxTextureClients(aMaxTextureClients)
|
||||
, mShrinkTimeoutMsec(aShrinkTimeoutMsec)
|
||||
, mOutstandingClients(0)
|
||||
, mSurfaceAllocator(aAllocator)
|
||||
{
|
||||
TCP_LOG("TexturePool %p created with maximum unused texture clients %u\n",
|
||||
this, mInitialPoolSize);
|
||||
TCP_LOG("TexturePool %p created with max size %u and timeout %u\n",
|
||||
this, mMaxTextureClients, aShrinkTimeoutMsec);
|
||||
mTimer = do_CreateInstance("@mozilla.org/timer;1");
|
||||
if (aFormat == gfx::SurfaceFormat::UNKNOWN) {
|
||||
gfxWarning() << "Creating texture pool for SurfaceFormat::UNKNOWN format";
|
||||
@ -87,65 +92,45 @@ TextureClientPool::GetTextureClient()
|
||||
{
|
||||
// Try to fetch a client from the pool
|
||||
RefPtr<TextureClient> textureClient;
|
||||
|
||||
// We initially allocate mInitialPoolSize for our pool. If we run
|
||||
// out of TextureClients, we allocate additional TextureClients to try and keep around
|
||||
// mPoolIncrementSize
|
||||
if (!mTextureClients.size()) {
|
||||
size_t size = mOutstandingClients ? mPoolIncrementSize : mInitialPoolSize;
|
||||
AllocateTextureClients(size);
|
||||
if (mTextureClients.size()) {
|
||||
mOutstandingClients++;
|
||||
textureClient = mTextureClients.top();
|
||||
mTextureClients.pop();
|
||||
#ifdef GFX_DEBUG_TRACK_CLIENTS_IN_POOL
|
||||
DebugOnly<bool> ok = TestClientPool("fetch", textureClient, this);
|
||||
MOZ_ASSERT(ok);
|
||||
#endif
|
||||
TCP_LOG("TexturePool %p giving %p from pool; size %u outstanding %u\n",
|
||||
this, textureClient.get(), mTextureClients.size(), mOutstandingClients);
|
||||
return textureClient.forget();
|
||||
}
|
||||
|
||||
if (!mTextureClients.size()) {
|
||||
// All our allocations failed, return nullptr
|
||||
return nullptr;
|
||||
// We're increasing the number of outstanding TextureClients without reusing a
|
||||
// client, we may need to free a deferred-return TextureClient.
|
||||
ShrinkToMaximumSize();
|
||||
|
||||
// No unused clients in the pool, create one
|
||||
if (gfxPrefs::ForceShmemTiles()) {
|
||||
// gfx::BackendType::NONE means use the content backend
|
||||
textureClient = TextureClient::CreateForRawBufferAccess(mSurfaceAllocator,
|
||||
mFormat, mSize, gfx::BackendType::NONE,
|
||||
mFlags, ALLOC_DEFAULT);
|
||||
} else {
|
||||
textureClient = TextureClient::CreateForDrawing(mSurfaceAllocator,
|
||||
mFormat, mSize, mBackend, BackendSelector::Content, mFlags);
|
||||
}
|
||||
|
||||
mOutstandingClients++;
|
||||
textureClient = mTextureClients.top();
|
||||
mTextureClients.pop();
|
||||
#ifdef GFX_DEBUG_TRACK_CLIENTS_IN_POOL
|
||||
if (textureClient) {
|
||||
textureClient->mPoolTracker = this;
|
||||
}
|
||||
DebugOnly<bool> ok = TestClientPool("fetch", textureClient, this);
|
||||
MOZ_ASSERT(ok);
|
||||
#endif
|
||||
TCP_LOG("TexturePool %p giving %p from pool; size %u outstanding %u\n",
|
||||
TCP_LOG("TexturePool %p giving new %p; size %u outstanding %u\n",
|
||||
this, textureClient.get(), mTextureClients.size(), mOutstandingClients);
|
||||
|
||||
return textureClient.forget();
|
||||
}
|
||||
|
||||
void
|
||||
TextureClientPool::AllocateTextureClients(size_t aSize)
|
||||
{
|
||||
TCP_LOG("TexturePool %p allocating %u clients, outstanding %u\n",
|
||||
this, aSize, mOutstandingClients);
|
||||
|
||||
RefPtr<TextureClient> newClient;
|
||||
while (mTextureClients.size() < aSize) {
|
||||
if (gfxPrefs::ForceShmemTiles()) {
|
||||
// gfx::BackendType::NONE means use the content backend
|
||||
newClient =
|
||||
TextureClient::CreateForRawBufferAccess(mSurfaceAllocator,
|
||||
mFormat, mSize,
|
||||
gfx::BackendType::NONE,
|
||||
mFlags, ALLOC_DEFAULT);
|
||||
} else {
|
||||
newClient =
|
||||
TextureClient::CreateForDrawing(mSurfaceAllocator,
|
||||
mFormat, mSize,
|
||||
mBackend,
|
||||
BackendSelector::Content,
|
||||
mFlags);
|
||||
}
|
||||
if (newClient) {
|
||||
mTextureClients.push(newClient.forget());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
TextureClientPool::ReturnTextureClient(TextureClient *aClient)
|
||||
{
|
||||
@ -165,6 +150,14 @@ TextureClientPool::ReturnTextureClient(TextureClient *aClient)
|
||||
|
||||
// Shrink down if we're beyond our maximum size
|
||||
ShrinkToMaximumSize();
|
||||
|
||||
// Kick off the pool shrinking timer if there are still more unused texture
|
||||
// clients than our desired minimum cache size.
|
||||
if (mTextureClients.size() > sMinCacheSize) {
|
||||
TCP_LOG("TexturePool %p scheduling a shrink-to-min-size\n", this);
|
||||
mTimer->InitWithFuncCallback(ShrinkCallback, this, mShrinkTimeoutMsec,
|
||||
nsITimer::TYPE_ONE_SHOT);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
@ -187,54 +180,80 @@ TextureClientPool::ReturnTextureClientDeferred(TextureClient* aClient)
|
||||
void
|
||||
TextureClientPool::ShrinkToMaximumSize()
|
||||
{
|
||||
uint32_t totalClientsOutstanding = mTextureClients.size() + mOutstandingClients;
|
||||
TCP_LOG("TexturePool %p shrinking to max size %u; total outstanding %u\n",
|
||||
this, mMaxTextureClients, totalClientsOutstanding);
|
||||
|
||||
// We're over our desired maximum size, immediately shrink down to the
|
||||
// maximum.
|
||||
//
|
||||
// maximum, or zero if we have too many outstanding texture clients.
|
||||
// We cull from the deferred TextureClients first, as we can't reuse those
|
||||
// until they get returned.
|
||||
uint32_t totalUnusedTextureClients = mTextureClients.size() + mTextureClientsDeferred.size();
|
||||
|
||||
// If we have > mInitialPoolSize outstanding, then we want to keep around
|
||||
// mPoolIncrementSize at a maximum. If we have fewer than mInitialPoolSize
|
||||
// outstanding, then keep around the entire initial pool size.
|
||||
uint32_t targetUnusedClients;
|
||||
if (mOutstandingClients > mInitialPoolSize) {
|
||||
targetUnusedClients = mPoolIncrementSize;
|
||||
} else {
|
||||
targetUnusedClients = mInitialPoolSize;
|
||||
}
|
||||
|
||||
TCP_LOG("TexturePool %p shrinking to maximum unused size %u; total outstanding %u\n",
|
||||
this, targetUnusedClients, mOutstandingClients);
|
||||
|
||||
while (totalUnusedTextureClients > targetUnusedClients) {
|
||||
while (totalClientsOutstanding > mMaxTextureClients) {
|
||||
if (mTextureClientsDeferred.size()) {
|
||||
MOZ_ASSERT(mOutstandingClients > 0);
|
||||
mOutstandingClients--;
|
||||
TCP_LOG("TexturePool %p dropped deferred client %p; %u remaining\n",
|
||||
this, mTextureClientsDeferred.front().get(),
|
||||
mTextureClientsDeferred.size() - 1);
|
||||
mTextureClientsDeferred.pop_front();
|
||||
} else {
|
||||
if (!mTextureClients.size()) {
|
||||
// Getting here means we're over our desired number of TextureClients
|
||||
// with none in the pool. This can happen during shutdown, or for
|
||||
// pathological cases, or it could mean that mMaxTextureClients needs
|
||||
// adjusting for whatever device we're running on.
|
||||
TCP_LOG("TexturePool %p encountering pathological case!\n", this);
|
||||
break;
|
||||
}
|
||||
TCP_LOG("TexturePool %p dropped non-deferred client %p; %u remaining\n",
|
||||
this, mTextureClients.top().get(), mTextureClients.size() - 1);
|
||||
mTextureClients.pop();
|
||||
}
|
||||
totalUnusedTextureClients--;
|
||||
totalClientsOutstanding--;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
TextureClientPool::ShrinkToMinimumSize()
|
||||
{
|
||||
ReturnUnlockedClients();
|
||||
|
||||
while (!mTextureClientsDeferred.empty()) {
|
||||
MOZ_ASSERT(mOutstandingClients > 0);
|
||||
mOutstandingClients--;
|
||||
TCP_LOG("TexturePool %p releasing deferred client %p\n",
|
||||
this, mTextureClientsDeferred.front().get());
|
||||
mTextureClientsDeferred.pop_front();
|
||||
}
|
||||
|
||||
TCP_LOG("TexturePool %p shrinking to minimum size %u\n", this, sMinCacheSize);
|
||||
while (mTextureClients.size() > sMinCacheSize) {
|
||||
TCP_LOG("TexturePool %p popped %p; shrunk to %u\n",
|
||||
this, mTextureClients.top().get(), mTextureClients.size() - 1);
|
||||
mTextureClients.pop();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
TextureClientPool::ReturnDeferredClients()
|
||||
{
|
||||
TCP_LOG("TexturePool %p returning %u deferred clients to pool\n",
|
||||
this, mTextureClientsDeferred.size());
|
||||
|
||||
if (mTextureClientsDeferred.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
TCP_LOG("TexturePool %p returning %u deferred clients to pool\n",
|
||||
this, mTextureClientsDeferred.size());
|
||||
|
||||
ReturnUnlockedClients();
|
||||
ShrinkToMaximumSize();
|
||||
|
||||
// Kick off the pool shrinking timer if there are still more unused texture
|
||||
// clients than our desired minimum cache size.
|
||||
if (mTextureClients.size() > sMinCacheSize) {
|
||||
TCP_LOG("TexturePool %p kicking off shrink-to-min timer\n", this);
|
||||
mTimer->InitWithFuncCallback(ShrinkCallback, this, mShrinkTimeoutMsec,
|
||||
nsITimer::TYPE_ONE_SHOT);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
@ -285,7 +304,7 @@ TextureClientPool::Clear()
|
||||
void TextureClientPool::Destroy()
|
||||
{
|
||||
Clear();
|
||||
mInitialPoolSize = 0;
|
||||
mMaxTextureClients = 0;
|
||||
}
|
||||
|
||||
} // namespace layers
|
||||
|
@ -48,8 +48,8 @@ public:
|
||||
gfx::SurfaceFormat aFormat,
|
||||
gfx::IntSize aSize,
|
||||
TextureFlags aFlags,
|
||||
uint32_t aInitialPoolSize,
|
||||
uint32_t aPoolIncrementSize,
|
||||
uint32_t aMaxTextureClients,
|
||||
uint32_t aShrinkTimeoutMsec,
|
||||
TextureForwarder* aAllocator);
|
||||
|
||||
/**
|
||||
@ -75,18 +75,24 @@ public:
|
||||
*/
|
||||
void ReturnTextureClientDeferred(TextureClient *aClient) override;
|
||||
|
||||
/**
|
||||
* Attempt to shrink the pool so that there are no more than
|
||||
* mMaxTextureClients clients outstanding.
|
||||
*/
|
||||
void ShrinkToMaximumSize();
|
||||
|
||||
/**
|
||||
* Attempt to shrink the pool so that there are no more than sMinCacheSize
|
||||
* unused clients.
|
||||
*/
|
||||
void ShrinkToMinimumSize();
|
||||
|
||||
/**
|
||||
* Return any clients to the pool that were previously returned in
|
||||
* ReturnTextureClientDeferred.
|
||||
*/
|
||||
void ReturnDeferredClients();
|
||||
|
||||
/**
|
||||
* Attempt to shrink the pool so that there are no more than
|
||||
* mInitialPoolSize outstanding.
|
||||
*/
|
||||
void ShrinkToMaximumSize();
|
||||
|
||||
/**
|
||||
* Report that a client retrieved via GetTextureClient() has become
|
||||
* unusable, so that it will no longer be tracked.
|
||||
@ -111,11 +117,9 @@ public:
|
||||
private:
|
||||
void ReturnUnlockedClients();
|
||||
|
||||
/// We maintain a number of unused texture clients for immediate return from
|
||||
/// GetTextureClient(). This will normally be called if there are no
|
||||
/// TextureClients available in the pool, which ideally should only ever
|
||||
/// be at startup.
|
||||
void AllocateTextureClients(size_t aSize);
|
||||
// The minimum size of the pool (the number of tiles that will be kept after
|
||||
// shrinking).
|
||||
static const uint32_t sMinCacheSize = 0;
|
||||
|
||||
/// Backend passed to the TextureClient for buffer creation.
|
||||
LayersBackend mBackend;
|
||||
@ -129,13 +133,13 @@ private:
|
||||
/// Flags passed to the TextureClient for buffer creation.
|
||||
const TextureFlags mFlags;
|
||||
|
||||
// The initial number of unused texture clients to seed the pool with
|
||||
// on construction
|
||||
uint32_t mInitialPoolSize;
|
||||
// The maximum number of texture clients managed by this pool that we want
|
||||
// to remain active.
|
||||
uint32_t mMaxTextureClients;
|
||||
|
||||
// How many unused texture clients to try and keep around if we go over
|
||||
// the initial allocation
|
||||
uint32_t mPoolIncrementSize;
|
||||
// The time in milliseconds before the pool will be shrunk to the minimum
|
||||
// size after returning a client.
|
||||
uint32_t mShrinkTimeoutMsec;
|
||||
|
||||
/// This is a total number of clients in the wild and in the stack of
|
||||
/// deferred clients (see below). So, the total number of clients in
|
||||
|
@ -954,8 +954,8 @@ CompositorBridgeChild::GetTexturePool(LayersBackend aBackend,
|
||||
IntSize(gfxPlatform::GetPlatform()->GetTileWidth(),
|
||||
gfxPlatform::GetPlatform()->GetTileHeight()),
|
||||
aFlags,
|
||||
gfxPrefs::LayersTileInitialPoolSize(),
|
||||
gfxPrefs::LayersTilePoolIncrementSize(),
|
||||
gfxPrefs::LayersTileMaxPoolSize(),
|
||||
gfxPrefs::LayersTileShrinkPoolTimeout(),
|
||||
this));
|
||||
|
||||
return mTexturePools.LastElement();
|
||||
@ -965,7 +965,7 @@ void
|
||||
CompositorBridgeChild::HandleMemoryPressure()
|
||||
{
|
||||
for (size_t i = 0; i < mTexturePools.Length(); i++) {
|
||||
mTexturePools[i]->Clear();
|
||||
mTexturePools[i]->ShrinkToMinimumSize();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -485,8 +485,8 @@ 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-increment-size", LayersTilePoolIncrementSize, uint32_t, (uint32_t)10);
|
||||
DECL_GFX_PREF(Once, "layers.tile-max-pool-size", LayersTileMaxPoolSize, uint32_t, (uint32_t)50);
|
||||
DECL_GFX_PREF(Once, "layers.tile-shrink-pool-timeout", LayersTileShrinkPoolTimeout, uint32_t, (uint32_t)1000);
|
||||
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);
|
||||
|
Loading…
Reference in New Issue
Block a user