gfx/layers/client/SimpleTextureClientPool.cpp

changeset 0
6474c204b198
equal deleted inserted replaced
-1:000000000000 0:22a16cb741ec
1 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 * This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5
6 #include "SimpleTextureClientPool.h"
7 #include "CompositableClient.h"
8 #include "mozilla/layers/ISurfaceAllocator.h"
9
10 #include "gfxPrefs.h"
11
12 #include "nsComponentManagerUtils.h"
13
14 #if 0
15 #define RECYCLE_LOG(...) printf_stderr(__VA_ARGS__)
16 #else
17 #define RECYCLE_LOG(...) do { } while (0)
18 #endif
19
20 namespace mozilla {
21 namespace layers {
22
23 using gfx::SurfaceFormat;
24
25 /* static */ void
26 SimpleTextureClientPool::ShrinkCallback(nsITimer *aTimer, void *aClosure)
27 {
28 static_cast<SimpleTextureClientPool*>(aClosure)->ShrinkToMinimumSize();
29 }
30
31 /* static */ void
32 SimpleTextureClientPool::RecycleCallback(TextureClient* aClient, void* aClosure)
33 {
34 SimpleTextureClientPool* pool =
35 static_cast<SimpleTextureClientPool*>(aClosure);
36
37 aClient->ClearRecycleCallback();
38 pool->ReturnTextureClient(aClient);
39 }
40
41 /* static */ void
42 SimpleTextureClientPool::WaitForCompositorRecycleCallback(TextureClient* aClient, void* aClosure)
43 {
44 // This will grab a reference that will be released once the compositor
45 // acknowledges the remote recycle. Once it is received the object
46 // will be fully recycled.
47 aClient->WaitForCompositorRecycle();
48 aClient->SetRecycleCallback(SimpleTextureClientPool::RecycleCallback, aClosure);
49 }
50
51 SimpleTextureClientPool::SimpleTextureClientPool(gfx::SurfaceFormat aFormat, gfx::IntSize aSize,
52 ISurfaceAllocator *aAllocator)
53 : mFormat(aFormat)
54 , mSize(aSize)
55 , mSurfaceAllocator(aAllocator)
56 {
57 mTimer = do_CreateInstance("@mozilla.org/timer;1");
58 }
59
60 TemporaryRef<TextureClient>
61 SimpleTextureClientPool::GetTextureClient(bool aAutoRecycle)
62 {
63 // Try to fetch a client from the pool
64 RefPtr<TextureClient> textureClient;
65 if (mAvailableTextureClients.size()) {
66 textureClient = mAvailableTextureClients.top();
67 textureClient->WaitReleaseFence();
68 mAvailableTextureClients.pop();
69 RECYCLE_LOG("%s Skip allocate (%i left), returning %p\n", (mFormat == SurfaceFormat::B8G8R8A8?"poolA":"poolX"), mAvailableTextureClients.size(), textureClient.get());
70
71 } else {
72 // No unused clients in the pool, create one
73 if (gfxPrefs::ForceShmemTiles()) {
74 textureClient = TextureClient::CreateBufferTextureClient(mSurfaceAllocator,
75 mFormat, TEXTURE_IMMEDIATE_UPLOAD | TEXTURE_RECYCLE, gfx::BackendType::NONE);
76 } else {
77 textureClient = TextureClient::CreateTextureClientForDrawing(mSurfaceAllocator,
78 mFormat, TEXTURE_FLAGS_DEFAULT | TEXTURE_RECYCLE, gfx::BackendType::NONE, mSize);
79 }
80 if (!textureClient->AllocateForSurface(mSize, ALLOC_DEFAULT)) {
81 NS_WARNING("TextureClient::AllocateForSurface failed!");
82 }
83 RECYCLE_LOG("%s Must allocate (0 left), returning %p\n", (mFormat == SurfaceFormat::B8G8R8A8?"poolA":"poolX"), textureClient.get());
84 }
85
86 if (aAutoRecycle) {
87 mOutstandingTextureClients.push_back(textureClient);
88 textureClient->SetRecycleCallback(SimpleTextureClientPool::WaitForCompositorRecycleCallback, this);
89 }
90
91 return textureClient;
92 }
93
94 void
95 SimpleTextureClientPool::ReturnTextureClient(TextureClient *aClient)
96 {
97 if (!aClient) {
98 return;
99 }
100
101 // If we haven't hit our max cached client limit, add this one
102 if (mAvailableTextureClients.size() < sMaxTextureClients) {
103 mAvailableTextureClients.push(aClient);
104 RECYCLE_LOG("%s recycled %p (have %d)\n", (mFormat == SurfaceFormat::B8G8R8A8?"poolA":"poolX"), aClient, mAvailableTextureClients.size());
105 } else {
106 RECYCLE_LOG("%s did not recycle %p (have %d)\n", (mFormat == SurfaceFormat::B8G8R8A8?"poolA":"poolX"), aClient, mAvailableTextureClients.size());
107 }
108
109 // Kick off the pool shrinking timer if there are still more unused texture
110 // clients than our desired minimum cache size.
111 if (mAvailableTextureClients.size() > sMinCacheSize) {
112 mTimer->InitWithFuncCallback(SimpleTextureClientPool::ShrinkCallback, this, sShrinkTimeout,
113 nsITimer::TYPE_ONE_SHOT);
114 }
115
116 mOutstandingTextureClients.remove(aClient);
117 }
118
119 void
120 SimpleTextureClientPool::ShrinkToMinimumSize()
121 {
122 RECYCLE_LOG("%s ShrinkToMinimumSize, removing %d clients", (mFormat == SurfaceFormat::B8G8R8A8?"poolA":"poolX"), mAvailableTextureClients.size() > sMinCacheSize ? mAvailableTextureClients.size() - sMinCacheSize : 0);
123
124 mTimer->Cancel();
125
126 while (mAvailableTextureClients.size() > sMinCacheSize) {
127 mAvailableTextureClients.pop();
128 }
129 }
130
131 void
132 SimpleTextureClientPool::Clear()
133 {
134 while (!mAvailableTextureClients.empty()) {
135 mAvailableTextureClients.pop();
136 }
137 }
138
139 }
140 }

mercurial