Bug 716439; backend of the mask layers system for basic layers (software). r=roc

This commit is contained in:
Nicholas Cameron 2012-02-08 11:27:21 +13:00
Родитель 472977cd01
Коммит 99e2641b5e
6 изменённых файлов: 244 добавлений и 70 удалений

Просмотреть файл

@ -70,7 +70,9 @@ ThebesLayerBuffer::GetQuadrantRectangle(XSide aXSide, YSide aYSide)
void void
ThebesLayerBuffer::DrawBufferQuadrant(gfxContext* aTarget, ThebesLayerBuffer::DrawBufferQuadrant(gfxContext* aTarget,
XSide aXSide, YSide aYSide, XSide aXSide, YSide aYSide,
float aOpacity) float aOpacity,
gfxASurface* aMask,
const gfxMatrix* aMaskTransform)
{ {
// The rectangle that we're going to fill. Basically we're going to // The rectangle that we're going to fill. Basically we're going to
// render the buffer at mBufferRect + quadrantTranslation to get the // render the buffer at mBufferRect + quadrantTranslation to get the
@ -103,26 +105,41 @@ ThebesLayerBuffer::DrawBufferQuadrant(gfxContext* aTarget,
pattern->SetMatrix(transform); pattern->SetMatrix(transform);
aTarget->SetPattern(pattern); aTarget->SetPattern(pattern);
if (aOpacity != 1.0) { if (aMask) {
aTarget->Save(); if (aOpacity == 1.0) {
aTarget->Clip(); aTarget->SetMatrix(*aMaskTransform);
aTarget->Paint(aOpacity); aTarget->Mask(aMask);
aTarget->Restore(); } else {
aTarget->PushGroup(gfxASurface::CONTENT_COLOR_ALPHA);
aTarget->Paint(aOpacity);
aTarget->PopGroupToSource();
aTarget->SetMatrix(*aMaskTransform);
aTarget->Mask(aMask);
}
} else { } else {
aTarget->Fill(); if (aOpacity == 1.0) {
aTarget->Fill();
} else {
aTarget->Save();
aTarget->Clip();
aTarget->Paint(aOpacity);
aTarget->Restore();
}
} }
} }
void void
ThebesLayerBuffer::DrawBufferWithRotation(gfxContext* aTarget, float aOpacity) ThebesLayerBuffer::DrawBufferWithRotation(gfxContext* aTarget, float aOpacity,
gfxASurface* aMask,
const gfxMatrix* aMaskTransform)
{ {
SAMPLE_LABEL("ThebesLayerBuffer", "DrawBufferWithRotation"); SAMPLE_LABEL("ThebesLayerBuffer", "DrawBufferWithRotation");
// Draw four quadrants. We could use REPEAT_, but it's probably better // Draw four quadrants. We could use REPEAT_, but it's probably better
// not to, to be performance-safe. // not to, to be performance-safe.
DrawBufferQuadrant(aTarget, LEFT, TOP, aOpacity); DrawBufferQuadrant(aTarget, LEFT, TOP, aOpacity, aMask, aMaskTransform);
DrawBufferQuadrant(aTarget, RIGHT, TOP, aOpacity); DrawBufferQuadrant(aTarget, RIGHT, TOP, aOpacity, aMask, aMaskTransform);
DrawBufferQuadrant(aTarget, LEFT, BOTTOM, aOpacity); DrawBufferQuadrant(aTarget, LEFT, BOTTOM, aOpacity, aMask, aMaskTransform);
DrawBufferQuadrant(aTarget, RIGHT, BOTTOM, aOpacity); DrawBufferQuadrant(aTarget, RIGHT, BOTTOM, aOpacity, aMask, aMaskTransform);
} }
already_AddRefed<gfxContext> already_AddRefed<gfxContext>

Просмотреть файл

@ -171,9 +171,18 @@ protected:
TOP, BOTTOM TOP, BOTTOM
}; };
nsIntRect GetQuadrantRectangle(XSide aXSide, YSide aYSide); nsIntRect GetQuadrantRectangle(XSide aXSide, YSide aYSide);
/*
* If aMask is non-null, then it is used as an alpha mask for rendering this
* buffer. aMaskTransform must be non-null if aMask is non-null, and is used
* to adjust the coordinate space of the mask.
*/
void DrawBufferQuadrant(gfxContext* aTarget, XSide aXSide, YSide aYSide, void DrawBufferQuadrant(gfxContext* aTarget, XSide aXSide, YSide aYSide,
float aOpacity); float aOpacity,
void DrawBufferWithRotation(gfxContext* aTarget, float aOpacity); gfxASurface* aMask,
const gfxMatrix* aMaskTransform);
void DrawBufferWithRotation(gfxContext* aTarget, float aOpacity,
gfxASurface* aMask = nsnull,
const gfxMatrix* aMaskTransform = nsnull);
/** /**
* |BufferRect()| is the rect of device pixels that this * |BufferRect()| is the rect of device pixels that this

Просмотреть файл

@ -50,7 +50,7 @@ public:
* set up to account for all the properties of the layer (transform, * set up to account for all the properties of the layer (transform,
* opacity, etc). * opacity, etc).
*/ */
virtual void Paint(gfxContext* aContext) {} virtual void Paint(gfxContext* aContext, Layer* aMaskLayer) {}
/** /**
* Like Paint() but called for ThebesLayers with the additional parameters * Like Paint() but called for ThebesLayers with the additional parameters
@ -59,6 +59,7 @@ public:
* effective visible region (snapped or unsnapped, it doesn't matter). * effective visible region (snapped or unsnapped, it doesn't matter).
*/ */
virtual void PaintThebes(gfxContext* aContext, virtual void PaintThebes(gfxContext* aContext,
Layer* aMasklayer,
LayerManager::DrawThebesLayerCallback aCallback, LayerManager::DrawThebesLayerCallback aCallback,
void* aCallbackData, void* aCallbackData,
ReadbackProcessor* aReadback) {} ReadbackProcessor* aReadback) {}
@ -99,6 +100,14 @@ public:
mOperator = aOperator; mOperator = aOperator;
} }
gfxContext::GraphicsOperator GetOperator() const { return mOperator; } gfxContext::GraphicsOperator GetOperator() const { return mOperator; }
/**
* Return a surface for this layer. Will use an existing surface, if
* possible, or may create a temporary surface.
* Implement this method for any layers that might be used as a mask.
* Should only return null if a surface cannor be created.
*/
virtual already_AddRefed<gfxASurface> GetAsSurface() { return nsnull; }
bool GetClipToVisibleRegion() { return mClipToVisibleRegion; } bool GetClipToVisibleRegion() { return mClipToVisibleRegion; }
void SetClipToVisibleRegion(bool aClip) { mClipToVisibleRegion = aClip; } void SetClipToVisibleRegion(bool aClip) { mClipToVisibleRegion = aClip; }

