Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quelle  WebRenderUserData.cpp   Sprache: C

 
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */


#include "WebRenderUserData.h"

#include "mozilla/image/WebRenderImageProvider.h"
#include "mozilla/layers/AnimationHelper.h"
#include "mozilla/layers/CompositorBridgeChild.h"
#include "mozilla/layers/ImageClient.h"
#include "mozilla/layers/WebRenderBridgeChild.h"
#include "mozilla/layers/RenderRootStateManager.h"
#include "mozilla/layers/WebRenderMessages.h"
#include "mozilla/layers/IpcResourceUpdateQueue.h"
#include "mozilla/layers/SharedSurfacesChild.h"
#include "mozilla/webgpu/WebGPUChild.h"
#include "nsDisplayListInvalidation.h"
#include "nsIFrame.h"
#include "WebRenderCanvasRenderer.h"

using namespace mozilla::image;

namespace mozilla {
namespace layers {

void WebRenderBackgroundData::AddWebRenderCommands(
    wr::DisplayListBuilder& aBuilder) {
  aBuilder.PushRect(mBounds, mBounds, truetruefalse, mColor);
}

/* static */
bool WebRenderUserData::SupportsAsyncUpdate(nsIFrame* aFrame) {
  if (!aFrame) {
    return false;
  }
  RefPtr<WebRenderImageData> data = GetWebRenderUserData<WebRenderImageData>(
      aFrame, static_cast<uint32_t>(DisplayItemType::TYPE_VIDEO));
  if (data) {
    return data->IsAsync();
  }

  return false;
}

/* static */
bool WebRenderUserData::ProcessInvalidateForImage(nsIFrame* aFrame,
                                                  DisplayItemType aType,
                                                  ImageProviderId aProviderId) {
  MOZ_ASSERT(aFrame);

  if (!aFrame->HasProperty(WebRenderUserDataProperty::Key())) {
    aFrame->SchedulePaint();
    return false;
  }

  auto type = static_cast<uint32_t>(aType);
  RefPtr<WebRenderFallbackData> fallback =
      GetWebRenderUserData<WebRenderFallbackData>(aFrame, type);
  if (fallback) {
    fallback->SetInvalid(true);
    aFrame->SchedulePaint();
    return true;
  }

  RefPtr<WebRenderImageProviderData> image =
      GetWebRenderUserData<WebRenderImageProviderData>(aFrame, type);
  if (image && image->Invalidate(aProviderId)) {
    return true;
  }

  aFrame->SchedulePaint();
  return false;
}

WebRenderUserData::WebRenderUserData(RenderRootStateManager* aManager,
                                     uint32_t aDisplayItemKey, nsIFrame* aFrame)
    : mManager(aManager),
      mFrame(aFrame),
      mDisplayItemKey(aDisplayItemKey),
      mTable(aManager->GetWebRenderUserDataTable()),
      mUsed(false) {}

WebRenderUserData::WebRenderUserData(RenderRootStateManager* aManager,
                                     nsDisplayItem* aItem)
    : mManager(aManager),
      mFrame(aItem->Frame()),
      mDisplayItemKey(aItem->GetPerFrameKey()),
      mTable(aManager->GetWebRenderUserDataTable()),
      mUsed(false) {}

WebRenderUserData::~WebRenderUserData() = default;

void WebRenderUserData::RemoveFromTable() { mTable->Remove(this); }

WebRenderBridgeChild* WebRenderUserData::WrBridge() const {
  return mManager->WrBridge();
}

WebRenderImageData::WebRenderImageData(RenderRootStateManager* aManager,
                                       nsDisplayItem* aItem)
    : WebRenderUserData(aManager, aItem) {}

WebRenderImageData::WebRenderImageData(RenderRootStateManager* aManager,
                                       uint32_t aDisplayItemKey,
                                       nsIFrame* aFrame)
    : WebRenderUserData(aManager, aDisplayItemKey, aFrame) {}

WebRenderImageData::~WebRenderImageData() {
  ClearImageKey();

  if (mPipelineId) {
    mManager->RemovePipelineIdForCompositable(mPipelineId.ref());
  }
}

void WebRenderImageData::ClearImageKey() {
  if (mKey) {
    mManager->AddImageKeyForDiscard(mKey.value());
    if (mTextureOfImage) {
      WrBridge()->ReleaseTextureOfImage(mKey.value());
      mTextureOfImage = nullptr;
    }
    mKey.reset();
  }
  MOZ_ASSERT(!mTextureOfImage);
}

Maybe<wr::ImageKey> WebRenderImageData::UpdateImageKey(
    ImageContainer* aContainer, wr::IpcResourceUpdateQueue& aResources,
    bool aFallback) {
  MOZ_ASSERT(aContainer);

  if (mContainer != aContainer) {
    mContainer = aContainer;
  }

  CreateImageClientIfNeeded();
  if (!mImageClient) {
    return Nothing();
  }

  MOZ_ASSERT(mImageClient->AsImageClientSingle());

  ImageClientSingle* imageClient = mImageClient->AsImageClientSingle();
  uint32_t oldCounter = imageClient->GetLastUpdateGenerationCounter();

  bool ret = imageClient->UpdateImage(aContainer);
  RefPtr<TextureClient> currentTexture = imageClient->GetForwardedTexture();
  if (!ret || !currentTexture) {
    // Delete old key
    ClearImageKey();
    return Nothing();
  }

  // Reuse old key if generation is not updated.
  if (!aFallback &&
      oldCounter == imageClient->GetLastUpdateGenerationCounter() && mKey) {
    return mKey;
  }

  // If we already had a texture and the format hasn't changed, better to reuse
  // the image keys than create new ones.
  bool useUpdate = mKey.isSome() && !!mTextureOfImage && !!currentTexture &&
                   mTextureOfImage->GetSize() == currentTexture->GetSize() &&
                   mTextureOfImage->GetFormat() == currentTexture->GetFormat();

  wr::MaybeExternalImageId extId = currentTexture->GetExternalImageKey();
  MOZ_RELEASE_ASSERT(extId.isSome());

  if (useUpdate) {
    MOZ_ASSERT(mKey.isSome());
    MOZ_ASSERT(mTextureOfImage);
    aResources.PushExternalImageForTexture(
        extId.ref(), mKey.ref(), currentTexture, /* aIsUpdate */ true);
  } else {
    ClearImageKey();
    wr::WrImageKey key = WrBridge()->GetNextImageKey();
    aResources.PushExternalImageForTexture(extId.ref(), key, currentTexture,
                                           /* aIsUpdate */ false);
    mKey = Some(key);
  }

  mTextureOfImage = currentTexture;
  return mKey;
}

already_AddRefed<ImageClient> WebRenderImageData::GetImageClient() {
  RefPtr<ImageClient> imageClient = mImageClient;
  return imageClient.forget();
}

void WebRenderImageData::CreateAsyncImageWebRenderCommands(
    mozilla::wr::DisplayListBuilder& aBuilder, ImageContainer* aContainer,
    const StackingContextHelper& aSc, const LayoutDeviceRect& aBounds,
    const LayoutDeviceRect& aSCBounds, wr::WrRotation aRotation,
    const wr::ImageRendering& aFilter, const wr::MixBlendMode& aMixBlendMode,
    bool aIsBackfaceVisible) {
  MOZ_ASSERT(aContainer->IsAsync());

  if (mPipelineId.isSome() && mContainer != aContainer) {
    // In this case, we need to remove the existed pipeline and create new one
    // because the ImageContainer is changed.
    WrBridge()->RemovePipelineIdForCompositable(mPipelineId.ref());
    mPipelineId.reset();
  }

  if (!mPipelineId) {
    // Alloc async image pipeline id.
    mPipelineId =
        Some(WrBridge()->GetCompositorBridgeChild()->GetNextPipelineId());
    WrBridge()->AddPipelineIdForCompositable(
        mPipelineId.ref(), aContainer->GetAsyncContainerHandle(),
        CompositableHandleOwner::ImageBridge);
    mContainer = aContainer;
  }
  MOZ_ASSERT(!mImageClient);

  // Push IFrame for async image pipeline.
  //
  // We don't push a stacking context for this async image pipeline here.
  // Instead, we do it inside the iframe that hosts the image. As a result,
  // a bunch of the calculations normally done as part of that stacking
  // context need to be done manually and pushed over to the parent side,
  // where it will be done when we build the display list for the iframe.
  // That happens in AsyncImagePipelineManager.
  aBuilder.PushIFrame(aBounds, aIsBackfaceVisible, mPipelineId.ref(),
                      /*ignoreMissingPipelines*/ false);

  WrBridge()->AddWebRenderParentCommand(OpUpdateAsyncImagePipeline(
      mPipelineId.value(), aSCBounds, aRotation, aFilter, aMixBlendMode));
}

void WebRenderImageData::CreateImageClientIfNeeded() {
  if (!mImageClient) {
    mImageClient = ImageClient::CreateImageClient(
        CompositableType::IMAGE, ImageUsageType::WebRenderImageData, WrBridge(),
        TextureFlags::DEFAULT);
    if (!mImageClient) {
      return;
    }

    mImageClient->Connect();
  }
}

WebRenderImageProviderData::WebRenderImageProviderData(
    RenderRootStateManager* aManager, nsDisplayItem* aItem)
    : WebRenderUserData(aManager, aItem) {}

WebRenderImageProviderData::WebRenderImageProviderData(
    RenderRootStateManager* aManager, uint32_t aDisplayItemKey,
    nsIFrame* aFrame)
    : WebRenderUserData(aManager, aDisplayItemKey, aFrame) {}

WebRenderImageProviderData::~WebRenderImageProviderData() = default;

Maybe<wr::ImageKey> WebRenderImageProviderData::UpdateImageKey(
    WebRenderImageProvider* aProvider, ImgDrawResult aDrawResult,
    wr::IpcResourceUpdateQueue& aResources) {
  if (mProvider != aProvider) {
    mProvider = aProvider;
  }

  wr::ImageKey key = {};
  nsresult rv = mProvider ? mProvider->UpdateKey(mManager, aResources, key)
                          : NS_ERROR_FAILURE;
  mKey = NS_SUCCEEDED(rv) ? Some(key) : Nothing();
  mDrawResult = aDrawResult;
  return mKey;
}

bool WebRenderImageProviderData::Invalidate(ImageProviderId aProviderId) const {
  if (!aProviderId || !mProvider || mProvider->GetProviderId() != aProviderId ||
      !mKey) {
    return false;
  }

  if (mDrawResult != ImgDrawResult::SUCCESS &&
      mDrawResult != ImgDrawResult::BAD_IMAGE) {
    return false;
  }

  wr::ImageKey key = {};
  nsresult rv =
      mProvider->UpdateKey(mManager, mManager->AsyncResourceUpdates(), key);
  return NS_SUCCEEDED(rv) && mKey.ref() == key;
}

WebRenderFallbackData::WebRenderFallbackData(RenderRootStateManager* aManager,
                                             nsDisplayItem* aItem)
    : WebRenderUserData(aManager, aItem), mOpacity(1.0f), mInvalid(false) {}

WebRenderFallbackData::~WebRenderFallbackData() { ClearImageKey(); }

void WebRenderFallbackData::SetBlobImageKey(const wr::BlobImageKey& aKey) {
  ClearImageKey();
  mBlobKey = Some(aKey);
}

Maybe<wr::ImageKey> WebRenderFallbackData::GetImageKey() {
  if (mBlobKey) {
    return Some(wr::AsImageKey(mBlobKey.value()));
  }

  if (mImageData) {
    return mImageData->GetImageKey();
  }

  return Nothing();
}

void WebRenderFallbackData::ClearImageKey() {
  if (mImageData) {
    mImageData->ClearImageKey();
    mImageData = nullptr;
  }

  if (mBlobKey) {
    mManager->AddBlobImageKeyForDiscard(mBlobKey.value());
    mBlobKey.reset();
  }
}

WebRenderImageData* WebRenderFallbackData::PaintIntoImage() {
  if (mBlobKey) {
    mManager->AddBlobImageKeyForDiscard(mBlobKey.value());
    mBlobKey.reset();
  }

  if (mImageData) {
    return mImageData.get();
  }

  mImageData = MakeAndAddRef<WebRenderImageData>(mManager.get(),
                                                 mDisplayItemKey, mFrame);

  return mImageData.get();
}

WebRenderAPZAnimationData::WebRenderAPZAnimationData(
    RenderRootStateManager* aManager, nsDisplayItem* aItem)
    : WebRenderUserData(aManager, aItem),
      mAnimationId(AnimationHelper::GetNextCompositorAnimationsId()) {}

WebRenderAnimationData::WebRenderAnimationData(RenderRootStateManager* aManager,
                                               nsDisplayItem* aItem)
    : WebRenderUserData(aManager, aItem) {}

WebRenderAnimationData::~WebRenderAnimationData() {
  // It may be the case that nsDisplayItem that created this WebRenderUserData
  // gets destroyed without getting a chance to discard the compositor animation
  // id, so we should do it as part of cleanup here.
  uint64_t animationId = mAnimationInfo.GetCompositorAnimationsId();
  // animationId might be 0 if mAnimationInfo never held any active animations.
  if (animationId) {
    mManager->AddCompositorAnimationsIdForDiscard(animationId);
  }
}

WebRenderCanvasData::WebRenderCanvasData(RenderRootStateManager* aManager,
                                         nsDisplayItem* aItem)
    : WebRenderUserData(aManager, aItem) {}

WebRenderCanvasData::~WebRenderCanvasData() {
  if (mCanvasRenderer) {
    mCanvasRenderer->ClearCachedResources();
  }
}

void WebRenderCanvasData::ClearCanvasRenderer() { mCanvasRenderer = nullptr; }

WebRenderCanvasRendererAsync* WebRenderCanvasData::GetCanvasRenderer() {
  return mCanvasRenderer.get();
}

WebRenderCanvasRendererAsync* WebRenderCanvasData::CreateCanvasRenderer() {
  mCanvasRenderer = new WebRenderCanvasRendererAsync(mManager);
  return mCanvasRenderer.get();
}

bool WebRenderCanvasData::SetCanvasRenderer(CanvasRenderer* aCanvasRenderer) {
  if (!aCanvasRenderer || !aCanvasRenderer->AsWebRenderCanvasRendererAsync()) {
    return false;
  }

  auto* renderer = aCanvasRenderer->AsWebRenderCanvasRendererAsync();
  if (mManager != renderer->GetRenderRootStateManager()) {
    return false;
  }

  mCanvasRenderer = renderer;
  return true;
}

void WebRenderCanvasData::SetImageContainer(ImageContainer* aImageContainer) {
  mContainer = aImageContainer;
}

ImageContainer* WebRenderCanvasData::GetImageContainer() {
  if (!mContainer) {
    mContainer = MakeAndAddRef<ImageContainer>(ImageUsageType::Canvas,
                                               ImageContainer::SYNCHRONOUS);
  }
  return mContainer;
}

void WebRenderCanvasData::ClearImageContainer() { mContainer = nullptr; }

void DestroyWebRenderUserDataTable(WebRenderUserDataTable* aTable) {
  for (const auto& value : aTable->Values()) {
    value->RemoveFromTable();
  }
  delete aTable;
}

}  // namespace layers
}  // namespace mozilla

Messung V0.5
C=92 H=98 G=94

¤ Dauer der Verarbeitung: 0.4 Sekunden  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge