1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/gfx/layers/client/SimpleTextureClientPool.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,140 @@ 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 "SimpleTextureClientPool.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 +#if 0 1.18 +#define RECYCLE_LOG(...) printf_stderr(__VA_ARGS__) 1.19 +#else 1.20 +#define RECYCLE_LOG(...) do { } while (0) 1.21 +#endif 1.22 + 1.23 +namespace mozilla { 1.24 +namespace layers { 1.25 + 1.26 +using gfx::SurfaceFormat; 1.27 + 1.28 +/* static */ void 1.29 +SimpleTextureClientPool::ShrinkCallback(nsITimer *aTimer, void *aClosure) 1.30 +{ 1.31 + static_cast<SimpleTextureClientPool*>(aClosure)->ShrinkToMinimumSize(); 1.32 +} 1.33 + 1.34 +/* static */ void 1.35 +SimpleTextureClientPool::RecycleCallback(TextureClient* aClient, void* aClosure) 1.36 +{ 1.37 + SimpleTextureClientPool* pool = 1.38 + static_cast<SimpleTextureClientPool*>(aClosure); 1.39 + 1.40 + aClient->ClearRecycleCallback(); 1.41 + pool->ReturnTextureClient(aClient); 1.42 +} 1.43 + 1.44 +/* static */ void 1.45 +SimpleTextureClientPool::WaitForCompositorRecycleCallback(TextureClient* aClient, void* aClosure) 1.46 +{ 1.47 + // This will grab a reference that will be released once the compositor 1.48 + // acknowledges the remote recycle. Once it is received the object 1.49 + // will be fully recycled. 1.50 + aClient->WaitForCompositorRecycle(); 1.51 + aClient->SetRecycleCallback(SimpleTextureClientPool::RecycleCallback, aClosure); 1.52 +} 1.53 + 1.54 +SimpleTextureClientPool::SimpleTextureClientPool(gfx::SurfaceFormat aFormat, gfx::IntSize aSize, 1.55 + ISurfaceAllocator *aAllocator) 1.56 + : mFormat(aFormat) 1.57 + , mSize(aSize) 1.58 + , mSurfaceAllocator(aAllocator) 1.59 +{ 1.60 + mTimer = do_CreateInstance("@mozilla.org/timer;1"); 1.61 +} 1.62 + 1.63 +TemporaryRef<TextureClient> 1.64 +SimpleTextureClientPool::GetTextureClient(bool aAutoRecycle) 1.65 +{ 1.66 + // Try to fetch a client from the pool 1.67 + RefPtr<TextureClient> textureClient; 1.68 + if (mAvailableTextureClients.size()) { 1.69 + textureClient = mAvailableTextureClients.top(); 1.70 + textureClient->WaitReleaseFence(); 1.71 + mAvailableTextureClients.pop(); 1.72 + RECYCLE_LOG("%s Skip allocate (%i left), returning %p\n", (mFormat == SurfaceFormat::B8G8R8A8?"poolA":"poolX"), mAvailableTextureClients.size(), textureClient.get()); 1.73 + 1.74 + } else { 1.75 + // No unused clients in the pool, create one 1.76 + if (gfxPrefs::ForceShmemTiles()) { 1.77 + textureClient = TextureClient::CreateBufferTextureClient(mSurfaceAllocator, 1.78 + mFormat, TEXTURE_IMMEDIATE_UPLOAD | TEXTURE_RECYCLE, gfx::BackendType::NONE); 1.79 + } else { 1.80 + textureClient = TextureClient::CreateTextureClientForDrawing(mSurfaceAllocator, 1.81 + mFormat, TEXTURE_FLAGS_DEFAULT | TEXTURE_RECYCLE, gfx::BackendType::NONE, mSize); 1.82 + } 1.83 + if (!textureClient->AllocateForSurface(mSize, ALLOC_DEFAULT)) { 1.84 + NS_WARNING("TextureClient::AllocateForSurface failed!"); 1.85 + } 1.86 + RECYCLE_LOG("%s Must allocate (0 left), returning %p\n", (mFormat == SurfaceFormat::B8G8R8A8?"poolA":"poolX"), textureClient.get()); 1.87 + } 1.88 + 1.89 + if (aAutoRecycle) { 1.90 + mOutstandingTextureClients.push_back(textureClient); 1.91 + textureClient->SetRecycleCallback(SimpleTextureClientPool::WaitForCompositorRecycleCallback, this); 1.92 + } 1.93 + 1.94 + return textureClient; 1.95 +} 1.96 + 1.97 +void 1.98 +SimpleTextureClientPool::ReturnTextureClient(TextureClient *aClient) 1.99 +{ 1.100 + if (!aClient) { 1.101 + return; 1.102 + } 1.103 + 1.104 + // If we haven't hit our max cached client limit, add this one 1.105 + if (mAvailableTextureClients.size() < sMaxTextureClients) { 1.106 + mAvailableTextureClients.push(aClient); 1.107 + RECYCLE_LOG("%s recycled %p (have %d)\n", (mFormat == SurfaceFormat::B8G8R8A8?"poolA":"poolX"), aClient, mAvailableTextureClients.size()); 1.108 + } else { 1.109 + RECYCLE_LOG("%s did not recycle %p (have %d)\n", (mFormat == SurfaceFormat::B8G8R8A8?"poolA":"poolX"), aClient, mAvailableTextureClients.size()); 1.110 + } 1.111 + 1.112 + // Kick off the pool shrinking timer if there are still more unused texture 1.113 + // clients than our desired minimum cache size. 1.114 + if (mAvailableTextureClients.size() > sMinCacheSize) { 1.115 + mTimer->InitWithFuncCallback(SimpleTextureClientPool::ShrinkCallback, this, sShrinkTimeout, 1.116 + nsITimer::TYPE_ONE_SHOT); 1.117 + } 1.118 + 1.119 + mOutstandingTextureClients.remove(aClient); 1.120 +} 1.121 + 1.122 +void 1.123 +SimpleTextureClientPool::ShrinkToMinimumSize() 1.124 +{ 1.125 + RECYCLE_LOG("%s ShrinkToMinimumSize, removing %d clients", (mFormat == SurfaceFormat::B8G8R8A8?"poolA":"poolX"), mAvailableTextureClients.size() > sMinCacheSize ? mAvailableTextureClients.size() - sMinCacheSize : 0); 1.126 + 1.127 + mTimer->Cancel(); 1.128 + 1.129 + while (mAvailableTextureClients.size() > sMinCacheSize) { 1.130 + mAvailableTextureClients.pop(); 1.131 + } 1.132 +} 1.133 + 1.134 +void 1.135 +SimpleTextureClientPool::Clear() 1.136 +{ 1.137 + while (!mAvailableTextureClients.empty()) { 1.138 + mAvailableTextureClients.pop(); 1.139 + } 1.140 +} 1.141 + 1.142 +} 1.143 +}