From ceb5b81a1a0910d8c3f051114f41ec3ccdd20a44 Mon Sep 17 00:00:00 2001 From: Matt Woodrow Date: Tue, 13 Nov 2012 22:26:29 -0800 Subject: [PATCH] Bug 808491 - Force 3d transformed layers to always be active. r=roc --- layout/base/nsDisplayList.cpp | 52 ++++++++++++++++++++--------------- layout/base/nsDisplayList.h | 10 +++---- 2 files changed, 35 insertions(+), 27 deletions(-) diff --git a/layout/base/nsDisplayList.cpp b/layout/base/nsDisplayList.cpp index 1ead55289e1..a0007353de9 100644 --- a/layout/base/nsDisplayList.cpp +++ b/layout/base/nsDisplayList.cpp @@ -2619,30 +2619,36 @@ void nsDisplayWrapList::Paint(nsDisplayListBuilder* aBuilder, NS_ERROR("nsDisplayWrapList should have been flattened away for painting"); } -bool nsDisplayWrapList::ChildrenCanBeInactive(nsDisplayListBuilder* aBuilder, - LayerManager* aManager, - const ContainerParameters& aParameters, - const nsDisplayList& aList, - nsIFrame* aActiveScrolledRoot) { +LayerState +nsDisplayWrapList::RequiredLayerStateForChildren(nsDisplayListBuilder* aBuilder, + LayerManager* aManager, + const ContainerParameters& aParameters, + const nsDisplayList& aList, + nsIFrame* aActiveScrolledRoot) { + LayerState result = LAYER_INACTIVE; for (nsDisplayItem* i = aList.GetBottom(); i; i = i->GetAbove()) { nsIFrame* f = i->GetUnderlyingFrame(); if (f) { nsIFrame* activeScrolledRoot = nsLayoutUtils::GetActiveScrolledRootFor(f, nullptr); - if (activeScrolledRoot != aActiveScrolledRoot) - return false; + if (activeScrolledRoot != aActiveScrolledRoot && result == LAYER_INACTIVE) + result = LAYER_ACTIVE; } LayerState state = i->GetLayerState(aBuilder, aManager, aParameters); - if (state == LAYER_ACTIVE || state == LAYER_ACTIVE_FORCE) - return false; + if ((state == LAYER_ACTIVE || state == LAYER_ACTIVE_FORCE) && (state > result)) + result = state; if (state == LAYER_NONE) { nsDisplayList* list = i->GetSameCoordinateSystemChildren(); - if (list && !ChildrenCanBeInactive(aBuilder, aManager, aParameters, *list, aActiveScrolledRoot)) - return false; + if (list) { + LayerState childState = RequiredLayerStateForChildren(aBuilder, aManager, aParameters, *list, aActiveScrolledRoot); + if (childState > result) { + result = childState; + } + } } } - return true; + return result; } nsRect nsDisplayWrapList::GetComponentAlphaBounds(nsDisplayListBuilder* aBuilder) @@ -2792,8 +2798,7 @@ nsDisplayOpacity::GetLayerState(nsDisplayListBuilder* aBuilder, } nsIFrame* activeScrolledRoot = nsLayoutUtils::GetActiveScrolledRootFor(mFrame, nullptr); - return !ChildrenCanBeInactive(aBuilder, aManager, aParameters, mList, activeScrolledRoot) - ? LAYER_ACTIVE : LAYER_INACTIVE; + return RequiredLayerStateForChildren(aBuilder, aManager, aParameters, mList, activeScrolledRoot); } bool @@ -3938,13 +3943,17 @@ nsDisplayItem::LayerState nsDisplayTransform::GetLayerState(nsDisplayListBuilder* aBuilder, LayerManager* aManager, const ContainerParameters& aParameters) { + // If the transform is 3d, or the layer takes part in preserve-3d sorting + // then we *always* want this to be an active layer. + if (!GetTransform(mFrame->PresContext()->AppUnitsPerDevPixel()).Is2D() || + mFrame->Preserves3D()) { + return LAYER_ACTIVE_FORCE; + } // Here we check if the *post-transform* bounds of this item are big enough // to justify an active layer. if (mFrame->AreLayersMarkedActive(nsChangeHint_UpdateTransformLayer) && !IsItemTooSmallForActiveLayer(this)) return LAYER_ACTIVE; - if (!GetTransform(mFrame->PresContext()->AppUnitsPerDevPixel()).Is2D() || mFrame->Preserves3D()) - return LAYER_ACTIVE; if (mFrame->GetContent()) { if (nsLayoutUtils::HasAnimationsForCompositor(mFrame->GetContent(), eCSSProperty_transform)) { @@ -3953,12 +3962,11 @@ nsDisplayTransform::GetLayerState(nsDisplayListBuilder* aBuilder, } nsIFrame* activeScrolledRoot = nsLayoutUtils::GetActiveScrolledRootFor(mFrame, nullptr); - return !mStoredList.ChildrenCanBeInactive(aBuilder, - aManager, - aParameters, - *mStoredList.GetChildren(), - activeScrolledRoot) - ? LAYER_ACTIVE : LAYER_INACTIVE; + return mStoredList.RequiredLayerStateForChildren(aBuilder, + aManager, + aParameters, + *mStoredList.GetChildren(), + activeScrolledRoot); } bool nsDisplayTransform::ComputeVisibility(nsDisplayListBuilder *aBuilder, diff --git a/layout/base/nsDisplayList.h b/layout/base/nsDisplayList.h index 15437d0f167..f482d964d4a 100644 --- a/layout/base/nsDisplayList.h +++ b/layout/base/nsDisplayList.h @@ -2129,11 +2129,11 @@ public: * ThebesLayer --- GetLayerState returns LAYER_INACTIVE or LAYER_NONE, * and they all have the given aActiveScrolledRoot. */ - static bool ChildrenCanBeInactive(nsDisplayListBuilder* aBuilder, - LayerManager* aManager, - const ContainerParameters& aParameters, - const nsDisplayList& aList, - nsIFrame* aActiveScrolledRoot); + static LayerState RequiredLayerStateForChildren(nsDisplayListBuilder* aBuilder, + LayerManager* aManager, + const ContainerParameters& aParameters, + const nsDisplayList& aList, + nsIFrame* aActiveScrolledRoot); protected: nsDisplayWrapList() {}