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 898541f214
commit 5aa1f5d7fe
4 changed files with 73 additions and 20 deletions

View File

@ -518,7 +518,6 @@ nsDisplayListBuilder::nsDisplayListBuilder(nsIFrame* aReferenceFrame,
mIsPaintingToWindow(false),
mIsCompositingCheap(false),
mContainsPluginItem(false),
mContainsBlendMode(false),
mAncestorHasTouchEventHandler(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,
nsIFrame* aFrame,
const nsRect& aDirtyRect)
@ -3384,6 +3390,18 @@ nsRegion nsDisplayMixBlendMode::GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
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
already_AddRefed<Layer>
nsDisplayMixBlendMode::BuildLayer(nsDisplayListBuilder* aBuilder,
@ -3437,8 +3455,19 @@ bool nsDisplayMixBlendMode::TryMerge(nsDisplayListBuilder* aBuilder, nsDisplayIt
nsDisplayBlendContainer::nsDisplayBlendContainer(nsDisplayListBuilder* aBuilder,
nsIFrame* aFrame, nsDisplayList* aList,
uint32_t aFlags)
: nsDisplayWrapList(aBuilder, aFrame, aList) {
BlendModeSet& aContainedBlendModes)
: 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);
}

View File

@ -45,6 +45,10 @@ class ImageContainer;
} //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
* 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
* nsDisplayBlendContainer in the parent stacking context.
*/
void SetContainsBlendMode(bool aContainsBlendMode) { mContainsBlendMode = aContainsBlendMode; }
bool ContainsBlendMode() const { return mContainsBlendMode; }
void SetContainsBlendMode(uint8_t aBlendMode);
void SetContainsBlendModes(const BlendModeSet& aModes) {
mContainedBlendModes = aModes;
}
bool ContainsBlendMode() const { return !mContainedBlendModes.isEmpty(); }
BlendModeSet& ContainedBlendModes() {
return mContainedBlendModes;
}
DisplayListClipState& ClipState() { return mClipState; }
@ -731,6 +741,7 @@ private:
nsTArray<DisplayItemClip*> mDisplayItemClipsToDestroy;
Mode mMode;
ViewID mCurrentScrollParentId;
BlendModeSet mContainedBlendModes;
bool mBuildCaret;
bool mIgnoreSuppression;
bool mHadToIgnoreSuppression;
@ -749,7 +760,6 @@ private:
bool mIsPaintingToWindow;
bool mIsCompositingCheap;
bool mContainsPluginItem;
bool mContainsBlendMode;
bool mAncestorHasTouchEventHandler;
// 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
@ -2730,10 +2740,7 @@ public:
}
virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
LayerManager* aManager,
const ContainerLayerParameters& aParameters) MOZ_OVERRIDE
{
return mozilla::LAYER_INACTIVE;
}
const ContainerLayerParameters& aParameters) MOZ_OVERRIDE;
virtual bool ComputeVisibility(nsDisplayListBuilder* aBuilder,
nsRegion* aVisibleRegion,
const nsRect& aAllowVisibleRegionExpansion) MOZ_OVERRIDE;
@ -2744,7 +2751,10 @@ public:
class nsDisplayBlendContainer : public nsDisplayWrapList {
public:
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
virtual ~nsDisplayBlendContainer();
#endif
@ -2756,10 +2766,20 @@ public:
LayerManager* aManager,
const ContainerLayerParameters& aParameters) MOZ_OVERRIDE
{
return mozilla::LAYER_INACTIVE;
if (mCanBeActive && aManager->SupportsMixBlendModes(mContainedBlendModes)) {
return mozilla::LAYER_ACTIVE;
}
return mozilla::LAYER_INACTIVE;
}
virtual bool TryMerge(nsDisplayListBuilder* aBuilder, nsDisplayItem* aItem) MOZ_OVERRIDE;
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
{
nsDisplayListBuilder& mBuilder;
bool AutoResetContainsBlendMode;
EnumSet<gfx::CompositionOp> mSavedBlendModes;
public:
AutoSaveRestoreBlendMode(nsDisplayListBuilder& aBuilder)
: mBuilder(aBuilder),
AutoResetContainsBlendMode(aBuilder.ContainsBlendMode()) {
}
: mBuilder(aBuilder)
, mSavedBlendModes(aBuilder.ContainedBlendModes())
{ }
~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
// so we keep track if the parent stacking context needs a container too.
AutoSaveRestoreBlendMode autoRestoreBlendMode(*aBuilder);
aBuilder->SetContainsBlendMode(false);
aBuilder->SetContainsBlendModes(BlendModeSet());
if (isTransformed) {
const nsRect overflow = GetVisualOverflowRectRelativeToSelf();
@ -2129,7 +2129,7 @@ nsIFrame::BuildDisplayListForStackingContext(nsDisplayListBuilder* aBuilder,
if (aBuilder->ContainsBlendMode()) {
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
@ -2343,7 +2343,7 @@ nsIFrame::BuildDisplayListForChild(nsDisplayListBuilder* aBuilder,
nsDisplayList extraPositionedDescendants;
if (isStackingContext) {
if (disp->mMixBlendMode != NS_STYLE_BLEND_NORMAL) {
aBuilder->SetContainsBlendMode(true);
aBuilder->SetContainsBlendMode(disp->mMixBlendMode);
}
// True stacking context.
// For stacking contexts, BuildDisplayListForStackingContext handles

View File

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