diff -r 000000000000 -r 6474c204b198 gfx/layers/client/TextureClientPool.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gfx/layers/client/TextureClientPool.cpp Wed Dec 31 06:09:35 2014 +0100 @@ -0,0 +1,155 @@ +/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- +* This Source Code Form is subject to the terms of the Mozilla Public +* License, v. 2.0. If a copy of the MPL was not distributed with this +* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "TextureClientPool.h" +#include "CompositableClient.h" +#include "mozilla/layers/ISurfaceAllocator.h" + +#include "gfxPrefs.h" + +#include "nsComponentManagerUtils.h" + +namespace mozilla { +namespace layers { + +static void +ShrinkCallback(nsITimer *aTimer, void *aClosure) +{ + static_cast(aClosure)->ShrinkToMinimumSize(); +} + +TextureClientPool::TextureClientPool(gfx::SurfaceFormat aFormat, gfx::IntSize aSize, + ISurfaceAllocator *aAllocator) + : mFormat(aFormat) + , mSize(aSize) + , mOutstandingClients(0) + , mSurfaceAllocator(aAllocator) +{ + mTimer = do_CreateInstance("@mozilla.org/timer;1"); +} + +TextureClientPool::~TextureClientPool() +{ + mTimer->Cancel(); +} + +TemporaryRef +TextureClientPool::GetTextureClient() +{ + mOutstandingClients++; + + // Try to fetch a client from the pool + RefPtr textureClient; + if (mTextureClients.size()) { + textureClient = mTextureClients.top(); + textureClient->WaitReleaseFence(); + mTextureClients.pop(); + return textureClient; + } + + // 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::CreateBufferTextureClient(mSurfaceAllocator, + mFormat, TEXTURE_IMMEDIATE_UPLOAD, gfx::BackendType::NONE); + } else { + textureClient = TextureClient::CreateTextureClientForDrawing(mSurfaceAllocator, + mFormat, TEXTURE_IMMEDIATE_UPLOAD, gfx::BackendType::NONE, mSize); + } + textureClient->AllocateForSurface(mSize, ALLOC_DEFAULT); + + return textureClient; +} + +void +TextureClientPool::ReturnTextureClient(TextureClient *aClient) +{ + if (!aClient) { + return; + } + MOZ_ASSERT(mOutstandingClients); + mOutstandingClients--; + + // Add the client to the pool and shrink down if we're beyond our maximum size + mTextureClients.push(aClient); + 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) { + mTimer->InitWithFuncCallback(ShrinkCallback, this, sShrinkTimeout, + nsITimer::TYPE_ONE_SHOT); + } +} + +void +TextureClientPool::ReturnTextureClientDeferred(TextureClient *aClient) +{ + mTextureClientsDeferred.push(aClient); + ShrinkToMaximumSize(); +} + +void +TextureClientPool::ShrinkToMaximumSize() +{ + uint32_t totalClientsOutstanding = mTextureClients.size() + mOutstandingClients; + + // We're over our desired maximum size, immediately shrink down to the + // 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. + while (totalClientsOutstanding > sMaxTextureClients) { + if (mTextureClientsDeferred.size()) { + mOutstandingClients--; + mTextureClientsDeferred.pop(); + } else { + if (!mTextureClients.size()) { + // Getting here means we're over our desired number of TextureClients + // with none in the pool. This can happen for pathological cases, or + // it could mean that sMaxTextureClients needs adjusting for whatever + // device we're running on. + break; + } + mTextureClients.pop(); + } + totalClientsOutstanding--; + } +} + +void +TextureClientPool::ShrinkToMinimumSize() +{ + while (mTextureClients.size() > sMinCacheSize) { + mTextureClients.pop(); + } +} + +void +TextureClientPool::ReturnDeferredClients() +{ + while (!mTextureClientsDeferred.empty()) { + ReturnTextureClient(mTextureClientsDeferred.top()); + mTextureClientsDeferred.pop(); + } +} + +void +TextureClientPool::Clear() +{ + while (!mTextureClients.empty()) { + mTextureClients.pop(); + } + while (!mTextureClientsDeferred.empty()) { + mOutstandingClients--; + mTextureClientsDeferred.pop(); + } +} + +} +}