|
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- |
|
2 * vim: sw=2 ts=8 et : |
|
3 */ |
|
4 /* This Source Code Form is subject to the terms of the Mozilla Public |
|
5 * License, v. 2.0. If a copy of the MPL was not distributed with this |
|
6 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
7 |
|
8 #include "CompositableTransactionParent.h" |
|
9 #include "CompositableHost.h" // for CompositableParent, etc |
|
10 #include "CompositorParent.h" // for CompositorParent |
|
11 #include "GLContext.h" // for GLContext |
|
12 #include "Layers.h" // for Layer |
|
13 #include "RenderTrace.h" // for RenderTraceInvalidateEnd, etc |
|
14 #include "TiledLayerBuffer.h" // for TiledLayerComposer |
|
15 #include "mozilla/Assertions.h" // for MOZ_ASSERT, etc |
|
16 #include "mozilla/RefPtr.h" // for RefPtr |
|
17 #include "mozilla/layers/CompositorTypes.h" |
|
18 #include "mozilla/layers/ContentHost.h" // for ContentHostBase |
|
19 #include "mozilla/layers/LayerManagerComposite.h" |
|
20 #include "mozilla/layers/LayersSurfaces.h" // for SurfaceDescriptor |
|
21 #include "mozilla/layers/LayersTypes.h" // for MOZ_LAYERS_LOG |
|
22 #include "mozilla/layers/TextureHost.h" // for TextureHost |
|
23 #include "mozilla/layers/TextureHostOGL.h" // for TextureHostOGL |
|
24 #include "mozilla/layers/ThebesLayerComposite.h" |
|
25 #include "mozilla/mozalloc.h" // for operator delete |
|
26 #include "nsDebug.h" // for NS_WARNING, NS_ASSERTION |
|
27 #include "nsRegion.h" // for nsIntRegion |
|
28 |
|
29 namespace mozilla { |
|
30 namespace layers { |
|
31 |
|
32 class ClientTiledLayerBuffer; |
|
33 class Compositor; |
|
34 |
|
35 template<typename Op> |
|
36 CompositableHost* AsCompositable(const Op& op) |
|
37 { |
|
38 return CompositableHost::FromIPDLActor(op.compositableParent()); |
|
39 } |
|
40 |
|
41 // This function can in some cases fail and return false without it being a bug. |
|
42 // This can theoretically happen if the ImageBridge sends frames before |
|
43 // we created the layer tree. Since we can't enforce that the layer |
|
44 // tree is already created before ImageBridge operates, there isn't much |
|
45 // we can do about it, but in practice it is very rare. |
|
46 // Typically when a tab with a video is dragged from a window to another, |
|
47 // there can be a short time when the video is still sending frames |
|
48 // asynchonously while the layer tree is not reconstructed. It's not a |
|
49 // big deal. |
|
50 // Note that Layers transactions do not need to call this because they always |
|
51 // schedule the composition, in LayerManagerComposite::EndTransaction. |
|
52 template<typename T> |
|
53 bool ScheduleComposition(const T& op) |
|
54 { |
|
55 CompositableHost* comp = AsCompositable(op); |
|
56 uint64_t id = comp->GetCompositorID(); |
|
57 if (!comp || !id) { |
|
58 return false; |
|
59 } |
|
60 CompositorParent* cp = CompositorParent::GetCompositor(id); |
|
61 if (!cp) { |
|
62 return false; |
|
63 } |
|
64 cp->ScheduleComposition(); |
|
65 return true; |
|
66 } |
|
67 |
|
68 bool |
|
69 CompositableParentManager::ReceiveCompositableUpdate(const CompositableOperation& aEdit, |
|
70 EditReplyVector& replyv) |
|
71 { |
|
72 switch (aEdit.type()) { |
|
73 case CompositableOperation::TOpCreatedIncrementalTexture: { |
|
74 MOZ_LAYERS_LOG(("[ParentSide] Created texture")); |
|
75 const OpCreatedIncrementalTexture& op = aEdit.get_OpCreatedIncrementalTexture(); |
|
76 CompositableHost* compositable = AsCompositable(op); |
|
77 |
|
78 bool success = |
|
79 compositable->CreatedIncrementalTexture(this, |
|
80 op.textureInfo(), |
|
81 op.bufferRect()); |
|
82 if (!success) { |
|
83 return false; |
|
84 } |
|
85 break; |
|
86 } |
|
87 case CompositableOperation::TOpPaintTextureRegion: { |
|
88 MOZ_LAYERS_LOG(("[ParentSide] Paint ThebesLayer")); |
|
89 |
|
90 const OpPaintTextureRegion& op = aEdit.get_OpPaintTextureRegion(); |
|
91 CompositableHost* compositable = AsCompositable(op); |
|
92 Layer* layer = compositable->GetLayer(); |
|
93 if (!layer || layer->GetType() != Layer::TYPE_THEBES) { |
|
94 return false; |
|
95 } |
|
96 ThebesLayerComposite* thebes = static_cast<ThebesLayerComposite*>(layer); |
|
97 |
|
98 const ThebesBufferData& bufferData = op.bufferData(); |
|
99 |
|
100 RenderTraceInvalidateStart(thebes, "FF00FF", op.updatedRegion().GetBounds()); |
|
101 |
|
102 nsIntRegion frontUpdatedRegion; |
|
103 if (!compositable->UpdateThebes(bufferData, |
|
104 op.updatedRegion(), |
|
105 thebes->GetValidRegion(), |
|
106 &frontUpdatedRegion)) |
|
107 { |
|
108 return false; |
|
109 } |
|
110 replyv.push_back( |
|
111 OpContentBufferSwap(op.compositableParent(), nullptr, frontUpdatedRegion)); |
|
112 |
|
113 RenderTraceInvalidateEnd(thebes, "FF00FF"); |
|
114 // return texure data to client if necessary |
|
115 ReturnTextureDataIfNecessary(compositable, replyv, op.compositableParent()); |
|
116 break; |
|
117 } |
|
118 case CompositableOperation::TOpPaintTextureIncremental: { |
|
119 MOZ_LAYERS_LOG(("[ParentSide] Paint ThebesLayer")); |
|
120 |
|
121 const OpPaintTextureIncremental& op = aEdit.get_OpPaintTextureIncremental(); |
|
122 |
|
123 CompositableHost* compositable = AsCompositable(op); |
|
124 |
|
125 SurfaceDescriptor desc = op.image(); |
|
126 |
|
127 compositable->UpdateIncremental(op.textureId(), |
|
128 desc, |
|
129 op.updatedRegion(), |
|
130 op.bufferRect(), |
|
131 op.bufferRotation()); |
|
132 break; |
|
133 } |
|
134 case CompositableOperation::TOpUpdatePictureRect: { |
|
135 const OpUpdatePictureRect& op = aEdit.get_OpUpdatePictureRect(); |
|
136 CompositableHost* compositable = AsCompositable(op); |
|
137 MOZ_ASSERT(compositable); |
|
138 compositable->SetPictureRect(op.picture()); |
|
139 break; |
|
140 } |
|
141 case CompositableOperation::TOpUseTiledLayerBuffer: { |
|
142 MOZ_LAYERS_LOG(("[ParentSide] Paint TiledLayerBuffer")); |
|
143 const OpUseTiledLayerBuffer& op = aEdit.get_OpUseTiledLayerBuffer(); |
|
144 CompositableHost* compositable = AsCompositable(op); |
|
145 |
|
146 TiledLayerComposer* tileComposer = compositable->AsTiledLayerComposer(); |
|
147 NS_ASSERTION(tileComposer, "compositable is not a tile composer"); |
|
148 |
|
149 const SurfaceDescriptorTiles& tileDesc = op.tileLayerDescriptor(); |
|
150 tileComposer->UseTiledLayerBuffer(this, tileDesc); |
|
151 break; |
|
152 } |
|
153 case CompositableOperation::TOpRemoveTexture: { |
|
154 const OpRemoveTexture& op = aEdit.get_OpRemoveTexture(); |
|
155 CompositableHost* compositable = AsCompositable(op); |
|
156 RefPtr<TextureHost> tex = TextureHost::AsTextureHost(op.textureParent()); |
|
157 |
|
158 MOZ_ASSERT(tex.get()); |
|
159 compositable->RemoveTextureHost(tex); |
|
160 // return texure data to client if necessary |
|
161 ReturnTextureDataIfNecessary(compositable, replyv, op.compositableParent()); |
|
162 break; |
|
163 } |
|
164 case CompositableOperation::TOpUseTexture: { |
|
165 const OpUseTexture& op = aEdit.get_OpUseTexture(); |
|
166 CompositableHost* compositable = AsCompositable(op); |
|
167 RefPtr<TextureHost> tex = TextureHost::AsTextureHost(op.textureParent()); |
|
168 |
|
169 MOZ_ASSERT(tex.get()); |
|
170 compositable->UseTextureHost(tex); |
|
171 |
|
172 if (IsAsync()) { |
|
173 ScheduleComposition(op); |
|
174 // Async layer updates don't trigger invalidation, manually tell the layer |
|
175 // that its content have changed. |
|
176 if (compositable->GetLayer()) { |
|
177 compositable->GetLayer()->SetInvalidRectToVisibleRegion(); |
|
178 } |
|
179 } |
|
180 // return texure data to client if necessary |
|
181 ReturnTextureDataIfNecessary(compositable, replyv, op.compositableParent()); |
|
182 break; |
|
183 } |
|
184 case CompositableOperation::TOpUseComponentAlphaTextures: { |
|
185 const OpUseComponentAlphaTextures& op = aEdit.get_OpUseComponentAlphaTextures(); |
|
186 CompositableHost* compositable = AsCompositable(op); |
|
187 RefPtr<TextureHost> texOnBlack = TextureHost::AsTextureHost(op.textureOnBlackParent()); |
|
188 RefPtr<TextureHost> texOnWhite = TextureHost::AsTextureHost(op.textureOnWhiteParent()); |
|
189 |
|
190 MOZ_ASSERT(texOnBlack && texOnWhite); |
|
191 compositable->UseComponentAlphaTextures(texOnBlack, texOnWhite); |
|
192 |
|
193 if (IsAsync()) { |
|
194 ScheduleComposition(op); |
|
195 } |
|
196 // return texure data to client if necessary |
|
197 ReturnTextureDataIfNecessary(compositable, replyv, op.compositableParent()); |
|
198 break; |
|
199 } |
|
200 case CompositableOperation::TOpUpdateTexture: { |
|
201 const OpUpdateTexture& op = aEdit.get_OpUpdateTexture(); |
|
202 RefPtr<TextureHost> texture = TextureHost::AsTextureHost(op.textureParent()); |
|
203 MOZ_ASSERT(texture); |
|
204 |
|
205 texture->Updated(op.region().type() == MaybeRegion::TnsIntRegion |
|
206 ? &op.region().get_nsIntRegion() |
|
207 : nullptr); // no region means invalidate the entire surface |
|
208 break; |
|
209 } |
|
210 |
|
211 default: { |
|
212 MOZ_ASSERT(false, "bad type"); |
|
213 } |
|
214 } |
|
215 |
|
216 return true; |
|
217 } |
|
218 |
|
219 #if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 17 |
|
220 void |
|
221 CompositableParentManager::ReturnTextureDataIfNecessary(CompositableHost* aCompositable, |
|
222 EditReplyVector& replyv, |
|
223 PCompositableParent* aParent) |
|
224 { |
|
225 if (!aCompositable || !aCompositable->GetCompositableBackendSpecificData()) { |
|
226 return; |
|
227 } |
|
228 |
|
229 const std::vector< RefPtr<TextureHost> > textureList = |
|
230 aCompositable->GetCompositableBackendSpecificData()->GetPendingReleaseFenceTextureList(); |
|
231 // Return pending Texture data |
|
232 for (size_t i = 0; i < textureList.size(); i++) { |
|
233 // File descriptor number is limited to 4 per IPC message. |
|
234 // See Bug 986253 |
|
235 if (mPrevFenceHandles.size() >= 4) { |
|
236 break; |
|
237 } |
|
238 TextureHostOGL* hostOGL = textureList[i]->AsHostOGL(); |
|
239 PTextureParent* actor = textureList[i]->GetIPDLActor(); |
|
240 if (!hostOGL || !actor) { |
|
241 continue; |
|
242 } |
|
243 android::sp<android::Fence> fence = hostOGL->GetAndResetReleaseFence(); |
|
244 if (fence.get() && fence->isValid()) { |
|
245 FenceHandle handle = FenceHandle(fence); |
|
246 replyv.push_back(ReturnReleaseFence(aParent, nullptr, actor, nullptr, handle)); |
|
247 // Hold fence handle to prevent fence's file descriptor is closed before IPC happens. |
|
248 mPrevFenceHandles.push_back(handle); |
|
249 } |
|
250 } |
|
251 aCompositable->GetCompositableBackendSpecificData()->ClearPendingReleaseFenceTextureList(); |
|
252 } |
|
253 #else |
|
254 void |
|
255 CompositableParentManager::ReturnTextureDataIfNecessary(CompositableHost* aCompositable, |
|
256 EditReplyVector& replyv, |
|
257 PCompositableParent* aParent) |
|
258 { |
|
259 if (!aCompositable || !aCompositable->GetCompositableBackendSpecificData()) { |
|
260 return; |
|
261 } |
|
262 aCompositable->GetCompositableBackendSpecificData()->ClearPendingReleaseFenceTextureList(); |
|
263 } |
|
264 #endif |
|
265 |
|
266 void |
|
267 CompositableParentManager::ClearPrevFenceHandles() |
|
268 { |
|
269 mPrevFenceHandles.clear(); |
|
270 } |
|
271 |
|
272 } // namespace |
|
273 } // namespace |
|
274 |