1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7 #include "mozilla/layers/CompositableClient.h"
8 #include <stdint.h> // for uint64_t, uint32_t
9 #include "gfxPlatform.h" // for gfxPlatform
10 #include "mozilla/layers/CompositableForwarder.h"
11 #include "mozilla/layers/ImageBridgeChild.h"
12 #include "mozilla/layers/TextureClient.h" // for TextureClient, etc
13 #include "mozilla/layers/TextureClientOGL.h"
14 #include "mozilla/mozalloc.h" // for operator delete, etc
15 #include "mozilla/layers/TextureClientRecycleAllocator.h"
16 #ifdef XP_WIN
17 #include "gfxWindowsPlatform.h" // for gfxWindowsPlatform
18 #include "mozilla/layers/TextureD3D11.h"
19 #endif
20 #include "gfxUtils.h"
21 #include "IPDLActor.h"
22
23 namespace mozilla {
24 namespace layers {
25
26 using namespace mozilla::gfx;
27
InitIPDL(const CompositableHandle & aHandle)28 void CompositableClient::InitIPDL(const CompositableHandle& aHandle) {
29 MOZ_ASSERT(aHandle);
30
31 mForwarder->AssertInForwarderThread();
32
33 mHandle = aHandle;
34 mIsAsync = !NS_IsMainThread();
35 }
36
CompositableClient(CompositableForwarder * aForwarder,TextureFlags aTextureFlags)37 CompositableClient::CompositableClient(CompositableForwarder* aForwarder,
38 TextureFlags aTextureFlags)
39 : mForwarder(aForwarder), mTextureFlags(aTextureFlags), mIsAsync(false) {}
40
~CompositableClient()41 CompositableClient::~CompositableClient() { Destroy(); }
42
GetCompositorBackendType() const43 LayersBackend CompositableClient::GetCompositorBackendType() const {
44 return mForwarder->GetCompositorBackendType();
45 }
46
Connect(ImageContainer * aImageContainer)47 bool CompositableClient::Connect(ImageContainer* aImageContainer) {
48 MOZ_ASSERT(!mHandle);
49 if (!GetForwarder() || mHandle) {
50 return false;
51 }
52
53 GetForwarder()->AssertInForwarderThread();
54 GetForwarder()->Connect(this, aImageContainer);
55 return true;
56 }
57
IsConnected() const58 bool CompositableClient::IsConnected() const {
59 // CanSend() is only reliable in the same thread as the IPDL channel.
60 mForwarder->AssertInForwarderThread();
61 return !!mHandle;
62 }
63
Destroy()64 void CompositableClient::Destroy() {
65 if (mTextureClientRecycler) {
66 mTextureClientRecycler->Destroy();
67 }
68
69 if (mHandle) {
70 mForwarder->ReleaseCompositable(mHandle);
71 mHandle = CompositableHandle();
72 }
73 }
74
GetAsyncHandle() const75 CompositableHandle CompositableClient::GetAsyncHandle() const {
76 if (mIsAsync) {
77 return mHandle;
78 }
79 return CompositableHandle();
80 }
81
CreateBufferTextureClient(gfx::SurfaceFormat aFormat,gfx::IntSize aSize,gfx::BackendType aMoz2DBackend,TextureFlags aTextureFlags)82 already_AddRefed<TextureClient> CompositableClient::CreateBufferTextureClient(
83 gfx::SurfaceFormat aFormat, gfx::IntSize aSize,
84 gfx::BackendType aMoz2DBackend, TextureFlags aTextureFlags) {
85 return TextureClient::CreateForRawBufferAccess(GetForwarder(), aFormat, aSize,
86 aMoz2DBackend,
87 aTextureFlags | mTextureFlags);
88 }
89
90 already_AddRefed<TextureClient>
CreateTextureClientForDrawing(gfx::SurfaceFormat aFormat,gfx::IntSize aSize,BackendSelector aSelector,TextureFlags aTextureFlags,TextureAllocationFlags aAllocFlags)91 CompositableClient::CreateTextureClientForDrawing(
92 gfx::SurfaceFormat aFormat, gfx::IntSize aSize, BackendSelector aSelector,
93 TextureFlags aTextureFlags, TextureAllocationFlags aAllocFlags) {
94 return TextureClient::CreateForDrawing(
95 GetForwarder(), aFormat, aSize, aSelector, aTextureFlags | mTextureFlags,
96 aAllocFlags);
97 }
98
99 already_AddRefed<TextureClient>
CreateTextureClientFromSurface(gfx::SourceSurface * aSurface,BackendSelector aSelector,TextureFlags aTextureFlags,TextureAllocationFlags aAllocFlags)100 CompositableClient::CreateTextureClientFromSurface(
101 gfx::SourceSurface* aSurface, BackendSelector aSelector,
102 TextureFlags aTextureFlags, TextureAllocationFlags aAllocFlags) {
103 return TextureClient::CreateFromSurface(GetForwarder(), aSurface, aSelector,
104 aTextureFlags | mTextureFlags,
105 aAllocFlags);
106 }
107
AddTextureClient(TextureClient * aClient)108 bool CompositableClient::AddTextureClient(TextureClient* aClient) {
109 if (!aClient) {
110 return false;
111 }
112 aClient->SetAddedToCompositableClient();
113 return aClient->InitIPDLActor(mForwarder);
114 }
115
ClearCachedResources()116 void CompositableClient::ClearCachedResources() {
117 if (mTextureClientRecycler) {
118 mTextureClientRecycler->ShrinkToMinimumSize();
119 }
120 }
121
HandleMemoryPressure()122 void CompositableClient::HandleMemoryPressure() {
123 if (mTextureClientRecycler) {
124 mTextureClientRecycler->ShrinkToMinimumSize();
125 }
126 }
127
RemoveTexture(TextureClient * aTexture)128 void CompositableClient::RemoveTexture(TextureClient* aTexture) {
129 mForwarder->RemoveTextureFromCompositable(this, aTexture);
130 }
131
GetTextureClientRecycler()132 TextureClientRecycleAllocator* CompositableClient::GetTextureClientRecycler() {
133 if (mTextureClientRecycler) {
134 return mTextureClientRecycler;
135 }
136
137 if (!mForwarder) {
138 return nullptr;
139 }
140
141 if (!mForwarder->GetTextureForwarder()->UsesImageBridge()) {
142 MOZ_ASSERT(NS_IsMainThread());
143 mTextureClientRecycler =
144 new layers::TextureClientRecycleAllocator(mForwarder);
145 return mTextureClientRecycler;
146 }
147
148 // Handle a case that mForwarder is ImageBridge
149
150 if (InImageBridgeChildThread()) {
151 mTextureClientRecycler =
152 new layers::TextureClientRecycleAllocator(mForwarder);
153 return mTextureClientRecycler;
154 }
155
156 ReentrantMonitor barrier("CompositableClient::GetTextureClientRecycler");
157 ReentrantMonitorAutoEnter mainThreadAutoMon(barrier);
158 bool done = false;
159
160 RefPtr<Runnable> runnable = NS_NewRunnableFunction(
161 "layers::CompositableClient::GetTextureClientRecycler", [&]() {
162 if (!mTextureClientRecycler) {
163 mTextureClientRecycler =
164 new layers::TextureClientRecycleAllocator(mForwarder);
165 }
166 ReentrantMonitorAutoEnter childThreadAutoMon(barrier);
167 done = true;
168 barrier.NotifyAll();
169 });
170
171 ImageBridgeChild::GetSingleton()->GetMessageLoop()->PostTask(
172 runnable.forget());
173
174 // should stop the thread until done.
175 while (!done) {
176 barrier.Wait();
177 }
178
179 return mTextureClientRecycler;
180 }
181
DumpTextureClient(std::stringstream & aStream,TextureClient * aTexture,TextureDumpMode aCompress)182 void CompositableClient::DumpTextureClient(std::stringstream& aStream,
183 TextureClient* aTexture,
184 TextureDumpMode aCompress) {
185 if (!aTexture) {
186 return;
187 }
188 RefPtr<gfx::DataSourceSurface> dSurf = aTexture->GetAsSurface();
189 if (!dSurf) {
190 return;
191 }
192 if (aCompress == TextureDumpMode::Compress) {
193 aStream << gfxUtils::GetAsLZ4Base64Str(dSurf).get();
194 } else {
195 aStream << gfxUtils::GetAsDataURI(dSurf).get();
196 }
197 }
198
~AutoRemoveTexture()199 AutoRemoveTexture::~AutoRemoveTexture() {
200 if (mCompositable && mTexture && mCompositable->IsConnected()) {
201 mCompositable->RemoveTexture(mTexture);
202 }
203 }
204
205 } // namespace layers
206 } // namespace mozilla
207