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/. */
6 #include "SimpleTextureClientPool.h"
7 #include "CompositableClient.h"
8 #include "mozilla/layers/ISurfaceAllocator.h"
12 #include "nsComponentManagerUtils.h"
15 #define RECYCLE_LOG(...) printf_stderr(__VA_ARGS__)
17 #define RECYCLE_LOG(...) do { } while (0)
23 using gfx::SurfaceFormat
;
26 SimpleTextureClientPool::ShrinkCallback(nsITimer
*aTimer
, void *aClosure
)
28 static_cast<SimpleTextureClientPool
*>(aClosure
)->ShrinkToMinimumSize();
32 SimpleTextureClientPool::RecycleCallback(TextureClient
* aClient
, void* aClosure
)
34 SimpleTextureClientPool
* pool
=
35 static_cast<SimpleTextureClientPool
*>(aClosure
);
37 aClient
->ClearRecycleCallback();
38 pool
->ReturnTextureClient(aClient
);
42 SimpleTextureClientPool::WaitForCompositorRecycleCallback(TextureClient
* aClient
, void* aClosure
)
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
);
51 SimpleTextureClientPool::SimpleTextureClientPool(gfx::SurfaceFormat aFormat
, gfx::IntSize aSize
,
52 ISurfaceAllocator
*aAllocator
)
55 , mSurfaceAllocator(aAllocator
)
57 mTimer
= do_CreateInstance("@mozilla.org/timer;1");
60 TemporaryRef
<TextureClient
>
61 SimpleTextureClientPool::GetTextureClient(bool aAutoRecycle
)
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());
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
);
77 textureClient
= TextureClient::CreateTextureClientForDrawing(mSurfaceAllocator
,
78 mFormat
, TEXTURE_FLAGS_DEFAULT
| TEXTURE_RECYCLE
, gfx::BackendType::NONE
, mSize
);
80 if (!textureClient
->AsTextureClientDrawTarget()->AllocateForSurface(mSize
, ALLOC_DEFAULT
)) {
81 NS_WARNING("TextureClient::AllocateForSurface failed!");
83 RECYCLE_LOG("%s Must allocate (0 left), returning %p\n", (mFormat
== SurfaceFormat::B8G8R8A8
?"poolA":"poolX"), textureClient
.get());
87 mOutstandingTextureClients
.push_back(textureClient
);
88 textureClient
->SetRecycleCallback(SimpleTextureClientPool::WaitForCompositorRecycleCallback
, this);
95 SimpleTextureClientPool::ReturnTextureClient(TextureClient
*aClient
)
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());
106 RECYCLE_LOG("%s did not recycle %p (have %d)\n", (mFormat
== SurfaceFormat::B8G8R8A8
?"poolA":"poolX"), aClient
, mAvailableTextureClients
.size());
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
);
116 mOutstandingTextureClients
.remove(aClient
);
120 SimpleTextureClientPool::ShrinkToMinimumSize()
122 RECYCLE_LOG("%s ShrinkToMinimumSize, removing %d clients", (mFormat
== SurfaceFormat::B8G8R8A8
?"poolA":"poolX"), mAvailableTextureClients
.size() > sMinCacheSize
? mAvailableTextureClients
.size() - sMinCacheSize
: 0);
126 while (mAvailableTextureClients
.size() > sMinCacheSize
) {
127 mAvailableTextureClients
.pop();
132 SimpleTextureClientPool::Clear()
134 while (!mAvailableTextureClients
.empty()) {
135 mAvailableTextureClients
.pop();