Bug 902525 - Part 1: Layers changes r=roc

This commit is contained in:
Rik Cabanier
2013-09-14 20:23:46 -07:00
parent e0d92169a9
commit 27beee6d24
4 changed files with 50 additions and 7 deletions

View File

@@ -181,6 +181,7 @@ Layer::Layer(LayerManager* aManager, void* aImplData) :
mPostXScale(1.0f), mPostXScale(1.0f),
mPostYScale(1.0f), mPostYScale(1.0f),
mOpacity(1.0), mOpacity(1.0),
mMixBlendMode(gfxContext::OPERATOR_OVER),
mContentFlags(0), mContentFlags(0),
mUseClipRect(false), mUseClipRect(false),
mUseTileSourceRect(false), mUseTileSourceRect(false),
@@ -680,6 +681,20 @@ Layer::GetEffectiveOpacity()
} }
return opacity; return opacity;
} }
gfxContext::GraphicsOperator
Layer::GetEffectiveMixBlendMode()
{
if(mMixBlendMode != gfxContext::OPERATOR_OVER)
return mMixBlendMode;
for (ContainerLayer* c = GetParent(); c && !c->UseIntermediateSurface();
c = c->GetParent()) {
if(c->mMixBlendMode != gfxContext::OPERATOR_OVER)
return c->mMixBlendMode;
}
return mMixBlendMode;
}
void void
Layer::ComputeEffectiveTransformForMaskLayer(const gfx3DMatrix& aTransformToSurface) Layer::ComputeEffectiveTransformForMaskLayer(const gfx3DMatrix& aTransformToSurface)

View File

@@ -12,6 +12,7 @@
#include "FrameMetrics.h" // for FrameMetrics #include "FrameMetrics.h" // for FrameMetrics
#include "Units.h" // for LayerMargin, LayerPoint #include "Units.h" // for LayerMargin, LayerPoint
#include "gfx3DMatrix.h" // for gfx3DMatrix #include "gfx3DMatrix.h" // for gfx3DMatrix
#include "gfxContext.h" // for GraphicsOperator
#include "gfxASurface.h" // for gfxASurface, etc #include "gfxASurface.h" // for gfxASurface, etc
#include "gfxColor.h" // for gfxRGBA #include "gfxColor.h" // for gfxRGBA
#include "gfxMatrix.h" // for gfxMatrix #include "gfxMatrix.h" // for gfxMatrix
@@ -732,6 +733,15 @@ public:
} }
} }
void SetMixBlendMode(gfxContext::GraphicsOperator aMixBlendMode)
{
if (mMixBlendMode != aMixBlendMode) {
MOZ_LAYERS_LOG_IF_SHADOWABLE(this, ("Layer::Mutated(%p) MixBlendMode", this));
mMixBlendMode = aMixBlendMode;
Mutated();
}
}
/** /**
* CONSTRUCTION PHASE ONLY * CONSTRUCTION PHASE ONLY
* Set a clip rect which will be applied to this layer as it is * Set a clip rect which will be applied to this layer as it is
@@ -937,6 +947,7 @@ public:
// These getters can be used anytime. // These getters can be used anytime.
float GetOpacity() { return mOpacity; } float GetOpacity() { return mOpacity; }
gfxContext::GraphicsOperator GetMixBlendMode() const { return mMixBlendMode; }
const nsIntRect* GetClipRect() { return mUseClipRect ? &mClipRect : nullptr; } const nsIntRect* GetClipRect() { return mUseClipRect ? &mClipRect : nullptr; }
uint32_t GetContentFlags() { return mContentFlags; } uint32_t GetContentFlags() { return mContentFlags; }
const nsIntRegion& GetVisibleRegion() { return mVisibleRegion; } const nsIntRegion& GetVisibleRegion() { return mVisibleRegion; }
@@ -1102,11 +1113,18 @@ public:
// accounting for this layer possibly being a shadow. // accounting for this layer possibly being a shadow.
const nsIntRect* GetEffectiveClipRect(); const nsIntRect* GetEffectiveClipRect();
const nsIntRegion& GetEffectiveVisibleRegion(); const nsIntRegion& GetEffectiveVisibleRegion();
/** /**
* Returns the product of the opacities of this layer and all ancestors up * Returns the product of the opacities of this layer and all ancestors up
* to and excluding the nearest ancestor that has UseIntermediateSurface() set. * to and excluding the nearest ancestor that has UseIntermediateSurface() set.
*/ */
float GetEffectiveOpacity(); float GetEffectiveOpacity();
/**
* Returns the blendmode of this layer.
*/
gfxContext::GraphicsOperator GetEffectiveMixBlendMode();
/** /**
* This returns the effective transform computed by * This returns the effective transform computed by
* ComputeEffectiveTransforms. Typically this is a transform that transforms * ComputeEffectiveTransforms. Typically this is a transform that transforms
@@ -1304,6 +1322,7 @@ protected:
AnimationArray mAnimations; AnimationArray mAnimations;
InfallibleTArray<AnimData> mAnimationData; InfallibleTArray<AnimData> mAnimationData;
float mOpacity; float mOpacity;
gfxContext::GraphicsOperator mMixBlendMode;
nsIntRect mClipRect; nsIntRect mClipRect;
nsIntRect mTileSourceRect; nsIntRect mTileSourceRect;
nsIntRegion mInvalidRegion; nsIntRegion mInvalidRegion;

View File

@@ -57,16 +57,24 @@ BasicContainerLayer::ComputeEffectiveTransforms(const gfx3DMatrix& aTransformToS
ComputeEffectiveTransformsForChildren(idealTransform); ComputeEffectiveTransformsForChildren(idealTransform);
ComputeEffectiveTransformForMaskLayer(aTransformToSurface); ComputeEffectiveTransformForMaskLayer(aTransformToSurface);
Layer* child = GetFirstChild();
bool hasSingleBlendingChild = false;
if (!HasMultipleChildren() && child) {
hasSingleBlendingChild = child->GetMixBlendMode() != gfxContext::OPERATOR_OVER;
}
/* If we have a single child, it can just inherit our opacity, /* If we have a single childand it is not blending,, it can just inherit our opacity,
* otherwise we need a PushGroup and we need to mark ourselves as using * otherwise we need a PushGroup and we need to mark ourselves as using
* an intermediate surface so our children don't inherit our opacity * an intermediate surface so our children don't inherit our opacity
* via GetEffectiveOpacity. * via GetEffectiveOpacity.
* Having a mask layer always forces our own push group * Having a mask layer always forces our own push group
* Having a blend mode also always forces our own push group
*/ */
mUseIntermediateSurface = mUseIntermediateSurface =
GetMaskLayer() || (GetEffectiveOpacity() != 1.0 && GetMaskLayer() ||
HasMultipleChildren()); (GetMixBlendMode() != gfxContext::OPERATOR_OVER && HasMultipleChildren()) ||
(GetEffectiveOpacity() != 1.0 && (HasMultipleChildren() || hasSingleBlendingChild));
} }
bool bool