Просмотреть файл

@ -108,6 +108,78 @@ static void ContainerInsertAfter(Layer* aChild, Layer* aAfter, Container* aConta
template<class Container> template<class Container>
static void ContainerRemoveChild(Layer* aChild, Container* aContainer); static void ContainerRemoveChild(Layer* aChild, Container* aContainer);
/*
* Extract a mask surface for a mask layer
* Returns a surface for the mask layer if a mask layer is present and has a
* valid surface and transform; nsnull otherwise.
* The transform for the layer will be put in aMaskTransform
*/
already_AddRefed<gfxASurface>
GetMaskSurfaceAndTransform(Layer* aMaskLayer, gfxMatrix* aMaskTransform)
{
if (aMaskLayer) {
nsRefPtr<gfxASurface> maskSurface =
static_cast<BasicImplData*>(aMaskLayer->ImplData())->GetAsSurface();
if (maskSurface) {
bool maskIs2D =
aMaskLayer->GetEffectiveTransform().CanDraw2D(aMaskTransform);
NS_ASSERTION(maskIs2D, "How did we end up with a 3D transform here?!");
return maskSurface.forget();
}
}
return nsnull;
}
// Paint the current source to a context using a mask, if present
void
PaintWithMask(gfxContext* aContext, float aOpacity, Layer* aMaskLayer)
{
gfxMatrix maskTransform;
if (nsRefPtr<gfxASurface> maskSurface =
GetMaskSurfaceAndTransform(aMaskLayer, &maskTransform)) {
if (aOpacity < 1.0) {
aContext->PushGroup(gfxASurface::CONTENT_COLOR_ALPHA);
aContext->Paint(aOpacity);
aContext->PopGroupToSource();
}
aContext->SetMatrix(maskTransform);
aContext->Mask(maskSurface);
return;
}
// if there is no mask, just paint normally
aContext->Paint(aOpacity);
}
// Fill the current path with the current source, using a
// mask and opacity, if present
void
FillWithMask(gfxContext* aContext, float aOpacity, Layer* aMaskLayer)
{
gfxMatrix maskTransform;
if (nsRefPtr<gfxASurface> maskSurface =
GetMaskSurfaceAndTransform(aMaskLayer, &maskTransform)) {
if (aOpacity < 1.0) {
aContext->PushGroup(gfxASurface::CONTENT_COLOR_ALPHA);
aContext->FillWithOpacity(aOpacity);
aContext->PopGroupToSource();
aContext->SetMatrix(maskTransform);
aContext->Mask(maskSurface);
} else {
aContext->Save();
aContext->Clip();
aContext->SetMatrix(maskTransform);
aContext->Mask(maskSurface);
aContext->NewPath();
aContext->Restore();
}
return;
}
// if there is no mask, just fill normally
aContext->FillWithOpacity(aOpacity);
}
class BasicContainerLayer : public ContainerLayer, public BasicImplData { class BasicContainerLayer : public ContainerLayer, public BasicImplData {
template<class Container> template<class Container>
friend void ContainerInsertAfter(Layer* aChild, Layer* aAfter, Container* aContainer); friend void ContainerInsertAfter(Layer* aChild, Layer* aAfter, Container* aContainer);
@ -155,6 +227,7 @@ public:
if (!idealTransform.CanDraw2D()) { if (!idealTransform.CanDraw2D()) {
mEffectiveTransform = idealTransform; mEffectiveTransform = idealTransform;
ComputeEffectiveTransformsForChildren(gfx3DMatrix()); ComputeEffectiveTransformsForChildren(gfx3DMatrix());
ComputeEffectiveTransformForMaskLayer(gfx3DMatrix());
mUseIntermediateSurface = true; mUseIntermediateSurface = true;
return; return;
} }
@ -164,12 +237,16 @@ public:
// need to apply any compensation using the residual from SnapTransform. // need to apply any compensation using the residual from SnapTransform.
ComputeEffectiveTransformsForChildren(idealTransform); ComputeEffectiveTransformsForChildren(idealTransform);
ComputeEffectiveTransformForMaskLayer(aTransformToSurface);
/* If we have a single child, it can just inherit our opacity, /* If we have a single child, 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
*/ */
mUseIntermediateSurface = GetEffectiveOpacity() != 1.0 && HasMultipleChildren(); mUseIntermediateSurface = GetMaskLayer() ||
(GetEffectiveOpacity() != 1.0 && HasMultipleChildren());
} }
/** /**
@ -335,7 +412,8 @@ public:
* drawn before this is called. The contents of the buffer are drawn * drawn before this is called. The contents of the buffer are drawn
* to aTarget. * to aTarget.
*/ */
void DrawTo(ThebesLayer* aLayer, gfxContext* aTarget, float aOpacity); void DrawTo(ThebesLayer* aLayer, gfxContext* aTarget, float aOpacity,
Layer* aMaskLayer);
virtual already_AddRefed<gfxASurface> virtual already_AddRefed<gfxASurface>
CreateBuffer(ContentType aType, const nsIntSize& aSize, PRUint32 aFlags); CreateBuffer(ContentType aType, const nsIntSize& aSize, PRUint32 aFlags);
@ -401,6 +479,7 @@ public:
} }
virtual void PaintThebes(gfxContext* aContext, virtual void PaintThebes(gfxContext* aContext,
Layer* aMaskLayer,
LayerManager::DrawThebesLayerCallback aCallback, LayerManager::DrawThebesLayerCallback aCallback,
void* aCallbackData, void* aCallbackData,
ReadbackProcessor* aReadback); ReadbackProcessor* aReadback);
@ -438,6 +517,7 @@ public:
mResidualTranslation = gfxPoint(0,0); mResidualTranslation = gfxPoint(0,0);
mValidRegion.SetEmpty(); mValidRegion.SetEmpty();
} }
ComputeEffectiveTransformForMaskLayer(aTransformToSurface);
return; return;
} }
ThebesLayer::ComputeEffectiveTransforms(aTransformToSurface); ThebesLayer::ComputeEffectiveTransforms(aTransformToSurface);
@ -563,6 +643,7 @@ BasicLayerManager::PushGroupForLayer(gfxContext* aContext, Layer* aLayer,
void void
BasicThebesLayer::PaintThebes(gfxContext* aContext, BasicThebesLayer::PaintThebes(gfxContext* aContext,
Layer* aMaskLayer,
LayerManager::DrawThebesLayerCallback aCallback, LayerManager::DrawThebesLayerCallback aCallback,
void* aCallbackData, void* aCallbackData,
ReadbackProcessor* aReadback) ReadbackProcessor* aReadback)
@ -583,7 +664,7 @@ 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();
if (!BasicManager()->IsRetained() || if (!BasicManager()->IsRetained() ||
(!canUseOpaqueSurface && (!canUseOpaqueSurface &&
(mContentFlags & CONTENT_COMPONENT_ALPHA) && (mContentFlags & CONTENT_COMPONENT_ALPHA) &&
@ -607,7 +688,7 @@ BasicThebesLayer::PaintThebes(gfxContext* aContext,
bool needsClipToVisibleRegion = GetClipToVisibleRegion(); bool needsClipToVisibleRegion = GetClipToVisibleRegion();
bool needsGroup = bool needsGroup =
opacity != 1.0 || GetOperator() != gfxContext::OPERATOR_OVER; opacity != 1.0 || GetOperator() != gfxContext::OPERATOR_OVER || aMaskLayer;
nsRefPtr<gfxContext> groupContext; nsRefPtr<gfxContext> groupContext;
if (needsGroup) { if (needsGroup) {
groupContext = groupContext =
@ -627,7 +708,7 @@ BasicThebesLayer::PaintThebes(gfxContext* aContext,
gfxUtils::ClipToRegion(aContext, toDraw); gfxUtils::ClipToRegion(aContext, toDraw);
} }
AutoSetOperator setOperator(aContext, GetOperator()); AutoSetOperator setOperator(aContext, GetOperator());
aContext->Paint(opacity); PaintWithMask(aContext, opacity, aMaskLayer);
} }
aContext->Restore(); aContext->Restore();
@ -688,7 +769,7 @@ BasicThebesLayer::PaintThebes(gfxContext* aContext,
clipExtents = aContext->GetClipExtents(); clipExtents = aContext->GetClipExtents();
if (!IsHidden() && !clipExtents.IsEmpty()) { if (!IsHidden() && !clipExtents.IsEmpty()) {
AutoSetOperator setOperator(aContext, GetOperator()); AutoSetOperator setOperator(aContext, GetOperator());
mBuffer.DrawTo(this, aContext, opacity); mBuffer.DrawTo(this, aContext, opacity, aMaskLayer);
} }
for (PRUint32 i = 0; i < readbackUpdates.Length(); ++i) { for (PRUint32 i = 0; i < readbackUpdates.Length(); ++i) {
@ -700,7 +781,7 @@ BasicThebesLayer::PaintThebes(gfxContext* aContext,
if (ctx) { if (ctx) {
NS_ASSERTION(opacity == 1.0, "Should only read back opaque layers"); NS_ASSERTION(opacity == 1.0, "Should only read back opaque layers");
ctx->Translate(gfxPoint(offset.x, offset.y)); ctx->Translate(gfxPoint(offset.x, offset.y));
mBuffer.DrawTo(this, ctx, 1.0); mBuffer.DrawTo(this, ctx, 1.0, aMaskLayer);
update.mLayer->GetSink()->EndUpdate(ctx, update.mUpdateRect + offset); update.mLayer->GetSink()->EndUpdate(ctx, update.mUpdateRect + offset);
} }
} }
@ -718,7 +799,8 @@ IsClippingCheap(gfxContext* aTarget, const nsIntRegion& aRegion)
void void
BasicThebesLayerBuffer::DrawTo(ThebesLayer* aLayer, BasicThebesLayerBuffer::DrawTo(ThebesLayer* aLayer,
gfxContext* aTarget, gfxContext* aTarget,
float aOpacity) float aOpacity,
Layer* aMaskLayer)
{ {
aTarget->Save(); aTarget->Save();
// If the entire buffer is valid, we can just draw the whole thing, // If the entire buffer is valid, we can just draw the whole thing,
@ -736,7 +818,16 @@ BasicThebesLayerBuffer::DrawTo(ThebesLayer* aLayer,
// and may cause gray lines. // and may cause gray lines.
gfxUtils::ClipToRegionSnapped(aTarget, aLayer->GetEffectiveVisibleRegion()); gfxUtils::ClipToRegionSnapped(aTarget, aLayer->GetEffectiveVisibleRegion());
} }
DrawBufferWithRotation(aTarget, aOpacity);
// Pull out the mask surface and transform here, because the mask
// is internal to basic layers
gfxMatrix maskTransform;
if (nsRefPtr<gfxASurface> maskSurface =
GetMaskSurfaceAndTransform(aMaskLayer, &maskTransform)) {
DrawBufferWithRotation(aTarget, aOpacity, maskSurface, &maskTransform);
} else {
DrawBufferWithRotation(aTarget, aOpacity);
}
aTarget->Restore(); aTarget->Restore();
} }
@ -785,12 +876,15 @@ public:
ImageLayer::SetVisibleRegion(aRegion); ImageLayer::SetVisibleRegion(aRegion);
} }
virtual void Paint(gfxContext* aContext); virtual void Paint(gfxContext* aContext, Layer* aMaskLayer);
static void PaintContext(gfxPattern* aPattern, static void PaintContext(gfxPattern* aPattern,
const nsIntRegion& aVisible, const nsIntRegion& aVisible,
float aOpacity, float aOpacity,
gfxContext* aContext); gfxContext* aContext,
Layer* aMaskLayer);
virtual already_AddRefed<gfxASurface> GetAsSurface();
protected: protected:
BasicLayerManager* BasicManager() BasicLayerManager* BasicManager()
@ -800,23 +894,25 @@ protected:
already_AddRefed<gfxPattern> already_AddRefed<gfxPattern>
GetAndPaintCurrentImage(gfxContext* aContext, GetAndPaintCurrentImage(gfxContext* aContext,
float aOpacity); float aOpacity,
Layer* aMaskLayer);
gfxIntSize mSize; gfxIntSize mSize;
}; };
void void
BasicImageLayer::Paint(gfxContext* aContext) BasicImageLayer::Paint(gfxContext* aContext, Layer* aMaskLayer)
{ {
if (IsHidden()) if (IsHidden())
return; return;
nsRefPtr<gfxPattern> dontcare = nsRefPtr<gfxPattern> dontcare =
GetAndPaintCurrentImage(aContext, GetEffectiveOpacity()); GetAndPaintCurrentImage(aContext, GetEffectiveOpacity(), aMaskLayer);
} }
already_AddRefed<gfxPattern> already_AddRefed<gfxPattern>
BasicImageLayer::GetAndPaintCurrentImage(gfxContext* aContext, BasicImageLayer::GetAndPaintCurrentImage(gfxContext* aContext,
float aOpacity) float aOpacity,
Layer* aMaskLayer)
{ {
if (!mContainer) if (!mContainer)
return nsnull; return nsnull;
@ -853,7 +949,7 @@ BasicImageLayer::GetAndPaintCurrentImage(gfxContext* aContext,
AutoSetOperator setOperator(aContext, GetOperator()); AutoSetOperator setOperator(aContext, GetOperator());
PaintContext(pat, PaintContext(pat,
nsIntRegion(nsIntRect(0, 0, size.width, size.height)), nsIntRegion(nsIntRect(0, 0, size.width, size.height)),
aOpacity, aContext); aOpacity, aContext, aMaskLayer);
GetContainer()->NotifyPaintedImage(image); GetContainer()->NotifyPaintedImage(image);
@ -864,7 +960,8 @@ BasicImageLayer::GetAndPaintCurrentImage(gfxContext* aContext,
BasicImageLayer::PaintContext(gfxPattern* aPattern, BasicImageLayer::PaintContext(gfxPattern* aPattern,
const nsIntRegion& aVisible, const nsIntRegion& aVisible,
float aOpacity, float aOpacity,
gfxContext* aContext) gfxContext* aContext,
Layer* aMaskLayer)
{ {
// Set PAD mode so that when the video is being scaled, we do not sample // Set PAD mode so that when the video is being scaled, we do not sample
// outside the bounds of the video image. // outside the bounds of the video image.
@ -888,12 +985,24 @@ BasicImageLayer::PaintContext(gfxPattern* aPattern,
gfxUtils::PathFromRegion(aContext, aVisible); gfxUtils::PathFromRegion(aContext, aVisible);
aPattern->SetExtend(extend); aPattern->SetExtend(extend);
aContext->SetPattern(aPattern); aContext->SetPattern(aPattern);
aContext->FillWithOpacity(aOpacity); FillWithMask(aContext, aOpacity, aMaskLayer);
// Reset extend mode for callers that need to reuse the pattern // Reset extend mode for callers that need to reuse the pattern
aPattern->SetExtend(extend); aPattern->SetExtend(extend);
} }
already_AddRefed<gfxASurface>
BasicImageLayer::GetAsSurface()
{
if (!mContainer) {
return nsnull;
}
gfxIntSize dontCare;
return mContainer->GetCurrentAsSurface(&dontCare);
}
class BasicColorLayer : public ColorLayer, public BasicImplData { class BasicColorLayer : public ColorLayer, public BasicImplData {
public: public:
BasicColorLayer(BasicLayerManager* aLayerManager) : BasicColorLayer(BasicLayerManager* aLayerManager) :
@ -913,16 +1022,17 @@ public:
ColorLayer::SetVisibleRegion(aRegion); ColorLayer::SetVisibleRegion(aRegion);
} }
virtual void Paint(gfxContext* aContext) virtual void Paint(gfxContext* aContext, Layer* aMaskLayer)
{ {
if (IsHidden()) if (IsHidden())
return; return;
AutoSetOperator setOperator(aContext, GetOperator()); AutoSetOperator setOperator(aContext, GetOperator());
PaintColorTo(mColor, GetEffectiveOpacity(), aContext); PaintColorTo(mColor, GetEffectiveOpacity(), aContext, aMaskLayer);
} }
static void PaintColorTo(gfxRGBA aColor, float aOpacity, static void PaintColorTo(gfxRGBA aColor, float aOpacity,
gfxContext* aContext); gfxContext* aContext,
Layer* aMaskLayer);
protected: protected:
BasicLayerManager* BasicManager() BasicLayerManager* BasicManager()
@ -933,10 +1043,11 @@ protected:
/*static*/ void /*static*/ void
BasicColorLayer::PaintColorTo(gfxRGBA aColor, float aOpacity, BasicColorLayer::PaintColorTo(gfxRGBA aColor, float aOpacity,
gfxContext* aContext) gfxContext* aContext,
Layer* aMaskLayer)
{ {
aContext->SetColor(aColor); aContext->SetColor(aColor);
aContext->Paint(aOpacity); PaintWithMask(aContext, aOpacity, aMaskLayer);
} }
class BasicCanvasLayer : public CanvasLayer, class BasicCanvasLayer : public CanvasLayer,
@ -961,10 +1072,11 @@ public:
} }
virtual void Initialize(const Data& aData); virtual void Initialize(const Data& aData);
virtual void Paint(gfxContext* aContext); virtual void Paint(gfxContext* aContext, Layer* aMaskLayer);
virtual void PaintWithOpacity(gfxContext* aContext, virtual void PaintWithOpacity(gfxContext* aContext,
float aOpacity); float aOpacity,
Layer* aMaskLayer = nsnull);
protected: protected:
BasicLayerManager* BasicManager() BasicLayerManager* BasicManager()
@ -1126,18 +1238,19 @@ BasicCanvasLayer::UpdateSurface(gfxASurface* aDestSurface)
} }
void void
BasicCanvasLayer::Paint(gfxContext* aContext) BasicCanvasLayer::Paint(gfxContext* aContext, Layer* aMaskLayer)
{ {
if (IsHidden()) if (IsHidden())
return; return;
UpdateSurface(); UpdateSurface();
FireDidTransactionCallback(); FireDidTransactionCallback();
PaintWithOpacity(aContext, GetEffectiveOpacity()); PaintWithOpacity(aContext, GetEffectiveOpacity(), aMaskLayer);
} }
void void
BasicCanvasLayer::PaintWithOpacity(gfxContext* aContext, BasicCanvasLayer::PaintWithOpacity(gfxContext* aContext,
float aOpacity) float aOpacity,
Layer* aMaskLayer)
{ {
NS_ASSERTION(BasicManager()->InDrawing(), NS_ASSERTION(BasicManager()->InDrawing(),
"Can only draw in drawing phase"); "Can only draw in drawing phase");
@ -1173,7 +1286,8 @@ BasicCanvasLayer::PaintWithOpacity(gfxContext* aContext,
// No need to snap here; our transform is already set up to snap our rect // No need to snap here; our transform is already set up to snap our rect
aContext->Rectangle(gfxRect(0, 0, mBounds.width, mBounds.height)); aContext->Rectangle(gfxRect(0, 0, mBounds.width, mBounds.height));
aContext->SetPattern(pat); aContext->SetPattern(pat);
aContext->FillWithOpacity(aOpacity);
FillWithMask(aContext, aOpacity, aMaskLayer);
#if defined (MOZ_X11) && defined (MOZ_EGL_XRENDER_COMPOSITE) #if defined (MOZ_X11) && defined (MOZ_EGL_XRENDER_COMPOSITE)
if (mGLContext) { if (mGLContext) {
@ -1779,15 +1893,20 @@ BasicLayerManager::PaintLayer(gfxContext* aTarget,
const nsIntRect* clipRect = aLayer->GetEffectiveClipRect(); const nsIntRect* clipRect = aLayer->GetEffectiveClipRect();
const gfx3DMatrix& effectiveTransform = aLayer->GetEffectiveTransform(); const gfx3DMatrix& effectiveTransform = aLayer->GetEffectiveTransform();
// aLayer might not be a container layer, but if so we take care not to use
// the container variable
BasicContainerLayer* container = static_cast<BasicContainerLayer*>(aLayer); BasicContainerLayer* container = static_cast<BasicContainerLayer*>(aLayer);
bool needsGroup = aLayer->GetFirstChild() && bool needsGroup = aLayer->GetFirstChild() &&
container->UseIntermediateSurface(); container->UseIntermediateSurface();
BasicImplData* data = ToData(aLayer); BasicImplData* data = ToData(aLayer);
bool needsClipToVisibleRegion = bool needsClipToVisibleRegion =
data->GetClipToVisibleRegion() && !aLayer->AsThebesLayer(); data->GetClipToVisibleRegion() && !aLayer->AsThebesLayer();
NS_ASSERTION(needsGroup || !aLayer->GetFirstChild() || NS_ASSERTION(needsGroup || !aLayer->GetFirstChild() ||
container->GetOperator() == gfxContext::OPERATOR_OVER, container->GetOperator() == gfxContext::OPERATOR_OVER,
"non-OVER operator should have forced UseIntermediateSurface"); "non-OVER operator should have forced UseIntermediateSurface");
NS_ASSERTION(!aLayer->GetFirstChild() || !aLayer->GetMaskLayer() ||
container->UseIntermediateSurface(),
"ContainerLayer with mask layer should force UseIntermediateSurface");
// If needsSaveRestore is false, we should still save and restore // If needsSaveRestore is false, we should still save and restore
// the CTM // the CTM
@ -1801,9 +1920,8 @@ BasicLayerManager::PaintLayer(gfxContext* aTarget,
aTarget->Rectangle(gfxRect(clipRect->x, clipRect->y, clipRect->width, clipRect->height), true); aTarget->Rectangle(gfxRect(clipRect->x, clipRect->y, clipRect->width, clipRect->height), true);
aTarget->Clip(); aTarget->Clip();
} }
} else {
savedMatrix = aTarget->CurrentMatrix();
} }
savedMatrix = aTarget->CurrentMatrix();
gfxMatrix transform; gfxMatrix transform;
// Will return an identity matrix for 3d transforms, and is handled separately below. // Will return an identity matrix for 3d transforms, and is handled separately below.
@ -1872,9 +1990,12 @@ BasicLayerManager::PaintLayer(gfxContext* aTarget,
(void*)aLayer, data->IsHidden())); (void*)aLayer, data->IsHidden()));
#endif #endif
if (aLayer->AsThebesLayer()) { if (aLayer->AsThebesLayer()) {
data->PaintThebes(groupTarget, aCallback, aCallbackData, aReadback); data->PaintThebes(groupTarget,
aLayer->GetMaskLayer(),
aCallback, aCallbackData,
aReadback);
} else { } else {
data->Paint(groupTarget); data->Paint(groupTarget, aLayer->GetMaskLayer());
} }
} else { } else {
ReadbackProcessor readback; ReadbackProcessor readback;
@ -1946,7 +2067,8 @@ BasicLayerManager::PaintLayer(gfxContext* aTarget,
gfxUtils::ClipToRegion(aTarget, aLayer->GetEffectiveVisibleRegion()); gfxUtils::ClipToRegion(aTarget, aLayer->GetEffectiveVisibleRegion());
} }
AutoSetOperator setOperator(aTarget, container->GetOperator()); AutoSetOperator setOperator(aTarget, container->GetOperator());
aTarget->Paint(aLayer->GetEffectiveOpacity()); gfxMatrix temp = aTarget->CurrentMatrix();
PaintWithMask(aTarget, aLayer->GetEffectiveOpacity(), aLayer->GetMaskLayer());
} }
} }
@ -2371,7 +2493,7 @@ public:
MOZ_COUNT_DTOR(BasicShadowableImageLayer); MOZ_COUNT_DTOR(BasicShadowableImageLayer);
} }
virtual void Paint(gfxContext* aContext); virtual void Paint(gfxContext* aContext, Layer* aMaskLayer);
virtual void FillSpecificAttributes(SpecificLayerAttributes& aAttrs) virtual void FillSpecificAttributes(SpecificLayerAttributes& aAttrs)
{ {
@ -2431,13 +2553,15 @@ private:
}; };
void void
BasicShadowableImageLayer::Paint(gfxContext* aContext) BasicShadowableImageLayer::Paint(gfxContext* aContext, Layer* aMaskLayer)
{ {
if (!HasShadow()) { if (!HasShadow()) {
BasicImageLayer::Paint(aContext); BasicImageLayer::Paint(aContext, aMaskLayer);
return; return;
} }
//TODO[nrc] masking
if (!mContainer) { if (!mContainer) {
return; return;
} }
@ -2495,7 +2619,8 @@ BasicShadowableImageLayer::Paint(gfxContext* aContext)
} }
gfxIntSize oldSize = mSize; gfxIntSize oldSize = mSize;
nsRefPtr<gfxPattern> pat = GetAndPaintCurrentImage(aContext, GetEffectiveOpacity()); nsRefPtr<gfxPattern> pat = GetAndPaintCurrentImage
(aContext, GetEffectiveOpacity(), aMaskLayer);
if (!pat || !HasShadow()) if (!pat || !HasShadow())
return; return;
@ -2520,7 +2645,7 @@ BasicShadowableImageLayer::Paint(gfxContext* aContext)
tmpCtx->SetOperator(gfxContext::OPERATOR_SOURCE); tmpCtx->SetOperator(gfxContext::OPERATOR_SOURCE);
PaintContext(pat, PaintContext(pat,
nsIntRegion(nsIntRect(0, 0, mSize.width, mSize.height)), nsIntRegion(nsIntRect(0, 0, mSize.width, mSize.height)),
1.0, tmpCtx); 1.0, tmpCtx, aMaskLayer);
BasicManager()->PaintedImage(BasicManager()->Hold(this), BasicManager()->PaintedImage(BasicManager()->Hold(this),
mBackBuffer); mBackBuffer);
@ -2572,7 +2697,7 @@ public:
} }
virtual void Initialize(const Data& aData); virtual void Initialize(const Data& aData);
virtual void Paint(gfxContext* aContext); virtual void Paint(gfxContext* aContext, Layer* aMaskLayer);
virtual void FillSpecificAttributes(SpecificLayerAttributes& aAttrs) virtual void FillSpecificAttributes(SpecificLayerAttributes& aAttrs)
{ {
@ -2631,13 +2756,15 @@ BasicShadowableCanvasLayer::Initialize(const Data& aData)
} }
void void
BasicShadowableCanvasLayer::Paint(gfxContext* aContext) BasicShadowableCanvasLayer::Paint(gfxContext* aContext, Layer* aMaskLayer)
{ {
if (!HasShadow()) { if (!HasShadow()) {
BasicCanvasLayer::Paint(aContext); BasicCanvasLayer::Paint(aContext, aMaskLayer);
return; return;
} }
//TODO[nrc] masking
bool isOpaque = (GetContentFlags() & CONTENT_OPAQUE); bool isOpaque = (GetContentFlags() & CONTENT_OPAQUE);
if (!IsSurfaceDescriptorValid(mBackBuffer) || if (!IsSurfaceDescriptorValid(mBackBuffer) ||
isOpaque != mBufferIsOpaque) { isOpaque != mBufferIsOpaque) {
@ -2746,6 +2873,7 @@ public:
} }
virtual void PaintThebes(gfxContext* aContext, virtual void PaintThebes(gfxContext* aContext,
Layer* aMaskLayer,
LayerManager::DrawThebesLayerCallback aCallback, LayerManager::DrawThebesLayerCallback aCallback,
void* aCallbackData, void* aCallbackData,
ReadbackProcessor* aReadback); ReadbackProcessor* aReadback);
@ -2815,6 +2943,7 @@ BasicShadowThebesLayer::Swap(const ThebesBuffer& aNewFront,
void void
BasicShadowThebesLayer::PaintThebes(gfxContext* aContext, BasicShadowThebesLayer::PaintThebes(gfxContext* aContext,
Layer* aMaskLayer,
LayerManager::DrawThebesLayerCallback aCallback, LayerManager::DrawThebesLayerCallback aCallback,
void* aCallbackData, void* aCallbackData,
ReadbackProcessor* aReadback) ReadbackProcessor* aReadback)
@ -2828,7 +2957,7 @@ BasicShadowThebesLayer::PaintThebes(gfxContext* aContext,
return; return;
} }
mFrontBuffer.DrawTo(this, aContext, GetEffectiveOpacity()); mFrontBuffer.DrawTo(this, aContext, GetEffectiveOpacity(), aMaskLayer);
} }
class BasicShadowContainerLayer : public ShadowContainerLayer, public BasicImplData { class BasicShadowContainerLayer : public ShadowContainerLayer, public BasicImplData {
@ -2882,8 +3011,10 @@ public:
* 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
*/ */
mUseIntermediateSurface = GetEffectiveOpacity() != 1.0 && HasMultipleChildren(); mUseIntermediateSurface = GetMaskLayer() ||
(GetEffectiveOpacity() != 1.0 && HasMultipleChildren());
} }
}; };
@ -2915,7 +3046,7 @@ public:
} }
} }
virtual void Paint(gfxContext* aContext); virtual void Paint(gfxContext* aContext, Layer* aMaskLayer);
protected: protected:
BasicShadowLayerManager* BasicManager() BasicShadowLayerManager* BasicManager()
@ -2955,7 +3086,7 @@ BasicShadowImageLayer::Swap(const SharedImage& aNewFront,
} }
void void
BasicShadowImageLayer::Paint(gfxContext* aContext) BasicShadowImageLayer::Paint(gfxContext* aContext, Layer* aMaskLayer)
{ {
if (!IsSurfaceDescriptorValid(mFrontBuffer)) { if (!IsSurfaceDescriptorValid(mFrontBuffer)) {
return; return;
@ -2971,7 +3102,8 @@ BasicShadowImageLayer::Paint(gfxContext* aContext)
AutoSetOperator setOperator(aContext, GetOperator()); AutoSetOperator setOperator(aContext, GetOperator());
BasicImageLayer::PaintContext(pat, BasicImageLayer::PaintContext(pat,
nsIntRegion(nsIntRect(0, 0, mSize.width, mSize.height)), nsIntRegion(nsIntRect(0, 0, mSize.width, mSize.height)),
GetEffectiveOpacity(), aContext); GetEffectiveOpacity(), aContext,
aMaskLayer);
} }
class BasicShadowColorLayer : public ShadowColorLayer, class BasicShadowColorLayer : public ShadowColorLayer,
@ -2988,10 +3120,11 @@ public:
MOZ_COUNT_DTOR(BasicShadowColorLayer); MOZ_COUNT_DTOR(BasicShadowColorLayer);
} }
virtual void Paint(gfxContext* aContext) virtual void Paint(gfxContext* aContext, Layer* aMaskLayer)
{ {
AutoSetOperator setOperator(aContext, GetOperator()); AutoSetOperator setOperator(aContext, GetOperator());
BasicColorLayer::PaintColorTo(mColor, GetEffectiveOpacity(), aContext); BasicColorLayer::PaintColorTo(mColor, GetEffectiveOpacity(),
aContext, aMaskLayer);
} }
}; };
@ -3025,7 +3158,7 @@ public:
} }
} }
virtual void Paint(gfxContext* aContext); virtual void Paint(gfxContext* aContext, Layer* aMaskLayer);
private: private:
BasicShadowLayerManager* BasicManager() BasicShadowLayerManager* BasicManager()
@ -3074,7 +3207,7 @@ BasicShadowCanvasLayer::Swap(const CanvasSurface& aNewFront, bool needYFlip,
} }
void void
BasicShadowCanvasLayer::Paint(gfxContext* aContext) BasicShadowCanvasLayer::Paint(gfxContext* aContext, Layer* aMaskLayer)
{ {
NS_ASSERTION(BasicManager()->InDrawing(), NS_ASSERTION(BasicManager()->InDrawing(),
"Can only draw in drawing phase"); "Can only draw in drawing phase");
@ -3104,6 +3237,7 @@ BasicShadowCanvasLayer::Paint(gfxContext* aContext)
// No need to snap here; our transform has already taken care of it // No need to snap here; our transform has already taken care of it
aContext->Rectangle(r); aContext->Rectangle(r);
aContext->SetPattern(pat); aContext->SetPattern(pat);
//TODO[nrc] masking
aContext->FillWithOpacity(GetEffectiveOpacity()); aContext->FillWithOpacity(GetEffectiveOpacity());
if (mNeedsYFlip) { if (mNeedsYFlip) {

Просмотреть файл

@ -69,7 +69,8 @@ BasicTiledLayerBuffer::PaintThebes(BasicTiledThebesLayer* aLayer,
const nsIntRegion& aNewValidRegion, const nsIntRegion& aNewValidRegion,
const nsIntRegion& aPaintRegion, const nsIntRegion& aPaintRegion,
LayerManager::DrawThebesLayerCallback aCallback, LayerManager::DrawThebesLayerCallback aCallback,
void* aCallbackData) void* aCallbackData,
Layer* aMaskLayer)
{ {
mThebesLayer = aLayer; mThebesLayer = aLayer;
mCallback = aCallback; mCallback = aCallback;
@ -95,6 +96,7 @@ BasicTiledLayerBuffer::PaintThebes(BasicTiledThebesLayer* aLayer,
start = PR_IntervalNow(); start = PR_IntervalNow();
#endif #endif
SAMPLE_LABEL("BasicTiledLayerBuffer", "PaintThebesSingleBufferDraw"); SAMPLE_LABEL("BasicTiledLayerBuffer", "PaintThebesSingleBufferDraw");
mCallback(mThebesLayer, ctxt, aPaintRegion, aPaintRegion, mCallbackData); mCallback(mThebesLayer, ctxt, aPaintRegion, aPaintRegion, mCallbackData);
} }
@ -213,6 +215,7 @@ BasicTiledThebesLayer::FillSpecificAttributes(SpecificLayerAttributes& aAttrs)
void void
BasicTiledThebesLayer::PaintThebes(gfxContext* aContext, BasicTiledThebesLayer::PaintThebes(gfxContext* aContext,
Layer* aMaskLayer,
LayerManager::DrawThebesLayerCallback aCallback, LayerManager::DrawThebesLayerCallback aCallback,
void* aCallbackData, void* aCallbackData,
ReadbackProcessor* aReadback) ReadbackProcessor* aReadback)
@ -232,7 +235,7 @@ BasicTiledThebesLayer::PaintThebes(gfxContext* aContext,
if (regionToPaint.IsEmpty()) if (regionToPaint.IsEmpty())
return; return;
mTiledBuffer.PaintThebes(this, mVisibleRegion, regionToPaint, aCallback, aCallbackData); mTiledBuffer.PaintThebes(this, mVisibleRegion, regionToPaint, aCallback, aCallbackData, aMaskLayer);
mTiledBuffer.ReadLock(); mTiledBuffer.ReadLock();
mValidRegion = mVisibleRegion; mValidRegion = mVisibleRegion;

Просмотреть файл

@ -86,7 +86,8 @@ public:
const nsIntRegion& aNewValidRegion, const nsIntRegion& aNewValidRegion,
const nsIntRegion& aPaintRegion, const nsIntRegion& aPaintRegion,
LayerManager::DrawThebesLayerCallback aCallback, LayerManager::DrawThebesLayerCallback aCallback,
void* aCallbackData); void* aCallbackData,
Layer* aMaskLayer);
BasicTiledLayerTile GetPlaceholderTile() const { BasicTiledLayerTile GetPlaceholderTile() const {
return mPlaceholder; return mPlaceholder;
@ -184,6 +185,7 @@ public:
} }
virtual void PaintThebes(gfxContext* aContext, virtual void PaintThebes(gfxContext* aContext,
Layer* aMaskLayer,
LayerManager::DrawThebesLayerCallback aCallback, LayerManager::DrawThebesLayerCallback aCallback,
void* aCallbackData, void* aCallbackData,
ReadbackProcessor* aReadback); ReadbackProcessor* aReadback);