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/WebRenderBridgeChild.h"
8 
9 #include "gfxPlatform.h"
10 #include "mozilla/StaticPrefs_gfx.h"
11 #include "mozilla/layers/CompositableClient.h"
12 #include "mozilla/layers/CompositorBridgeChild.h"
13 #include "mozilla/layers/ImageDataSerializer.h"
14 #include "mozilla/layers/IpcResourceUpdateQueue.h"
15 #include "mozilla/layers/StackingContextHelper.h"
16 #include "mozilla/layers/PTextureChild.h"
17 #include "mozilla/layers/WebRenderLayerManager.h"
18 #include "mozilla/webrender/WebRenderAPI.h"
19 #include "PDMFactory.h"
20 
21 namespace mozilla {
22 namespace layers {
23 
24 using namespace mozilla::gfx;
25 
WebRenderBridgeChild(const wr::PipelineId & aPipelineId)26 WebRenderBridgeChild::WebRenderBridgeChild(const wr::PipelineId& aPipelineId)
27     : mIsInTransaction(false),
28       mIsInClearCachedResources(false),
29       mIdNamespace{0},
30       mResourceId(0),
31       mPipelineId(aPipelineId),
32       mManager(nullptr),
33       mIPCOpen(false),
34       mDestroyed(false),
35       mSentDisplayList(false),
36       mFontKeysDeleted(0),
37       mFontInstanceKeysDeleted(0) {}
38 
~WebRenderBridgeChild()39 WebRenderBridgeChild::~WebRenderBridgeChild() {
40   MOZ_ASSERT(NS_IsMainThread());
41   MOZ_ASSERT(mDestroyed);
42 }
43 
Destroy(bool aIsSync)44 void WebRenderBridgeChild::Destroy(bool aIsSync) {
45   if (!IPCOpen()) {
46     return;
47   }
48 
49   DoDestroy();
50 
51   if (aIsSync) {
52     SendShutdownSync();
53   } else {
54     SendShutdown();
55   }
56 }
57 
ActorDestroy(ActorDestroyReason why)58 void WebRenderBridgeChild::ActorDestroy(ActorDestroyReason why) { DoDestroy(); }
59 
DoDestroy()60 void WebRenderBridgeChild::DoDestroy() {
61   if (RefCountedShm::IsValid(mResourceShm) &&
62       RefCountedShm::Release(mResourceShm) == 0) {
63     RefCountedShm::Dealloc(this, mResourceShm);
64     mResourceShm = RefCountedShmem();
65   }
66 
67   // mDestroyed is used to prevent calling Send__delete__() twice.
68   // When this function is called from CompositorBridgeChild::Destroy().
69   // mActiveResourceTracker is not cleared here, since it is
70   // used by PersistentBufferProviderShared.
71   mDestroyed = true;
72   mManager = nullptr;
73 }
74 
AddWebRenderParentCommand(const WebRenderParentCommand & aCmd)75 void WebRenderBridgeChild::AddWebRenderParentCommand(
76     const WebRenderParentCommand& aCmd) {
77   mParentCommands.AppendElement(aCmd);
78 }
79 
BeginTransaction()80 void WebRenderBridgeChild::BeginTransaction() {
81   MOZ_ASSERT(!mDestroyed);
82 
83   UpdateFwdTransactionId();
84   mIsInTransaction = true;
85 }
86 
UpdateResources(wr::IpcResourceUpdateQueue & aResources)87 void WebRenderBridgeChild::UpdateResources(
88     wr::IpcResourceUpdateQueue& aResources) {
89   if (!IPCOpen()) {
90     aResources.Clear();
91     return;
92   }
93 
94   if (aResources.IsEmpty()) {
95     return;
96   }
97 
98   nsTArray<OpUpdateResource> resourceUpdates;
99   nsTArray<RefCountedShmem> smallShmems;
100   nsTArray<ipc::Shmem> largeShmems;
101   aResources.Flush(resourceUpdates, smallShmems, largeShmems);
102 
103   this->SendUpdateResources(mIdNamespace, resourceUpdates, smallShmems,
104                             std::move(largeShmems));
105 }
106 
EndTransaction(DisplayListData && aDisplayListData,TransactionId aTransactionId,bool aContainsSVGGroup,const mozilla::VsyncId & aVsyncId,const mozilla::TimeStamp & aVsyncStartTime,const mozilla::TimeStamp & aRefreshStartTime,const mozilla::TimeStamp & aTxnStartTime,const nsCString & aTxnURL)107 bool WebRenderBridgeChild::EndTransaction(
108     DisplayListData&& aDisplayListData, TransactionId aTransactionId,
109     bool aContainsSVGGroup, const mozilla::VsyncId& aVsyncId,
110     const mozilla::TimeStamp& aVsyncStartTime,
111     const mozilla::TimeStamp& aRefreshStartTime,
112     const mozilla::TimeStamp& aTxnStartTime, const nsCString& aTxnURL) {
113   MOZ_ASSERT(!mDestroyed);
114   MOZ_ASSERT(mIsInTransaction);
115 
116   TimeStamp fwdTime = TimeStamp::Now();
117 
118   aDisplayListData.mCommands = std::move(mParentCommands);
119   aDisplayListData.mIdNamespace = mIdNamespace;
120 
121   nsTArray<CompositionPayload> payloads;
122   if (mManager) {
123     mManager->TakeCompositionPayloads(payloads);
124   }
125 
126   mSentDisplayList = true;
127   bool ret = this->SendSetDisplayList(
128       std::move(aDisplayListData), mDestroyedActors, GetFwdTransactionId(),
129       aTransactionId, aContainsSVGGroup, aVsyncId, aVsyncStartTime,
130       aRefreshStartTime, aTxnStartTime, aTxnURL, fwdTime, payloads);
131 
132   // With multiple render roots, we may not have sent all of our
133   // mParentCommands, so go ahead and go through our mParentCommands and ensure
134   // they get sent.
135   ProcessWebRenderParentCommands();
136   mDestroyedActors.Clear();
137   mIsInTransaction = false;
138 
139   return ret;
140 }
141 
EndEmptyTransaction(const FocusTarget & aFocusTarget,Maybe<TransactionData> && aTransactionData,TransactionId aTransactionId,const mozilla::VsyncId & aVsyncId,const mozilla::TimeStamp & aVsyncStartTime,const mozilla::TimeStamp & aRefreshStartTime,const mozilla::TimeStamp & aTxnStartTime,const nsCString & aTxnURL)142 void WebRenderBridgeChild::EndEmptyTransaction(
143     const FocusTarget& aFocusTarget, Maybe<TransactionData>&& aTransactionData,
144     TransactionId aTransactionId, const mozilla::VsyncId& aVsyncId,
145     const mozilla::TimeStamp& aVsyncStartTime,
146     const mozilla::TimeStamp& aRefreshStartTime,
147     const mozilla::TimeStamp& aTxnStartTime, const nsCString& aTxnURL) {
148   MOZ_ASSERT(!mDestroyed);
149   MOZ_ASSERT(mIsInTransaction);
150 
151   TimeStamp fwdTime = TimeStamp::Now();
152 
153   if (aTransactionData) {
154     aTransactionData->mCommands = std::move(mParentCommands);
155   }
156 
157   nsTArray<CompositionPayload> payloads;
158   if (mManager) {
159     mManager->TakeCompositionPayloads(payloads);
160   }
161 
162   this->SendEmptyTransaction(
163       aFocusTarget, std::move(aTransactionData), mDestroyedActors,
164       GetFwdTransactionId(), aTransactionId, aVsyncId, aVsyncStartTime,
165       aRefreshStartTime, aTxnStartTime, aTxnURL, fwdTime, payloads);
166 
167   // With multiple render roots, we may not have sent all of our
168   // mParentCommands, so go ahead and go through our mParentCommands and ensure
169   // they get sent.
170   ProcessWebRenderParentCommands();
171   mDestroyedActors.Clear();
172   mIsInTransaction = false;
173 }
174 
ProcessWebRenderParentCommands()175 void WebRenderBridgeChild::ProcessWebRenderParentCommands() {
176   MOZ_ASSERT(!mDestroyed);
177 
178   if (!mParentCommands.IsEmpty()) {
179     this->SendParentCommands(mParentCommands);
180     mParentCommands.Clear();
181   }
182 }
183 
AddPipelineIdForAsyncCompositable(const wr::PipelineId & aPipelineId,const CompositableHandle & aHandle)184 void WebRenderBridgeChild::AddPipelineIdForAsyncCompositable(
185     const wr::PipelineId& aPipelineId, const CompositableHandle& aHandle) {
186   AddWebRenderParentCommand(
187       OpAddPipelineIdForCompositable(aPipelineId, aHandle, /* isAsync */ true));
188 }
189 
AddPipelineIdForCompositable(const wr::PipelineId & aPipelineId,const CompositableHandle & aHandle)190 void WebRenderBridgeChild::AddPipelineIdForCompositable(
191     const wr::PipelineId& aPipelineId, const CompositableHandle& aHandle) {
192   AddWebRenderParentCommand(OpAddPipelineIdForCompositable(
193       aPipelineId, aHandle, /* isAsync */ false));
194 }
195 
RemovePipelineIdForCompositable(const wr::PipelineId & aPipelineId)196 void WebRenderBridgeChild::RemovePipelineIdForCompositable(
197     const wr::PipelineId& aPipelineId) {
198   AddWebRenderParentCommand(OpRemovePipelineIdForCompositable(aPipelineId));
199 }
200 
GetNextExternalImageId()201 wr::ExternalImageId WebRenderBridgeChild::GetNextExternalImageId() {
202   wr::MaybeExternalImageId id =
203       GetCompositorBridgeChild()->GetNextExternalImageId();
204   MOZ_RELEASE_ASSERT(id.isSome());
205   return id.value();
206 }
207 
ReleaseTextureOfImage(const wr::ImageKey & aKey)208 void WebRenderBridgeChild::ReleaseTextureOfImage(const wr::ImageKey& aKey) {
209   AddWebRenderParentCommand(OpReleaseTextureOfImage(aKey));
210 }
211 
212 struct FontFileDataSink {
213   wr::FontKey* mFontKey;
214   WebRenderBridgeChild* mWrBridge;
215   wr::IpcResourceUpdateQueue* mResources;
216 };
217 
WriteFontFileData(const uint8_t * aData,uint32_t aLength,uint32_t aIndex,void * aBaton)218 static void WriteFontFileData(const uint8_t* aData, uint32_t aLength,
219                               uint32_t aIndex, void* aBaton) {
220   FontFileDataSink* sink = static_cast<FontFileDataSink*>(aBaton);
221 
222   *sink->mFontKey = sink->mWrBridge->GetNextFontKey();
223 
224   sink->mResources->AddRawFont(
225       *sink->mFontKey, Range<uint8_t>(const_cast<uint8_t*>(aData), aLength),
226       aIndex);
227 }
228 
WriteFontDescriptor(const uint8_t * aData,uint32_t aLength,uint32_t aIndex,void * aBaton)229 static void WriteFontDescriptor(const uint8_t* aData, uint32_t aLength,
230                                 uint32_t aIndex, void* aBaton) {
231   FontFileDataSink* sink = static_cast<FontFileDataSink*>(aBaton);
232 
233   *sink->mFontKey = sink->mWrBridge->GetNextFontKey();
234 
235   sink->mResources->AddFontDescriptor(
236       *sink->mFontKey, Range<uint8_t>(const_cast<uint8_t*>(aData), aLength),
237       aIndex);
238 }
239 
PushGlyphs(wr::DisplayListBuilder & aBuilder,Range<const wr::GlyphInstance> aGlyphs,gfx::ScaledFont * aFont,const wr::ColorF & aColor,const StackingContextHelper & aSc,const wr::LayoutRect & aBounds,const wr::LayoutRect & aClip,bool aBackfaceVisible,const wr::GlyphOptions * aGlyphOptions)240 void WebRenderBridgeChild::PushGlyphs(
241     wr::DisplayListBuilder& aBuilder, Range<const wr::GlyphInstance> aGlyphs,
242     gfx::ScaledFont* aFont, const wr::ColorF& aColor,
243     const StackingContextHelper& aSc, const wr::LayoutRect& aBounds,
244     const wr::LayoutRect& aClip, bool aBackfaceVisible,
245     const wr::GlyphOptions* aGlyphOptions) {
246   MOZ_ASSERT(aFont);
247 
248   Maybe<wr::WrFontInstanceKey> key = GetFontKeyForScaledFont(aFont);
249   MOZ_ASSERT(key.isSome());
250 
251   if (key.isSome()) {
252     aBuilder.PushText(aBounds, aClip, aBackfaceVisible, aColor, key.value(),
253                       aGlyphs, aGlyphOptions);
254   }
255 }
256 
GetFontKeyForScaledFont(gfx::ScaledFont * aScaledFont,wr::IpcResourceUpdateQueue * aResources)257 Maybe<wr::FontInstanceKey> WebRenderBridgeChild::GetFontKeyForScaledFont(
258     gfx::ScaledFont* aScaledFont, wr::IpcResourceUpdateQueue* aResources) {
259   MOZ_ASSERT(!mDestroyed);
260   MOZ_ASSERT(aScaledFont);
261   MOZ_ASSERT(aScaledFont->CanSerialize());
262 
263   return mFontInstanceKeys.WithEntryHandle(
264       aScaledFont, [&](auto&& entry) -> Maybe<wr::FontInstanceKey> {
265         if (!entry) {
266           Maybe<wr::IpcResourceUpdateQueue> resources =
267               aResources ? Nothing() : Some(wr::IpcResourceUpdateQueue(this));
268           aResources = resources.ptrOr(aResources);
269 
270           Maybe<wr::FontKey> fontKey = GetFontKeyForUnscaledFont(
271               aScaledFont->GetUnscaledFont(), aResources);
272           if (fontKey.isNothing()) {
273             return Nothing();
274           }
275 
276           wr::FontInstanceKey instanceKey = GetNextFontInstanceKey();
277 
278           Maybe<wr::FontInstanceOptions> options;
279           Maybe<wr::FontInstancePlatformOptions> platformOptions;
280           std::vector<FontVariation> variations;
281           aScaledFont->GetWRFontInstanceOptions(&options, &platformOptions,
282                                                 &variations);
283 
284           aResources->AddFontInstance(
285               instanceKey, fontKey.value(), aScaledFont->GetSize(),
286               options.ptrOr(nullptr), platformOptions.ptrOr(nullptr),
287               Range<const FontVariation>(variations.data(), variations.size()));
288           if (resources.isSome()) {
289             UpdateResources(resources.ref());
290           }
291 
292           entry.Insert(instanceKey);
293         }
294 
295         return Some(*entry);
296       });
297 }
298 
GetFontKeyForUnscaledFont(gfx::UnscaledFont * aUnscaled,wr::IpcResourceUpdateQueue * aResources)299 Maybe<wr::FontKey> WebRenderBridgeChild::GetFontKeyForUnscaledFont(
300     gfx::UnscaledFont* aUnscaled, wr::IpcResourceUpdateQueue* aResources) {
301   MOZ_ASSERT(!mDestroyed);
302 
303   return mFontKeys.WithEntryHandle(
304       aUnscaled, [&](auto&& entry) -> Maybe<wr::FontKey> {
305         if (!entry) {
306           Maybe<wr::IpcResourceUpdateQueue> resources =
307               aResources ? Nothing() : Some(wr::IpcResourceUpdateQueue(this));
308 
309           wr::FontKey fontKey = {wr::IdNamespace{0}, 0};
310           FontFileDataSink sink = {&fontKey, this, resources.ptrOr(aResources)};
311           // First try to retrieve a descriptor for the font, as this is much
312           // cheaper to send over IPC than the full raw font data. If this is
313           // not possible, then and only then fall back to getting the raw font
314           // file data. If that fails, then the only thing left to do is signal
315           // failure by returning a null font key.
316           if (!aUnscaled->GetFontDescriptor(WriteFontDescriptor, &sink) &&
317               !aUnscaled->GetFontFileData(WriteFontFileData, &sink)) {
318             return Nothing();
319           }
320 
321           if (resources.isSome()) {
322             UpdateResources(resources.ref());
323           }
324 
325           entry.Insert(fontKey);
326         }
327 
328         return Some(*entry);
329       });
330 }
331 
RemoveExpiredFontKeys(wr::IpcResourceUpdateQueue & aResourceUpdates)332 void WebRenderBridgeChild::RemoveExpiredFontKeys(
333     wr::IpcResourceUpdateQueue& aResourceUpdates) {
334   uint32_t counter = gfx::ScaledFont::DeletionCounter();
335   if (mFontInstanceKeysDeleted != counter) {
336     mFontInstanceKeysDeleted = counter;
337     for (auto iter = mFontInstanceKeys.Iter(); !iter.Done(); iter.Next()) {
338       if (!iter.Key()) {
339         aResourceUpdates.DeleteFontInstance(iter.Data());
340         iter.Remove();
341       }
342     }
343   }
344   counter = gfx::UnscaledFont::DeletionCounter();
345   if (mFontKeysDeleted != counter) {
346     mFontKeysDeleted = counter;
347     for (auto iter = mFontKeys.Iter(); !iter.Done(); iter.Next()) {
348       if (!iter.Key()) {
349         aResourceUpdates.DeleteFont(iter.Data());
350         iter.Remove();
351       }
352     }
353   }
354 }
355 
GetCompositorBridgeChild()356 CompositorBridgeChild* WebRenderBridgeChild::GetCompositorBridgeChild() {
357   if (!IPCOpen()) {
358     return nullptr;
359   }
360   return static_cast<CompositorBridgeChild*>(Manager());
361 }
362 
GetTextureForwarder()363 TextureForwarder* WebRenderBridgeChild::GetTextureForwarder() {
364   return static_cast<TextureForwarder*>(GetCompositorBridgeChild());
365 }
366 
GetLayersIPCActor()367 LayersIPCActor* WebRenderBridgeChild::GetLayersIPCActor() {
368   return static_cast<LayersIPCActor*>(GetCompositorBridgeChild());
369 }
370 
SyncWithCompositor()371 void WebRenderBridgeChild::SyncWithCompositor() {
372   if (!IPCOpen()) {
373     return;
374   }
375   SendSyncWithCompositor();
376 }
377 
Connect(CompositableClient * aCompositable,ImageContainer * aImageContainer)378 void WebRenderBridgeChild::Connect(CompositableClient* aCompositable,
379                                    ImageContainer* aImageContainer) {
380   MOZ_ASSERT(!mDestroyed);
381   MOZ_ASSERT(aCompositable);
382 
383   static uint64_t sNextID = 1;
384   uint64_t id = sNextID++;
385 
386   mCompositables.InsertOrUpdate(id, aCompositable);
387 
388   CompositableHandle handle(id);
389   aCompositable->InitIPDL(handle);
390   SendNewCompositable(handle, aCompositable->GetTextureInfo());
391 }
392 
UseTiledLayerBuffer(CompositableClient * aCompositable,const SurfaceDescriptorTiles & aTiledDescriptor)393 void WebRenderBridgeChild::UseTiledLayerBuffer(
394     CompositableClient* aCompositable,
395     const SurfaceDescriptorTiles& aTiledDescriptor) {}
396 
UpdateTextureRegion(CompositableClient * aCompositable,const ThebesBufferData & aThebesBufferData,const nsIntRegion & aUpdatedRegion)397 void WebRenderBridgeChild::UpdateTextureRegion(
398     CompositableClient* aCompositable,
399     const ThebesBufferData& aThebesBufferData,
400     const nsIntRegion& aUpdatedRegion) {}
401 
AddOpDestroy(const OpDestroy & aOp)402 bool WebRenderBridgeChild::AddOpDestroy(const OpDestroy& aOp) {
403   if (!mIsInTransaction) {
404     return false;
405   }
406 
407   mDestroyedActors.AppendElement(aOp);
408   return true;
409 }
410 
ReleaseCompositable(const CompositableHandle & aHandle)411 void WebRenderBridgeChild::ReleaseCompositable(
412     const CompositableHandle& aHandle) {
413   if (!IPCOpen()) {
414     // This can happen if the IPC connection was torn down, because, e.g.
415     // the GPU process died.
416     return;
417   }
418   if (!DestroyInTransaction(aHandle)) {
419     SendReleaseCompositable(aHandle);
420   }
421   mCompositables.Remove(aHandle.Value());
422 }
423 
DestroyInTransaction(PTextureChild * aTexture)424 bool WebRenderBridgeChild::DestroyInTransaction(PTextureChild* aTexture) {
425   return AddOpDestroy(OpDestroy(aTexture));
426 }
427 
DestroyInTransaction(const CompositableHandle & aHandle)428 bool WebRenderBridgeChild::DestroyInTransaction(
429     const CompositableHandle& aHandle) {
430   return AddOpDestroy(OpDestroy(aHandle));
431 }
432 
RemoveTextureFromCompositable(CompositableClient * aCompositable,TextureClient * aTexture)433 void WebRenderBridgeChild::RemoveTextureFromCompositable(
434     CompositableClient* aCompositable, TextureClient* aTexture) {
435   MOZ_ASSERT(aCompositable);
436   MOZ_ASSERT(aTexture);
437   MOZ_ASSERT(aTexture->GetIPDLActor());
438   MOZ_RELEASE_ASSERT(aTexture->GetIPDLActor()->GetIPCChannel() ==
439                      GetIPCChannel());
440   if (!aCompositable->IsConnected() || !aTexture->GetIPDLActor()) {
441     // We don't have an actor anymore, don't try to use it!
442     return;
443   }
444 
445   AddWebRenderParentCommand(CompositableOperation(
446       aCompositable->GetIPCHandle(),
447       OpRemoveTexture(nullptr, aTexture->GetIPDLActor())));
448 }
449 
UseTextures(CompositableClient * aCompositable,const nsTArray<TimedTextureClient> & aTextures)450 void WebRenderBridgeChild::UseTextures(
451     CompositableClient* aCompositable,
452     const nsTArray<TimedTextureClient>& aTextures) {
453   MOZ_ASSERT(aCompositable);
454 
455   if (!aCompositable->IsConnected()) {
456     return;
457   }
458 
459   AutoTArray<TimedTexture, 4> textures;
460 
461   for (auto& t : aTextures) {
462     MOZ_ASSERT(t.mTextureClient);
463     MOZ_ASSERT(t.mTextureClient->GetIPDLActor());
464     MOZ_RELEASE_ASSERT(t.mTextureClient->GetIPDLActor()->GetIPCChannel() ==
465                        GetIPCChannel());
466     bool readLocked = t.mTextureClient->OnForwardedToHost();
467 
468     textures.AppendElement(
469         TimedTexture(nullptr, t.mTextureClient->GetIPDLActor(), t.mTimeStamp,
470                      t.mPictureRect, t.mFrameID, t.mProducerID, readLocked));
471     GetCompositorBridgeChild()->HoldUntilCompositableRefReleasedIfNecessary(
472         t.mTextureClient);
473 
474     auto fenceFd = t.mTextureClient->GetInternalData()->GetAcquireFence();
475     if (fenceFd.IsValid()) {
476       AddWebRenderParentCommand(CompositableOperation(
477           aCompositable->GetIPCHandle(),
478           OpDeliverAcquireFence(nullptr, t.mTextureClient->GetIPDLActor(),
479                                 fenceFd)));
480     }
481   }
482   AddWebRenderParentCommand(CompositableOperation(aCompositable->GetIPCHandle(),
483                                                   OpUseTexture(textures)));
484 }
485 
UseComponentAlphaTextures(CompositableClient * aCompositable,TextureClient * aClientOnBlack,TextureClient * aClientOnWhite)486 void WebRenderBridgeChild::UseComponentAlphaTextures(
487     CompositableClient* aCompositable, TextureClient* aClientOnBlack,
488     TextureClient* aClientOnWhite) {}
489 
UpdateFwdTransactionId()490 void WebRenderBridgeChild::UpdateFwdTransactionId() {
491   GetCompositorBridgeChild()->UpdateFwdTransactionId();
492 }
493 
GetFwdTransactionId()494 uint64_t WebRenderBridgeChild::GetFwdTransactionId() {
495   return GetCompositorBridgeChild()->GetFwdTransactionId();
496 }
497 
InForwarderThread()498 bool WebRenderBridgeChild::InForwarderThread() { return NS_IsMainThread(); }
499 
RecvWrUpdated(const wr::IdNamespace & aNewIdNamespace,const TextureFactoryIdentifier & textureFactoryIdentifier)500 mozilla::ipc::IPCResult WebRenderBridgeChild::RecvWrUpdated(
501     const wr::IdNamespace& aNewIdNamespace,
502     const TextureFactoryIdentifier& textureFactoryIdentifier) {
503   if (mManager) {
504     mManager->WrUpdated();
505   }
506   IdentifyTextureHost(textureFactoryIdentifier);
507   // Update mIdNamespace to identify obsolete keys and messages by
508   // WebRenderBridgeParent. Since usage of invalid keys could cause crash in
509   // webrender.
510   mIdNamespace = aNewIdNamespace;
511   // Just clear FontInstaceKeys/FontKeys, they are removed during WebRenderAPI
512   // destruction.
513   mFontInstanceKeys.Clear();
514   mFontKeys.Clear();
515   return IPC_OK();
516 }
517 
RecvWrReleasedImages(nsTArray<wr::ExternalImageKeyPair> && aPairs)518 mozilla::ipc::IPCResult WebRenderBridgeChild::RecvWrReleasedImages(
519     nsTArray<wr::ExternalImageKeyPair>&& aPairs) {
520   if (mManager) {
521     mManager->WrReleasedImages(aPairs);
522   }
523   return IPC_OK();
524 }
525 
BeginClearCachedResources()526 void WebRenderBridgeChild::BeginClearCachedResources() {
527   mSentDisplayList = false;
528   mIsInClearCachedResources = true;
529   // Clear display list and animtaions at parent side before clearing cached
530   // resources on client side. It prevents to clear resources before clearing
531   // display list at parent side.
532   SendClearCachedResources();
533 }
534 
EndClearCachedResources()535 void WebRenderBridgeChild::EndClearCachedResources() {
536   if (!IPCOpen()) {
537     mIsInClearCachedResources = false;
538     return;
539   }
540   ProcessWebRenderParentCommands();
541   mIsInClearCachedResources = false;
542 }
543 
SetWebRenderLayerManager(WebRenderLayerManager * aManager)544 void WebRenderBridgeChild::SetWebRenderLayerManager(
545     WebRenderLayerManager* aManager) {
546   MOZ_ASSERT(aManager && !mManager);
547   mManager = aManager;
548 
549   MOZ_ASSERT(NS_IsMainThread() || !XRE_IsContentProcess());
550   mActiveResourceTracker =
551       MakeUnique<ActiveResourceTracker>(1000, "CompositableForwarder", nullptr);
552 }
553 
GetShmemAllocator()554 ipc::IShmemAllocator* WebRenderBridgeChild::GetShmemAllocator() {
555   if (!IPCOpen()) {
556     return nullptr;
557   }
558   return static_cast<CompositorBridgeChild*>(Manager());
559 }
560 
GetForMedia()561 RefPtr<KnowsCompositor> WebRenderBridgeChild::GetForMedia() {
562   MOZ_ASSERT(NS_IsMainThread());
563 
564   // Ensure device initialization for video playback unless they are all remote.
565   // The devices are lazily initialized with WebRender to reduce memory usage.
566   if (!PDMFactory::AllDecodersAreRemote()) {
567     gfxPlatform::GetPlatform()->EnsureDevicesInitialized();
568   }
569 
570   return MakeAndAddRef<KnowsCompositorMediaProxy>(
571       GetTextureFactoryIdentifier());
572 }
573 
AllocResourceShmem(size_t aSize,RefCountedShmem & aShm)574 bool WebRenderBridgeChild::AllocResourceShmem(size_t aSize,
575                                               RefCountedShmem& aShm) {
576   // We keep a single shmem around to reuse later if it is reference count has
577   // dropped back to 1 (the reference held by the WebRenderBridgeChild).
578 
579   // If the cached shmem exists, has the correct size and isn't held by anything
580   // other than us, recycle it.
581   bool alreadyAllocated = RefCountedShm::IsValid(mResourceShm);
582   if (alreadyAllocated) {
583     if (RefCountedShm::GetSize(mResourceShm) == aSize &&
584         RefCountedShm::GetReferenceCount(mResourceShm) <= 1) {
585       MOZ_ASSERT(RefCountedShm::GetReferenceCount(mResourceShm) == 1);
586       aShm = mResourceShm;
587       return true;
588     }
589   }
590 
591   // If there was no cached shmem or we couldn't recycle it, alloc a new one.
592   if (!RefCountedShm::Alloc(this, aSize, aShm)) {
593     return false;
594   }
595 
596   // Now that we have a valid shmem, put it in the cache if we don't have one
597   // yet.
598   if (!alreadyAllocated) {
599     mResourceShm = aShm;
600     RefCountedShm::AddRef(aShm);
601   }
602 
603   return true;
604 }
605 
DeallocResourceShmem(RefCountedShmem & aShm)606 void WebRenderBridgeChild::DeallocResourceShmem(RefCountedShmem& aShm) {
607   if (!RefCountedShm::IsValid(aShm)) {
608     return;
609   }
610   MOZ_ASSERT(RefCountedShm::GetReferenceCount(aShm) == 0);
611 
612   RefCountedShm::Dealloc(this, aShm);
613 }
614 
Capture()615 void WebRenderBridgeChild::Capture() { this->SendCapture(); }
616 
StartCaptureSequence(const nsCString & aPath,uint32_t aFlags)617 void WebRenderBridgeChild::StartCaptureSequence(const nsCString& aPath,
618                                                 uint32_t aFlags) {
619   this->SendStartCaptureSequence(aPath, aFlags);
620 }
621 
StopCaptureSequence()622 void WebRenderBridgeChild::StopCaptureSequence() {
623   this->SendStopCaptureSequence();
624 }
625 
626 }  // namespace layers
627 }  // namespace mozilla
628