diff options
Diffstat (limited to 'gfx/layers/wr/StackingContextHelper.cpp')
-rw-r--r-- | gfx/layers/wr/StackingContextHelper.cpp | 150 |
1 files changed, 150 insertions, 0 deletions
diff --git a/gfx/layers/wr/StackingContextHelper.cpp b/gfx/layers/wr/StackingContextHelper.cpp new file mode 100644 index 0000000000..15645d2539 --- /dev/null +++ b/gfx/layers/wr/StackingContextHelper.cpp @@ -0,0 +1,150 @@ +/* -*- 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 "mozilla/PresShell.h" +#include "UnitTransforms.h" +#include "nsDisplayList.h" + +namespace mozilla { +namespace layers { + +StackingContextHelper::StackingContextHelper() + : mBuilder(nullptr), + mScale(1.0f, 1.0f), + mAffectsClipPositioning(false), + mRasterizeLocally(false) { + // mOrigin remains at 0,0 +} + +StackingContextHelper::StackingContextHelper( + const StackingContextHelper& aParentSC, const ActiveScrolledRoot* aAsr, + nsIFrame* aContainerFrame, nsDisplayItem* aContainerItem, + wr::DisplayListBuilder& aBuilder, const wr::StackingContextParams& aParams, + const LayoutDeviceRect& aBounds) + : mBuilder(&aBuilder), + mScale(1.0f, 1.0f), + mDeferredTransformItem(aParams.mDeferredTransformItem), + mRasterizeLocally(aParams.mRasterizeLocally || + aParentSC.mRasterizeLocally) { + mOrigin = aParentSC.mOrigin + aBounds.TopLeft(); + // Compute scale for fallback rendering. We don't try to guess a scale for 3d + // transformed items + + if (aParams.mBoundTransform) { + gfx::Matrix transform2d; + bool canDraw2D = aParams.mBoundTransform->CanDraw2D(&transform2d); + if (canDraw2D && + aParams.reference_frame_kind != wr::WrReferenceFrameKind::Perspective && + !aContainerFrame->Combines3DTransformWithAncestors()) { + mInheritedTransform = transform2d * aParentSC.mInheritedTransform; + + int32_t apd = aContainerFrame->PresContext()->AppUnitsPerDevPixel(); + nsRect r = LayoutDevicePixel::ToAppUnits(aBounds, apd); + mScale = FrameLayerBuilder::ChooseScale( + aContainerFrame, aContainerItem, r, aParentSC.mScale.width, + aParentSC.mScale.height, mInheritedTransform, + /* aCanDraw2D = */ true); + } else { + mScale = gfx::Size(1.0f, 1.0f); + mInheritedTransform = gfx::Matrix::Scaling(1.f, 1.f); + } + + if (aParams.mAnimated) { + mSnappingSurfaceTransform = + gfx::Matrix::Scaling(mScale.width, mScale.height); + } else { + mSnappingSurfaceTransform = + transform2d * aParentSC.mSnappingSurfaceTransform; + } + + } else if (aParams.reference_frame_kind == wr::WrReferenceFrameKind::Zoom && + aContainerItem && + aContainerItem->GetType() == DisplayItemType::TYPE_ASYNC_ZOOM && + aContainerItem->Frame()) { + double resolution = aContainerItem->Frame()->PresShell()->GetResolution(); + gfx::Matrix transform = gfx::Matrix::Scaling(resolution, resolution); + + mInheritedTransform = transform * aParentSC.mInheritedTransform; + mScale = resolution * aParentSC.mScale; + + MOZ_ASSERT(!aParams.mAnimated); + mSnappingSurfaceTransform = transform * aParentSC.mSnappingSurfaceTransform; + + } else { + mInheritedTransform = aParentSC.mInheritedTransform; + mScale = aParentSC.mScale; + } + + auto rasterSpace = + mRasterizeLocally + ? wr::RasterSpace::Local(std::max(mScale.width, mScale.height)) + : wr::RasterSpace::Screen(); + + MOZ_ASSERT(!aParams.clip.IsNone()); + mReferenceFrameId = mBuilder->PushStackingContext( + aParams, wr::ToLayoutRect(aBounds), 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 = result * *mDeferredAncestorTransform; + } + return Some(result); + } else { + return Nothing(); + } +} + +} // namespace layers +} // namespace mozilla |