Bug 1473136: Cache mNeedsActiveLayer once for nsDisplayOpacity. r=mattwoodrow
MozReview-Commit-ID: 16cdOpAFtyu
--- a/layout/generic/nsFrame.cpp
+++ b/layout/generic/nsFrame.cpp
@@ -2947,24 +2947,26 @@ nsIFrame::BuildDisplayListForStackingCon
if (usingSVGEffects) {
dirtyRect =
nsSVGIntegrationUtils::GetRequiredSourceForInvalidArea(this, dirtyRect);
visibleRect =
nsSVGIntegrationUtils::GetRequiredSourceForInvalidArea(this, visibleRect);
aBuilder->EnterSVGEffectsContents(&hoistedScrollInfoItemsStorage);
}
+
+ bool needsActiveLayer = false;
// 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(effectSet) &&
!nsSVGUtils::CanOptimizeOpacity(this) &&
- (!usingSVGEffects || nsDisplayOpacity::NeedsActiveLayer(aBuilder, this));
+ ((needsActiveLayer = nsDisplayOpacity::NeedsActiveLayer(aBuilder, this)) || !usingSVGEffects);
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 &&
(nsLayoutUtils::IsFixedPosFrameInDisplayPort(this) || BuilderHasScrolledClip(aBuilder));
@@ -3254,19 +3256,20 @@ nsIFrame::BuildDisplayListForStackingCon
* effects, wrap it up in an opacity item.
*/
if (useOpacity) {
// Don't clip nsDisplayOpacity items. We clip their descendants instead.
// The clip we would set on an element with opacity would clip
// all descendant content, but some should not be clipped.
DisplayListClipState::AutoSaveRestore opacityClipState(aBuilder);
resultList.AppendToTop(
- MakeDisplayItem<nsDisplayOpacity>(aBuilder, this, &resultList,
+ MakeDisplayItem<nsDisplayOpacity>(aBuilder, this, &resultList,
containerItemASR,
- opacityItemForEventsAndPluginsOnly));
+ opacityItemForEventsAndPluginsOnly,
+ needsActiveLayer));
if (aCreatedContainerItem) {
*aCreatedContainerItem = true;
}
}
/* If we're going to apply a transformation and don't have preserve-3d set, wrap
* everything in an nsDisplayTransform. If there's nothing in the list, don't add
* anything.
--- a/layout/painting/nsDisplayList.cpp
+++ b/layout/painting/nsDisplayList.cpp
@@ -6232,21 +6232,23 @@ nsresult nsDisplayWrapper::WrapListsInPl
NS_ENSURE_SUCCESS(rv, rv);
// The outlines may not be in-flow
return WrapEachDisplayItem(aBuilder, aLists.Outlines(), this);
}
nsDisplayOpacity::nsDisplayOpacity(nsDisplayListBuilder* aBuilder,
nsIFrame* aFrame, nsDisplayList* aList,
const ActiveScrolledRoot* aActiveScrolledRoot,
- bool aForEventsAndPluginsOnly)
+ bool aForEventsAndPluginsOnly,
+ bool aNeedsActiveLayer)
: nsDisplayWrapList(aBuilder, aFrame, aList, aActiveScrolledRoot, true)
, mOpacity(aFrame->StyleEffects()->mOpacity)
, mForEventsAndPluginsOnly(aForEventsAndPluginsOnly)
, mChildOpacityState(ChildOpacityState::Unknown)
+ , mNeedsActiveLayer(aNeedsActiveLayer)
{
MOZ_COUNT_CTOR(nsDisplayOpacity);
mState.mOpacity = mOpacity;
}
#ifdef NS_BUILD_REFCNT_LOGGING
nsDisplayOpacity::~nsDisplayOpacity() {
MOZ_COUNT_DTOR(nsDisplayOpacity);
@@ -6429,17 +6431,17 @@ nsDisplayOpacity::ShouldFlattenAway(nsDi
{
if (mFrame->GetPrevContinuation() || mFrame->GetNextContinuation() ||
mFrame->HasAnyStateBits(NS_FRAME_PART_OF_IBSPLIT)) {
// If we've been split, then we might need to merge, so
// don't flatten us away.
return false;
}
- if (NeedsActiveLayer(aBuilder, mFrame) || mOpacity == 0.0) {
+ if (mNeedsActiveLayer || mOpacity == 0.0) {
// If our opacity is zero then we'll discard all descendant display items
// except for layer event regions, so there's no point in doing this
// optimization (and if we do do it, then invalidations of those descendants
// might trigger repainting).
return false;
}
if (mList.IsEmpty()) {
@@ -6459,17 +6461,17 @@ nsDisplayOpacity::GetLayerState(nsDispla
// If we only created this item so that we'd get correct nsDisplayEventRegions for child
// frames, then force us to inactive to avoid unnecessary layerization changes for content
// that won't ever be painted.
if (mForEventsAndPluginsOnly) {
MOZ_ASSERT(mOpacity == 0);
return LAYER_INACTIVE;
}
- if (NeedsActiveLayer(aBuilder, mFrame)) {
+ if (mNeedsActiveLayer) {
// Returns LAYER_ACTIVE_FORCE to avoid flatterning the layer for async
// animations.
return LAYER_ACTIVE_FORCE;
}
return RequiredLayerStateForChildren(aBuilder, aManager, aParameters, mList, GetAnimatedGeometryRoot());
}
--- a/layout/painting/nsDisplayList.h
+++ b/layout/painting/nsDisplayList.h
@@ -5116,24 +5116,26 @@ protected:
* The standard display item to paint a stacking context with translucency
* set by the stacking context root frame's 'opacity' style.
*/
class nsDisplayOpacity : public nsDisplayWrapList {
public:
nsDisplayOpacity(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
nsDisplayList* aList,
const ActiveScrolledRoot* aActiveScrolledRoot,
- bool aForEventsAndPluginsOnly);
+ bool aForEventsAndPluginsOnly,
+ bool aNeedsActiveLayer);
nsDisplayOpacity(nsDisplayListBuilder* aBuilder,
const nsDisplayOpacity& aOther)
: nsDisplayWrapList(aBuilder, aOther)
, mOpacity(aOther.mOpacity)
, mForEventsAndPluginsOnly(aOther.mForEventsAndPluginsOnly)
, mChildOpacityState(ChildOpacityState::Unknown)
+ , mNeedsActiveLayer(aOther.mNeedsActiveLayer)
{
// We should not try to merge flattened opacities.
MOZ_ASSERT(aOther.mChildOpacityState != ChildOpacityState::Applied);
}
#ifdef NS_BUILD_REFCNT_LOGGING
virtual ~nsDisplayOpacity();
#endif
@@ -5220,16 +5222,17 @@ private:
enum class ChildOpacityState : uint8_t {
// Our child list has changed since the last time ApplyOpacityToChildren was called.
Unknown,
// Our children defer opacity handling to us.
Deferred,
// Opacity is applied to our children.
Applied
};
+ bool mNeedsActiveLayer : 1;
#ifndef __GNUC__
ChildOpacityState mChildOpacityState : 2;
#else
ChildOpacityState mChildOpacityState;
#endif
struct {
float mOpacity;