View File

@@ -109,7 +109,8 @@ BasicThebesLayer::PaintThebes(gfxContext* aContext,
canUseOpaqueSurface ? gfxASurface::CONTENT_COLOR : canUseOpaqueSurface ? gfxASurface::CONTENT_COLOR :
gfxASurface::CONTENT_COLOR_ALPHA; gfxASurface::CONTENT_COLOR_ALPHA;
float opacity = GetEffectiveOpacity(); float opacity = GetEffectiveOpacity();
gfxContext::GraphicsOperator mixBlendMode = GetEffectiveMixBlendMode();
if (!BasicManager()->IsRetained()) { if (!BasicManager()->IsRetained()) {
NS_ASSERTION(readbackUpdates.IsEmpty(), "Can't do readback for non-retained layer"); NS_ASSERTION(readbackUpdates.IsEmpty(), "Can't do readback for non-retained layer");
@@ -130,13 +131,13 @@ BasicThebesLayer::PaintThebes(gfxContext* aContext,
bool needsClipToVisibleRegion = GetClipToVisibleRegion(); bool needsClipToVisibleRegion = GetClipToVisibleRegion();
bool needsGroup = bool needsGroup =
opacity != 1.0 || GetOperator() != gfxContext::OPERATOR_OVER || aMaskLayer; opacity != 1.0 || GetOperator() != gfxContext::OPERATOR_OVER || mixBlendMode != gfxContext::OPERATOR_OVER || aMaskLayer;
nsRefPtr<gfxContext> groupContext; nsRefPtr<gfxContext> groupContext;
if (needsGroup) { if (needsGroup) {
groupContext = groupContext =
BasicManager()->PushGroupForLayer(aContext, this, toDraw, BasicManager()->PushGroupForLayer(aContext, this, toDraw,
&needsClipToVisibleRegion); &needsClipToVisibleRegion);
if (GetOperator() != gfxContext::OPERATOR_OVER) { if (GetOperator() != gfxContext::OPERATOR_OVER || mixBlendMode != gfxContext::OPERATOR_OVER) {
needsClipToVisibleRegion = true; needsClipToVisibleRegion = true;
} }
} else { } else {
@@ -149,7 +150,7 @@ BasicThebesLayer::PaintThebes(gfxContext* aContext,
if (needsClipToVisibleRegion) { if (needsClipToVisibleRegion) {
gfxUtils::ClipToRegion(aContext, toDraw); gfxUtils::ClipToRegion(aContext, toDraw);
} }
AutoSetOperator setOperator(aContext, GetOperator()); AutoSetOperator setOptimizedOperator(aContext, mixBlendMode != gfxContext::OPERATOR_OVER ? mixBlendMode : GetOperator());
PaintWithMask(aContext, opacity, aMaskLayer); PaintWithMask(aContext, opacity, aMaskLayer);
} }