--- a/layout/base/nsDisplayList.cpp
+++ b/layout/base/nsDisplayList.cpp
@@ -4716,17 +4716,17 @@ nsDisplayTransform::nsDisplayTransform(n
ComputeTransformFunction aTransformGetter,
uint32_t aIndex)
: nsDisplayItem(aBuilder, aFrame)
, mStoredList(aBuilder, aFrame, aList)
, mTransformGetter(aTransformGetter)
, mChildrenVisibleRect(aChildrenVisibleRect)
, mIndex(aIndex)
, mNoExtendContext(false)
- , mIsTransformSeparator(false)
+ , mHasPresetTransform(false)
, mTransformPreserves3DInited(false)
{
MOZ_COUNT_CTOR(nsDisplayTransform);
MOZ_ASSERT(aFrame, "Must have a frame!");
Init(aBuilder);
}
void
@@ -4737,17 +4737,16 @@ nsDisplayTransform::SetReferenceFrameToA
aBuilder->FindReferenceFrameFor(outerFrame);
mToReferenceFrame = mFrame->GetOffsetToCrossDoc(mReferenceFrame);
mVisibleRect = aBuilder->GetDirtyRect() + mToReferenceFrame;
}
void
nsDisplayTransform::Init(nsDisplayListBuilder* aBuilder)
{
- mHasBounds = false;
mStoredList.SetClip(aBuilder, DisplayItemClip::NoClip());
mStoredList.SetVisibleRect(mChildrenVisibleRect);
mMaybePrerender = ShouldPrerenderTransformedContent(aBuilder, mFrame);
const nsStyleDisplay* disp = mFrame->StyleDisplay();
if ((disp->mWillChangeBitField & NS_STYLE_WILL_CHANGE_TRANSFORM)) {
// We will only pre-render if this will-change is on budget.
mMaybePrerender = true;
@@ -4764,37 +4763,36 @@ nsDisplayTransform::nsDisplayTransform(n
const nsRect& aChildrenVisibleRect,
uint32_t aIndex)
: nsDisplayItem(aBuilder, aFrame)
, mStoredList(aBuilder, aFrame, aList)
, mTransformGetter(nullptr)
, mChildrenVisibleRect(aChildrenVisibleRect)
, mIndex(aIndex)
, mNoExtendContext(false)
- , mIsTransformSeparator(false)
+ , mHasPresetTransform(false)
, mTransformPreserves3DInited(false)
{
MOZ_COUNT_CTOR(nsDisplayTransform);
MOZ_ASSERT(aFrame, "Must have a frame!");
SetReferenceFrameToAncestor(aBuilder);
Init(aBuilder);
- UpdateBoundsFor3D(aBuilder);
}
nsDisplayTransform::nsDisplayTransform(nsDisplayListBuilder* aBuilder,
nsIFrame *aFrame, nsDisplayItem *aItem,
const nsRect& aChildrenVisibleRect,
uint32_t aIndex)
: nsDisplayItem(aBuilder, aFrame)
, mStoredList(aBuilder, aFrame, aItem)
, mTransformGetter(nullptr)
, mChildrenVisibleRect(aChildrenVisibleRect)
, mIndex(aIndex)
, mNoExtendContext(false)
- , mIsTransformSeparator(false)
+ , mHasPresetTransform(false)
, mTransformPreserves3DInited(false)
{
MOZ_COUNT_CTOR(nsDisplayTransform);
MOZ_ASSERT(aFrame, "Must have a frame!");
SetReferenceFrameToAncestor(aBuilder);
Init(aBuilder);
}
@@ -4805,23 +4803,22 @@ nsDisplayTransform::nsDisplayTransform(n
uint32_t aIndex)
: nsDisplayItem(aBuilder, aFrame)
, mStoredList(aBuilder, aFrame, aList)
, mTransform(aTransform)
, mTransformGetter(nullptr)
, mChildrenVisibleRect(aChildrenVisibleRect)
, mIndex(aIndex)
, mNoExtendContext(false)
- , mIsTransformSeparator(true)
+ , mHasPresetTransform(true)
, mTransformPreserves3DInited(false)
{
MOZ_COUNT_CTOR(nsDisplayTransform);
MOZ_ASSERT(aFrame, "Must have a frame!");
Init(aBuilder);
- UpdateBoundsFor3D(aBuilder);
}
/* Returns the delta specified by the transform-origin property.
* This is a positive delta, meaning that it indicates the direction to move
* to get from (0, 0) of the frame to the transform origin. This function is
* called off the main thread.
*/
/* static */ Point3D
@@ -5315,17 +5312,17 @@ nsDisplayTransform::GetTransform()
float scale = mFrame->PresContext()->AppUnitsPerDevPixel();
Point3D newOrigin =
Point3D(NSAppUnitsToFloatPixels(mToReferenceFrame.x, scale),
NSAppUnitsToFloatPixels(mToReferenceFrame.y, scale),
0.0f);
if (mTransformGetter) {
mTransform = mTransformGetter(mFrame, scale);
mTransform.ChangeBasis(newOrigin.x, newOrigin.y, newOrigin.z);
- } else if (!mIsTransformSeparator) {
+ } else if (!mHasPresetTransform) {
bool isReference =
mFrame->IsTransformed() ||
mFrame->Combines3DTransformWithAncestors() || mFrame->Extend3DContext();
/**
* Passing true as the final argument means that we want to shift the
* coordinates to be relative to our reference frame instead of relative
* to this frame.
* When we have preserve-3d, our reference frame is already guaranteed
@@ -5577,79 +5574,71 @@ nsDisplayTransform::GetHitDepthAtPoint(n
Point3D transformed = matrix * Point3D(point2d.x, point2d.y, 0);
return transformed.z;
}
/* The bounding rectangle for the object is the overflow rectangle translated
* by the reference point.
*/
-nsRect
-nsDisplayTransform::GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap)
-{
- *aSnap = false;
-
- if (mHasBounds) {
- return mBounds;
- }
-
- if (mFrame->Extend3DContext()) {
- return nsRect();
- }
-
- nsRect untransformedBounds = MaybePrerender() ?
- mFrame->GetVisualOverflowRectRelativeToSelf() :
- mStoredList.GetBounds(aBuilder, aSnap);
- // GetTransform always operates in dev pixels.
- float factor = mFrame->PresContext()->AppUnitsPerDevPixel();
- mBounds = nsLayoutUtils::MatrixTransformRect(untransformedBounds,
- GetTransform(),
- factor);
- mHasBounds = true;
- return mBounds;
-}
-
-void
-nsDisplayTransform::ComputeBounds(nsDisplayListBuilder* aBuilder)
-{
- MOZ_ASSERT(mFrame->Extend3DContext() || IsLeafOf3DContext());
-
+nsRect nsDisplayTransform::GetBounds(nsDisplayListBuilder *aBuilder, bool* aSnap)
+{
/* For some cases, the transform would make an empty bounds, but it
* may be turned back again to get a non-empty bounds. We should
* not depend on transforming bounds level by level.
*
* Here, it applies accumulated transforms on the leaf frames of the
* 3d rendering context, and track and accmulate bounds at
* nsDisplayListBuilder.
*/
nsDisplayListBuilder::AutoAccumulateTransform accTransform(aBuilder);
+ Maybe<nsDisplayListBuilder::AutoAccumulateRect> accRect;
+ bool startPreserves3D =
+ mFrame->Extend3DContext() && !mFrame->Combines3DTransformWithAncestors();
+
+ if (!mFrame->Combines3DTransformWithAncestors()) {
+ accTransform.StartRoot();
+ }
accTransform.Accumulate(GetTransform());
-
- if (!IsLeafOf3DContext()) {
- // Do not dive into another 3D context.
- mStoredList.DoUpdateBoundsPreserves3D(aBuilder);
+ if (startPreserves3D) {
+ accRect.emplace(aBuilder);
}
/* For Preserves3D, it is bounds of only children as leaf frames.
* For non-leaf frames, their bounds are accumulated and kept at
* nsDisplayListBuilder.
*/
- bool snap;
nsRect untransformedBounds = MaybePrerender() ?
mFrame->GetVisualOverflowRectRelativeToSelf() :
- mStoredList.GetBounds(aBuilder, &snap);
+ mStoredList.GetBounds(aBuilder, aSnap);
+ *aSnap = false;
// GetTransform always operates in dev pixels.
float factor = mFrame->PresContext()->AppUnitsPerDevPixel();
nsRect rect =
nsLayoutUtils::MatrixTransformRect(untransformedBounds,
accTransform.GetCurrentTransform(),
factor);
- aBuilder->AccumulateRect(rect);
+ if (mFrame->Combines3DTransformWithAncestors()) {
+ if (!mFrame->Extend3DContext() &&
+ !aBuilder->GetAccumulatedRectLevels()) {
+ // For preserve-3d, only leaf frames and frames start
+ // preserve-3d chain have non-empty bounds.
+ return rect;
+ }
+ aBuilder->AccumulateRect(rect);
+ return nsRect();
+ }
+
+ if (startPreserves3D) {
+ rect.UnionRect(rect, aBuilder->GetAccumulatedRect());
+ }
+
+ return rect;
}
/* The transform is opaque iff the transform consists solely of scales and
* translations and if the underlying content is opaque. Thus if the transform
* is of the form
*
* |a c e|
* |b d f|
--- a/layout/base/nsDisplayList.h
+++ b/layout/base/nsDisplayList.h
@@ -848,20 +848,16 @@ public:
};
void AccumulateRect(const nsRect& aRect) {
mPreserves3DCtx.mAccumulatedRect.UnionRect(mPreserves3DCtx.mAccumulatedRect, aRect);
}
const nsRect& GetAccumulatedRect() {
return mPreserves3DCtx.mAccumulatedRect;
}
- /**
- * The level is increased by one for items establishing 3D rendering
- * context and starting a new accumulation.
- */
int GetAccumulatedRectLevels() {
return mPreserves3DCtx.mAccumulatedRectLevels;
}
// Helpers for tables
nsDisplayTableItem* GetCurrentTableItem() { return mCurrentTableItem; }
void SetCurrentTableItem(nsDisplayTableItem* aTableItem) { mCurrentTableItem = aTableItem; }
@@ -1617,31 +1613,16 @@ public:
/**
* If this has a child list where the children are in the same coordinate
* system as this item (i.e., they have the same reference frame),
* return the list.
*/
virtual nsDisplayList* GetSameCoordinateSystemChildren() { return nullptr; }
virtual void UpdateBounds(nsDisplayListBuilder* aBuilder) {}
- /**
- * Do UpdateBounds() for items with frames establishing or extending
- * 3D rendering context.
- *
- * This function is called by UpdateBoundsFor3D() of
- * nsDisplayTransform(), and it is called by
- * BuildDisplayListForStackingContext() on transform items
- * establishing 3D rendering context.
- *
- * The bounds of a transform item with the frame establishing 3D
- * rendering context should be computed by calling
- * DoUpdateBoundsPreserves3D() on all descendants that participate
- * the same 3d rendering context.
- */
- virtual void DoUpdateBoundsPreserves3D(nsDisplayListBuilder* aBuilder) {}
/**
* If this has a child list, return it, even if the children are in
* a different coordinate system to this item.
*/
virtual nsDisplayList* GetChildren() { return nullptr; }
/**
@@ -3637,28 +3618,23 @@ class nsDisplayTransform: public nsDispl
StoreList(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
nsDisplayList* aList) :
nsDisplayWrapList(aBuilder, aFrame, aList) {}
StoreList(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
nsDisplayItem* aItem) :
nsDisplayWrapList(aBuilder, aFrame, aItem) {}
virtual ~StoreList() {}
- virtual void UpdateBounds(nsDisplayListBuilder* aBuilder) override {
- // For extending 3d rendering context, the bounds would be
- // updated by DoUpdateBoundsPreserves3D(), not here.
- if (!mFrame->Extend3DContext()) {
- nsDisplayWrapList::UpdateBounds(aBuilder);
- }
- }
- virtual void DoUpdateBoundsPreserves3D(nsDisplayListBuilder* aBuilder) override {
- for (nsDisplayItem *i = mList.GetBottom(); i; i = i->GetAbove()) {
- i->DoUpdateBoundsPreserves3D(aBuilder);
- }
+ virtual void UpdateBounds(nsDisplayListBuilder* aBuilder) override {}
+ virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder,
+ bool* aSnap) override {
+ // The bounds should not be computed until now, because we don't
+ // get accmulated transform before.
nsDisplayWrapList::UpdateBounds(aBuilder);
+ return nsDisplayWrapList::GetBounds(aBuilder, aSnap);
}
};
public:
/**
* Returns a matrix (in pixels) for the current frame. The matrix should be relative to
* the current frame's coordinate space.
*
@@ -3890,64 +3866,17 @@ public:
bool ShouldPrerender(nsDisplayListBuilder* aBuilder);
virtual void WriteDebugInfo(std::stringstream& aStream) override;
// Force the layer created for this item not to extend 3D context.
// See nsIFrame::BuildDisplayListForStackingContext()
void SetNoExtendContext() { mNoExtendContext = true; }
- virtual void DoUpdateBoundsPreserves3D(nsDisplayListBuilder* aBuilder) override {
- MOZ_ASSERT(mFrame->Combines3DTransformWithAncestors() ||
- IsTransformSeparator());
- // Updating is not going through to child 3D context.
- ComputeBounds(aBuilder);
- }
-
- /**
- * This function updates bounds for items with a frame establishing
- * 3D rendering context.
- *
- * \see nsDisplayItem::DoUpdateBoundsPreserves3D()
- */
- void UpdateBoundsFor3D(nsDisplayListBuilder* aBuilder) {
- if (!mFrame->Extend3DContext() ||
- mFrame->Combines3DTransformWithAncestors() ||
- IsTransformSeparator()) {
- // Not an establisher of a 3D rendering context.
- return;
- }
- // Always start updating from an establisher of a 3D rendering context.
-
- nsDisplayListBuilder::AutoAccumulateRect accRect(aBuilder);
- nsDisplayListBuilder::AutoAccumulateTransform accTransform(aBuilder);
- accTransform.StartRoot();
- ComputeBounds(aBuilder);
- mBounds = aBuilder->GetAccumulatedRect();
- mHasBounds = true;
- }
-
- /**
- * This item is an additional item as the boundary between parent
- * and child 3D rendering context.
- * \see nsIFrame::BuildDisplayListForStackingContext().
- */
- bool IsTransformSeparator() { return mIsTransformSeparator; }
- /**
- * This item is the boundary between parent and child 3D rendering
- * context.
- */
- bool IsLeafOf3DContext() {
- return (IsTransformSeparator() ||
- (!mFrame->Extend3DContext() &&
- mFrame->Combines3DTransformWithAncestors()));
- }
-
private:
- void ComputeBounds(nsDisplayListBuilder* aBuilder);
void SetReferenceFrameToAncestor(nsDisplayListBuilder* aBuilder);
void Init(nsDisplayListBuilder* aBuilder);
static Matrix4x4 GetResultingTransformMatrixInternal(const FrameTransformProperties& aProperties,
const nsPoint& aOrigin,
float aAppUnitsPerPixel,
const nsRect* aBoundsOverride,
nsIFrame** aOutAncestor,
@@ -3956,32 +3885,28 @@ private:
StoreList mStoredList;
Matrix4x4 mTransform;
// Accumulated transform of ancestors on the preserves-3d chain.
Matrix4x4 mTransformPreserves3D;
ComputeTransformFunction mTransformGetter;
nsRect mChildrenVisibleRect;
uint32_t mIndex;
- nsRect mBounds;
- // True for mBounds is valid.
- bool mHasBounds;
// We wont know if we pre-render until the layer building phase where we can
// check layers will-change budget.
bool mMaybePrerender;
// Be forced not to extend 3D context. Since we don't create a
// transform item, a container layer, for every frames in a
// preserves3d context, the transform items of a child preserves3d
// context may extend the parent context not intented if the root of
// the child preserves3d context doesn't create a transform item.
// With this flags, we force the item not extending 3D context.
bool mNoExtendContext;
- // This item is a separator between 3D rendering contexts, and
// mTransform have been presetted by the constructor.
- bool mIsTransformSeparator;
+ bool mHasPresetTransform;
// True if mTransformPreserves3D have been initialized.
bool mTransformPreserves3DInited;
};
/**
* This class adds basic support for limiting the rendering (in the inline axis
* of the writing mode) to the part inside the specified edges. It's a base
* class for the display item classes that do the actual work.