gfx/layers/wr/StackingContextHelper.cpp
author Brindusan Cristian <cbrindusan@mozilla.com>
Thu, 17 Jan 2019 19:20:00 +0200
changeset 454319 855970c5fa721b829d664f4596df61b5fff8163b
parent 454315 bbc57e229df64bdf5b4fa2d86bf419686bacf496
child 454341 3ce47eeea41a4e62bd52be3aea7d720933a8d24a
permissions -rw-r--r--
Backed out changeset bbc57e229df6 (bug 1520664) for webrender bustages. CLOSED TREE

/* -*- 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 "mozilla/layers/StackingContextHelper.h"

#include "UnitTransforms.h"
#include "nsDisplayList.h"

namespace mozilla {
namespace layers {

StackingContextHelper::StackingContextHelper()
    : mBuilder(nullptr),
      mScale(1.0f, 1.0f),
      mAffectsClipPositioning(false),
      mIsPreserve3D(false),
      mRasterizeLocally(false) {
  // mOrigin remains at 0,0
}

StackingContextHelper::StackingContextHelper(
    const StackingContextHelper& aParentSC, const ActiveScrolledRoot* aAsr,
    nsIFrame* aContainerFrame, nsDisplayItem* aContainerItem,
    wr::DisplayListBuilder& aBuilder, const nsTArray<wr::FilterOp>& aFilters,
    const LayoutDeviceRect& aBounds, const gfx::Matrix4x4* aBoundTransform,
    const wr::WrAnimationProperty* aAnimation, const float* aOpacityPtr,
    const gfx::Matrix4x4* aTransformPtr, const gfx::Matrix4x4* aPerspectivePtr,
    const gfx::CompositionOp& aMixBlendMode, bool aBackfaceVisible,
    bool aIsPreserve3D,
    const Maybe<nsDisplayTransform*>& aDeferredTransformItem,
    const wr::WrStackingContextClip& aClip, bool aAnimated)
    : mBuilder(&aBuilder),
      mScale(1.0f, 1.0f),
      mDeferredTransformItem(aDeferredTransformItem),
      mIsPreserve3D(aIsPreserve3D),
      mRasterizeLocally(aAnimated || aParentSC.mRasterizeLocally) {
  // Compute scale for fallback rendering. We don't try to guess a scale for 3d
  // transformed items
  gfx::Matrix transform2d;
  if (aBoundTransform && aBoundTransform->CanDraw2D(&transform2d) &&
      !aPerspectivePtr && !aParentSC.mIsPreserve3D) {
    mInheritedTransform = transform2d * aParentSC.mInheritedTransform;

    int32_t apd = aContainerFrame->PresContext()->AppUnitsPerDevPixel();
    nsRect r = LayoutDevicePixel::ToAppUnits(aBounds, apd);
    mScale = FrameLayerBuilder::ChooseScale(aContainerFrame, aContainerItem, r,
                                            1.f, 1.f, mInheritedTransform,
                                            /* aCanDraw2D = */ true);

    if (aAnimated) {
      mSnappingSurfaceTransform =
          gfx::Matrix::Scaling(mScale.width, mScale.height);
    } else {
      mSnappingSurfaceTransform =
          transform2d * aParentSC.mSnappingSurfaceTransform;
    }
  } else {
    mInheritedTransform = aParentSC.mInheritedTransform;
    mScale = aParentSC.mScale;
  }

  auto rasterSpace =
      mRasterizeLocally
          ? wr::RasterSpace::Local(std::max(mScale.width, mScale.height))
          : wr::RasterSpace::Screen();

  mReferenceFrameId = mBuilder->PushStackingContext(
      wr::ToLayoutRect(aBounds), aClip, aAnimation, aOpacityPtr, aTransformPtr,
      aIsPreserve3D ? wr::TransformStyle::Preserve3D : wr::TransformStyle::Flat,
      aPerspectivePtr, wr::ToMixBlendMode(aMixBlendMode), aFilters,
      aBackfaceVisible, rasterSpace);

  if (mReferenceFrameId) {
    mSpaceAndClipChainHelper.emplace(aBuilder, mReferenceFrameId.ref());
  }

  mAffectsClipPositioning =
      mReferenceFrameId.isSome() || (aBounds.TopLeft() != LayoutDevicePoint());

  // If the parent stacking context has a deferred transform item, inherit it
  // into this stacking context, as long as the ASR hasn't changed. Refer to
  // the comments on StackingContextHelper::mDeferredTransformItem for an
  // explanation of what goes in these fields.
  if (aParentSC.mDeferredTransformItem &&
      aAsr == (*aParentSC.mDeferredTransformItem)->GetActiveScrolledRoot()) {
    if (mDeferredTransformItem) {
      // If we are deferring another transform, put the combined transform from
      // all the ancestor deferred items into mDeferredAncestorTransform
      mDeferredAncestorTransform = aParentSC.GetDeferredTransformMatrix();
    } else {
      // We are not deferring another transform, so we can just inherit the
      // parent stacking context's deferred data without any modification.
      mDeferredTransformItem = aParentSC.mDeferredTransformItem;
      mDeferredAncestorTransform = aParentSC.mDeferredAncestorTransform;
    }
  }
}

StackingContextHelper::~StackingContextHelper() {
  if (mBuilder) {
    mSpaceAndClipChainHelper.reset();
    mBuilder->PopStackingContext(mReferenceFrameId.isSome());
  }
}

const Maybe<nsDisplayTransform*>&
StackingContextHelper::GetDeferredTransformItem() const {
  return mDeferredTransformItem;
}

Maybe<gfx::Matrix4x4> StackingContextHelper::GetDeferredTransformMatrix()
    const {
  if (mDeferredTransformItem) {
    // See the comments on StackingContextHelper::mDeferredTransformItem for
    // an explanation of what's stored in mDeferredTransformItem and
    // mDeferredAncestorTransform. Here we need to return the combined transform
    // transform from all the deferred ancestors, including
    // mDeferredTransformItem.
    gfx::Matrix4x4 result =
        (*mDeferredTransformItem)->GetTransform().GetMatrix();
    if (mDeferredAncestorTransform) {
      result = *mDeferredAncestorTransform * result;
    }
    return Some(result);
  } else {
    return Nothing();
  }
}

}  // namespace layers
}  // namespace mozilla