author Doug Thayer <>
Mon, 07 Jan 2019 21:33:10 +0000
changeset 452767 ee870d4a43083769491e0964ae180304542fc10f
parent 451725 fe95776b47d90f62d202633df9e4a7c0373a91d3
child 454614 096cd49afd334998208b46af3bbfc32d1ebd0760
permissions -rw-r--r--
Bug 1441308 - Split out document pieces of WebRenderLayerManager r=jrmuizel Per our discussion, this patch splits out the state management bits of WebRenderLayerManager, allowing for them to be maintained per-document. Differential Revision:

/* -*- 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 */


#include <vector>
#include "BasicLayers.h"  // for BasicLayerManager
#include "mozilla/layers/StackingContextHelper.h"
#include "mozilla/webrender/WebRenderAPI.h"
#include "mozilla/layers/AnimationInfo.h"
#include "nsIFrame.h"

class nsDisplayItemGeometry;

namespace mozilla {
namespace wr {
class IpcResourceUpdateQueue;

namespace gfx {
class SourceSurface;

namespace layers {
class CanvasLayer;
class ImageClient;
class ImageContainer;
class WebRenderBridgeChild;
class WebRenderCanvasData;
class WebRenderCanvasRendererAsync;
class WebRenderImageData;
class WebRenderFallbackData;
class RenderRootStateManager;
class WebRenderGroupData;

class WebRenderBackgroundData {
  WebRenderBackgroundData(wr::LayoutRect aBounds, wr::ColorF aColor)
      : mBounds(aBounds), mColor(aColor) {}
  void AddWebRenderCommands(wr::DisplayListBuilder& aBuilder);

  wr::LayoutRect mBounds;
  wr::ColorF mColor;

class WebRenderUserData {
  typedef nsTHashtable<nsRefPtrHashKey<WebRenderUserData>>

  static bool SupportsAsyncUpdate(nsIFrame* aFrame);

  static bool ProcessInvalidateForImage(nsIFrame* aFrame,
                                        DisplayItemType aType);


  WebRenderUserData(RenderRootStateManager* aManager, nsDisplayItem* aItem);

  virtual WebRenderImageData* AsImageData() { return nullptr; }
  virtual WebRenderFallbackData* AsFallbackData() { return nullptr; }
  virtual WebRenderCanvasData* AsCanvasData() { return nullptr; }
  virtual WebRenderGroupData* AsGroupData() { return nullptr; }

  enum class UserDataType {

  virtual UserDataType GetType() = 0;
  bool IsUsed() { return mUsed; }
  void SetUsed(bool aUsed) { mUsed = aUsed; }
  nsIFrame* GetFrame() { return mFrame; }
  uint32_t GetDisplayItemKey() { return mDisplayItemKey; }
  void RemoveFromTable();
  virtual nsDisplayItemGeometry* GetGeometry() { return nullptr; }

  virtual ~WebRenderUserData();

  WebRenderBridgeChild* WrBridge() const;

  RefPtr<RenderRootStateManager> mManager;
  nsIFrame* mFrame;
  uint32_t mDisplayItemKey;
  WebRenderUserDataRefTable* mTable;
  bool mUsed;

struct WebRenderUserDataKey {
  WebRenderUserDataKey(uint32_t aFrameKey,
                       WebRenderUserData::UserDataType aType)
      : mFrameKey(aFrameKey), mType(aType) {}

