1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/gfx/layers/client/TextureClientPool.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,155 @@ 1.4 +/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- 1.5 +* This Source Code Form is subject to the terms of the Mozilla Public 1.6 +* License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 +* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 +#include "TextureClientPool.h" 1.10 +#include "CompositableClient.h" 1.11 +#include "mozilla/layers/ISurfaceAllocator.h" 1.12 + 1.13 +#include "gfxPrefs.h" 1.14 + 1.15 +#include "nsComponentManagerUtils.h" 1.16 + 1.17 +namespace mozilla { 1.18 +namespace layers { 1.19 + 1.20 +static void 1.21 +ShrinkCallback(nsITimer *aTimer, void *aClosure) 1.22 +{ 1.23 + static_cast<TextureClientPool*>(aClosure)->ShrinkToMinimumSize(); 1.24 +} 1.25 + 1.26 +TextureClientPool::TextureClientPool(gfx::SurfaceFormat aFormat, gfx::IntSize aSize, 1.27 + ISurfaceAllocator *aAllocator) 1.28 + : mFormat(aFormat) 1.29 + , mSize(aSize) 1.30 + , mOutstandingClients(0) 1.31 + , mSurfaceAllocator(aAllocator) 1.32 +{ 1.33 + mTimer = do_CreateInstance("@mozilla.org/timer;1"); 1.34 +} 1.35 + 1.36 +TextureClientPool::~TextureClientPool() 1.37 +{ 1.38 + mTimer->Cancel(); 1.39 +} 1.40 + 1.41 +TemporaryRef<TextureClient> 1.42 +TextureClientPool::GetTextureClient() 1.43 +{ 1.44 + mOutstandingClients++; 1.45 + 1.46 + // Try to fetch a client from the pool 1.47 + RefPtr<TextureClient> textureClient; 1.48 + if (mTextureClients.size()) { 1.49 + textureClient = mTextureClients.top(); 1.50 + textureClient->WaitReleaseFence(); 1.51 + mTextureClients.pop(); 1.52 + return textureClient; 1.53 + } 1.54 + 1.55 + // We're increasing the number of outstanding TextureClients without reusing a 1.56 + // client, we may need to free a deferred-return TextureClient. 1.57 + ShrinkToMaximumSize(); 1.58 + 1.59 + // No unused clients in the pool, create one 1.60 + if (gfxPrefs::ForceShmemTiles()) { 1.61 + // gfx::BackendType::NONE means use the content backend 1.62 + textureClient = TextureClient::CreateBufferTextureClient(mSurfaceAllocator, 1.63 + mFormat, TEXTURE_IMMEDIATE_UPLOAD, gfx::BackendType::NONE); 1.64 + } else { 1.65 + textureClient = TextureClient::CreateTextureClientForDrawing(mSurfaceAllocator, 1.66 + mFormat, TEXTURE_IMMEDIATE_UPLOAD, gfx::BackendType::NONE, mSize); 1.67 + } 1.68 + textureClient->AllocateForSurface(mSize, ALLOC_DEFAULT); 1.69 + 1.70 + return textureClient; 1.71 +} 1.72 + 1.73 +void 1.74 +TextureClientPool::ReturnTextureClient(TextureClient *aClient) 1.75 +{ 1.76 + if (!aClient) { 1.77 + return; 1.78 + } 1.79 + MOZ_ASSERT(mOutstandingClients); 1.80 + mOutstandingClients--; 1.81 + 1.82 + // Add the client to the pool and shrink down if we're beyond our maximum size 1.83 + mTextureClients.push(aClient); 1.84 + ShrinkToMaximumSize(); 1.85 + 1.86 + // Kick off the pool shrinking timer if there are still more unused texture 1.87 + // clients than our desired minimum cache size. 1.88 + if (mTextureClients.size() > sMinCacheSize) { 1.89 + mTimer->InitWithFuncCallback(ShrinkCallback, this, sShrinkTimeout, 1.90 + nsITimer::TYPE_ONE_SHOT); 1.91 + } 1.92 +} 1.93 + 1.94 +void 1.95 +TextureClientPool::ReturnTextureClientDeferred(TextureClient *aClient) 1.96 +{ 1.97 + mTextureClientsDeferred.push(aClient); 1.98 + ShrinkToMaximumSize(); 1.99 +} 1.100 + 1.101 +void 1.102 +TextureClientPool::ShrinkToMaximumSize() 1.103 +{ 1.104 + uint32_t totalClientsOutstanding = mTextureClients.size() + mOutstandingClients; 1.105 + 1.106 + // We're over our desired maximum size, immediately shrink down to the 1.107 + // maximum, or zero if we have too many outstanding texture clients. 1.108 + // We cull from the deferred TextureClients first, as we can't reuse those 1.109 + // until they get returned. 1.110 + while (totalClientsOutstanding > sMaxTextureClients) { 1.111 + if (mTextureClientsDeferred.size()) { 1.112 + mOutstandingClients--; 1.113 + mTextureClientsDeferred.pop(); 1.114 + } else { 1.115 + if (!mTextureClients.size()) { 1.116 + // Getting here means we're over our desired number of TextureClients 1.117 + // with none in the pool. This can happen for pathological cases, or 1.118 + // it could mean that sMaxTextureClients needs adjusting for whatever 1.119 + // device we're running on. 1.120 + break; 1.121 + } 1.122 + mTextureClients.pop(); 1.123 + } 1.124 + totalClientsOutstanding--; 1.125 + } 1.126 +} 1.127 + 1.128 +void 1.129 +TextureClientPool::ShrinkToMinimumSize() 1.130 +{ 1.131 + while (mTextureClients.size() > sMinCacheSize) { 1.132 + mTextureClients.pop(); 1.133 + } 1.134 +} 1.135 + 1.136 +void 1.137 +TextureClientPool::ReturnDeferredClients() 1.138 +{ 1.139 + while (!mTextureClientsDeferred.empty()) { 1.140 + ReturnTextureClient(mTextureClientsDeferred.top()); 1.141 + mTextureClientsDeferred.pop(); 1.142 + } 1.143 +} 1.144 + 1.145 +void 1.146 +TextureClientPool::Clear() 1.147 +{ 1.148 + while (!mTextureClients.empty()) { 1.149 + mTextureClients.pop(); 1.150 + } 1.151 + while (!mTextureClientsDeferred.empty()) { 1.152 + mOutstandingClients--; 1.153 + mTextureClientsDeferred.pop(); 1.154 + } 1.155 +} 1.156 + 1.157 +} 1.158 +}