mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-02-23 02:47:07 +00:00
Bug 902525 - Part 2: Create layers for isolated groups when blending is involved r=roc
This commit is contained in:
parent
7fc7fb42af
commit
0383e51844
@ -182,6 +182,7 @@ Layer::Layer(LayerManager* aManager, void* aImplData) :
|
|||||||
mPostYScale(1.0f),
|
mPostYScale(1.0f),
|
||||||
mOpacity(1.0),
|
mOpacity(1.0),
|
||||||
mMixBlendMode(gfxContext::OPERATOR_OVER),
|
mMixBlendMode(gfxContext::OPERATOR_OVER),
|
||||||
|
mForceIsolatedGroup(false),
|
||||||
mContentFlags(0),
|
mContentFlags(0),
|
||||||
mUseClipRect(false),
|
mUseClipRect(false),
|
||||||
mUseTileSourceRect(false),
|
mUseTileSourceRect(false),
|
||||||
|
@ -741,6 +741,20 @@ public:
|
|||||||
Mutated();
|
Mutated();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SetForceIsolatedGroup(bool aForceIsolatedGroup)
|
||||||
|
{
|
||||||
|
if(mForceIsolatedGroup != aForceIsolatedGroup) {
|
||||||
|
MOZ_LAYERS_LOG_IF_SHADOWABLE(this, ("Layer::Mutated(%p) ForceIsolatedGroup", this));
|
||||||
|
mForceIsolatedGroup = aForceIsolatedGroup;
|
||||||
|
Mutated();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GetForceIsolatedGroup() const
|
||||||
|
{
|
||||||
|
return mForceIsolatedGroup;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* CONSTRUCTION PHASE ONLY
|
* CONSTRUCTION PHASE ONLY
|
||||||
@ -1323,6 +1337,7 @@ protected:
|
|||||||
InfallibleTArray<AnimData> mAnimationData;
|
InfallibleTArray<AnimData> mAnimationData;
|
||||||
float mOpacity;
|
float mOpacity;
|
||||||
gfxContext::GraphicsOperator mMixBlendMode;
|
gfxContext::GraphicsOperator mMixBlendMode;
|
||||||
|
bool mForceIsolatedGroup;
|
||||||
nsIntRect mClipRect;
|
nsIntRect mClipRect;
|
||||||
nsIntRect mTileSourceRect;
|
nsIntRect mTileSourceRect;
|
||||||
nsIntRegion mInvalidRegion;
|
nsIntRegion mInvalidRegion;
|
||||||
|
@ -73,6 +73,7 @@ BasicContainerLayer::ComputeEffectiveTransforms(const gfx3DMatrix& aTransformToS
|
|||||||
*/
|
*/
|
||||||
mUseIntermediateSurface =
|
mUseIntermediateSurface =
|
||||||
GetMaskLayer() ||
|
GetMaskLayer() ||
|
||||||
|
GetForceIsolatedGroup() ||
|
||||||
(GetMixBlendMode() != gfxContext::OPERATOR_OVER && HasMultipleChildren()) ||
|
(GetMixBlendMode() != gfxContext::OPERATOR_OVER && HasMultipleChildren()) ||
|
||||||
(GetEffectiveOpacity() != 1.0 && (HasMultipleChildren() || hasSingleBlendingChild));
|
(GetEffectiveOpacity() != 1.0 && (HasMultipleChildren() || hasSingleBlendingChild));
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@ DECLARE_DISPLAY_ITEM_TYPE(ALT_FEEDBACK)
|
|||||||
DECLARE_DISPLAY_ITEM_TYPE(BACKGROUND)
|
DECLARE_DISPLAY_ITEM_TYPE(BACKGROUND)
|
||||||
DECLARE_DISPLAY_ITEM_TYPE(THEMED_BACKGROUND)
|
DECLARE_DISPLAY_ITEM_TYPE(THEMED_BACKGROUND)
|
||||||
DECLARE_DISPLAY_ITEM_TYPE_FLAGS(BACKGROUND_COLOR,TYPE_RENDERS_NO_IMAGES)
|
DECLARE_DISPLAY_ITEM_TYPE_FLAGS(BACKGROUND_COLOR,TYPE_RENDERS_NO_IMAGES)
|
||||||
|
DECLARE_DISPLAY_ITEM_TYPE(BLEND_CONTAINER)
|
||||||
DECLARE_DISPLAY_ITEM_TYPE(BORDER)
|
DECLARE_DISPLAY_ITEM_TYPE(BORDER)
|
||||||
DECLARE_DISPLAY_ITEM_TYPE(BOX_SHADOW_OUTER)
|
DECLARE_DISPLAY_ITEM_TYPE(BOX_SHADOW_OUTER)
|
||||||
DECLARE_DISPLAY_ITEM_TYPE(BOX_SHADOW_INNER)
|
DECLARE_DISPLAY_ITEM_TYPE(BOX_SHADOW_INNER)
|
||||||
|
@ -487,7 +487,8 @@ nsDisplayListBuilder::nsDisplayListBuilder(nsIFrame* aReferenceFrame,
|
|||||||
mHasFixedItems(false),
|
mHasFixedItems(false),
|
||||||
mIsInFixedPosition(false),
|
mIsInFixedPosition(false),
|
||||||
mIsCompositingCheap(false),
|
mIsCompositingCheap(false),
|
||||||
mContainsPluginItem(false)
|
mContainsPluginItem(false),
|
||||||
|
mContainsBlendMode(false)
|
||||||
{
|
{
|
||||||
MOZ_COUNT_CTOR(nsDisplayListBuilder);
|
MOZ_COUNT_CTOR(nsDisplayListBuilder);
|
||||||
PL_InitArenaPool(&mPool, "displayListArena", 1024,
|
PL_InitArenaPool(&mPool, "displayListArena", 1024,
|
||||||
@ -3118,6 +3119,49 @@ bool nsDisplayOpacity::TryMerge(nsDisplayListBuilder* aBuilder, nsDisplayItem* a
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nsDisplayBlendContainer::nsDisplayBlendContainer(nsDisplayListBuilder* aBuilder,
|
||||||
|
nsIFrame* aFrame, nsDisplayList* aList,
|
||||||
|
uint32_t aFlags)
|
||||||
|
: nsDisplayWrapList(aBuilder, aFrame, aList) {
|
||||||
|
MOZ_COUNT_CTOR(nsDisplayBlendContainer);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef NS_BUILD_REFCNT_LOGGING
|
||||||
|
nsDisplayBlendContainer::~nsDisplayBlendContainer() {
|
||||||
|
MOZ_COUNT_DTOR(nsDisplayBlendContainer);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// nsDisplayBlendContainer uses layers for rendering
|
||||||
|
already_AddRefed<Layer>
|
||||||
|
nsDisplayBlendContainer::BuildLayer(nsDisplayListBuilder* aBuilder,
|
||||||
|
LayerManager* aManager,
|
||||||
|
const ContainerParameters& aContainerParameters) {
|
||||||
|
nsRefPtr<Layer> container = aManager->GetLayerBuilder()->
|
||||||
|
BuildContainerLayerFor(aBuilder, aManager, mFrame, this, mList,
|
||||||
|
aContainerParameters, nullptr);
|
||||||
|
if (!container) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
container->SetForceIsolatedGroup(true);
|
||||||
|
return container.forget();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool nsDisplayBlendContainer::TryMerge(nsDisplayListBuilder* aBuilder, nsDisplayItem* aItem) {
|
||||||
|
if (aItem->GetType() != TYPE_BLEND_CONTAINER)
|
||||||
|
return false;
|
||||||
|
// items for the same content element should be merged into a single
|
||||||
|
// compositing group
|
||||||
|
// aItem->GetUnderlyingFrame() returns non-null because it's nsDisplayOpacity
|
||||||
|
if (aItem->Frame()->GetContent() != mFrame->GetContent())
|
||||||
|
return false;
|
||||||
|
if (aItem->GetClip() != GetClip())
|
||||||
|
return false;
|
||||||
|
MergeFromTrackingMergedFrames(static_cast<nsDisplayBlendContainer*>(aItem));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
nsDisplayOwnLayer::nsDisplayOwnLayer(nsDisplayListBuilder* aBuilder,
|
nsDisplayOwnLayer::nsDisplayOwnLayer(nsDisplayListBuilder* aBuilder,
|
||||||
nsIFrame* aFrame, nsDisplayList* aList,
|
nsIFrame* aFrame, nsDisplayList* aList,
|
||||||
uint32_t aFlags)
|
uint32_t aFlags)
|
||||||
|
@ -622,6 +622,14 @@ public:
|
|||||||
void SetContainsPluginItem() { mContainsPluginItem = true; }
|
void SetContainsPluginItem() { mContainsPluginItem = true; }
|
||||||
bool ContainsPluginItem() { return mContainsPluginItem; }
|
bool ContainsPluginItem() { return mContainsPluginItem; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* mContainsBlendMode is true if we processed a display item that
|
||||||
|
* has a blend mode attached. We do this so we can insert a
|
||||||
|
* nsDisplayBlendContainer in the parent stacking context.
|
||||||
|
*/
|
||||||
|
void SetContainsBlendMode(bool aContainsBlendMode) { mContainsBlendMode = aContainsBlendMode; }
|
||||||
|
bool ContainsBlendMode() const { return mContainsBlendMode; }
|
||||||
|
|
||||||
DisplayListClipState& ClipState() { return mClipState; }
|
DisplayListClipState& ClipState() { return mClipState; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -680,6 +688,7 @@ private:
|
|||||||
bool mIsInFixedPosition;
|
bool mIsInFixedPosition;
|
||||||
bool mIsCompositingCheap;
|
bool mIsCompositingCheap;
|
||||||
bool mContainsPluginItem;
|
bool mContainsPluginItem;
|
||||||
|
bool mContainsBlendMode;
|
||||||
};
|
};
|
||||||
|
|
||||||
class nsDisplayItem;
|
class nsDisplayItem;
|
||||||
@ -2498,6 +2507,27 @@ public:
|
|||||||
bool CanUseAsyncAnimations(nsDisplayListBuilder* aBuilder) MOZ_OVERRIDE;
|
bool CanUseAsyncAnimations(nsDisplayListBuilder* aBuilder) MOZ_OVERRIDE;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class nsDisplayBlendContainer : public nsDisplayWrapList {
|
||||||
|
public:
|
||||||
|
nsDisplayBlendContainer(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
|
||||||
|
nsDisplayList* aList, uint32_t aFlags = 0);
|
||||||
|
#ifdef NS_BUILD_REFCNT_LOGGING
|
||||||
|
virtual ~nsDisplayBlendContainer();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
|
||||||
|
LayerManager* aManager,
|
||||||
|
const ContainerParameters& aContainerParameters) MOZ_OVERRIDE;
|
||||||
|
virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
|
||||||
|
LayerManager* aManager,
|
||||||
|
const ContainerParameters& aParameters) MOZ_OVERRIDE
|
||||||
|
{
|
||||||
|
return mozilla::LAYER_INACTIVE;
|
||||||
|
}
|
||||||
|
virtual bool TryMerge(nsDisplayListBuilder* aBuilder, nsDisplayItem* aItem) MOZ_OVERRIDE;
|
||||||
|
NS_DISPLAY_DECL_NAME("BlendContainer", TYPE_BLEND_CONTAINER)
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A display item that has no purpose but to ensure its contents get
|
* A display item that has no purpose but to ensure its contents get
|
||||||
* their own layer.
|
* their own layer.
|
||||||
|
@ -1758,6 +1758,21 @@ WrapPreserve3DList(nsIFrame* aFrame, nsDisplayListBuilder* aBuilder, nsDisplayLi
|
|||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class AutoSaveRestoreBlendMode
|
||||||
|
{
|
||||||
|
nsDisplayListBuilder& mBuilder;
|
||||||
|
bool AutoResetContainsBlendMode;
|
||||||
|
public:
|
||||||
|
AutoSaveRestoreBlendMode(nsDisplayListBuilder& aBuilder)
|
||||||
|
: mBuilder(aBuilder),
|
||||||
|
AutoResetContainsBlendMode(aBuilder.ContainsBlendMode()) {
|
||||||
|
}
|
||||||
|
|
||||||
|
~AutoSaveRestoreBlendMode() {
|
||||||
|
mBuilder.SetContainsBlendMode(AutoResetContainsBlendMode);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
void
|
void
|
||||||
nsIFrame::BuildDisplayListForStackingContext(nsDisplayListBuilder* aBuilder,
|
nsIFrame::BuildDisplayListForStackingContext(nsDisplayListBuilder* aBuilder,
|
||||||
const nsRect& aDirtyRect,
|
const nsRect& aDirtyRect,
|
||||||
@ -1786,6 +1801,12 @@ nsIFrame::BuildDisplayListForStackingContext(nsDisplayListBuilder* aBuilder,
|
|||||||
|
|
||||||
bool inTransform = aBuilder->IsInTransform();
|
bool inTransform = aBuilder->IsInTransform();
|
||||||
bool isTransformed = IsTransformed();
|
bool isTransformed = IsTransformed();
|
||||||
|
// 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.
|
||||||
|
AutoSaveRestoreBlendMode autoRestoreBlendMode(*aBuilder);
|
||||||
|
aBuilder->SetContainsBlendMode(false);
|
||||||
|
|
||||||
if (isTransformed) {
|
if (isTransformed) {
|
||||||
if (aBuilder->IsForPainting() &&
|
if (aBuilder->IsForPainting() &&
|
||||||
nsDisplayTransform::ShouldPrerenderTransformedContent(aBuilder, this)) {
|
nsDisplayTransform::ShouldPrerenderTransformedContent(aBuilder, this)) {
|
||||||
@ -1818,6 +1839,7 @@ nsIFrame::BuildDisplayListForStackingContext(nsDisplayListBuilder* aBuilder,
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool useOpacity = HasOpacity() && !nsSVGUtils::CanOptimizeOpacity(this);
|
bool useOpacity = HasOpacity() && !nsSVGUtils::CanOptimizeOpacity(this);
|
||||||
|
bool useBlendMode = disp->mMixBlendMode != NS_STYLE_BLEND_NORMAL;
|
||||||
bool usingSVGEffects = nsSVGIntegrationUtils::UsingEffectsForFrame(this);
|
bool usingSVGEffects = nsSVGIntegrationUtils::UsingEffectsForFrame(this);
|
||||||
bool useStickyPosition = disp->mPosition == NS_STYLE_POSITION_STICKY &&
|
bool useStickyPosition = disp->mPosition == NS_STYLE_POSITION_STICKY &&
|
||||||
IsScrollFrameActive(nsLayoutUtils::GetNearestScrollableFrame(GetParent(),
|
IsScrollFrameActive(nsLayoutUtils::GetNearestScrollableFrame(GetParent(),
|
||||||
@ -1826,7 +1848,7 @@ nsIFrame::BuildDisplayListForStackingContext(nsDisplayListBuilder* aBuilder,
|
|||||||
|
|
||||||
DisplayListClipState::AutoSaveRestore clipState(aBuilder);
|
DisplayListClipState::AutoSaveRestore clipState(aBuilder);
|
||||||
|
|
||||||
if (isTransformed || useOpacity || usingSVGEffects || useStickyPosition) {
|
if (isTransformed || useOpacity || useBlendMode || usingSVGEffects || useStickyPosition) {
|
||||||
// We don't need to pass ancestor clipping down to our children;
|
// We don't need to pass ancestor clipping down to our children;
|
||||||
// everything goes inside a display item's child list, and the display
|
// everything goes inside a display item's child list, and the display
|
||||||
// item itself will be clipped.
|
// item itself will be clipped.
|
||||||
@ -1975,6 +1997,11 @@ nsIFrame::BuildDisplayListForStackingContext(nsDisplayListBuilder* aBuilder,
|
|||||||
new (aBuilder) nsDisplayTransform(aBuilder, this, &resultList));
|
new (aBuilder) nsDisplayTransform(aBuilder, this, &resultList));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (aBuilder->ContainsBlendMode()) {
|
||||||
|
resultList.AppendNewToTop(
|
||||||
|
new (aBuilder) nsDisplayBlendContainer(aBuilder, this, &resultList));
|
||||||
|
}
|
||||||
|
|
||||||
aList->AppendToTop(&resultList);
|
aList->AppendToTop(&resultList);
|
||||||
}
|
}
|
||||||
@ -2106,11 +2133,12 @@ nsIFrame::BuildDisplayListForChild(nsDisplayListBuilder* aBuilder,
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
// Child is composited if it's transformed, partially transparent, or has
|
// Child is composited if it's transformed, partially transparent, or has
|
||||||
// SVG effects.
|
// SVG effects or a blend mode..
|
||||||
const nsStyleDisplay* disp = child->StyleDisplay();
|
const nsStyleDisplay* disp = child->StyleDisplay();
|
||||||
const nsStylePosition* pos = child->StylePosition();
|
const nsStylePosition* pos = child->StylePosition();
|
||||||
bool isVisuallyAtomic = child->HasOpacity()
|
bool isVisuallyAtomic = child->HasOpacity()
|
||||||
|| child->IsTransformed()
|
|| child->IsTransformed()
|
||||||
|
|| disp->mMixBlendMode != NS_STYLE_BLEND_NORMAL
|
||||||
|| nsSVGIntegrationUtils::UsingEffectsForFrame(child);
|
|| nsSVGIntegrationUtils::UsingEffectsForFrame(child);
|
||||||
|
|
||||||
bool isPositioned = disp->IsPositioned(child);
|
bool isPositioned = disp->IsPositioned(child);
|
||||||
@ -2165,6 +2193,9 @@ nsIFrame::BuildDisplayListForChild(nsDisplayListBuilder* aBuilder,
|
|||||||
nsDisplayList list;
|
nsDisplayList list;
|
||||||
nsDisplayList extraPositionedDescendants;
|
nsDisplayList extraPositionedDescendants;
|
||||||
if (isStackingContext) {
|
if (isStackingContext) {
|
||||||
|
if (disp->mMixBlendMode != NS_STYLE_BLEND_NORMAL) {
|
||||||
|
aBuilder->SetContainsBlendMode(true);
|
||||||
|
}
|
||||||
// True stacking context.
|
// True stacking context.
|
||||||
// For stacking contexts, BuildDisplayListForStackingContext handles
|
// For stacking contexts, BuildDisplayListForStackingContext handles
|
||||||
// clipping and MarkAbsoluteFramesForDisplayList.
|
// clipping and MarkAbsoluteFramesForDisplayList.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user