summaryrefslogtreecommitdiffstats
path: root/gfx/layers/wr/StackingContextHelper.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'gfx/layers/wr/StackingContextHelper.cpp')
-rw-r--r--gfx/layers/wr/StackingContextHelper.cpp150
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