CompositorBridgeChild.cpp (20181B)
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/CompositorBridgeChild.h" 8 #include "mozilla/layers/CompositorBridgeParent.h" 9 #include "mozilla/layers/CompositorThread.h" 10 #include <stddef.h> // for size_t 11 #include "base/task.h" // for NewRunnableMethod, etc 12 #include "mozilla/StaticPrefs_layers.h" 13 #include "mozilla/layers/CompositorManagerChild.h" 14 #include "mozilla/layers/ImageBridgeChild.h" 15 #include "mozilla/layers/APZChild.h" 16 #include "mozilla/layers/IAPZCTreeManager.h" 17 #include "mozilla/layers/APZCTreeManagerChild.h" 18 #include "mozilla/layers/CanvasChild.h" 19 #include "mozilla/layers/WebRenderLayerManager.h" 20 #include "mozilla/layers/PTextureChild.h" 21 #include "mozilla/layers/TextureClient.h" // for TextureClient 22 #include "mozilla/layers/WebRenderBridgeChild.h" 23 #include "mozilla/layers/SyncObject.h" // for SyncObjectClient 24 #include "mozilla/gfx/CanvasManagerChild.h" 25 #include "mozilla/gfx/gfxVars.h" 26 #include "mozilla/gfx/GPUProcessManager.h" 27 #include "mozilla/gfx/Logging.h" 28 #include "mozilla/ipc/Endpoint.h" 29 #include "mozilla/mozalloc.h" // for operator new, etc 30 #include "gfxConfig.h" 31 #include "nsDebug.h" // for NS_WARNING 32 #include "nsISupportsImpl.h" // for MOZ_COUNT_CTOR, etc 33 #include "nsTArray.h" // for nsTArray, nsTArray_Impl 34 #include "mozilla/dom/BrowserChild.h" 35 #include "mozilla/dom/BrowserParent.h" 36 #include "mozilla/dom/ContentChild.h" 37 #include "mozilla/SpinEventLoopUntil.h" 38 #include "nsThreadUtils.h" 39 #if defined(XP_WIN) 40 # include "WinUtils.h" 41 #endif 42 #include "mozilla/widget/CompositorWidget.h" 43 #ifdef MOZ_WIDGET_SUPPORTS_OOP_COMPOSITING 44 # include "mozilla/widget/CompositorWidgetChild.h" 45 #endif 46 #include "VsyncSource.h" 47 48 using mozilla::gfx::GPUProcessManager; 49 50 namespace mozilla { 51 namespace layers { 52 53 static int sShmemCreationCounter = 0; 54 55 static void ResetShmemCounter() { sShmemCreationCounter = 0; } 56 57 static void ShmemAllocated(CompositorBridgeChild* aProtocol) { 58 sShmemCreationCounter++; 59 if (sShmemCreationCounter > 256) { 60 aProtocol->SendSyncWithCompositor(); 61 ResetShmemCounter(); 62 MOZ_PERFORMANCE_WARNING( 63 "gfx", "The number of shmem allocations is too damn high!"); 64 } 65 } 66 67 static StaticRefPtr<CompositorBridgeChild> sCompositorBridge; 68 69 Atomic<int32_t> KnowsCompositor::sSerialCounter(0); 70 71 CompositorBridgeChild::CompositorBridgeChild(CompositorManagerChild* aManager) 72 : mCompositorManager(aManager), 73 mIdNamespace(0), 74 mResourceId(0), 75 mCanSend(false), 76 mActorDestroyed(false), 77 mPaused(false), 78 mForceSyncFlushRendering(false), 79 mThread(NS_GetCurrentThread()), 80 mProcessToken(0), 81 mSectionAllocator(nullptr) { 82 MOZ_ASSERT(NS_IsMainThread()); 83 } 84 85 CompositorBridgeChild::~CompositorBridgeChild() { 86 if (mCanSend) { 87 gfxCriticalError() << "CompositorBridgeChild was not deinitialized"; 88 } 89 } 90 91 bool CompositorBridgeChild::IsSameProcess() const { 92 return OtherPid() == base::GetCurrentProcId(); 93 } 94 95 void CompositorBridgeChild::PrepareFinalDestroy() { 96 // Because of medium high priority DidComposite, we need to repost to 97 // medium high priority queue to ensure the actor is destroyed after possible 98 // pending DidComposite message. 99 nsCOMPtr<nsIRunnable> runnable = 100 NewRunnableMethod("CompositorBridgeChild::AfterDestroy", this, 101 &CompositorBridgeChild::AfterDestroy); 102 NS_DispatchToCurrentThreadQueue(runnable.forget(), 103 EventQueuePriority::MediumHigh); 104 } 105 106 void CompositorBridgeChild::AfterDestroy() { 107 // Note that we cannot rely upon mCanSend here because we already set that to 108 // false to prevent normal IPDL calls from being made after SendWillClose. 109 // The only time we should not issue Send__delete__ is if the actor is already 110 // destroyed, e.g. the compositor process crashed. 111 if (!mActorDestroyed) { 112 // We saw this send fail quite often with "Channel closing", probably a race 113 // with the other side closing or some event scheduling order. 114 if (GetIPCChannel()->CanSend()) { 115 Send__delete__(this); 116 } 117 mActorDestroyed = true; 118 } 119 120 if (sCompositorBridge == this) { 121 sCompositorBridge = nullptr; 122 } 123 } 124 125 void CompositorBridgeChild::Destroy() { 126 // This must not be called from the destructor! 127 mTexturesWaitingNotifyNotUsed.clear(); 128 129 // Destroying the layer manager may cause all sorts of things to happen, so 130 // let's make sure there is still a reference to keep this alive whatever 131 // happens. 132 RefPtr<CompositorBridgeChild> selfRef = this; 133 134 if (mSectionAllocator) { 135 delete mSectionAllocator; 136 mSectionAllocator = nullptr; 137 } 138 139 if (mLayerManager) { 140 mLayerManager->Destroy(); 141 mLayerManager = nullptr; 142 } 143 144 if (!mCanSend) { 145 // We may have already called destroy but still have lingering references 146 // or CompositorBridgeChild::ActorDestroy was called. Ensure that we do our 147 // post destroy clean up no matter what. It is safe to call multiple times. 148 NS_GetCurrentThread()->Dispatch( 149 NewRunnableMethod("CompositorBridgeChild::PrepareFinalDestroy", selfRef, 150 &CompositorBridgeChild::PrepareFinalDestroy)); 151 return; 152 } 153 154 AutoTArray<PWebRenderBridgeChild*, 16> wrBridges; 155 ManagedPWebRenderBridgeChild(wrBridges); 156 for (int i = wrBridges.Length() - 1; i >= 0; --i) { 157 RefPtr<WebRenderBridgeChild> wrBridge = 158 static_cast<WebRenderBridgeChild*>(wrBridges[i]); 159 wrBridge->Destroy(/* aIsSync */ false); 160 } 161 162 AutoTArray<PAPZChild*, 16> apzChildren; 163 ManagedPAPZChild(apzChildren); 164 for (PAPZChild* child : apzChildren) { 165 (void)child->SendDestroy(); 166 } 167 168 const ManagedContainer<PTextureChild>& textures = ManagedPTextureChild(); 169 for (const auto& key : textures) { 170 RefPtr<TextureClient> texture = TextureClient::AsTextureClient(key); 171 172 if (texture) { 173 texture->Destroy(); 174 } 175 } 176 177 // The WillClose message is synchronous, so we know that after it returns 178 // any messages sent by the above code will have been processed on the 179 // other side. 180 SendWillClose(); 181 mCanSend = false; 182 183 // We no longer care about unexpected shutdowns, in the remote process case. 184 mProcessToken = 0; 185 186 // The call just made to SendWillClose can result in IPC from the 187 // CompositorBridgeParent to the CompositorBridgeChild (e.g. caused by the 188 // destruction of shared memory). We need to ensure this gets processed by the 189 // CompositorBridgeChild before it gets destroyed. It suffices to ensure that 190 // events already in the thread get processed before the 191 // CompositorBridgeChild is destroyed, so we add a task to the thread to 192 // handle compositor destruction. 193 194 // From now on we can't send any message message. 195 NS_GetCurrentThread()->Dispatch( 196 NewRunnableMethod("CompositorBridgeChild::PrepareFinalDestroy", selfRef, 197 &CompositorBridgeChild::PrepareFinalDestroy)); 198 } 199 200 // static 201 void CompositorBridgeChild::ShutDown() { 202 if (sCompositorBridge) { 203 sCompositorBridge->Destroy(); 204 SpinEventLoopUntil("CompositorBridgeChild::ShutDown"_ns, 205 [&]() { return !sCompositorBridge; }); 206 } 207 } 208 209 void CompositorBridgeChild::InitForContent(uint32_t aNamespace) { 210 MOZ_ASSERT(NS_IsMainThread()); 211 MOZ_ASSERT(aNamespace); 212 213 if (RefPtr<CompositorBridgeChild> old = sCompositorBridge.forget()) { 214 // Note that at this point, ActorDestroy may not have been called yet, 215 // meaning mCanSend is still true. In this case we will try to send a 216 // synchronous WillClose message to the parent, and will certainly get 217 // a false result and a MsgDropped processing error. This is okay. 218 old->Destroy(); 219 } 220 221 mCanSend = true; 222 mIdNamespace = aNamespace; 223 224 sCompositorBridge = this; 225 } 226 227 void CompositorBridgeChild::InitForWidget(uint64_t aProcessToken, 228 WebRenderLayerManager* aLayerManager, 229 uint32_t aNamespace) { 230 MOZ_ASSERT(NS_IsMainThread()); 231 MOZ_ASSERT(aProcessToken); 232 MOZ_ASSERT(aLayerManager); 233 MOZ_ASSERT(aNamespace); 234 235 mCanSend = true; 236 mProcessToken = aProcessToken; 237 mLayerManager = aLayerManager; 238 mIdNamespace = aNamespace; 239 } 240 241 /*static*/ 242 CompositorBridgeChild* CompositorBridgeChild::Get() { 243 // This is only expected to be used in child processes. While the parent 244 // process does have CompositorBridgeChild instances, it has _multiple_ (one 245 // per window), and therefore there is no global singleton available. 246 MOZ_ASSERT(!XRE_IsParentProcess()); 247 return sCompositorBridge; 248 } 249 250 /* static */ 251 bool CompositorBridgeChild::CompositorIsInGPUProcess() { 252 MOZ_ASSERT(NS_IsMainThread()); 253 254 if (XRE_IsParentProcess()) { 255 return !!GPUProcessManager::Get()->GetGPUChild(); 256 } 257 258 MOZ_ASSERT(XRE_IsContentProcess()); 259 CompositorBridgeChild* bridge = CompositorBridgeChild::Get(); 260 if (!bridge) { 261 return false; 262 } 263 264 return bridge->OtherPid() != dom::ContentChild::GetSingleton()->OtherPid(); 265 } 266 267 mozilla::ipc::IPCResult CompositorBridgeChild::RecvDidComposite( 268 const LayersId& aId, const nsTArray<TransactionId>& aTransactionIds, 269 const TimeStamp& aCompositeStart, const TimeStamp& aCompositeEnd) { 270 for (const auto& id : aTransactionIds) { 271 if (mLayerManager) { 272 MOZ_ASSERT(!aId.IsValid()); 273 MOZ_ASSERT(mLayerManager->GetBackendType() == LayersBackend::LAYERS_WR); 274 // Hold a reference to keep LayerManager alive. See Bug 1242668. 275 RefPtr<WebRenderLayerManager> m = mLayerManager; 276 m->DidComposite(id, aCompositeStart, aCompositeEnd); 277 } else if (aId.IsValid()) { 278 RefPtr<dom::BrowserChild> child = dom::BrowserChild::GetFrom(aId); 279 if (child) { 280 child->DidComposite(id, aCompositeStart, aCompositeEnd); 281 } 282 } 283 } 284 285 return IPC_OK(); 286 } 287 288 mozilla::ipc::IPCResult CompositorBridgeChild::RecvNotifyFrameStats( 289 nsTArray<FrameStats>&& aFrameStats) { 290 gfxPlatform::GetPlatform()->NotifyFrameStats(std::move(aFrameStats)); 291 return IPC_OK(); 292 } 293 294 void CompositorBridgeChild::ActorDestroy(ActorDestroyReason aWhy) { 295 if (aWhy == AbnormalShutdown) { 296 // If the parent side runs into a problem then the actor will be destroyed. 297 // There is nothing we can do in the child side, here sets mCanSend as 298 // false. 299 gfxCriticalNote << "CompositorBridgeChild receives IPC close with " 300 "reason=AbnormalShutdown"; 301 } 302 303 mCanSend = false; 304 mActorDestroyed = true; 305 306 if (mProcessToken && XRE_IsParentProcess()) { 307 GPUProcessManager::Get()->NotifyRemoteActorDestroyed(mProcessToken); 308 } 309 } 310 311 bool CompositorBridgeChild::SendWillClose() { 312 MOZ_RELEASE_ASSERT(mCanSend); 313 return PCompositorBridgeChild::SendWillClose(); 314 } 315 316 bool CompositorBridgeChild::SendPause() { 317 if (!mCanSend) { 318 return false; 319 } 320 mPaused = true; 321 return PCompositorBridgeChild::SendPause(); 322 } 323 324 bool CompositorBridgeChild::SendResume() { 325 if (!mCanSend) { 326 return false; 327 } 328 mPaused = false; 329 return PCompositorBridgeChild::SendResume(); 330 } 331 332 bool CompositorBridgeChild::SendResumeAsync() { 333 if (!mCanSend) { 334 return false; 335 } 336 mPaused = false; 337 return PCompositorBridgeChild::SendResumeAsync(); 338 } 339 340 bool CompositorBridgeChild::SendAdoptChild(const LayersId& id) { 341 if (!mCanSend) { 342 return false; 343 } 344 return PCompositorBridgeChild::SendAdoptChild(id); 345 } 346 347 bool CompositorBridgeChild::SendFlushRendering( 348 const wr::RenderReasons& aReasons) { 349 if (!mCanSend) { 350 return false; 351 } 352 return PCompositorBridgeChild::SendFlushRendering(aReasons); 353 } 354 355 bool CompositorBridgeChild::SendFlushRenderingAsync( 356 const wr::RenderReasons& aReasons) { 357 if (mForceSyncFlushRendering) { 358 return SendFlushRendering(aReasons); 359 } 360 if (!mCanSend) { 361 return false; 362 } 363 return PCompositorBridgeChild::SendFlushRenderingAsync(aReasons); 364 } 365 366 void CompositorBridgeChild::SetForceSyncFlushRendering( 367 bool aForceSyncFlushRendering) { 368 mForceSyncFlushRendering = aForceSyncFlushRendering; 369 } 370 371 bool CompositorBridgeChild::SendStartFrameTimeRecording( 372 const int32_t& bufferSize, uint32_t* startIndex) { 373 if (!mCanSend) { 374 return false; 375 } 376 return PCompositorBridgeChild::SendStartFrameTimeRecording(bufferSize, 377 startIndex); 378 } 379 380 bool CompositorBridgeChild::SendStopFrameTimeRecording( 381 const uint32_t& startIndex, nsTArray<float>* intervals) { 382 if (!mCanSend) { 383 return false; 384 } 385 return PCompositorBridgeChild::SendStopFrameTimeRecording(startIndex, 386 intervals); 387 } 388 389 PTextureChild* CompositorBridgeChild::AllocPTextureChild( 390 const SurfaceDescriptor&, ReadLockDescriptor&, const LayersBackend&, 391 const TextureFlags&, const LayersId&, const uint64_t& aSerial, 392 const wr::MaybeExternalImageId& aExternalImageId) { 393 return TextureClient::CreateIPDLActor(); 394 } 395 396 bool CompositorBridgeChild::DeallocPTextureChild(PTextureChild* actor) { 397 return TextureClient::DestroyIPDLActor(actor); 398 } 399 400 mozilla::ipc::IPCResult CompositorBridgeChild::RecvParentAsyncMessages( 401 nsTArray<AsyncParentMessageData>&& aMessages) { 402 for (AsyncParentMessageArray::index_type i = 0; i < aMessages.Length(); ++i) { 403 const AsyncParentMessageData& message = aMessages[i]; 404 405 switch (message.type()) { 406 case AsyncParentMessageData::TOpNotifyNotUsed: { 407 const OpNotifyNotUsed& op = message.get_OpNotifyNotUsed(); 408 NotifyNotUsed(op.TextureId(), op.fwdTransactionId()); 409 break; 410 } 411 default: 412 NS_ERROR("unknown AsyncParentMessageData type"); 413 return IPC_FAIL_NO_REASON(this); 414 } 415 } 416 return IPC_OK(); 417 } 418 419 mozilla::ipc::IPCResult CompositorBridgeChild::RecvObserveLayersUpdate( 420 const LayersId& aLayersId, const bool& aActive) { 421 // This message is sent via the window compositor, not the tab compositor - 422 // however it still has a layers id. 423 MOZ_ASSERT(aLayersId.IsValid()); 424 MOZ_ASSERT(XRE_IsParentProcess()); 425 426 if (RefPtr<dom::BrowserParent> tab = 427 dom::BrowserParent::GetBrowserParentFromLayersId(aLayersId)) { 428 tab->LayerTreeUpdate(aActive); 429 } 430 return IPC_OK(); 431 } 432 433 mozilla::ipc::IPCResult CompositorBridgeChild::RecvCompositorOptionsChanged( 434 const LayersId& aLayersId, const CompositorOptions& aNewOptions) { 435 MOZ_ASSERT(aLayersId.IsValid()); 436 MOZ_ASSERT(XRE_IsParentProcess()); 437 438 if (RefPtr<dom::BrowserParent> tab = 439 dom::BrowserParent::GetBrowserParentFromLayersId(aLayersId)) { 440 (void)tab->SendCompositorOptionsChanged(aNewOptions); 441 } 442 return IPC_OK(); 443 } 444 445 mozilla::ipc::IPCResult CompositorBridgeChild::RecvNotifyJankedAnimations( 446 const LayersId& aLayersId, nsTArray<uint64_t>&& aJankedAnimations) { 447 if (mLayerManager) { 448 MOZ_ASSERT(!aLayersId.IsValid()); 449 mLayerManager->UpdatePartialPrerenderedAnimations(aJankedAnimations); 450 } else if (aLayersId.IsValid()) { 451 RefPtr<dom::BrowserChild> child = dom::BrowserChild::GetFrom(aLayersId); 452 if (child) { 453 child->NotifyJankedAnimations(aJankedAnimations); 454 } 455 } 456 457 return IPC_OK(); 458 } 459 460 void CompositorBridgeChild::HoldUntilCompositableRefReleasedIfNecessary( 461 TextureClient* aClient) { 462 if (!aClient) { 463 return; 464 } 465 466 bool waitNotifyNotUsed = 467 aClient->GetFlags() & TextureFlags::RECYCLE || 468 aClient->GetFlags() & TextureFlags::WAIT_HOST_USAGE_END; 469 if (!waitNotifyNotUsed) { 470 return; 471 } 472 473 aClient->SetLastFwdTransactionId( 474 GetFwdTransactionCounter().mFwdTransactionId); 475 mTexturesWaitingNotifyNotUsed.emplace(aClient->GetSerial(), aClient); 476 } 477 478 void CompositorBridgeChild::NotifyNotUsed(uint64_t aTextureId, 479 uint64_t aFwdTransactionId) { 480 auto it = mTexturesWaitingNotifyNotUsed.find(aTextureId); 481 if (it != mTexturesWaitingNotifyNotUsed.end()) { 482 if (aFwdTransactionId < it->second->GetLastFwdTransactionId()) { 483 // Released on host side, but client already requested newer use texture. 484 return; 485 } 486 mTexturesWaitingNotifyNotUsed.erase(it); 487 } 488 } 489 490 void CompositorBridgeChild::CancelWaitForNotifyNotUsed(uint64_t aTextureId) { 491 mTexturesWaitingNotifyNotUsed.erase(aTextureId); 492 } 493 494 FixedSizeSmallShmemSectionAllocator* 495 CompositorBridgeChild::GetTileLockAllocator() { 496 if (!IPCOpen()) { 497 return nullptr; 498 } 499 500 if (!mSectionAllocator) { 501 mSectionAllocator = new FixedSizeSmallShmemSectionAllocator(this); 502 } 503 return mSectionAllocator; 504 } 505 506 PTextureChild* CompositorBridgeChild::CreateTexture( 507 const SurfaceDescriptor& aSharedData, ReadLockDescriptor&& aReadLock, 508 LayersBackend aLayersBackend, TextureFlags aFlags, 509 const dom::ContentParentId& aContentId, uint64_t aSerial, 510 wr::MaybeExternalImageId& aExternalImageId) { 511 PTextureChild* textureChild = 512 AllocPTextureChild(aSharedData, aReadLock, aLayersBackend, aFlags, 513 LayersId{0} /* FIXME */, aSerial, aExternalImageId); 514 515 return SendPTextureConstructor( 516 textureChild, aSharedData, std::move(aReadLock), aLayersBackend, aFlags, 517 LayersId{0} /* FIXME? */, aSerial, aExternalImageId); 518 } 519 520 already_AddRefed<CanvasChild> CompositorBridgeChild::GetCanvasChild() { 521 MOZ_ASSERT(gfxPlatform::UseRemoteCanvas()); 522 if (auto* cm = gfx::CanvasManagerChild::Get()) { 523 return cm->GetCanvasChild().forget(); 524 } 525 return nullptr; 526 } 527 528 void CompositorBridgeChild::EndCanvasTransaction() { 529 if (auto* cm = gfx::CanvasManagerChild::Get()) { 530 cm->EndCanvasTransaction(); 531 } 532 } 533 534 void CompositorBridgeChild::ClearCachedResources() { 535 if (auto* cm = gfx::CanvasManagerChild::Get()) { 536 cm->ClearCachedResources(); 537 } 538 } 539 540 bool CompositorBridgeChild::AllocUnsafeShmem(size_t aSize, ipc::Shmem* aShmem) { 541 ShmemAllocated(this); 542 return PCompositorBridgeChild::AllocUnsafeShmem(aSize, aShmem); 543 } 544 545 bool CompositorBridgeChild::AllocShmem(size_t aSize, ipc::Shmem* aShmem) { 546 ShmemAllocated(this); 547 return PCompositorBridgeChild::AllocShmem(aSize, aShmem); 548 } 549 550 bool CompositorBridgeChild::DeallocShmem(ipc::Shmem& aShmem) { 551 if (!mCanSend) { 552 return false; 553 } 554 return PCompositorBridgeChild::DeallocShmem(aShmem); 555 } 556 557 PAPZCTreeManagerChild* CompositorBridgeChild::AllocPAPZCTreeManagerChild( 558 const LayersId& aLayersId) { 559 APZCTreeManagerChild* child = new APZCTreeManagerChild(); 560 child->AddIPDLReference(); 561 562 return child; 563 } 564 565 PAPZChild* CompositorBridgeChild::AllocPAPZChild(const LayersId& aLayersId) { 566 // We send the constructor manually. 567 MOZ_CRASH("Should not be called"); 568 return nullptr; 569 } 570 571 bool CompositorBridgeChild::DeallocPAPZChild(PAPZChild* aActor) { 572 delete aActor; 573 return true; 574 } 575 576 bool CompositorBridgeChild::DeallocPAPZCTreeManagerChild( 577 PAPZCTreeManagerChild* aActor) { 578 APZCTreeManagerChild* child = static_cast<APZCTreeManagerChild*>(aActor); 579 child->ReleaseIPDLReference(); 580 return true; 581 } 582 583 // - 584 585 PWebRenderBridgeChild* CompositorBridgeChild::AllocPWebRenderBridgeChild( 586 const wr::PipelineId& aPipelineId, const LayoutDeviceIntSize&, 587 const WindowKind&) { 588 WebRenderBridgeChild* child = new WebRenderBridgeChild(aPipelineId); 589 child->AddIPDLReference(); 590 return child; 591 } 592 593 bool CompositorBridgeChild::DeallocPWebRenderBridgeChild( 594 PWebRenderBridgeChild* aActor) { 595 WebRenderBridgeChild* child = static_cast<WebRenderBridgeChild*>(aActor); 596 child->ReleaseIPDLReference(); 597 return true; 598 } 599 600 uint64_t CompositorBridgeChild::GetNextResourceId() { 601 ++mResourceId; 602 MOZ_RELEASE_ASSERT(mResourceId != UINT32_MAX); 603 604 uint64_t id = mIdNamespace; 605 id = (id << 32) | mResourceId; 606 607 return id; 608 } 609 610 wr::MaybeExternalImageId CompositorBridgeChild::GetNextExternalImageId() { 611 return Some(wr::ToExternalImageId(GetNextResourceId())); 612 } 613 614 wr::PipelineId CompositorBridgeChild::GetNextPipelineId() { 615 return wr::AsPipelineId(GetNextResourceId()); 616 } 617 618 FwdTransactionCounter& CompositorBridgeChild::GetFwdTransactionCounter() { 619 return mCompositorManager->GetFwdTransactionCounter(); 620 } 621 622 } // namespace layers 623 } // namespace mozilla