Bug 950312 - Part 4: Create active layers for nsDisplayMixBlendMode and nsDisplayBlendContainer if the layer manager supports all contained blend mode. r=roc

This commit is contained in:
Matt Woodrow 2014-05-09 21:49:27 +12:00
parent f1253774f4
commit 41d4a92470
4 changed files with 73 additions and 20 deletions

View File

@ -518,7 +518,6 @@ nsDisplayListBuilder::nsDisplayListBuilder(nsIFrame* aReferenceFrame,
mIsPaintingToWindow(false), mIsPaintingToWindow(false),
mIsCompositingCheap(false), mIsCompositingCheap(false),
mContainsPluginItem(false), mContainsPluginItem(false),
mContainsBlendMode(false),
mAncestorHasTouchEventHandler(false), mAncestorHasTouchEventHandler(false),
mHaveScrollableDisplayPort(false) mHaveScrollableDisplayPort(false)
{ {
@ -553,6 +552,13 @@ static void MarkFrameForDisplay(nsIFrame* aFrame, nsIFrame* aStopAtFrame) {
} }
} }
void nsDisplayListBuilder::SetContainsBlendMode(uint8_t aBlendMode)
{
MOZ_ASSERT(aBlendMode != NS_STYLE_BLEND_NORMAL);
gfxContext::GraphicsOperator op = nsCSSRendering::GetGFXBlendMode(aBlendMode);
mContainedBlendModes += gfx::CompositionOpForOp(op);
}
void nsDisplayListBuilder::MarkOutOfFlowFrameForDisplay(nsIFrame* aDirtyFrame, void nsDisplayListBuilder::MarkOutOfFlowFrameForDisplay(nsIFrame* aDirtyFrame,
nsIFrame* aFrame, nsIFrame* aFrame,
const nsRect& aDirtyRect) const nsRect& aDirtyRect)
@ -3384,6 +3390,18 @@ nsRegion nsDisplayMixBlendMode::GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
return nsRegion(); return nsRegion();
} }
LayerState
nsDisplayMixBlendMode::GetLayerState(nsDisplayListBuilder* aBuilder,
LayerManager* aManager,
const ContainerLayerParameters& aParameters)
{
gfxContext::GraphicsOperator op = nsCSSRendering::GetGFXBlendMode(mFrame->StyleDisplay()->mMixBlendMode);
if (aManager->SupportsMixBlendMode(gfx::CompositionOpForOp(op))) {
return LAYER_ACTIVE;
}
return LAYER_INACTIVE;
}
// nsDisplayMixBlendMode uses layers for rendering // nsDisplayMixBlendMode uses layers for rendering
already_AddRefed<Layer> already_AddRefed<Layer>
nsDisplayMixBlendMode::BuildLayer(nsDisplayListBuilder* aBuilder, nsDisplayMixBlendMode::BuildLayer(nsDisplayListBuilder* aBuilder,
@ -3437,8 +3455,19 @@ bool nsDisplayMixBlendMode::TryMerge(nsDisplayListBuilder* aBuilder, nsDisplayIt
nsDisplayBlendContainer::nsDisplayBlendContainer(nsDisplayListBuilder* aBuilder, nsDisplayBlendContainer::nsDisplayBlendContainer(nsDisplayListBuilder* aBuilder,
nsIFrame* aFrame, nsDisplayList* aList, nsIFrame* aFrame, nsDisplayList* aList,
uint32_t aFlags) BlendModeSet& aContainedBlendModes)
: nsDisplayWrapList(aBuilder, aFrame, aList) { : nsDisplayWrapList(aBuilder, aFrame, aList)
, mContainedBlendModes(aContainedBlendModes)
, mCanBeActive(true)
{
MOZ_COUNT_CTOR(nsDisplayBlendContainer);
}
nsDisplayBlendContainer::nsDisplayBlendContainer(nsDisplayListBuilder* aBuilder,
nsIFrame* aFrame, nsDisplayList* aList)
: nsDisplayWrapList(aBuilder, aFrame, aList)
, mCanBeActive(false)
{
MOZ_COUNT_CTOR(nsDisplayBlendContainer); MOZ_COUNT_CTOR(nsDisplayBlendContainer);
} }

View File

@ -45,6 +45,10 @@ class ImageContainer;
} //namepsace } //namepsace
} //namepsace } //namepsace
// A set of blend modes, that never includes OP_OVER (since it's
// considered the default, rather than a specific blend mode).
typedef mozilla::EnumSet<mozilla::gfx::CompositionOp> BlendModeSet;
/* /*
* An nsIFrame can have many different visual parts. For example an image frame * An nsIFrame can have many different visual parts. For example an image frame
* can have a background, border, and outline, the image itself, and a * can have a background, border, and outline, the image itself, and a
@ -688,8 +692,14 @@ public:
* has a blend mode attached. We do this so we can insert a * has a blend mode attached. We do this so we can insert a
* nsDisplayBlendContainer in the parent stacking context. * nsDisplayBlendContainer in the parent stacking context.
*/ */
void SetContainsBlendMode(bool aContainsBlendMode) { mContainsBlendMode = aContainsBlendMode; } void SetContainsBlendMode(uint8_t aBlendMode);
bool ContainsBlendMode() const { return mContainsBlendMode; } void SetContainsBlendModes(const BlendModeSet& aModes) {
mContainedBlendModes = aModes;
}
bool ContainsBlendMode() const { return !mContainedBlendModes.isEmpty(); }
BlendModeSet& ContainedBlendModes() {
return mContainedBlendModes;
}
DisplayListClipState& ClipState() { return mClipState; } DisplayListClipState& ClipState() { return mClipState; }
@ -731,6 +741,7 @@ private:
nsTArray<DisplayItemClip*> mDisplayItemClipsToDestroy; nsTArray<DisplayItemClip*> mDisplayItemClipsToDestroy;
Mode mMode; Mode mMode;
ViewID mCurrentScrollParentId; ViewID mCurrentScrollParentId;
BlendModeSet mContainedBlendModes;
bool mBuildCaret; bool mBuildCaret;
bool mIgnoreSuppression; bool mIgnoreSuppression;
bool mHadToIgnoreSuppression; bool mHadToIgnoreSuppression;
@ -749,7 +760,6 @@ private:
bool mIsPaintingToWindow; bool mIsPaintingToWindow;
bool mIsCompositingCheap; bool mIsCompositingCheap;
bool mContainsPluginItem; bool mContainsPluginItem;
bool mContainsBlendMode;
bool mAncestorHasTouchEventHandler; bool mAncestorHasTouchEventHandler;
// True when the first async-scrollable scroll frame for which we build a // True when the first async-scrollable scroll frame for which we build a
// display list has a display port. An async-scrollable scroll frame is one // display list has a display port. An async-scrollable scroll frame is one
@ -2730,10 +2740,7 @@ public:
} }
virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder, virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
LayerManager* aManager, LayerManager* aManager,
const ContainerLayerParameters& aParameters) MOZ_OVERRIDE const ContainerLayerParameters& aParameters) MOZ_OVERRIDE;
{
return mozilla::LAYER_INACTIVE;
}
virtual bool ComputeVisibility(nsDisplayListBuilder* aBuilder, virtual bool ComputeVisibility(nsDisplayListBuilder* aBuilder,
nsRegion* aVisibleRegion, nsRegion* aVisibleRegion,
const nsRect& aAllowVisibleRegionExpansion) MOZ_OVERRIDE; const nsRect& aAllowVisibleRegionExpansion) MOZ_OVERRIDE;
@ -2744,7 +2751,10 @@ public:
class nsDisplayBlendContainer : public nsDisplayWrapList { class nsDisplayBlendContainer : public nsDisplayWrapList {
public: public:
nsDisplayBlendContainer(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame, nsDisplayBlendContainer(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
nsDisplayList* aList, uint32_t aFlags = 0); nsDisplayList* aList,
BlendModeSet& aContainedBlendModes);
nsDisplayBlendContainer(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
nsDisplayList* aList);
#ifdef NS_BUILD_REFCNT_LOGGING #ifdef NS_BUILD_REFCNT_LOGGING
virtual ~nsDisplayBlendContainer(); virtual ~nsDisplayBlendContainer();
#endif #endif
@ -2756,10 +2766,20 @@ public:
LayerManager* aManager, LayerManager* aManager,
const ContainerLayerParameters& aParameters) MOZ_OVERRIDE const ContainerLayerParameters& aParameters) MOZ_OVERRIDE
{ {
if (mCanBeActive && aManager->SupportsMixBlendModes(mContainedBlendModes)) {
return mozilla::LAYER_ACTIVE;
}
return mozilla::LAYER_INACTIVE; return mozilla::LAYER_INACTIVE;
} }
virtual bool TryMerge(nsDisplayListBuilder* aBuilder, nsDisplayItem* aItem) MOZ_OVERRIDE; virtual bool TryMerge(nsDisplayListBuilder* aBuilder, nsDisplayItem* aItem) MOZ_OVERRIDE;
NS_DISPLAY_DECL_NAME("BlendContainer", TYPE_BLEND_CONTAINER) NS_DISPLAY_DECL_NAME("BlendContainer", TYPE_BLEND_CONTAINER)
private:
// The set of all blend modes used by nsDisplayMixBlendMode descendents of this container.
BlendModeSet mContainedBlendModes;
// If this is true, then we should make the layer active if all contained blend
// modes can be supported by the current layer manager.
bool mCanBeActive;
}; };
/** /**

View File

@ -1868,15 +1868,15 @@ WrapPreserve3DList(nsIFrame* aFrame, nsDisplayListBuilder* aBuilder, nsDisplayLi
class AutoSaveRestoreBlendMode class AutoSaveRestoreBlendMode
{ {
nsDisplayListBuilder& mBuilder; nsDisplayListBuilder& mBuilder;
bool AutoResetContainsBlendMode; EnumSet<gfx::CompositionOp> mSavedBlendModes;
public: public:
AutoSaveRestoreBlendMode(nsDisplayListBuilder& aBuilder) AutoSaveRestoreBlendMode(nsDisplayListBuilder& aBuilder)
: mBuilder(aBuilder), : mBuilder(aBuilder)
AutoResetContainsBlendMode(aBuilder.ContainsBlendMode()) { , mSavedBlendModes(aBuilder.ContainedBlendModes())
} { }
~AutoSaveRestoreBlendMode() { ~AutoSaveRestoreBlendMode() {
mBuilder.SetContainsBlendMode(AutoResetContainsBlendMode); mBuilder.SetContainsBlendModes(mSavedBlendModes);
} }
}; };
@ -1929,7 +1929,7 @@ nsIFrame::BuildDisplayListForStackingContext(nsDisplayListBuilder* aBuilder,
// a nsDisplayBlendContainer. Set the blend mode back when the routine exits // a nsDisplayBlendContainer. Set the blend mode back when the routine exits
// so we keep track if the parent stacking context needs a container too. // so we keep track if the parent stacking context needs a container too.
AutoSaveRestoreBlendMode autoRestoreBlendMode(*aBuilder); AutoSaveRestoreBlendMode autoRestoreBlendMode(*aBuilder);
aBuilder->SetContainsBlendMode(false); aBuilder->SetContainsBlendModes(BlendModeSet());
if (isTransformed) { if (isTransformed) {
const nsRect overflow = GetVisualOverflowRectRelativeToSelf(); const nsRect overflow = GetVisualOverflowRectRelativeToSelf();
@ -2129,7 +2129,7 @@ nsIFrame::BuildDisplayListForStackingContext(nsDisplayListBuilder* aBuilder,
if (aBuilder->ContainsBlendMode()) { if (aBuilder->ContainsBlendMode()) {
resultList.AppendNewToTop( resultList.AppendNewToTop(
new (aBuilder) nsDisplayBlendContainer(aBuilder, this, &resultList)); new (aBuilder) nsDisplayBlendContainer(aBuilder, this, &resultList, aBuilder->ContainedBlendModes()));
} }
/* If there's blending, wrap up the list in a blend-mode item. Note /* If there's blending, wrap up the list in a blend-mode item. Note
@ -2343,7 +2343,7 @@ nsIFrame::BuildDisplayListForChild(nsDisplayListBuilder* aBuilder,
nsDisplayList extraPositionedDescendants; nsDisplayList extraPositionedDescendants;
if (isStackingContext) { if (isStackingContext) {
if (disp->mMixBlendMode != NS_STYLE_BLEND_NORMAL) { if (disp->mMixBlendMode != NS_STYLE_BLEND_NORMAL) {
aBuilder->SetContainsBlendMode(true); aBuilder->SetContainsBlendMode(disp->mMixBlendMode);
} }
// True stacking context. // True stacking context.
// For stacking contexts, BuildDisplayListForStackingContext handles // For stacking contexts, BuildDisplayListForStackingContext handles

View File

@ -162,6 +162,10 @@ class EnumSet
return count; return count;
} }
bool isEmpty() const {
return mBitField == 0;
}
uint32_t serialize() const { uint32_t serialize() const {
return mBitField; return mBitField;
} }