Bug 1205475 - Part 2. Prevent multiple EffectSet property look up.
Functions like BuildDisplayListForStackingContext or BuildDisplayListForChild look
up EffectSet property several times in callees, such as IsTransformed() or
HasOpacity(), which is time wasting.
We should look up EffectSet just once, and pass the found one to all callees
that need it.
MozReview-Commit-ID: GZywm2UcpU7
--- a/layout/base/nsLayoutUtils.cpp
+++ b/layout/base/nsLayoutUtils.cpp
@@ -526,34 +526,40 @@ MayHaveAnimationOfProperty(EffectSet* ef
!effects->MayHaveOpacityAnimation()) {
return false;
}
return true;
}
bool
-nsLayoutUtils::HasAnimationOfProperty(const nsIFrame* aFrame,
+nsLayoutUtils::HasAnimationOfProperty(EffectSet* aEffectSet,
nsCSSPropertyID aProperty)
{
- EffectSet* effects = EffectSet::GetEffectSet(aFrame);
- if (!effects || !MayHaveAnimationOfProperty(effects, aProperty)) {
+ if (!aEffectSet || !MayHaveAnimationOfProperty(aEffectSet, aProperty)) {
return false;
}
- return HasMatchingAnimations(effects,
+ return HasMatchingAnimations(aEffectSet,
[&aProperty](KeyframeEffectReadOnly& aEffect)
{
return (aEffect.IsInEffect() || aEffect.IsCurrent()) &&
aEffect.HasAnimationOfProperty(aProperty);
}
);
}
bool
+nsLayoutUtils::HasAnimationOfProperty(const nsIFrame* aFrame,
+ nsCSSPropertyID aProperty)
+{
+ return HasAnimationOfProperty(EffectSet::GetEffectSet(aFrame), aProperty);
+}
+
+bool
nsLayoutUtils::HasEffectiveAnimation(const nsIFrame* aFrame,
nsCSSPropertyID aProperty)
{
EffectSet* effects = EffectSet::GetEffectSet(aFrame);
if (!effects || !MayHaveAnimationOfProperty(effects, aProperty)) {
return false;
}
--- a/layout/base/nsLayoutUtils.h
+++ b/layout/base/nsLayoutUtils.h
@@ -66,16 +66,17 @@ struct nsOverflowAreas;
namespace mozilla {
enum class CSSPseudoElementType : uint8_t;
class EventListenerManager;
enum class LayoutFrameType : uint8_t;
struct IntrinsicSize;
struct ContainerLayerParameters;
class WritingMode;
class DisplayItemClip;
+class EffectSet;
namespace dom {
class CanvasRenderingContext2D;
class DOMRectList;
class Element;
class HTMLImageElement;
class HTMLCanvasElement;
class HTMLVideoElement;
class OffscreenCanvas;
@@ -2251,16 +2252,23 @@ public:
/**
* Returns true if |aFrame| has an animation of |aProperty| regardless of
* whether the property is overridden by !important rule.
*/
static bool HasAnimationOfProperty(const nsIFrame* aFrame,
nsCSSPropertyID aProperty);
/**
+ * Returns true if |aEffectSet| has an animation of |aProperty| regardless of
+ * whether the property is overridden by !important rule.
+ */
+ static bool HasAnimationOfProperty(mozilla::EffectSet* aEffectSet,
+ nsCSSPropertyID aProperty);
+
+ /**
* Returns true if |aFrame| has an animation of |aProperty| which is
* not overridden by !important rules.
*/
static bool HasEffectiveAnimation(const nsIFrame* aFrame,
nsCSSPropertyID aProperty);
/**
* Checks if off-main-thread animations are enabled.
--- a/layout/generic/nsFrame.cpp
+++ b/layout/generic/nsFrame.cpp
@@ -1300,100 +1300,112 @@ nsIFrame::GetMarginRectRelativeToSelf()
nsMargin m = GetUsedMargin();
m.ApplySkipSides(GetSkipSides());
nsRect r(0, 0, mRect.width, mRect.height);
r.Inflate(m);
return r;
}
bool
-nsIFrame::IsTransformed(const nsStyleDisplay* aStyleDisplay) const
+nsIFrame::IsTransformed(const nsStyleDisplay* aStyleDisplay,
+ EffectSet* aEffectSet) const
{
MOZ_ASSERT(aStyleDisplay == StyleDisplay());
return ((mState & NS_FRAME_MAY_BE_TRANSFORMED) &&
(aStyleDisplay->HasTransform(this) ||
IsSVGTransformed() ||
- HasAnimationOfTransform()));
+ HasAnimationOfTransform(aEffectSet)));
}
bool
-nsIFrame::HasAnimationOfTransform() const
-{
+nsIFrame::HasAnimationOfTransform(EffectSet* aEffectSet) const
+{
+ EffectSet* effects =
+ aEffectSet ? aEffectSet : EffectSet::GetEffectSet(this);
+
return mContent &&
- nsLayoutUtils::HasAnimationOfProperty(this, eCSSProperty_transform) &&
+ nsLayoutUtils::HasAnimationOfProperty(effects, eCSSProperty_transform) &&
IsFrameOfType(eSupportsCSSTransforms) &&
mContent->GetPrimaryFrame() == this;
}
bool
-nsIFrame::HasOpacityInternal(float aThreshold) const
+nsIFrame::HasOpacityInternal(float aThreshold,
+ EffectSet* aEffectSet) const
{
MOZ_ASSERT(0.0 <= aThreshold && aThreshold <= 1.0, "Invalid argument");
- return StyleEffects()->mOpacity < aThreshold ||
- (StyleDisplay()->mWillChangeBitField & NS_STYLE_WILL_CHANGE_OPACITY) ||
- (mContent &&
- nsLayoutUtils::HasAnimationOfProperty(this, eCSSProperty_opacity) &&
- mContent->GetPrimaryFrame() == this);
+ if (StyleEffects()->mOpacity < aThreshold ||
+ (StyleDisplay()->mWillChangeBitField & NS_STYLE_WILL_CHANGE_OPACITY)) {
+ return true;
+ }
+
+ EffectSet* effects =
+ aEffectSet ? aEffectSet : EffectSet::GetEffectSet(this);
+ return (mContent && mContent->GetPrimaryFrame() == this &&
+ nsLayoutUtils::HasAnimationOfProperty(effects, eCSSProperty_opacity));
}
bool
nsIFrame::IsSVGTransformed(gfx::Matrix *aOwnTransforms,
gfx::Matrix *aFromParentTransforms) const
{
return false;
}
bool
-nsIFrame::Extend3DContext(const nsStyleDisplay* aStyleDisplay) const
+nsIFrame::Extend3DContext(const nsStyleDisplay* aStyleDisplay, mozilla::EffectSet* aEffectSet) const
{
const nsStyleDisplay* disp = StyleDisplayWithOptionalParam(aStyleDisplay);
if (disp->mTransformStyle != NS_STYLE_TRANSFORM_STYLE_PRESERVE_3D ||
!IsFrameOfType(nsIFrame::eSupportsCSSTransforms)) {
return false;
}
// If we're all scroll frame, then all descendants will be clipped, so we can't preserve 3d.
if (IsScrollFrame()) {
return false;
}
- if (HasOpacity()) {
+ if (HasOpacity(aEffectSet)) {
return false;
}
const nsStyleEffects* effects = StyleEffects();
return !nsFrame::ShouldApplyOverflowClipping(this, disp) &&
!GetClipPropClipRect(disp, effects, GetSize()) &&
!nsSVGIntegrationUtils::UsingEffectsForFrame(this);
}
bool
-nsIFrame::Combines3DTransformWithAncestors(const nsStyleDisplay* aStyleDisplay) const
+nsIFrame::Combines3DTransformWithAncestors(const nsStyleDisplay* aStyleDisplay,
+ EffectSet* aEffectSet) const
{
MOZ_ASSERT(aStyleDisplay == StyleDisplay());
- if (!GetParent() || !GetParent()->Extend3DContext()) {
+ if (!GetParent() || !GetParent()->Extend3DContext(aEffectSet)) {
return false;
}
- return IsTransformed(aStyleDisplay) || BackfaceIsHidden(aStyleDisplay);
+ return IsTransformed(aStyleDisplay,aEffectSet) ||
+ BackfaceIsHidden(aStyleDisplay);
}
bool
-nsIFrame::In3DContextAndBackfaceIsHidden() const
+nsIFrame::In3DContextAndBackfaceIsHidden(EffectSet* aEffectSet) const
{
// While both tests fail most of the time, test BackfaceIsHidden()
// first since it's likely to fail faster.
const nsStyleDisplay* disp = StyleDisplay();
- return BackfaceIsHidden(disp) && Combines3DTransformWithAncestors(disp);
+ return BackfaceIsHidden(disp) &&
+ Combines3DTransformWithAncestors(disp, aEffectSet);
}
bool
-nsIFrame::HasPerspective(const nsStyleDisplay* aStyleDisplay) const
+nsIFrame::HasPerspective(const nsStyleDisplay* aStyleDisplay, EffectSet* aEffectSet) const
{
MOZ_ASSERT(aStyleDisplay == StyleDisplay());
- if (!IsTransformed(aStyleDisplay)) {
+ if (!IsTransformed(aStyleDisplay, aEffectSet)) {
return false;
}
nsIFrame* containingBlock = GetContainingBlock(SKIP_SCROLLED_FRAME, aStyleDisplay);
if (!containingBlock) {
return false;
}
return containingBlock->ChildrenHavePerspective();
}
@@ -2343,59 +2355,60 @@ nsIFrame::BuildDisplayListForStackingCon
// Replaced elements have their visibility handled here, because
// they're visually atomic
if (IsFrameOfType(eReplaced) && !IsVisibleForPainting(aBuilder))
return;
const nsStyleDisplay* disp = StyleDisplay();
const nsStyleEffects* effects = StyleEffects();
+ EffectSet* effectSet = EffectSet::GetEffectSet(this);
// We can stop right away if this is a zero-opacity stacking context and
// we're painting, and we're not animating opacity. Don't do this
// if we're going to compute plugin geometry, since opacity-0 plugins
// need to have display items built for them.
bool needEventRegions =
aBuilder->IsBuildingLayerEventRegions() &&
StyleUserInterface()->GetEffectivePointerEvents(this) !=
NS_STYLE_POINTER_EVENTS_NONE;
bool opacityItemForEventsAndPluginsOnly = false;
if (effects->mOpacity == 0.0 && aBuilder->IsForPainting() &&
!(disp->mWillChangeBitField & NS_STYLE_WILL_CHANGE_OPACITY) &&
- !nsLayoutUtils::HasAnimationOfProperty(this, eCSSProperty_opacity)) {
+ !nsLayoutUtils::HasAnimationOfProperty(effectSet, eCSSProperty_opacity)) {
if (needEventRegions ||
aBuilder->WillComputePluginGeometry()) {
opacityItemForEventsAndPluginsOnly = true;
} else {
return;
}
}
if (disp->mWillChangeBitField != 0) {
aBuilder->AddToWillChangeBudget(this, GetSize());
}
- bool extend3DContext = Extend3DContext(disp);
+ bool extend3DContext = Extend3DContext(disp, effectSet);
Maybe<nsDisplayListBuilder::AutoPreserves3DContext> autoPreserves3DContext;
if (extend3DContext && !Combines3DTransformWithAncestors(disp)) {
// Start a new preserves3d context to keep informations on
// nsDisplayListBuilder.
autoPreserves3DContext.emplace(aBuilder);
// Save dirty rect on the builder to avoid being distorted for
// multiple transforms along the chain.
aBuilder->SetPreserves3DDirtyRect(aDirtyRect);
}
// For preserves3d, use the dirty rect already installed on the
// builder, since aDirtyRect maybe distorted for transforms along
// the chain.
nsRect dirtyRect = aDirtyRect;
bool inTransform = aBuilder->IsInTransform();
- bool isTransformed = IsTransformed(disp);
- bool hasPerspective = HasPerspective();
+ bool isTransformed = IsTransformed(disp, effectSet);
+ bool hasPerspective = HasPerspective(effectSet);
// reset blend mode so we can keep track if this stacking context needs have
// a nsDisplayBlendContainer. Set the blend mode back when the routine exits
// so we keep track if the parent stacking context needs a container too.
AutoSaveRestoreContainsBlendMode autoRestoreBlendMode(*aBuilder);
aBuilder->SetContainsBlendMode(false);
nsRect dirtyRectOutsideTransform = dirtyRect;
bool allowAsyncAnimation = false;
@@ -2446,17 +2459,18 @@ nsIFrame::BuildDisplayListForStackingCon
aBuilder->EnterSVGEffectsContents(&hoistedScrollInfoItemsStorage);
}
// We build an opacity item if it's not going to be drawn by SVG content, or
// SVG effects. SVG effects won't handle the opacity if we want an active
// layer (for async animations), see
// nsSVGIntegrationsUtils::PaintMaskAndClipPath or
// nsSVGIntegrationsUtils::PaintFilter.
- bool useOpacity = HasVisualOpacity() && !nsSVGUtils::CanOptimizeOpacity(this) &&
+ bool useOpacity = HasVisualOpacity(effectSet) &&
+ !nsSVGUtils::CanOptimizeOpacity(this) &&
(!usingSVGEffects || nsDisplayOpacity::NeedsActiveLayer(aBuilder, this));
bool useBlendMode = effects->mMixBlendMode != NS_STYLE_BLEND_NORMAL;
bool useStickyPosition = disp->mPosition == NS_STYLE_POSITION_STICKY &&
IsScrollFrameActive(aBuilder,
nsLayoutUtils::GetNearestScrollableFrame(GetParent(),
nsLayoutUtils::SCROLLABLE_SAME_DOC |
nsLayoutUtils::SCROLLABLE_INCLUDE_HIDDEN));
bool useFixedPosition = disp->mPosition == NS_STYLE_POSITION_FIXED &&
@@ -3063,21 +3077,22 @@ nsIFrame::BuildDisplayListForChild(nsDis
// within the displayport.
if (aBuilder->IsPaintingToWindow() && child->TrackingVisibility()) {
child->PresContext()->PresShell()->EnsureFrameInApproximatelyVisibleList(child);
awayFromCommonPath = true;
}
// Child is composited if it's transformed, partially transparent, or has
// SVG effects or a blend mode..
+ EffectSet* effectSet = EffectSet::GetEffectSet(this);
const nsStyleDisplay* disp = child->StyleDisplay();
const nsStyleEffects* effects = child->StyleEffects();
const nsStylePosition* pos = child->StylePosition();
- bool isVisuallyAtomic = child->HasOpacity()
- || child->IsTransformed(disp)
+ bool isVisuallyAtomic = child->HasOpacity(effectSet)
+ || child->IsTransformed(disp, effectSet)
// strictly speaking, 'perspective' doesn't require visual atomicity,
// but the spec says it acts like the rest of these
|| disp->mChildPerspective.GetUnit() == eStyleUnit_Coord
|| effects->mMixBlendMode != NS_STYLE_BLEND_NORMAL
|| nsSVGIntegrationUtils::UsingEffectsForFrame(child);
bool isPositioned = disp->IsAbsPosContainingBlock(child);
bool isStackingContext =
@@ -8957,17 +8972,18 @@ bool
nsIFrame::FinishAndStoreOverflow(nsOverflowAreas& aOverflowAreas,
nsSize aNewSize, nsSize* aOldSize,
const nsStyleDisplay* aStyleDisplay)
{
MOZ_ASSERT(FrameMaintainsOverflow(),
"Don't call - overflow rects not maintained on these SVG frames");
const nsStyleDisplay* disp = StyleDisplayWithOptionalParam(aStyleDisplay);
- bool hasTransform = IsTransformed(disp);
+ EffectSet* effectSet = EffectSet::GetEffectSet(this);
+ bool hasTransform = IsTransformed(disp, effectSet);
nsRect bounds(nsPoint(0, 0), aNewSize);
// Store the passed in overflow area if we are a preserve-3d frame or we have
// a transform, and it's not just the frame bounds.
if (hasTransform || Combines3DTransformWithAncestors(disp)) {
if (!aOverflowAreas.VisualOverflow().IsEqualEdges(bounds) ||
!aOverflowAreas.ScrollableOverflow().IsEqualEdges(bounds)) {
nsOverflowAreas* initial =
@@ -9070,17 +9086,17 @@ nsIFrame::FinishAndStoreOverflow(nsOverf
/* Since our size might not actually have been computed yet, we need to make sure that we use the
* correct dimensions by overriding the stored bounding rectangle with the value the caller has
* ensured us we'll use.
*/
SetSize(aNewSize);
if (ChildrenHavePerspective(disp) && sizeChanged) {
nsRect newBounds(nsPoint(0, 0), aNewSize);
- RecomputePerspectiveChildrenOverflow(this);
+ RecomputePerspectiveChildrenOverflow(this, effectSet);
}
if (hasTransform) {
Properties().Set(nsIFrame::PreTransformOverflowAreasProperty(),
new nsOverflowAreas(aOverflowAreas));
if (Combines3DTransformWithAncestors(disp)) {
/* If we're a preserve-3d leaf frame, then our pre-transform overflow should be correct. Our
@@ -9095,17 +9111,17 @@ nsIFrame::FinishAndStoreOverflow(nsOverf
nsRect& o = aOverflowAreas.Overflow(otype);
o = nsDisplayTransform::TransformRect(o, this);
}
/* If we're the root of the 3d context, then we want to include the overflow areas of all
* the participants. This won't have happened yet as the code above set their overflow
* area to empty. Manually collect these overflow areas now.
*/
- if (Extend3DContext(disp)) {
+ if (Extend3DContext(disp, effectSet)) {
ComputePreserve3DChildrenOverflow(aOverflowAreas);
}
}
} else {
Properties().Delete(nsIFrame::PreTransformOverflowAreasProperty());
}
/* Revert the size change in case some caller is depending on this. */
@@ -9120,27 +9136,28 @@ nsIFrame::FinishAndStoreOverflow(nsOverf
if (anyOverflowChanged) {
nsSVGEffects::InvalidateDirectRenderingObservers(this);
}
return anyOverflowChanged;
}
void
-nsIFrame::RecomputePerspectiveChildrenOverflow(const nsIFrame* aStartFrame)
+nsIFrame::RecomputePerspectiveChildrenOverflow(const nsIFrame* aStartFrame,
+ EffectSet* aEffectSet)
{
nsIFrame::ChildListIterator lists(this);
for (; !lists.IsDone(); lists.Next()) {
nsFrameList::Enumerator childFrames(lists.CurrentList());
for (; !childFrames.AtEnd(); childFrames.Next()) {
nsIFrame* child = childFrames.get();
if (!child->FrameMaintainsOverflow()) {
continue; // frame does not maintain overflow rects
}
- if (child->HasPerspective()) {
+ if (child->HasPerspective(aEffectSet)) {
nsOverflowAreas* overflow =
child->Properties().Get(nsIFrame::InitialOverflowProperty());
nsRect bounds(nsPoint(0, 0), child->GetSize());
if (overflow) {
nsOverflowAreas overflowCopy = *overflow;
child->FinishAndStoreOverflow(overflowCopy, bounds.Size());
} else {
nsOverflowAreas boundsOverflow;
@@ -9148,17 +9165,17 @@ nsIFrame::RecomputePerspectiveChildrenOv
child->FinishAndStoreOverflow(boundsOverflow, bounds.Size());
}
} else if (child->GetContainingBlock(SKIP_SCROLLED_FRAME) == aStartFrame) {
// If a frame is using perspective, then the size used to compute
// perspective-origin is the size of the frame belonging to its parent
// style context. We must find any descendant frames using our size
// (by recursing into frames that have the same containing block)
// to update their overflow rects too.
- child->RecomputePerspectiveChildrenOverflow(aStartFrame);
+ child->RecomputePerspectiveChildrenOverflow(aStartFrame, aEffectSet);
}
}
}
}
void
nsIFrame::ComputePreserve3DChildrenOverflow(nsOverflowAreas& aOverflowAreas)
{
--- a/layout/generic/nsIFrame.h
+++ b/layout/generic/nsIFrame.h
@@ -95,16 +95,17 @@ struct CharacterDataChangeInfo;
namespace mozilla {
enum class CSSPseudoElementType : uint8_t;
class EventStates;
struct ReflowInput;
class ReflowOutput;
class ServoStyleSet;
class DisplayItemData;
+class EffectSet;
namespace layers {
class Layer;
} // namespace layers
namespace gfx {
class Matrix;
} // namespace gfx
@@ -1665,44 +1666,59 @@ public:
/**
* Returns true if this frame is transformed (e.g. has CSS or SVG transforms)
* or if its parent is an SVG frame that has children-only transforms (e.g.
* an SVG viewBox attribute) or if its transform-style is preserve-3d or
* the frame has transform animations.
*
* @param aStyleDisplay: If the caller has this->StyleDisplay(), providing
* it here will improve performance.
+ * @param aEffectSet: This function may need to look up EffectSet property.
+ * If a caller already have one, pass it in can save property look up
+ * time; otherwise, just left it as nullptr.
*/
- bool IsTransformed(const nsStyleDisplay* aStyleDisplay) const;
- bool IsTransformed() const {
- return IsTransformed(StyleDisplay());
+ bool IsTransformed(const nsStyleDisplay* aStyleDisplay, mozilla::EffectSet* aEffectSet = nullptr) const;
+ bool IsTransformed(mozilla::EffectSet* aEffectSet = nullptr) const {
+ return IsTransformed(StyleDisplay(), aEffectSet);
}
/**
* True if this frame has any animation of transform in effect.
+ *
+ * @param aEffectSet: This function may need to look up EffectSet property.
+ * If a caller already have one, pass it in can save property look up
+ * time; otherwise, just left it as nullptr.
*/
- bool HasAnimationOfTransform() const;
+ bool HasAnimationOfTransform(mozilla::EffectSet* aEffectSet = nullptr) const;
/**
* Returns true if the frame is translucent or the frame has opacity
* animations for the purposes of creating a stacking context.
+ *
+ * @param aEffectSet: This function may need to look up EffectSet property.
+ * If a caller already have one, pass it in can save property look up
+ * time; otherwise, just left it as nullptr.
*/
- bool HasOpacity() const
+ bool HasOpacity(mozilla::EffectSet* aEffectSet = nullptr) const
{
- return HasOpacityInternal(1.0f);
+ return HasOpacityInternal(1.0f, aEffectSet);
}
/**
* Returns true if the frame is translucent for display purposes.
+ *
+ * @param aEffectSet: This function may need to look up EffectSet property.
+ * If a caller already have one, pass it in can save property look up
+ * time; otherwise, just left it as nullptr.
*/
- bool HasVisualOpacity() const
+ bool HasVisualOpacity(mozilla::EffectSet* aEffectSet = nullptr) const
{
// Treat an opacity value of 0.99 and above as opaque. This is an
// optimization aimed at Web content which use opacity:0.99 as a hint for
// creating a stacking context only.
- return HasOpacityInternal(0.99f);
+ return HasOpacityInternal(0.99f, aEffectSet);
}
/**
* Return true if this frame might be using a transform getter.
*/
virtual bool HasTransformGetter() const { return false; }
/**
@@ -1719,70 +1735,86 @@ public:
/**
* Returns whether this frame will attempt to extend the 3d transforms of its
* children. This requires transform-style: preserve-3d, as well as no clipping
* or svg effects.
*
* @param aStyleDisplay: If the caller has this->StyleDisplay(), providing
* it here will improve performance.
+ *
+ * @param aEffectSet: This function may need to look up EffectSet property.
+ * If a caller already have one, pass it in can save property look up
+ * time; otherwise, just left it as nullptr.
*/
- bool Extend3DContext(const nsStyleDisplay* aStyleDisplay) const;
- bool Extend3DContext() const {
- return Extend3DContext(StyleDisplay());
+ bool Extend3DContext(const nsStyleDisplay* aStyleDisplay,
+ mozilla::EffectSet* aEffectSet = nullptr) const;
+ bool Extend3DContext(mozilla::EffectSet* aEffectSet = nullptr) const {
+ return Extend3DContext(StyleDisplay(), aEffectSet);
}
/**
* Returns whether this frame has a parent that Extend3DContext() and has
* its own transform (or hidden backface) to be combined with the parent's
* transform.
*
* @param aStyleDisplay: If the caller has this->StyleDisplay(), providing
* it here will improve performance.
+ * @param aEffectSet: This function may need to look up EffectSet property.
+ * If a caller already have one, pass it in can save property look up
+ * time; otherwise, just left it as nullptr.
*/
- bool Combines3DTransformWithAncestors(const nsStyleDisplay* aStyleDisplay) const;
- bool Combines3DTransformWithAncestors() const {
- return Combines3DTransformWithAncestors(StyleDisplay());
+ bool Combines3DTransformWithAncestors(const nsStyleDisplay* aStyleDisplay,
+ mozilla::EffectSet* aEffectSet = nullptr) const;
+ bool Combines3DTransformWithAncestors(mozilla::EffectSet* aEffectSet = nullptr) const {
+ return Combines3DTransformWithAncestors(StyleDisplay(), aEffectSet);
}
/**
* Returns whether this frame has a hidden backface and has a parent that
* Extend3DContext(). This is useful because in some cases the hidden
* backface can safely be ignored if it could not be visible anyway.
+ *
+ * @param aEffectSet: This function may need to look up EffectSet property.
+ * If a caller already have one, pass it in can save property look up
+ * time; otherwise, just left it as nullptr.
*/
- bool In3DContextAndBackfaceIsHidden() const;
-
- bool IsPreserve3DLeaf(const nsStyleDisplay* aStyleDisplay) const {
+ bool In3DContextAndBackfaceIsHidden(mozilla::EffectSet* aEffectSet = nullptr) const;
+
+ bool IsPreserve3DLeaf(const nsStyleDisplay* aStyleDisplay,
+ mozilla::EffectSet* aEffectSet = nullptr) const {
return Combines3DTransformWithAncestors(aStyleDisplay) &&
- !Extend3DContext(aStyleDisplay);
+ !Extend3DContext(aStyleDisplay, aEffectSet);
}
- bool IsPreserve3DLeaf() const {
- return IsPreserve3DLeaf(StyleDisplay());
+ bool IsPreserve3DLeaf(mozilla::EffectSet* aEffectSet = nullptr) const {
+ return IsPreserve3DLeaf(StyleDisplay(), aEffectSet);
}
- bool HasPerspective(const nsStyleDisplay* aStyleDisplay) const;
- bool HasPerspective() const {
- return HasPerspective(StyleDisplay());
+ bool HasPerspective(const nsStyleDisplay* aStyleDisplay,
+ mozilla::EffectSet* aEffectSet = nullptr) const;
+ bool HasPerspective(mozilla::EffectSet* aEffectSet = nullptr) const {
+ return HasPerspective(StyleDisplay(), aEffectSet);
}
bool ChildrenHavePerspective(const nsStyleDisplay* aStyleDisplay) const {
MOZ_ASSERT(aStyleDisplay == StyleDisplay());
return aStyleDisplay->HasPerspectiveStyle();
}
bool ChildrenHavePerspective() const {
return ChildrenHavePerspective(StyleDisplay());
}
/**
* Includes the overflow area of all descendants that participate in the current
* 3d context into aOverflowAreas.
*/
void ComputePreserve3DChildrenOverflow(nsOverflowAreas& aOverflowAreas);
- void RecomputePerspectiveChildrenOverflow(const nsIFrame* aStartFrame);
+ void RecomputePerspectiveChildrenOverflow(const nsIFrame* aStartFrame,
+ mozilla::EffectSet* aEffectSet = nullptr);
/**
* Returns the number of ancestors between this and the root of our frame tree
*/
uint32_t GetDepthInFrameTree() const;
/**
* Event handling of GUI events.
@@ -3969,17 +4001,18 @@ private:
// Helper-functions for SortFrameList():
template<bool IsLessThanOrEqual(nsIFrame*, nsIFrame*)>
static nsIFrame* SortedMerge(nsIFrame *aLeft, nsIFrame *aRight);
template<bool IsLessThanOrEqual(nsIFrame*, nsIFrame*)>
static nsIFrame* MergeSort(nsIFrame *aSource);
- bool HasOpacityInternal(float aThreshold) const;
+ bool HasOpacityInternal(float aThreshold,
+ mozilla::EffectSet* aEffectSet = nullptr) const;
#ifdef DEBUG_FRAME_DUMP
public:
static void IndentBy(FILE* out, int32_t aIndent) {
while (--aIndent >= 0) fputs(" ", out);
}
void ListTag(FILE* out) const {
ListTag(out, this);