Line data Source code
1 : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 : /* vim: set sw=4 ts=8 et 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/WebRenderBridgeChild.h"
8 :
9 : #include "gfxPlatform.h"
10 : #include "mozilla/layers/CompositableClient.h"
11 : #include "mozilla/layers/CompositorBridgeChild.h"
12 : #include "mozilla/layers/ImageDataSerializer.h"
13 : #include "mozilla/layers/StackingContextHelper.h"
14 : #include "mozilla/layers/PTextureChild.h"
15 : #include "mozilla/webrender/WebRenderAPI.h"
16 :
17 : namespace mozilla {
18 : namespace layers {
19 :
20 : using namespace mozilla::gfx;
21 :
22 0 : WebRenderBridgeChild::WebRenderBridgeChild(const wr::PipelineId& aPipelineId)
23 : : mReadLockSequenceNumber(0)
24 : , mIsInTransaction(false)
25 : , mIdNamespace(0)
26 : , mResourceId(0)
27 : , mPipelineId(aPipelineId)
28 : , mIPCOpen(false)
29 : , mDestroyed(false)
30 0 : , mFontKeysDeleted(0)
31 : {
32 0 : }
33 :
34 : void
35 0 : WebRenderBridgeChild::Destroy(bool aIsSync)
36 : {
37 0 : if (!IPCOpen()) {
38 0 : return;
39 : }
40 : // mDestroyed is used to prevent calling Send__delete__() twice.
41 : // When this function is called from CompositorBridgeChild::Destroy().
42 0 : mDestroyed = true;
43 :
44 0 : if (aIsSync) {
45 0 : SendShutdownSync();
46 : } else {
47 0 : SendShutdown();
48 : }
49 : }
50 :
51 : void
52 0 : WebRenderBridgeChild::ActorDestroy(ActorDestroyReason why)
53 : {
54 0 : mDestroyed = true;
55 0 : }
56 :
57 : void
58 0 : WebRenderBridgeChild::AddWebRenderParentCommand(const WebRenderParentCommand& aCmd)
59 : {
60 0 : MOZ_ASSERT(mIsInTransaction);
61 0 : mParentCommands.AppendElement(aCmd);
62 0 : }
63 :
64 : void
65 0 : WebRenderBridgeChild::AddWebRenderParentCommands(const nsTArray<WebRenderParentCommand>& aCommands)
66 : {
67 0 : MOZ_ASSERT(mIsInTransaction);
68 0 : mParentCommands.AppendElements(aCommands);
69 0 : }
70 :
71 : bool
72 0 : WebRenderBridgeChild::DPBegin(const gfx::IntSize& aSize)
73 : {
74 0 : MOZ_ASSERT(!mDestroyed);
75 :
76 0 : UpdateFwdTransactionId();
77 0 : this->SendDPBegin(aSize);
78 0 : mIsInTransaction = true;
79 0 : mReadLockSequenceNumber = 0;
80 0 : mReadLocks.AppendElement();
81 0 : return true;
82 : }
83 :
84 : void
85 0 : WebRenderBridgeChild::ClearReadLocks()
86 : {
87 0 : for (nsTArray<ReadLockInit>& locks : mReadLocks) {
88 0 : if (locks.Length()) {
89 0 : if (!SendInitReadLocks(locks)) {
90 0 : NS_WARNING("WARNING: sending read locks failed!");
91 0 : return;
92 : }
93 : }
94 : }
95 :
96 0 : mReadLocks.Clear();
97 : }
98 :
99 : void
100 0 : WebRenderBridgeChild::DPEnd(wr::DisplayListBuilder &aBuilder,
101 : const gfx::IntSize& aSize,
102 : bool aIsSync,
103 : uint64_t aTransactionId,
104 : const WebRenderScrollData& aScrollData)
105 : {
106 0 : MOZ_ASSERT(!mDestroyed);
107 0 : MOZ_ASSERT(mIsInTransaction);
108 :
109 0 : wr::BuiltDisplayList dl;
110 : WrSize contentSize;
111 0 : aBuilder.Finalize(contentSize, dl);
112 0 : ByteBuffer dlData(Move(dl.dl));
113 :
114 0 : if (aIsSync) {
115 0 : this->SendDPSyncEnd(aSize, mParentCommands, mDestroyedActors, GetFwdTransactionId(), aTransactionId,
116 0 : contentSize, dlData, dl.dl_desc, aScrollData, mIdNamespace);
117 : } else {
118 0 : this->SendDPEnd(aSize, mParentCommands, mDestroyedActors, GetFwdTransactionId(), aTransactionId,
119 0 : contentSize, dlData, dl.dl_desc, aScrollData, mIdNamespace);
120 : }
121 :
122 0 : mParentCommands.Clear();
123 0 : mDestroyedActors.Clear();
124 0 : mIsInTransaction = false;
125 0 : }
126 :
127 : void
128 0 : WebRenderBridgeChild::ProcessWebRenderParentCommands()
129 : {
130 0 : if (mParentCommands.IsEmpty()) {
131 0 : return;
132 : }
133 0 : this->SendParentCommands(mParentCommands);
134 0 : mParentCommands.Clear();
135 : }
136 :
137 : void
138 0 : WebRenderBridgeChild::AddPipelineIdForAsyncCompositable(const wr::PipelineId& aPipelineId,
139 : const CompositableHandle& aHandle)
140 : {
141 0 : SendAddPipelineIdForAsyncCompositable(aPipelineId, aHandle);
142 0 : }
143 :
144 : void
145 0 : WebRenderBridgeChild::RemovePipelineIdForAsyncCompositable(const wr::PipelineId& aPipelineId)
146 : {
147 0 : SendRemovePipelineIdForAsyncCompositable(aPipelineId);
148 0 : }
149 :
150 : wr::ExternalImageId
151 0 : WebRenderBridgeChild::GetNextExternalImageId()
152 : {
153 0 : wr::MaybeExternalImageId id = GetCompositorBridgeChild()->GetNextExternalImageId();
154 0 : MOZ_RELEASE_ASSERT(id.isSome());
155 0 : return id.value();
156 : }
157 :
158 : wr::ExternalImageId
159 0 : WebRenderBridgeChild::AllocExternalImageIdForCompositable(CompositableClient* aCompositable)
160 : {
161 0 : MOZ_ASSERT(!mDestroyed);
162 0 : MOZ_ASSERT(aCompositable->IsConnected());
163 :
164 0 : wr::ExternalImageId imageId = GetNextExternalImageId();
165 0 : SendAddExternalImageIdForCompositable(imageId, aCompositable->GetIPCHandle());
166 0 : return imageId;
167 : }
168 :
169 : void
170 0 : WebRenderBridgeChild::DeallocExternalImageId(wr::ExternalImageId& aImageId)
171 : {
172 0 : if (mDestroyed) {
173 : // This can happen if the IPC connection was torn down, because, e.g.
174 : // the GPU process died.
175 0 : return;
176 : }
177 0 : SendRemoveExternalImageId(aImageId);
178 : }
179 :
180 0 : struct FontFileData
181 : {
182 : wr::ByteBuffer mFontBuffer;
183 : uint32_t mFontIndex;
184 : };
185 :
186 : static void
187 0 : WriteFontFileData(const uint8_t* aData, uint32_t aLength, uint32_t aIndex,
188 : void* aBaton)
189 : {
190 0 : FontFileData* data = static_cast<FontFileData*>(aBaton);
191 :
192 0 : if (!data->mFontBuffer.Allocate(aLength)) {
193 0 : return;
194 : }
195 0 : memcpy(data->mFontBuffer.mData, aData, aLength);
196 :
197 0 : data->mFontIndex = aIndex;
198 : }
199 :
200 : void
201 0 : WebRenderBridgeChild::PushGlyphs(wr::DisplayListBuilder& aBuilder, const nsTArray<GlyphArray>& aGlyphs,
202 : gfx::ScaledFont* aFont, const StackingContextHelper& aSc,
203 : const LayerRect& aBounds, const LayerRect& aClip)
204 : {
205 0 : MOZ_ASSERT(aFont);
206 0 : MOZ_ASSERT(!aGlyphs.IsEmpty());
207 :
208 0 : WrFontKey key = GetFontKeyForScaledFont(aFont);
209 0 : MOZ_ASSERT(key.mNamespace && key.mHandle);
210 :
211 0 : for (size_t i = 0; i < aGlyphs.Length(); i++) {
212 0 : GlyphArray glyph_array = aGlyphs[i];
213 0 : nsTArray<gfx::Glyph>& glyphs = glyph_array.glyphs();
214 :
215 0 : nsTArray<WrGlyphInstance> wr_glyph_instances;
216 0 : wr_glyph_instances.SetLength(glyphs.Length());
217 :
218 0 : for (size_t j = 0; j < glyphs.Length(); j++) {
219 0 : wr_glyph_instances[j].index = glyphs[j].mIndex;
220 0 : wr_glyph_instances[j].point = aSc.ToRelativeWrPoint(
221 0 : LayerPoint::FromUnknownPoint(glyphs[j].mPosition));
222 : }
223 :
224 0 : aBuilder.PushText(aSc.ToRelativeWrRect(aBounds),
225 0 : aSc.ToRelativeWrRect(aClip),
226 0 : glyph_array.color().value(),
227 : key,
228 0 : Range<const WrGlyphInstance>(wr_glyph_instances.Elements(), wr_glyph_instances.Length()),
229 0 : aFont->GetSize());
230 :
231 : }
232 0 : }
233 :
234 : wr::FontKey
235 0 : WebRenderBridgeChild::GetFontKeyForScaledFont(gfx::ScaledFont* aScaledFont)
236 : {
237 0 : MOZ_ASSERT(!mDestroyed);
238 0 : MOZ_ASSERT(aScaledFont);
239 0 : MOZ_ASSERT((aScaledFont->GetType() == gfx::FontType::DWRITE) ||
240 : (aScaledFont->GetType() == gfx::FontType::MAC) ||
241 : (aScaledFont->GetType() == gfx::FontType::FONTCONFIG));
242 :
243 0 : RefPtr<gfx::UnscaledFont> unscaled = aScaledFont->GetUnscaledFont();
244 0 : MOZ_ASSERT(unscaled);
245 :
246 0 : wr::FontKey key = {0, 0};
247 0 : if (mFontKeys.Get(unscaled, &key)) {
248 0 : return key;
249 : }
250 :
251 0 : FontFileData data;
252 0 : if (!unscaled->GetFontFileData(WriteFontFileData, &data) ||
253 0 : !data.mFontBuffer.mData) {
254 0 : return key;
255 : }
256 :
257 0 : key.mNamespace = GetNamespace();
258 0 : key.mHandle = GetNextResourceId();
259 :
260 0 : SendAddRawFont(key, data.mFontBuffer, data.mFontIndex);
261 :
262 0 : mFontKeys.Put(unscaled, key);
263 :
264 0 : return key;
265 : }
266 :
267 : void
268 0 : WebRenderBridgeChild::RemoveExpiredFontKeys()
269 : {
270 0 : uint32_t counter = gfx::UnscaledFont::DeletionCounter();
271 0 : if (mFontKeysDeleted != counter) {
272 0 : mFontKeysDeleted = counter;
273 0 : for (auto iter = mFontKeys.Iter(); !iter.Done(); iter.Next()) {
274 0 : if (!iter.Key()) {
275 0 : SendDeleteFont(iter.Data());
276 0 : iter.Remove();
277 : }
278 : }
279 : }
280 0 : }
281 :
282 : CompositorBridgeChild*
283 0 : WebRenderBridgeChild::GetCompositorBridgeChild()
284 : {
285 0 : return static_cast<CompositorBridgeChild*>(Manager());
286 : }
287 :
288 : TextureForwarder*
289 0 : WebRenderBridgeChild::GetTextureForwarder()
290 : {
291 0 : return static_cast<TextureForwarder*>(GetCompositorBridgeChild());
292 : }
293 :
294 : LayersIPCActor*
295 0 : WebRenderBridgeChild::GetLayersIPCActor()
296 : {
297 0 : return static_cast<LayersIPCActor*>(GetCompositorBridgeChild());
298 : }
299 :
300 : void
301 0 : WebRenderBridgeChild::Connect(CompositableClient* aCompositable,
302 : ImageContainer* aImageContainer)
303 : {
304 0 : MOZ_ASSERT(aCompositable);
305 :
306 : static uint64_t sNextID = 1;
307 0 : uint64_t id = sNextID++;
308 :
309 0 : mCompositables.Put(id, aCompositable);
310 :
311 0 : CompositableHandle handle(id);
312 0 : aCompositable->InitIPDL(handle);
313 0 : SendNewCompositable(handle, aCompositable->GetTextureInfo());
314 0 : }
315 :
316 : void
317 0 : WebRenderBridgeChild::UseTiledLayerBuffer(CompositableClient* aCompositable,
318 : const SurfaceDescriptorTiles& aTiledDescriptor)
319 : {
320 :
321 0 : }
322 :
323 : void
324 0 : WebRenderBridgeChild::UpdateTextureRegion(CompositableClient* aCompositable,
325 : const ThebesBufferData& aThebesBufferData,
326 : const nsIntRegion& aUpdatedRegion)
327 : {
328 :
329 0 : }
330 :
331 : bool
332 0 : WebRenderBridgeChild::AddOpDestroy(const OpDestroy& aOp)
333 : {
334 0 : if (!mIsInTransaction) {
335 0 : return false;
336 : }
337 :
338 0 : mDestroyedActors.AppendElement(aOp);
339 0 : return true;
340 : }
341 :
342 : void
343 0 : WebRenderBridgeChild::ReleaseCompositable(const CompositableHandle& aHandle)
344 : {
345 0 : if (!IPCOpen()) {
346 : // This can happen if the IPC connection was torn down, because, e.g.
347 : // the GPU process died.
348 0 : return;
349 : }
350 0 : if (!DestroyInTransaction(aHandle)) {
351 0 : SendReleaseCompositable(aHandle);
352 : }
353 0 : mCompositables.Remove(aHandle.Value());
354 : }
355 :
356 : bool
357 0 : WebRenderBridgeChild::DestroyInTransaction(PTextureChild* aTexture)
358 : {
359 0 : return AddOpDestroy(OpDestroy(aTexture));
360 : }
361 :
362 : bool
363 0 : WebRenderBridgeChild::DestroyInTransaction(const CompositableHandle& aHandle)
364 : {
365 0 : return AddOpDestroy(OpDestroy(aHandle));
366 : }
367 :
368 : void
369 0 : WebRenderBridgeChild::RemoveTextureFromCompositable(CompositableClient* aCompositable,
370 : TextureClient* aTexture)
371 : {
372 0 : MOZ_ASSERT(aCompositable);
373 0 : MOZ_ASSERT(aTexture);
374 0 : MOZ_ASSERT(aTexture->GetIPDLActor());
375 0 : MOZ_RELEASE_ASSERT(aTexture->GetIPDLActor()->GetIPCChannel() == GetIPCChannel());
376 0 : if (!aCompositable->IsConnected() || !aTexture->GetIPDLActor()) {
377 : // We don't have an actor anymore, don't try to use it!
378 0 : return;
379 : }
380 :
381 0 : AddWebRenderParentCommand(
382 0 : CompositableOperation(
383 0 : aCompositable->GetIPCHandle(),
384 0 : OpRemoveTexture(nullptr, aTexture->GetIPDLActor())));
385 : }
386 :
387 : void
388 0 : WebRenderBridgeChild::UseTextures(CompositableClient* aCompositable,
389 : const nsTArray<TimedTextureClient>& aTextures)
390 : {
391 0 : MOZ_ASSERT(aCompositable);
392 :
393 0 : if (!aCompositable->IsConnected()) {
394 0 : return;
395 : }
396 :
397 0 : AutoTArray<TimedTexture,4> textures;
398 :
399 0 : for (auto& t : aTextures) {
400 0 : MOZ_ASSERT(t.mTextureClient);
401 0 : MOZ_ASSERT(t.mTextureClient->GetIPDLActor());
402 0 : MOZ_RELEASE_ASSERT(t.mTextureClient->GetIPDLActor()->GetIPCChannel() == GetIPCChannel());
403 0 : ReadLockDescriptor readLock;
404 0 : ReadLockHandle readLockHandle;
405 0 : if (t.mTextureClient->SerializeReadLock(readLock)) {
406 0 : readLockHandle = ReadLockHandle(++mReadLockSequenceNumber);
407 0 : if (mReadLocks.LastElement().Length() >= GetMaxFileDescriptorsPerMessage()) {
408 0 : mReadLocks.AppendElement();
409 : }
410 0 : mReadLocks.LastElement().AppendElement(ReadLockInit(readLock, readLockHandle));
411 : }
412 0 : textures.AppendElement(TimedTexture(nullptr, t.mTextureClient->GetIPDLActor(),
413 : readLockHandle,
414 : t.mTimeStamp, t.mPictureRect,
415 0 : t.mFrameID, t.mProducerID));
416 0 : GetCompositorBridgeChild()->HoldUntilCompositableRefReleasedIfNecessary(t.mTextureClient);
417 : }
418 0 : AddWebRenderParentCommand(CompositableOperation(aCompositable->GetIPCHandle(),
419 0 : OpUseTexture(textures)));
420 : }
421 :
422 : void
423 0 : WebRenderBridgeChild::UseComponentAlphaTextures(CompositableClient* aCompositable,
424 : TextureClient* aClientOnBlack,
425 : TextureClient* aClientOnWhite)
426 : {
427 :
428 0 : }
429 :
430 : void
431 0 : WebRenderBridgeChild::UpdateFwdTransactionId()
432 : {
433 0 : GetCompositorBridgeChild()->UpdateFwdTransactionId();
434 0 : }
435 :
436 : uint64_t
437 0 : WebRenderBridgeChild::GetFwdTransactionId()
438 : {
439 0 : return GetCompositorBridgeChild()->GetFwdTransactionId();
440 : }
441 :
442 : bool
443 0 : WebRenderBridgeChild::InForwarderThread()
444 : {
445 0 : return NS_IsMainThread();
446 : }
447 :
448 : mozilla::ipc::IPCResult
449 0 : WebRenderBridgeChild::RecvWrUpdated(const uint32_t& aNewIdNameSpace)
450 : {
451 : // Update mIdNamespace to identify obsolete keys and messages by WebRenderBridgeParent.
452 : // Since usage of invalid keys could cause crash in webrender.
453 0 : mIdNamespace = aNewIdNameSpace;
454 : // Remove all FontKeys since they are removed by WebRenderBridgeParent
455 0 : for (auto iter = mFontKeys.Iter(); !iter.Done(); iter.Next()) {
456 0 : SendDeleteFont(iter.Data());
457 : }
458 0 : mFontKeys.Clear();
459 0 : GetCompositorBridgeChild()->RecvInvalidateLayers(wr::AsUint64(mPipelineId));
460 0 : return IPC_OK();
461 : }
462 :
463 : } // namespace layers
464 : } // namespace mozilla
|