|
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 "CompositableHost.h" |
|
7 #include <map> // for _Rb_tree_iterator, map, etc |
|
8 #include <utility> // for pair |
|
9 #include "ContentHost.h" // for ContentHostDoubleBuffered, etc |
|
10 #include "Effects.h" // for EffectMask, Effect, etc |
|
11 #include "ImageHost.h" // for ImageHostBuffered, etc |
|
12 #include "TiledContentHost.h" // for TiledContentHost |
|
13 #include "mozilla/layers/LayersSurfaces.h" // for SurfaceDescriptor |
|
14 #include "mozilla/layers/TextureHost.h" // for TextureHost, etc |
|
15 #include "nsAutoPtr.h" // for nsRefPtr |
|
16 #include "nsDebug.h" // for NS_WARNING |
|
17 #include "nsISupportsImpl.h" // for MOZ_COUNT_CTOR, etc |
|
18 #include "gfxPlatform.h" // for gfxPlatform |
|
19 |
|
20 namespace mozilla { |
|
21 namespace layers { |
|
22 |
|
23 class Compositor; |
|
24 |
|
25 /** |
|
26 * IPDL actor used by CompositableHost to match with its corresponding |
|
27 * CompositableClient on the content side. |
|
28 * |
|
29 * CompositableParent is owned by the IPDL system. It's deletion is triggered |
|
30 * by either the CompositableChild's deletion, or by the IPDL communication |
|
31 * goind down. |
|
32 */ |
|
33 class CompositableParent : public PCompositableParent |
|
34 { |
|
35 public: |
|
36 CompositableParent(CompositableParentManager* aMgr, |
|
37 const TextureInfo& aTextureInfo, |
|
38 uint64_t aID = 0) |
|
39 { |
|
40 MOZ_COUNT_CTOR(CompositableParent); |
|
41 mHost = CompositableHost::Create(aTextureInfo); |
|
42 mHost->SetAsyncID(aID); |
|
43 if (aID) { |
|
44 CompositableMap::Set(aID, this); |
|
45 } |
|
46 } |
|
47 |
|
48 ~CompositableParent() |
|
49 { |
|
50 MOZ_COUNT_DTOR(CompositableParent); |
|
51 CompositableMap::Erase(mHost->GetAsyncID()); |
|
52 } |
|
53 |
|
54 virtual void ActorDestroy(ActorDestroyReason why) MOZ_OVERRIDE |
|
55 { |
|
56 if (mHost) { |
|
57 mHost->Detach(nullptr, CompositableHost::FORCE_DETACH); |
|
58 } |
|
59 } |
|
60 |
|
61 RefPtr<CompositableHost> mHost; |
|
62 }; |
|
63 |
|
64 CompositableHost::CompositableHost(const TextureInfo& aTextureInfo) |
|
65 : mTextureInfo(aTextureInfo) |
|
66 , mAsyncID(0) |
|
67 , mCompositorID(0) |
|
68 , mCompositor(nullptr) |
|
69 , mLayer(nullptr) |
|
70 , mFlashCounter(0) |
|
71 , mAttached(false) |
|
72 , mKeepAttached(false) |
|
73 { |
|
74 MOZ_COUNT_CTOR(CompositableHost); |
|
75 } |
|
76 |
|
77 CompositableHost::~CompositableHost() |
|
78 { |
|
79 MOZ_COUNT_DTOR(CompositableHost); |
|
80 if (mBackendData) { |
|
81 mBackendData->ClearData(); |
|
82 } |
|
83 } |
|
84 |
|
85 PCompositableParent* |
|
86 CompositableHost::CreateIPDLActor(CompositableParentManager* aMgr, |
|
87 const TextureInfo& aTextureInfo, |
|
88 uint64_t aID) |
|
89 { |
|
90 return new CompositableParent(aMgr, aTextureInfo, aID); |
|
91 } |
|
92 |
|
93 bool |
|
94 CompositableHost::DestroyIPDLActor(PCompositableParent* aActor) |
|
95 { |
|
96 delete aActor; |
|
97 return true; |
|
98 } |
|
99 |
|
100 CompositableHost* |
|
101 CompositableHost::FromIPDLActor(PCompositableParent* aActor) |
|
102 { |
|
103 MOZ_ASSERT(aActor); |
|
104 return static_cast<CompositableParent*>(aActor)->mHost; |
|
105 } |
|
106 |
|
107 void |
|
108 CompositableHost::UseTextureHost(TextureHost* aTexture) |
|
109 { |
|
110 if (!aTexture) { |
|
111 return; |
|
112 } |
|
113 aTexture->SetCompositor(GetCompositor()); |
|
114 aTexture->SetCompositableBackendSpecificData(GetCompositableBackendSpecificData()); |
|
115 } |
|
116 |
|
117 void |
|
118 CompositableHost::UseComponentAlphaTextures(TextureHost* aTextureOnBlack, |
|
119 TextureHost* aTextureOnWhite) |
|
120 { |
|
121 MOZ_ASSERT(aTextureOnBlack && aTextureOnWhite); |
|
122 aTextureOnBlack->SetCompositor(GetCompositor()); |
|
123 aTextureOnBlack->SetCompositableBackendSpecificData(GetCompositableBackendSpecificData()); |
|
124 aTextureOnWhite->SetCompositor(GetCompositor()); |
|
125 aTextureOnWhite->SetCompositableBackendSpecificData(GetCompositableBackendSpecificData()); |
|
126 } |
|
127 |
|
128 void |
|
129 CompositableHost::RemoveTextureHost(TextureHost* aTexture) |
|
130 { |
|
131 // Clear strong refrence to CompositableBackendSpecificData |
|
132 aTexture->SetCompositableBackendSpecificData(nullptr); |
|
133 } |
|
134 |
|
135 void |
|
136 CompositableHost::SetCompositor(Compositor* aCompositor) |
|
137 { |
|
138 mCompositor = aCompositor; |
|
139 } |
|
140 |
|
141 bool |
|
142 CompositableHost::AddMaskEffect(EffectChain& aEffects, |
|
143 const gfx::Matrix4x4& aTransform, |
|
144 bool aIs3D) |
|
145 { |
|
146 RefPtr<TextureSource> source; |
|
147 RefPtr<TextureHost> host = GetAsTextureHost(); |
|
148 if (host && host->Lock()) { |
|
149 source = host->GetTextureSources(); |
|
150 } |
|
151 |
|
152 if (!source) { |
|
153 NS_WARNING("Using compositable with no texture host as mask layer"); |
|
154 return false; |
|
155 } |
|
156 |
|
157 RefPtr<EffectMask> effect = new EffectMask(source, |
|
158 source->GetSize(), |
|
159 aTransform); |
|
160 effect->mIs3D = aIs3D; |
|
161 aEffects.mSecondaryEffects[EFFECT_MASK] = effect; |
|
162 return true; |
|
163 } |
|
164 |
|
165 void |
|
166 CompositableHost::RemoveMaskEffect() |
|
167 { |
|
168 RefPtr<TextureHost> host = GetAsTextureHost(); |
|
169 if (host) { |
|
170 host->Unlock(); |
|
171 } |
|
172 } |
|
173 |
|
174 // implemented in TextureHostOGL.cpp |
|
175 TemporaryRef<CompositableBackendSpecificData> CreateCompositableBackendSpecificDataOGL(); |
|
176 |
|
177 /* static */ TemporaryRef<CompositableHost> |
|
178 CompositableHost::Create(const TextureInfo& aTextureInfo) |
|
179 { |
|
180 RefPtr<CompositableHost> result; |
|
181 switch (aTextureInfo.mCompositableType) { |
|
182 case BUFFER_BRIDGE: |
|
183 NS_ERROR("Cannot create an image bridge compositable this way"); |
|
184 break; |
|
185 case BUFFER_CONTENT_INC: |
|
186 result = new ContentHostIncremental(aTextureInfo); |
|
187 break; |
|
188 case BUFFER_TILED: |
|
189 case BUFFER_SIMPLE_TILED: |
|
190 result = new TiledContentHost(aTextureInfo); |
|
191 break; |
|
192 case COMPOSITABLE_IMAGE: |
|
193 result = new ImageHost(aTextureInfo); |
|
194 break; |
|
195 case COMPOSITABLE_CONTENT_SINGLE: |
|
196 result = new ContentHostSingleBuffered(aTextureInfo); |
|
197 break; |
|
198 case COMPOSITABLE_CONTENT_DOUBLE: |
|
199 result = new ContentHostDoubleBuffered(aTextureInfo); |
|
200 break; |
|
201 default: |
|
202 NS_ERROR("Unknown CompositableType"); |
|
203 } |
|
204 // We know that Tiled buffers don't use the compositable backend-specific |
|
205 // data, so don't bother creating it. |
|
206 if (result && aTextureInfo.mCompositableType != BUFFER_TILED) { |
|
207 RefPtr<CompositableBackendSpecificData> data = CreateCompositableBackendSpecificDataOGL(); |
|
208 result->SetCompositableBackendSpecificData(data); |
|
209 } |
|
210 return result; |
|
211 } |
|
212 |
|
213 #ifdef MOZ_DUMP_PAINTING |
|
214 void |
|
215 CompositableHost::DumpTextureHost(FILE* aFile, TextureHost* aTexture) |
|
216 { |
|
217 if (!aTexture) { |
|
218 return; |
|
219 } |
|
220 RefPtr<gfx::DataSourceSurface> dSurf = aTexture->GetAsSurface(); |
|
221 if (!dSurf) { |
|
222 return; |
|
223 } |
|
224 gfxPlatform *platform = gfxPlatform::GetPlatform(); |
|
225 RefPtr<gfx::DrawTarget> dt = platform->CreateDrawTargetForData(dSurf->GetData(), |
|
226 dSurf->GetSize(), |
|
227 dSurf->Stride(), |
|
228 dSurf->GetFormat()); |
|
229 nsRefPtr<gfxASurface> surf = platform->GetThebesSurfaceForDrawTarget(dt); |
|
230 if (!surf) { |
|
231 return; |
|
232 } |
|
233 surf->DumpAsDataURL(aFile ? aFile : stderr); |
|
234 } |
|
235 #endif |
|
236 |
|
237 namespace CompositableMap { |
|
238 |
|
239 typedef std::map<uint64_t, PCompositableParent*> CompositableMap_t; |
|
240 static CompositableMap_t* sCompositableMap = nullptr; |
|
241 bool IsCreated() { |
|
242 return sCompositableMap != nullptr; |
|
243 } |
|
244 PCompositableParent* Get(uint64_t aID) |
|
245 { |
|
246 if (!IsCreated() || aID == 0) { |
|
247 return nullptr; |
|
248 } |
|
249 CompositableMap_t::iterator it = sCompositableMap->find(aID); |
|
250 if (it == sCompositableMap->end()) { |
|
251 return nullptr; |
|
252 } |
|
253 return it->second; |
|
254 } |
|
255 void Set(uint64_t aID, PCompositableParent* aParent) |
|
256 { |
|
257 if (!IsCreated() || aID == 0) { |
|
258 return; |
|
259 } |
|
260 (*sCompositableMap)[aID] = aParent; |
|
261 } |
|
262 void Erase(uint64_t aID) |
|
263 { |
|
264 if (!IsCreated() || aID == 0) { |
|
265 return; |
|
266 } |
|
267 CompositableMap_t::iterator it = sCompositableMap->find(aID); |
|
268 if (it != sCompositableMap->end()) { |
|
269 sCompositableMap->erase(it); |
|
270 } |
|
271 } |
|
272 void Clear() |
|
273 { |
|
274 if (!IsCreated()) { |
|
275 return; |
|
276 } |
|
277 sCompositableMap->clear(); |
|
278 } |
|
279 void Create() |
|
280 { |
|
281 if (sCompositableMap == nullptr) { |
|
282 sCompositableMap = new CompositableMap_t; |
|
283 } |
|
284 } |
|
285 void Destroy() |
|
286 { |
|
287 Clear(); |
|
288 delete sCompositableMap; |
|
289 sCompositableMap = nullptr; |
|
290 } |
|
291 |
|
292 } // namespace CompositableMap |
|
293 |
|
294 } // namespace layers |
|
295 } // namespace mozilla |