tor-browser

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

WebRenderUserData.cpp (15280B)


      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 "WebRenderUserData.h"
      8 
      9 #include "mozilla/image/WebRenderImageProvider.h"
     10 #include "mozilla/layers/AnimationHelper.h"
     11 #include "mozilla/layers/CompositorBridgeChild.h"
     12 #include "mozilla/layers/ImageClient.h"
     13 #include "mozilla/layers/WebRenderBridgeChild.h"
     14 #include "mozilla/layers/RenderRootStateManager.h"
     15 #include "mozilla/layers/WebRenderMessages.h"
     16 #include "mozilla/layers/IpcResourceUpdateQueue.h"
     17 #include "mozilla/layers/SharedSurfacesChild.h"
     18 #include "mozilla/webgpu/WebGPUChild.h"
     19 #include "nsDisplayListInvalidation.h"
     20 #include "nsIFrame.h"
     21 #include "WebRenderCanvasRenderer.h"
     22 
     23 using namespace mozilla::image;
     24 
     25 namespace mozilla {
     26 namespace layers {
     27 
     28 void WebRenderBackgroundData::AddWebRenderCommands(
     29    wr::DisplayListBuilder& aBuilder) {
     30  aBuilder.PushRect(mBounds, mBounds, true, true, false, mColor);
     31 }
     32 
     33 /* static */
     34 bool WebRenderUserData::SupportsAsyncUpdate(nsIFrame* aFrame) {
     35  if (!aFrame) {
     36    return false;
     37  }
     38  RefPtr<WebRenderImageData> data = GetWebRenderUserData<WebRenderImageData>(
     39      aFrame, static_cast<uint32_t>(DisplayItemType::TYPE_VIDEO));
     40  if (data) {
     41    return data->IsAsync();
     42  }
     43 
     44  return false;
     45 }
     46 
     47 /* static */
     48 bool WebRenderUserData::ProcessInvalidateForImage(nsIFrame* aFrame,
     49                                                  DisplayItemType aType,
     50                                                  ImageProviderId aProviderId) {
     51  MOZ_ASSERT(aFrame);
     52 
     53  if (!aFrame->HasProperty(WebRenderUserDataProperty::Key())) {
     54    aFrame->SchedulePaint();
     55    return false;
     56  }
     57 
     58  auto type = static_cast<uint32_t>(aType);
     59  RefPtr<WebRenderFallbackData> fallback =
     60      GetWebRenderUserData<WebRenderFallbackData>(aFrame, type);
     61  if (fallback) {
     62    fallback->SetInvalid(true);
     63    aFrame->SchedulePaint();
     64    return true;
     65  }
     66 
     67  RefPtr<WebRenderImageProviderData> image =
     68      GetWebRenderUserData<WebRenderImageProviderData>(aFrame, type);
     69  if (image && image->Invalidate(aProviderId)) {
     70    return true;
     71  }
     72 
     73  aFrame->SchedulePaint();
     74  return false;
     75 }
     76 
     77 WebRenderUserData::WebRenderUserData(RenderRootStateManager* aManager,
     78                                     uint32_t aDisplayItemKey, nsIFrame* aFrame)
     79    : mManager(aManager),
     80      mFrame(aFrame),
     81      mDisplayItemKey(aDisplayItemKey),
     82      mTable(aManager->GetWebRenderUserDataTable()),
     83      mUsed(false) {}
     84 
     85 WebRenderUserData::WebRenderUserData(RenderRootStateManager* aManager,
     86                                     nsDisplayItem* aItem)
     87    : mManager(aManager),
     88      mFrame(aItem->Frame()),
     89      mDisplayItemKey(aItem->GetPerFrameKey()),
     90      mTable(aManager->GetWebRenderUserDataTable()),
     91      mUsed(false) {}
     92 
     93 WebRenderUserData::~WebRenderUserData() = default;
     94 
     95 void WebRenderUserData::RemoveFromTable() { mTable->Remove(this); }
     96 
     97 WebRenderBridgeChild* WebRenderUserData::WrBridge() const {
     98  return mManager->WrBridge();
     99 }
    100 
    101 WebRenderImageData::WebRenderImageData(RenderRootStateManager* aManager,
    102                                       nsDisplayItem* aItem)
    103    : WebRenderUserData(aManager, aItem) {}
    104 
    105 WebRenderImageData::WebRenderImageData(RenderRootStateManager* aManager,
    106                                       uint32_t aDisplayItemKey,
    107                                       nsIFrame* aFrame)
    108    : WebRenderUserData(aManager, aDisplayItemKey, aFrame) {}
    109 
    110 WebRenderImageData::~WebRenderImageData() {
    111  ClearImageKey();
    112 
    113  if (mPipelineId) {
    114    mManager->RemovePipelineIdForCompositable(mPipelineId.ref());
    115  }
    116 }
    117 
    118 void WebRenderImageData::ClearImageKey() {
    119  if (mKey) {
    120    mManager->AddImageKeyForDiscard(mKey.value());
    121    if (mTextureOfImage) {
    122      WrBridge()->ReleaseTextureOfImage(mKey.value());
    123      mTextureOfImage = nullptr;
    124    }
    125    mKey.reset();
    126  }
    127  MOZ_ASSERT(!mTextureOfImage);
    128 }
    129 
    130 Maybe<wr::ImageKey> WebRenderImageData::UpdateImageKey(
    131    ImageContainer* aContainer, wr::IpcResourceUpdateQueue& aResources,
    132    bool aFallback) {
    133  MOZ_ASSERT(aContainer);
    134 
    135  if (mContainer != aContainer) {
    136    mContainer = aContainer;
    137  }
    138 
    139  CreateImageClientIfNeeded();
    140  if (!mImageClient) {
    141    return Nothing();
    142  }
    143 
    144  MOZ_ASSERT(mImageClient->AsImageClientSingle());
    145 
    146  ImageClientSingle* imageClient = mImageClient->AsImageClientSingle();
    147  uint32_t oldCounter = imageClient->GetLastUpdateGenerationCounter();
    148 
    149  bool ret = imageClient->UpdateImage(aContainer);
    150  RefPtr<TextureClient> currentTexture = imageClient->GetForwardedTexture();
    151  if (!ret || !currentTexture) {
    152    // Delete old key
    153    ClearImageKey();
    154    return Nothing();
    155  }
    156 
    157  // Reuse old key if generation is not updated.
    158  if (!aFallback &&
    159      oldCounter == imageClient->GetLastUpdateGenerationCounter() && mKey) {
    160    return mKey;
    161  }
    162 
    163  // If we already had a texture and the format hasn't changed, better to reuse
    164  // the image keys than create new ones.
    165  bool useUpdate = mKey.isSome() && !!mTextureOfImage && !!currentTexture &&
    166                   mTextureOfImage->GetSize() == currentTexture->GetSize() &&
    167                   mTextureOfImage->GetFormat() == currentTexture->GetFormat();
    168 
    169  wr::MaybeExternalImageId extId = currentTexture->GetExternalImageKey();
    170  MOZ_RELEASE_ASSERT(extId.isSome());
    171 
    172  if (useUpdate) {
    173    MOZ_ASSERT(mKey.isSome());
    174    MOZ_ASSERT(mTextureOfImage);
    175    aResources.PushExternalImageForTexture(
    176        extId.ref(), mKey.ref(), currentTexture, /* aIsUpdate */ true);
    177  } else {
    178    ClearImageKey();
    179    wr::WrImageKey key = WrBridge()->GetNextImageKey();
    180    aResources.PushExternalImageForTexture(extId.ref(), key, currentTexture,
    181                                           /* aIsUpdate */ false);
    182    mKey = Some(key);
    183  }
    184 
    185  mTextureOfImage = currentTexture;
    186  return mKey;
    187 }
    188 
    189 already_AddRefed<ImageClient> WebRenderImageData::GetImageClient() {
    190  RefPtr<ImageClient> imageClient = mImageClient;
    191  return imageClient.forget();
    192 }
    193 
    194 void WebRenderImageData::CreateAsyncImageWebRenderCommands(
    195    mozilla::wr::DisplayListBuilder& aBuilder, ImageContainer* aContainer,
    196    const StackingContextHelper& aSc, const LayoutDeviceRect& aBounds,
    197    const LayoutDeviceRect& aSCBounds, wr::WrRotation aRotation,
    198    const wr::ImageRendering& aFilter, const wr::MixBlendMode& aMixBlendMode,
    199    bool aIsBackfaceVisible) {
    200  MOZ_ASSERT(aContainer->IsAsync());
    201 
    202  if (mPipelineId.isSome() && mContainer != aContainer) {
    203    // In this case, we need to remove the existed pipeline and create new one
    204    // because the ImageContainer is changed.
    205    WrBridge()->RemovePipelineIdForCompositable(mPipelineId.ref());
    206    mPipelineId.reset();
    207  }
    208 
    209  if (!mPipelineId) {
    210    // Alloc async image pipeline id.
    211    mPipelineId =
    212        Some(WrBridge()->GetCompositorBridgeChild()->GetNextPipelineId());
    213    WrBridge()->AddPipelineIdForCompositable(
    214        mPipelineId.ref(), aContainer->GetAsyncContainerHandle(),
    215        CompositableHandleOwner::ImageBridge);
    216    mContainer = aContainer;
    217  }
    218  MOZ_ASSERT(!mImageClient);
    219 
    220  // Push IFrame for async image pipeline.
    221  //
    222  // We don't push a stacking context for this async image pipeline here.
    223  // Instead, we do it inside the iframe that hosts the image. As a result,
    224  // a bunch of the calculations normally done as part of that stacking
    225  // context need to be done manually and pushed over to the parent side,
    226  // where it will be done when we build the display list for the iframe.
    227  // That happens in AsyncImagePipelineManager.
    228  aBuilder.PushIFrame(aBounds, aIsBackfaceVisible, mPipelineId.ref(),
    229                      /*ignoreMissingPipelines*/ false);
    230 
    231  WrBridge()->AddWebRenderParentCommand(OpUpdateAsyncImagePipeline(
    232      mPipelineId.value(), aSCBounds, aRotation, aFilter, aMixBlendMode));
    233 }
    234 
    235 void WebRenderImageData::CreateImageClientIfNeeded() {
    236  if (!mImageClient) {
    237    mImageClient = ImageClient::CreateImageClient(
    238        CompositableType::IMAGE, ImageUsageType::WebRenderImageData, WrBridge(),
    239        TextureFlags::DEFAULT);
    240    if (!mImageClient) {
    241      return;
    242    }
    243 
    244    mImageClient->Connect();
    245  }
    246 }
    247 
    248 WebRenderImageProviderData::WebRenderImageProviderData(
    249    RenderRootStateManager* aManager, nsDisplayItem* aItem)
    250    : WebRenderUserData(aManager, aItem) {}
    251 
    252 WebRenderImageProviderData::WebRenderImageProviderData(
    253    RenderRootStateManager* aManager, uint32_t aDisplayItemKey,
    254    nsIFrame* aFrame)
    255    : WebRenderUserData(aManager, aDisplayItemKey, aFrame) {}
    256 
    257 WebRenderImageProviderData::~WebRenderImageProviderData() = default;
    258 
    259 Maybe<wr::ImageKey> WebRenderImageProviderData::UpdateImageKey(
    260    WebRenderImageProvider* aProvider, ImgDrawResult aDrawResult,
    261    wr::IpcResourceUpdateQueue& aResources) {
    262  if (mProvider != aProvider) {
    263    mProvider = aProvider;
    264  }
    265 
    266  wr::ImageKey key = {};
    267  nsresult rv = mProvider ? mProvider->UpdateKey(mManager, aResources, key)
    268                          : NS_ERROR_FAILURE;
    269  mKey = NS_SUCCEEDED(rv) ? Some(key) : Nothing();
    270  mDrawResult = aDrawResult;
    271  return mKey;
    272 }
    273 
    274 bool WebRenderImageProviderData::Invalidate(ImageProviderId aProviderId) const {
    275  if (!aProviderId || !mProvider || mProvider->GetProviderId() != aProviderId ||
    276      !mKey) {
    277    return false;
    278  }
    279 
    280  if (mDrawResult != ImgDrawResult::SUCCESS &&
    281      mDrawResult != ImgDrawResult::BAD_IMAGE) {
    282    return false;
    283  }
    284 
    285  wr::ImageKey key = {};
    286  nsresult rv =
    287      mProvider->UpdateKey(mManager, mManager->AsyncResourceUpdates(), key);
    288  return NS_SUCCEEDED(rv) && mKey.ref() == key;
    289 }
    290 
    291 WebRenderFallbackData::WebRenderFallbackData(RenderRootStateManager* aManager,
    292                                             nsDisplayItem* aItem)
    293    : WebRenderFallbackData(aManager, aItem->GetPerFrameKey(), aItem->Frame()) {
    294 }
    295 
    296 WebRenderFallbackData::WebRenderFallbackData(RenderRootStateManager* aManager,
    297                                             uint32_t aDisplayItemKey,
    298                                             nsIFrame* aFrame)
    299    : WebRenderUserData(aManager, aDisplayItemKey, aFrame),
    300      mOpacity(1.0f),
    301      mInvalid(false) {}
    302 
    303 WebRenderFallbackData::~WebRenderFallbackData() { ClearImageKey(); }
    304 
    305 void WebRenderFallbackData::SetBlobImageKey(const wr::BlobImageKey& aKey) {
    306  ClearImageKey();
    307  mBlobKey = Some(aKey);
    308 }
    309 
    310 Maybe<wr::ImageKey> WebRenderFallbackData::GetImageKey() {
    311  if (mBlobKey) {
    312    return Some(wr::AsImageKey(mBlobKey.value()));
    313  }
    314 
    315  if (mImageData) {
    316    return mImageData->GetImageKey();
    317  }
    318 
    319  return Nothing();
    320 }
    321 
    322 void WebRenderFallbackData::ClearImageKey() {
    323  if (mImageData) {
    324    mImageData->ClearImageKey();
    325    mImageData = nullptr;
    326  }
    327 
    328  if (mBlobKey) {
    329    mManager->AddBlobImageKeyForDiscard(mBlobKey.value());
    330    mBlobKey.reset();
    331  }
    332 }
    333 
    334 WebRenderImageData* WebRenderFallbackData::PaintIntoImage() {
    335  if (mBlobKey) {
    336    mManager->AddBlobImageKeyForDiscard(mBlobKey.value());
    337    mBlobKey.reset();
    338  }
    339 
    340  if (mImageData) {
    341    return mImageData.get();
    342  }
    343 
    344  mImageData = MakeAndAddRef<WebRenderImageData>(mManager.get(),
    345                                                 mDisplayItemKey, mFrame);
    346 
    347  return mImageData.get();
    348 }
    349 
    350 WebRenderAPZAnimationData::WebRenderAPZAnimationData(
    351    RenderRootStateManager* aManager, nsDisplayItem* aItem)
    352    : WebRenderAPZAnimationData(aManager, aItem->GetPerFrameKey(),
    353                                aItem->Frame()) {}
    354 
    355 WebRenderAPZAnimationData::WebRenderAPZAnimationData(
    356    RenderRootStateManager* aManager, uint32_t aDisplayItemKey,
    357    nsIFrame* aFrame)
    358    : WebRenderUserData(aManager, aDisplayItemKey, aFrame),
    359      mAnimationId(AnimationHelper::GetNextCompositorAnimationsId()) {}
    360 
    361 WebRenderAnimationData::WebRenderAnimationData(RenderRootStateManager* aManager,
    362                                               nsDisplayItem* aItem)
    363    : WebRenderUserData(aManager, aItem) {}
    364 
    365 WebRenderAnimationData::WebRenderAnimationData(RenderRootStateManager* aManager,
    366                                               uint32_t aDisplayItemKey,
    367                                               nsIFrame* aFrame)
    368    : WebRenderUserData(aManager, aDisplayItemKey, aFrame) {}
    369 
    370 WebRenderAnimationData::~WebRenderAnimationData() {
    371  // It may be the case that nsDisplayItem that created this WebRenderUserData
    372  // gets destroyed without getting a chance to discard the compositor animation
    373  // id, so we should do it as part of cleanup here.
    374  uint64_t animationId = mAnimationInfo.GetCompositorAnimationsId();
    375  // animationId might be 0 if mAnimationInfo never held any active animations.
    376  if (animationId) {
    377    mManager->AddCompositorAnimationsIdForDiscard(animationId);
    378  }
    379 }
    380 
    381 WebRenderCanvasData::WebRenderCanvasData(RenderRootStateManager* aManager,
    382                                         nsDisplayItem* aItem)
    383    : WebRenderUserData(aManager, aItem) {}
    384 
    385 WebRenderCanvasData::WebRenderCanvasData(RenderRootStateManager* aManager,
    386                                         uint32_t aDisplayItemKey,
    387                                         nsIFrame* aFrame)
    388    : WebRenderUserData(aManager, aDisplayItemKey, aFrame) {}
    389 
    390 WebRenderCanvasData::~WebRenderCanvasData() {
    391  if (mCanvasRenderer) {
    392    mCanvasRenderer->ClearCachedResources();
    393  }
    394 }
    395 
    396 void WebRenderCanvasData::ClearCanvasRenderer() { mCanvasRenderer = nullptr; }
    397 
    398 WebRenderCanvasRendererAsync* WebRenderCanvasData::GetCanvasRenderer() {
    399  return mCanvasRenderer.get();
    400 }
    401 
    402 WebRenderCanvasRendererAsync* WebRenderCanvasData::CreateCanvasRenderer() {
    403  mCanvasRenderer = new WebRenderCanvasRendererAsync(mManager);
    404  return mCanvasRenderer.get();
    405 }
    406 
    407 bool WebRenderCanvasData::SetCanvasRenderer(CanvasRenderer* aCanvasRenderer) {
    408  if (!aCanvasRenderer || !aCanvasRenderer->AsWebRenderCanvasRendererAsync()) {
    409    return false;
    410  }
    411 
    412  auto* renderer = aCanvasRenderer->AsWebRenderCanvasRendererAsync();
    413  if (mManager != renderer->GetRenderRootStateManager()) {
    414    return false;
    415  }
    416 
    417  mCanvasRenderer = renderer;
    418  return true;
    419 }
    420 
    421 void WebRenderCanvasData::SetImageContainer(ImageContainer* aImageContainer) {
    422  mContainer = aImageContainer;
    423 }
    424 
    425 ImageContainer* WebRenderCanvasData::GetImageContainer() {
    426  if (!mContainer) {
    427    mContainer = MakeAndAddRef<ImageContainer>(ImageUsageType::Canvas,
    428                                               ImageContainer::SYNCHRONOUS);
    429  }
    430  return mContainer;
    431 }
    432 
    433 void WebRenderCanvasData::ClearImageContainer() { mContainer = nullptr; }
    434 
    435 void DestroyWebRenderUserDataTable(WebRenderUserDataTable* aTable) {
    436  for (const auto& value : aTable->Values()) {
    437    value->RemoveFromTable();
    438  }
    439  delete aTable;
    440 }
    441 
    442 WebRenderMaskData::WebRenderMaskData(RenderRootStateManager* aManager,
    443                                     nsDisplayItem* aItem)
    444    : WebRenderMaskData(aManager, aItem->GetPerFrameKey(), aItem->Frame()) {}
    445 WebRenderMaskData::WebRenderMaskData(RenderRootStateManager* aManager,
    446                                     uint32_t aDisplayItemKey, nsIFrame* aFrame)
    447    : WebRenderUserData(aManager, aDisplayItemKey, aFrame),
    448      mMaskStyle(nsStyleImageLayers::LayerType::Mask),
    449      mShouldHandleOpacity(false) {
    450  MOZ_COUNT_CTOR(WebRenderMaskData);
    451 }
    452 
    453 }  // namespace layers
    454 }  // namespace mozilla