зеркало из https://github.com/mozilla/gecko-dev.git
Bug 902525 - Part 2: Create layers for isolated groups when blending is involved r=roc
This commit is contained in:
Родитель
7fc7fb42af
Коммит
0383e51844
|
@ -182,6 +182,7 @@ Layer::Layer(LayerManager* aManager, void* aImplData) :
|
|||
mPostYScale(1.0f),
|
||||
mOpacity(1.0),
|
||||
mMixBlendMode(gfxContext::OPERATOR_OVER),
|
||||
mForceIsolatedGroup(false),
|
||||
mContentFlags(0),
|
||||
mUseClipRect(false),
|
||||
mUseTileSourceRect(false),
|
||||
|
|
|
@ -741,6 +741,20 @@ public:
|
|||
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
|
||||
|
@ -1323,6 +1337,7 @@ protected:
|
|||
InfallibleTArray<AnimData> mAnimationData;
|
||||
float mOpacity;
|
||||
gfxContext::GraphicsOperator mMixBlendMode;
|
||||
bool mForceIsolatedGroup;
|
||||
nsIntRect mClipRect;
|
||||
nsIntRect mTileSourceRect;
|
||||
nsIntRegion mInvalidRegion;
|
||||
|
|
|
@ -73,6 +73,7 @@ BasicContainerLayer::ComputeEffectiveTransforms(const gfx3DMatrix& aTransformToS
|
|||
*/
|
||||
mUseIntermediateSurface =
|
||||
GetMaskLayer() ||
|
||||
GetForceIsolatedGroup() ||
|
||||
(GetMixBlendMode() != gfxContext::OPERATOR_OVER && HasMultipleChildren()) ||
|
||||
(GetEffectiveOpacity() != 1.0 && (HasMultipleChildren() || hasSingleBlendingChild));
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ DECLARE_DISPLAY_ITEM_TYPE(ALT_FEEDBACK)
|
|||
DECLARE_DISPLAY_ITEM_TYPE(BACKGROUND)
|
||||
DECLARE_DISPLAY_ITEM_TYPE(THEMED_BACKGROUND)
|
||||
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(BOX_SHADOW_OUTER)
|
||||
DECLARE_DISPLAY_ITEM_TYPE(BOX_SHADOW_INNER)
|
||||
|
|
|
@ -487,7 +487,8 @@ nsDisplayListBuilder::nsDisplayListBuilder(nsIFrame* aReferenceFrame,
|
|||
mHasFixedItems(false),
|
||||
mIsInFixedPosition(false),
|
||||
mIsCompositingCheap(false),
|
||||
mContainsPluginItem(false)
|
||||
mContainsPluginItem(false),
|
||||
mContainsBlendMode(false)
|
||||
{
|
||||
MOZ_COUNT_CTOR(nsDisplayListBuilder);
|
||||
PL_InitArenaPool(&mPool, "displayListArena", 1024,
|
||||
|
@ -3118,6 +3119,49 @@ bool nsDisplayOpacity::TryMerge(nsDisplayListBuilder* aBuilder, nsDisplayItem* a
|
|||
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,
|
||||
nsIFrame* aFrame, nsDisplayList* aList,
|
||||
uint32_t aFlags)
|
||||
|
|
|
@ -622,6 +622,14 @@ public:
|
|||
void SetContainsPluginItem() { mContainsPluginItem = true; }
|
||||
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; }
|
||||
|
||||
private:
|
||||
|
@ -680,6 +688,7 @@ private:
|
|||
bool mIsInFixedPosition;
|
||||
bool mIsCompositingCheap;
|
||||
bool mContainsPluginItem;
|
||||
bool mContainsBlendMode;
|
||||
};
|
||||
|
||||
class nsDisplayItem;
|
||||
|
@ -2498,6 +2507,27 @@ public:
|
|||
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
|
||||
* their own layer.
|
||||
|
|
|
@ -1758,6 +1758,21 @@ WrapPreserve3DList(nsIFrame* aFrame, nsDisplayListBuilder* aBuilder, nsDisplayLi
|
|||
return rv;
|
||||
}
|
||||
|
||||
class AutoSaveRestoreBlendMode
|
||||
{
|
||||
nsDisplayListBuilder& mBuilder;
|
||||
bool AutoResetContainsBlendMode;
|
||||
public:
|
||||
AutoSaveRestoreBlendMode(nsDisplayListBuilder& aBuilder)
|
||||
: mBuilder(aBuilder),
|
||||
AutoResetContainsBlendMode(aBuilder.ContainsBlendMode()) {
|
||||
}
|
||||
|
||||
~AutoSaveRestoreBlendMode() {
|
||||
mBuilder.SetContainsBlendMode(AutoResetContainsBlendMode);
|
||||
}
|
||||
};
|
||||
|
||||
void
|
||||
nsIFrame::BuildDisplayListForStackingContext(nsDisplayListBuilder* aBuilder,
|
||||
const nsRect& aDirtyRect,
|
||||
|
@ -1786,6 +1801,12 @@ nsIFrame::BuildDisplayListForStackingContext(nsDisplayListBuilder* aBuilder,
|
|||
|
||||
bool inTransform = aBuilder->IsInTransform();
|
||||
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 (aBuilder->IsForPainting() &&
|
||||
nsDisplayTransform::ShouldPrerenderTransformedContent(aBuilder, this)) {
|
||||
|
@ -1818,6 +1839,7 @@ nsIFrame::BuildDisplayListForStackingContext(nsDisplayListBuilder* aBuilder,
|
|||
}
|
||||
|
||||
bool useOpacity = HasOpacity() && !nsSVGUtils::CanOptimizeOpacity(this);
|
||||
bool useBlendMode = disp->mMixBlendMode != NS_STYLE_BLEND_NORMAL;
|
||||
bool usingSVGEffects = nsSVGIntegrationUtils::UsingEffectsForFrame(this);
|
||||
bool useStickyPosition = disp->mPosition == NS_STYLE_POSITION_STICKY &&
|
||||
IsScrollFrameActive(nsLayoutUtils::GetNearestScrollableFrame(GetParent(),
|
||||
|
@ -1826,7 +1848,7 @@ nsIFrame::BuildDisplayListForStackingContext(nsDisplayListBuilder* 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;
|
||||
// everything goes inside a display item's child list, and the display
|
||||
// item itself will be clipped.
|
||||
|
@ -1975,6 +1997,11 @@ nsIFrame::BuildDisplayListForStackingContext(nsDisplayListBuilder* aBuilder,
|
|||
new (aBuilder) nsDisplayTransform(aBuilder, this, &resultList));
|
||||
}
|
||||
}
|
||||
|
||||
if (aBuilder->ContainsBlendMode()) {
|
||||
resultList.AppendNewToTop(
|
||||
new (aBuilder) nsDisplayBlendContainer(aBuilder, this, &resultList));
|
||||
}
|
||||
|
||||
aList->AppendToTop(&resultList);
|
||||
}
|
||||
|
@ -2106,11 +2133,12 @@ nsIFrame::BuildDisplayListForChild(nsDisplayListBuilder* aBuilder,
|
|||
return;
|
||||
|
||||
// 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 nsStylePosition* pos = child->StylePosition();
|
||||
bool isVisuallyAtomic = child->HasOpacity()
|
||||
|| child->IsTransformed()
|
||||
|| disp->mMixBlendMode != NS_STYLE_BLEND_NORMAL
|
||||
|| nsSVGIntegrationUtils::UsingEffectsForFrame(child);
|
||||
|
||||
bool isPositioned = disp->IsPositioned(child);
|
||||
|
@ -2165,6 +2193,9 @@ nsIFrame::BuildDisplayListForChild(nsDisplayListBuilder* aBuilder,
|
|||
nsDisplayList list;
|
||||
nsDisplayList extraPositionedDescendants;
|
||||
if (isStackingContext) {
|
||||
if (disp->mMixBlendMode != NS_STYLE_BLEND_NORMAL) {
|
||||
aBuilder->SetContainsBlendMode(true);
|
||||
}
|
||||
// True stacking context.
|
||||
// For stacking contexts, BuildDisplayListForStackingContext handles
|
||||
// clipping and MarkAbsoluteFramesForDisplayList.
|
||||
|
|
Загрузка…
Ссылка в новой задаче