Line data Source code
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 "mozilla/layers/CompositableClient.h"
7 : #include <stdint.h> // for uint64_t, uint32_t
8 : #include "gfxPlatform.h" // for gfxPlatform
9 : #include "mozilla/layers/CompositableForwarder.h"
10 : #include "mozilla/layers/ImageBridgeChild.h"
11 : #include "mozilla/layers/TextureClient.h" // for TextureClient, etc
12 : #include "mozilla/layers/TextureClientOGL.h"
13 : #include "mozilla/mozalloc.h" // for operator delete, etc
14 : #include "mozilla/layers/TextureClientRecycleAllocator.h"
15 : #ifdef XP_WIN
16 : #include "gfxWindowsPlatform.h" // for gfxWindowsPlatform
17 : #include "mozilla/layers/TextureD3D11.h"
18 : #endif
19 : #include "gfxUtils.h"
20 : #include "IPDLActor.h"
21 :
22 : namespace mozilla {
23 : namespace layers {
24 :
25 : using namespace mozilla::gfx;
26 :
27 : void
28 22 : CompositableClient::InitIPDL(const CompositableHandle& aHandle)
29 : {
30 22 : MOZ_ASSERT(aHandle);
31 :
32 22 : mForwarder->AssertInForwarderThread();
33 :
34 22 : mHandle = aHandle;
35 22 : mIsAsync = !NS_IsMainThread();
36 22 : }
37 :
38 79 : CompositableClient::CompositableClient(CompositableForwarder* aForwarder,
39 79 : TextureFlags aTextureFlags)
40 : : mForwarder(aForwarder)
41 : , mTextureFlags(aTextureFlags)
42 79 : , mIsAsync(false)
43 : {
44 79 : }
45 :
46 146 : CompositableClient::~CompositableClient()
47 : {
48 73 : Destroy();
49 73 : }
50 :
51 : LayersBackend
52 0 : CompositableClient::GetCompositorBackendType() const
53 : {
54 0 : return mForwarder->GetCompositorBackendType();
55 : }
56 :
57 : bool
58 22 : CompositableClient::Connect(ImageContainer* aImageContainer)
59 : {
60 22 : MOZ_ASSERT(!mHandle);
61 22 : if (!GetForwarder() || mHandle) {
62 0 : return false;
63 : }
64 :
65 22 : GetForwarder()->AssertInForwarderThread();
66 22 : GetForwarder()->Connect(this, aImageContainer);
67 22 : return true;
68 : }
69 :
70 : bool
71 66 : CompositableClient::IsConnected() const
72 : {
73 : // CanSend() is only reliable in the same thread as the IPDL channel.
74 66 : mForwarder->AssertInForwarderThread();
75 66 : return !!mHandle;
76 : }
77 :
78 : void
79 73 : CompositableClient::Destroy()
80 : {
81 73 : if (mTextureClientRecycler) {
82 0 : mTextureClientRecycler->Destroy();
83 : }
84 :
85 73 : if (mHandle) {
86 19 : mForwarder->ReleaseCompositable(mHandle);
87 19 : mHandle = CompositableHandle();
88 : }
89 73 : }
90 :
91 : CompositableHandle
92 0 : CompositableClient::GetAsyncHandle() const
93 : {
94 0 : if (mIsAsync) {
95 0 : return mHandle;
96 : }
97 0 : return CompositableHandle();
98 : }
99 :
100 : already_AddRefed<TextureClient>
101 0 : CompositableClient::CreateBufferTextureClient(gfx::SurfaceFormat aFormat,
102 : gfx::IntSize aSize,
103 : gfx::BackendType aMoz2DBackend,
104 : TextureFlags aTextureFlags)
105 : {
106 0 : return TextureClient::CreateForRawBufferAccess(GetForwarder(),
107 : aFormat, aSize, aMoz2DBackend,
108 0 : aTextureFlags | mTextureFlags);
109 : }
110 :
111 : already_AddRefed<TextureClient>
112 9 : CompositableClient::CreateTextureClientForDrawing(gfx::SurfaceFormat aFormat,
113 : gfx::IntSize aSize,
114 : BackendSelector aSelector,
115 : TextureFlags aTextureFlags,
116 : TextureAllocationFlags aAllocFlags)
117 : {
118 9 : return TextureClient::CreateForDrawing(GetForwarder(),
119 : aFormat, aSize, aSelector,
120 18 : aTextureFlags | mTextureFlags,
121 27 : aAllocFlags);
122 : }
123 :
124 : already_AddRefed<TextureClient>
125 0 : CompositableClient::CreateTextureClientFromSurface(gfx::SourceSurface* aSurface,
126 : BackendSelector aSelector,
127 : TextureFlags aTextureFlags,
128 : TextureAllocationFlags aAllocFlags)
129 : {
130 0 : return TextureClient::CreateFromSurface(GetForwarder(),
131 : aSurface,
132 : aSelector,
133 0 : aTextureFlags | mTextureFlags,
134 0 : aAllocFlags);
135 : }
136 :
137 : bool
138 9 : CompositableClient::AddTextureClient(TextureClient* aClient)
139 : {
140 9 : if(!aClient) {
141 0 : return false;
142 : }
143 9 : aClient->SetAddedToCompositableClient();
144 9 : return aClient->InitIPDLActor(mForwarder);
145 : }
146 :
147 : void
148 0 : CompositableClient::ClearCachedResources()
149 : {
150 0 : if (mTextureClientRecycler) {
151 0 : mTextureClientRecycler->ShrinkToMinimumSize();
152 : }
153 0 : }
154 :
155 : void
156 0 : CompositableClient::HandleMemoryPressure()
157 : {
158 0 : if (mTextureClientRecycler) {
159 0 : mTextureClientRecycler->ShrinkToMinimumSize();
160 : }
161 0 : }
162 :
163 : void
164 0 : CompositableClient::RemoveTexture(TextureClient* aTexture)
165 : {
166 0 : mForwarder->RemoveTextureFromCompositable(this, aTexture);
167 0 : }
168 :
169 : TextureClientRecycleAllocator*
170 0 : CompositableClient::GetTextureClientRecycler()
171 : {
172 0 : if (mTextureClientRecycler) {
173 0 : return mTextureClientRecycler;
174 : }
175 :
176 0 : if (!mForwarder) {
177 0 : return nullptr;
178 : }
179 :
180 0 : if(!mForwarder->GetTextureForwarder()->UsesImageBridge()) {
181 0 : MOZ_ASSERT(NS_IsMainThread());
182 0 : mTextureClientRecycler = new layers::TextureClientRecycleAllocator(mForwarder);
183 0 : return mTextureClientRecycler;
184 : }
185 :
186 : // Handle a case that mForwarder is ImageBridge
187 :
188 0 : if (InImageBridgeChildThread()) {
189 0 : mTextureClientRecycler = new layers::TextureClientRecycleAllocator(mForwarder);
190 0 : return mTextureClientRecycler;
191 : }
192 :
193 0 : ReentrantMonitor barrier("CompositableClient::GetTextureClientRecycler");
194 0 : ReentrantMonitorAutoEnter mainThreadAutoMon(barrier);
195 0 : bool done = false;
196 :
197 0 : RefPtr<Runnable> runnable = NS_NewRunnableFunction(
198 0 : "layers::CompositableClient::GetTextureClientRecycler", [&]() {
199 0 : if (!mTextureClientRecycler) {
200 0 : mTextureClientRecycler = new layers::TextureClientRecycleAllocator(mForwarder);
201 : }
202 0 : ReentrantMonitorAutoEnter childThreadAutoMon(barrier);
203 0 : done = true;
204 0 : barrier.NotifyAll();
205 0 : });
206 :
207 0 : ImageBridgeChild::GetSingleton()->GetMessageLoop()->PostTask(runnable.forget());
208 :
209 : // should stop the thread until done.
210 0 : while (!done) {
211 0 : barrier.Wait();
212 : }
213 :
214 0 : return mTextureClientRecycler;
215 : }
216 :
217 : void
218 0 : CompositableClient::DumpTextureClient(std::stringstream& aStream,
219 : TextureClient* aTexture,
220 : TextureDumpMode aCompress)
221 : {
222 0 : if (!aTexture) {
223 0 : return;
224 : }
225 0 : RefPtr<gfx::DataSourceSurface> dSurf = aTexture->GetAsSurface();
226 0 : if (!dSurf) {
227 0 : return;
228 : }
229 0 : if (aCompress == TextureDumpMode::Compress) {
230 0 : aStream << gfxUtils::GetAsLZ4Base64Str(dSurf).get();
231 : } else {
232 0 : aStream << gfxUtils::GetAsDataURI(dSurf).get();
233 : }
234 : }
235 :
236 0 : AutoRemoveTexture::~AutoRemoveTexture()
237 : {
238 0 : if (mCompositable && mTexture && mCompositable->IsConnected()) {
239 0 : mCompositable->RemoveTexture(mTexture);
240 : }
241 0 : }
242 :
243 : } // namespace layers
244 : } // namespace mozilla
|