  bool operator==(const WebRenderUserDataKey& other) const {
    return mFrameKey == other.mFrameKey && mType == other.mType;
  PLDHashNumber Hash() const {
    return HashGeneric(

  uint32_t mFrameKey;
  WebRenderUserData::UserDataType mType;

typedef nsRefPtrHashtable<
    nsGenericHashKey<mozilla::layers::WebRenderUserDataKey>, WebRenderUserData>

/// Holds some data used to share TextureClient/ImageClient with the parent
/// process except if used with blob images (watch your step).
class WebRenderImageData : public WebRenderUserData {
  WebRenderImageData(RenderRootStateManager* aManager, nsDisplayItem* aItem);
  virtual ~WebRenderImageData();

  virtual WebRenderImageData* AsImageData() override { return this; }
  virtual UserDataType GetType() override { return UserDataType::eImage; }
  static UserDataType Type() { return UserDataType::eImage; }
  virtual Maybe<wr::ImageKey> GetImageKey() { return mKey; }
  void SetImageKey(const wr::ImageKey& aKey);
  already_AddRefed<ImageClient> GetImageClient();

  Maybe<wr::ImageKey> UpdateImageKey(ImageContainer* aContainer,
                                     wr::IpcResourceUpdateQueue& aResources,
                                     bool aFallback = false);

  void CreateAsyncImageWebRenderCommands(
      mozilla::wr::DisplayListBuilder& aBuilder, ImageContainer* aContainer,
      const StackingContextHelper& aSc, const LayoutDeviceRect& aBounds,
      const LayoutDeviceRect& aSCBounds, const gfx::Matrix4x4& aSCTransform,
      const gfx::MaybeIntSize& aScaleToSize, const wr::ImageRendering& aFilter,
      const wr::MixBlendMode& aMixBlendMode, bool aIsBackfaceVisible);

  void CreateImageClientIfNeeded();

  bool IsAsync() { return mPipelineId.isSome(); }

  bool IsAsyncAnimatedImage() const;

  virtual void ClearImageKey();

  RefPtr<TextureClient> mTextureOfImage;
  Maybe<wr::ImageKey> mKey;
  RefPtr<ImageClient> mImageClient;
  Maybe<wr::PipelineId> mPipelineId;
  RefPtr<ImageContainer> mContainer;
  bool mOwnsKey;

/// Used for fallback rendering.
/// In most cases this uses blob images but it can also render on the content
/// side directly into a texture.
/// TODO(nical) It would be much better to separate the two use cases into
/// separate classes and not have the blob image related code inherit from
/// WebRenderImageData (the current code only works if we carefully use a subset
/// of the parent code).
class WebRenderFallbackData : public WebRenderImageData {
  WebRenderFallbackData(RenderRootStateManager* aManager, nsDisplayItem* aItem);
  virtual ~WebRenderFallbackData();

  virtual WebRenderFallbackData* AsFallbackData() override { return this; }
  virtual UserDataType GetType() override { return UserDataType::eFallback; }
  static UserDataType Type() { return UserDataType::eFallback; }
  nsDisplayItemGeometry* GetGeometry() override;
  void SetGeometry(nsAutoPtr<nsDisplayItemGeometry> aGeometry);
  nsRect GetBounds() { return mBounds; }
  void SetBounds(const nsRect& aRect) { mBounds = aRect; }
  void SetInvalid(bool aInvalid) { mInvalid = aInvalid; }
  void SetScale(gfx::Size aScale) { mScale = aScale; }
  gfx::Size GetScale() { return mScale; }
  bool IsInvalid() { return mInvalid; }
  void SetFonts(const std::vector<RefPtr<gfx::ScaledFont>>& aFonts) {
    mFonts = aFonts;
  Maybe<wr::BlobImageKey> GetBlobImageKey() { return mBlobKey; }
  virtual Maybe<wr::ImageKey> GetImageKey() override;
  void SetBlobImageKey(const wr::BlobImageKey& aKey);

  RefPtr<BasicLayerManager> mBasicLayerManager;
  std::vector<RefPtr<gfx::SourceSurface>> mExternalSurfaces;

  virtual void ClearImageKey() override;

  Maybe<wr::BlobImageKey> mBlobKey;
  nsAutoPtr<nsDisplayItemGeometry> mGeometry;
  nsRect mBounds;
  bool mInvalid;
  gfx::Size mScale;
  std::vector<RefPtr<gfx::ScaledFont>> mFonts;

class WebRenderAnimationData : public WebRenderUserData {
  WebRenderAnimationData(RenderRootStateManager* aManager,
                         nsDisplayItem* aItem);
  virtual ~WebRenderAnimationData();

  virtual UserDataType GetType() override { return UserDataType::eAnimation; }
  static UserDataType Type() { return UserDataType::eAnimation; }
  AnimationInfo& GetAnimationInfo() { return mAnimationInfo; }

  AnimationInfo mAnimationInfo;

class WebRenderCanvasData : public WebRenderUserData {
  WebRenderCanvasData(RenderRootStateManager* aManager, nsDisplayItem* aItem);
  virtual ~WebRenderCanvasData();

  virtual WebRenderCanvasData* AsCanvasData() override { return this; }
  virtual UserDataType GetType() override { return UserDataType::eCanvas; }
  static UserDataType Type() { return UserDataType::eCanvas; }

  void ClearCanvasRenderer();
  WebRenderCanvasRendererAsync* GetCanvasRenderer();
  WebRenderCanvasRendererAsync* CreateCanvasRenderer();

  UniquePtr<WebRenderCanvasRendererAsync> mCanvasRenderer;

extern void DestroyWebRenderUserDataTable(WebRenderUserDataTable* aTable);

struct WebRenderUserDataProperty {

template <class T>
already_AddRefed<T> GetWebRenderUserData(const nsIFrame* aFrame,
                                         uint32_t aPerFrameKey) {
  WebRenderUserDataTable* userDataTable =
  if (!userDataTable) {
    return nullptr;

  WebRenderUserData* data =
      userDataTable->GetWeak(WebRenderUserDataKey(aPerFrameKey, T::Type()));
  if (data) {
    RefPtr<T> result = static_cast<T*>(data);
    return result.forget();

  return nullptr;

}  // namespace layers
}  // namespace mozilla