mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-29 07:42:04 +00:00
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:
parent
898541f214
commit
5aa1f5d7fe
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -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
|
||||
|
@ -162,6 +162,10 @@ class EnumSet
|
||||
return count;
|
||||
}
|
||||
|
||||
bool isEmpty() const {
|
||||
return mBitField == 0;
|
||||
}
|
||||
|
||||
uint32_t serialize() const {
|
||||
return mBitField;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user