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