tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

WebRenderBridgeChild.cpp (20135B)


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