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

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

@ -171,9 +171,18 @@ protected:
TOP, BOTTOM
};
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,
float aOpacity);
void DrawBufferWithRotation(gfxContext* aTarget, float aOpacity);
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

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

@ -50,7 +50,7 @@ public:
* set up to account for all the properties of the layer (transform,
* opacity, etc).
*/
virtual void Paint(gfxContext* aContext) {}
virtual void Paint(gfxContext* aContext, Layer* aMaskLayer) {}
/**
* 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).
*/
virtual void PaintThebes(gfxContext* aContext,
Layer* aMasklayer,
LayerManager::DrawThebesLayerCallback aCallback,
void* aCallbackData,
ReadbackProcessor* aReadback) {}
@ -99,6 +100,14 @@ public:
mOperator = aOperator;
}
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; }
void SetClipToVisibleRegion(bool aClip) { mClipToVisibleRegion = aClip; }

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

@ -108,6 +108,78 @@ static void ContainerInsertAfter(Layer* aChild, Layer* aAfter, Container* aConta
template<class Container>
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 {
template<class Container>
friend void ContainerInsertAfter(Layer* aChild, Layer* aAfter, Container* aContainer);
@ -155,6 +227,7 @@ public:
if (!idealTransform.CanDraw2D()) {
mEffectiveTransform = idealTransform;
ComputeEffectiveTransformsForChildren(gfx3DMatrix());
ComputeEffectiveTransformForMaskLayer(gfx3DMatrix());
mUseIntermediateSurface = true;
return;
}
@ -164,12 +237,16 @@ public:
// need to apply any compensation using the residual from SnapTransform.
ComputeEffectiveTransformsForChildren(idealTransform);
ComputeEffectiveTransformForMaskLayer(aTransformToSurface);
/* 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
* an intermediate surface so our children don't inherit our opacity
* 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
* to aTarget.
*/
void DrawTo(ThebesLayer* aLayer, gfxContext* aTarget, float aOpacity);
void DrawTo(ThebesLayer* aLayer, gfxContext* aTarget, float aOpacity,
Layer* aMaskLayer);
virtual already_AddRefed<gfxASurface>
CreateBuffer(ContentType aType, const nsIntSize& aSize, PRUint32 aFlags);
@ -401,6 +479,7 @@ public:
}
virtual void PaintThebes(gfxContext* aContext,
Layer* aMaskLayer,
LayerManager::DrawThebesLayerCallback aCallback,
void* aCallbackData,
ReadbackProcessor* aReadback);
@ -438,6 +517,7 @@ public:
mResidualTranslation = gfxPoint(0,0);
mValidRegion.SetEmpty();
}
ComputeEffectiveTransformForMaskLayer(aTransformToSurface);
return;
}
ThebesLayer::ComputeEffectiveTransforms(aTransformToSurface);
@ -563,6 +643,7 @@ BasicLayerManager::PushGroupForLayer(gfxContext* aContext, Layer* aLayer,
void
BasicThebesLayer::PaintThebes(gfxContext* aContext,
Layer* aMaskLayer,
LayerManager::DrawThebesLayerCallback aCallback,
void* aCallbackData,
ReadbackProcessor* aReadback)
@ -583,7 +664,7 @@ BasicThebesLayer::PaintThebes(gfxContext* aContext,
canUseOpaqueSurface ? gfxASurface::CONTENT_COLOR :
gfxASurface::CONTENT_COLOR_ALPHA;
float opacity = GetEffectiveOpacity();
if (!BasicManager()->IsRetained() ||
(!canUseOpaqueSurface &&
(mContentFlags & CONTENT_COMPONENT_ALPHA) &&
@ -607,7 +688,7 @@ BasicThebesLayer::PaintThebes(gfxContext* aContext,
bool needsClipToVisibleRegion = GetClipToVisibleRegion();
bool needsGroup =
opacity != 1.0 || GetOperator() != gfxContext::OPERATOR_OVER;
opacity != 1.0 || GetOperator() != gfxContext::OPERATOR_OVER || aMaskLayer;
nsRefPtr<gfxContext> groupContext;
if (needsGroup) {
groupContext =
@ -627,7 +708,7 @@ BasicThebesLayer::PaintThebes(gfxContext* aContext,
gfxUtils::ClipToRegion(aContext, toDraw);
}
AutoSetOperator setOperator(aContext, GetOperator());
aContext->Paint(opacity);
PaintWithMask(aContext, opacity, aMaskLayer);
}
aContext->Restore();
@ -688,7 +769,7 @@ BasicThebesLayer::PaintThebes(gfxContext* aContext,
clipExtents = aContext->GetClipExtents();
if (!IsHidden() && !clipExtents.IsEmpty()) {
AutoSetOperator setOperator(aContext, GetOperator());
mBuffer.DrawTo(this, aContext, opacity);
mBuffer.DrawTo(this, aContext, opacity, aMaskLayer);
}
for (PRUint32 i = 0; i < readbackUpdates.Length(); ++i) {
@ -700,7 +781,7 @@ BasicThebesLayer::PaintThebes(gfxContext* aContext,
if (ctx) {
NS_ASSERTION(opacity == 1.0, "Should only read back opaque layers");
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);
}
}
@ -718,7 +799,8 @@ IsClippingCheap(gfxContext* aTarget, const nsIntRegion& aRegion)
void
BasicThebesLayerBuffer::DrawTo(ThebesLayer* aLayer,
gfxContext* aTarget,
float aOpacity)
float aOpacity,
Layer* aMaskLayer)
{
aTarget->Save();
// 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.
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();
}
@ -785,12 +876,15 @@ public:
ImageLayer::SetVisibleRegion(aRegion);
}
virtual void Paint(gfxContext* aContext);
virtual void Paint(gfxContext* aContext, Layer* aMaskLayer);
static void PaintContext(gfxPattern* aPattern,
const nsIntRegion& aVisible,
float aOpacity,
gfxContext* aContext);
gfxContext* aContext,
Layer* aMaskLayer);
virtual already_AddRefed<gfxASurface> GetAsSurface();
protected:
BasicLayerManager* BasicManager()
@ -800,23 +894,25 @@ protected:
already_AddRefed<gfxPattern>
GetAndPaintCurrentImage(gfxContext* aContext,
float aOpacity);
float aOpacity,
Layer* aMaskLayer);
gfxIntSize mSize;
};
void
BasicImageLayer::Paint(gfxContext* aContext)
BasicImageLayer::Paint(gfxContext* aContext, Layer* aMaskLayer)
{
if (IsHidden())
return;
nsRefPtr<gfxPattern> dontcare =
GetAndPaintCurrentImage(aContext, GetEffectiveOpacity());
GetAndPaintCurrentImage(aContext, GetEffectiveOpacity(), aMaskLayer);
}
already_AddRefed<gfxPattern>
BasicImageLayer::GetAndPaintCurrentImage(gfxContext* aContext,
float aOpacity)
float aOpacity,
Layer* aMaskLayer)
{
if (!mContainer)
return nsnull;
@ -853,7 +949,7 @@ BasicImageLayer::GetAndPaintCurrentImage(gfxContext* aContext,
AutoSetOperator setOperator(aContext, GetOperator());
PaintContext(pat,
nsIntRegion(nsIntRect(0, 0, size.width, size.height)),
aOpacity, aContext);
aOpacity, aContext, aMaskLayer);
GetContainer()->NotifyPaintedImage(image);
@ -864,7 +960,8 @@ BasicImageLayer::GetAndPaintCurrentImage(gfxContext* aContext,
BasicImageLayer::PaintContext(gfxPattern* aPattern,
const nsIntRegion& aVisible,
float aOpacity,
gfxContext* aContext)
gfxContext* aContext,
Layer* aMaskLayer)
{
// Set PAD mode so that when the video is being scaled, we do not sample
// outside the bounds of the video image.
@ -888,12 +985,24 @@ BasicImageLayer::PaintContext(gfxPattern* aPattern,
gfxUtils::PathFromRegion(aContext, aVisible);
aPattern->SetExtend(extend);
aContext->SetPattern(aPattern);
aContext->FillWithOpacity(aOpacity);
FillWithMask(aContext, aOpacity, aMaskLayer);
// Reset extend mode for callers that need to reuse the pattern
aPattern->SetExtend(extend);
}
already_AddRefed<gfxASurface>
BasicImageLayer::GetAsSurface()
{
if (!mContainer) {
return nsnull;
}
gfxIntSize dontCare;
return mContainer->GetCurrentAsSurface(&dontCare);
}
class BasicColorLayer : public ColorLayer, public BasicImplData {
public:
BasicColorLayer(BasicLayerManager* aLayerManager) :
@ -913,16 +1022,17 @@ public:
ColorLayer::SetVisibleRegion(aRegion);
}
virtual void Paint(gfxContext* aContext)
virtual void Paint(gfxContext* aContext, Layer* aMaskLayer)
{
if (IsHidden())
return;
AutoSetOperator setOperator(aContext, GetOperator());
PaintColorTo(mColor, GetEffectiveOpacity(), aContext);
PaintColorTo(mColor, GetEffectiveOpacity(), aContext, aMaskLayer);
}
static void PaintColorTo(gfxRGBA aColor, float aOpacity,
gfxContext* aContext);
gfxContext* aContext,
Layer* aMaskLayer);
protected:
BasicLayerManager* BasicManager()
@ -933,10 +1043,11 @@ protected:
/*static*/ void
BasicColorLayer::PaintColorTo(gfxRGBA aColor, float aOpacity,
gfxContext* aContext)
gfxContext* aContext,
Layer* aMaskLayer)
{
aContext->SetColor(aColor);
aContext->Paint(aOpacity);
PaintWithMask(aContext, aOpacity, aMaskLayer);
}
class BasicCanvasLayer : public CanvasLayer,
@ -961,10 +1072,11 @@ public:
}
virtual void Initialize(const Data& aData);
virtual void Paint(gfxContext* aContext);
virtual void Paint(gfxContext* aContext, Layer* aMaskLayer);
virtual void PaintWithOpacity(gfxContext* aContext,
float aOpacity);
float aOpacity,
Layer* aMaskLayer = nsnull);
protected:
BasicLayerManager* BasicManager()
@ -1126,18 +1238,19 @@ BasicCanvasLayer::UpdateSurface(gfxASurface* aDestSurface)
}
void
BasicCanvasLayer::Paint(gfxContext* aContext)
BasicCanvasLayer::Paint(gfxContext* aContext, Layer* aMaskLayer)
{
if (IsHidden())
return;
UpdateSurface();
FireDidTransactionCallback();
PaintWithOpacity(aContext, GetEffectiveOpacity());
PaintWithOpacity(aContext, GetEffectiveOpacity(), aMaskLayer);
}
void
BasicCanvasLayer::PaintWithOpacity(gfxContext* aContext,
float aOpacity)
float aOpacity,
Layer* aMaskLayer)
{
NS_ASSERTION(BasicManager()->InDrawing(),
"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
aContext->Rectangle(gfxRect(0, 0, mBounds.width, mBounds.height));
aContext->SetPattern(pat);
aContext->FillWithOpacity(aOpacity);
FillWithMask(aContext, aOpacity, aMaskLayer);
#if defined (MOZ_X11) && defined (MOZ_EGL_XRENDER_COMPOSITE)
if (mGLContext) {
@ -1779,15 +1893,20 @@ BasicLayerManager::PaintLayer(gfxContext* aTarget,
const nsIntRect* clipRect = aLayer->GetEffectiveClipRect();
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);
bool needsGroup = aLayer->GetFirstChild() &&
container->UseIntermediateSurface();
container->UseIntermediateSurface();
BasicImplData* data = ToData(aLayer);
bool needsClipToVisibleRegion =
data->GetClipToVisibleRegion() && !aLayer->AsThebesLayer();
NS_ASSERTION(needsGroup || !aLayer->GetFirstChild() ||
container->GetOperator() == gfxContext::OPERATOR_OVER,
"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
// the CTM
@ -1801,9 +1920,8 @@ BasicLayerManager::PaintLayer(gfxContext* aTarget,
aTarget->Rectangle(gfxRect(clipRect->x, clipRect->y, clipRect->width, clipRect->height), true);
aTarget->Clip();
}
} else {
savedMatrix = aTarget->CurrentMatrix();
}
savedMatrix = aTarget->CurrentMatrix();
gfxMatrix transform;
// 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()));
#endif
if (aLayer->AsThebesLayer()) {
data->PaintThebes(groupTarget, aCallback, aCallbackData, aReadback);
data->PaintThebes(groupTarget,
aLayer->GetMaskLayer(),
aCallback, aCallbackData,
aReadback);
} else {
data->Paint(groupTarget);
data->Paint(groupTarget, aLayer->GetMaskLayer());
}
} else {
ReadbackProcessor readback;
@ -1946,7 +2067,8 @@ BasicLayerManager::PaintLayer(gfxContext* aTarget,
gfxUtils::ClipToRegion(aTarget, aLayer->GetEffectiveVisibleRegion());
}
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);
}
virtual void Paint(gfxContext* aContext);
virtual void Paint(gfxContext* aContext, Layer* aMaskLayer);
virtual void FillSpecificAttributes(SpecificLayerAttributes& aAttrs)
{
@ -2431,13 +2553,15 @@ private:
};
void
BasicShadowableImageLayer::Paint(gfxContext* aContext)
BasicShadowableImageLayer::Paint(gfxContext* aContext, Layer* aMaskLayer)
{
if (!HasShadow()) {
BasicImageLayer::Paint(aContext);
BasicImageLayer::Paint(aContext, aMaskLayer);
return;
}
//TODO[nrc] masking
if (!mContainer) {
return;
}
@ -2495,7 +2619,8 @@ BasicShadowableImageLayer::Paint(gfxContext* aContext)
}
gfxIntSize oldSize = mSize;
nsRefPtr<gfxPattern> pat = GetAndPaintCurrentImage(aContext, GetEffectiveOpacity());
nsRefPtr<gfxPattern> pat = GetAndPaintCurrentImage
(aContext, GetEffectiveOpacity(), aMaskLayer);
if (!pat || !HasShadow())
return;
@ -2520,7 +2645,7 @@ BasicShadowableImageLayer::Paint(gfxContext* aContext)
tmpCtx->SetOperator(gfxContext::OPERATOR_SOURCE);
PaintContext(pat,
nsIntRegion(nsIntRect(0, 0, mSize.width, mSize.height)),
1.0, tmpCtx);
1.0, tmpCtx, aMaskLayer);
BasicManager()->PaintedImage(BasicManager()->Hold(this),
mBackBuffer);
@ -2572,7 +2697,7 @@ public:
}
virtual void Initialize(const Data& aData);
virtual void Paint(gfxContext* aContext);
virtual void Paint(gfxContext* aContext, Layer* aMaskLayer);
virtual void FillSpecificAttributes(SpecificLayerAttributes& aAttrs)
{
@ -2631,13 +2756,15 @@ BasicShadowableCanvasLayer::Initialize(const Data& aData)
}
void
BasicShadowableCanvasLayer::Paint(gfxContext* aContext)
BasicShadowableCanvasLayer::Paint(gfxContext* aContext, Layer* aMaskLayer)
{
if (!HasShadow()) {
BasicCanvasLayer::Paint(aContext);
BasicCanvasLayer::Paint(aContext, aMaskLayer);
return;
}
//TODO[nrc] masking
bool isOpaque = (GetContentFlags() & CONTENT_OPAQUE);
if (!IsSurfaceDescriptorValid(mBackBuffer) ||
isOpaque != mBufferIsOpaque) {
@ -2746,6 +2873,7 @@ public:
}
virtual void PaintThebes(gfxContext* aContext,
Layer* aMaskLayer,
LayerManager::DrawThebesLayerCallback aCallback,
void* aCallbackData,
ReadbackProcessor* aReadback);
@ -2815,6 +2943,7 @@ BasicShadowThebesLayer::Swap(const ThebesBuffer& aNewFront,
void
BasicShadowThebesLayer::PaintThebes(gfxContext* aContext,
Layer* aMaskLayer,
LayerManager::DrawThebesLayerCallback aCallback,
void* aCallbackData,
ReadbackProcessor* aReadback)
@ -2828,7 +2957,7 @@ BasicShadowThebesLayer::PaintThebes(gfxContext* aContext,
return;
}
mFrontBuffer.DrawTo(this, aContext, GetEffectiveOpacity());
mFrontBuffer.DrawTo(this, aContext, GetEffectiveOpacity(), aMaskLayer);
}
class BasicShadowContainerLayer : public ShadowContainerLayer, public BasicImplData {
@ -2882,8 +3011,10 @@ public:
* otherwise we need a PushGroup and we need to mark ourselves as using
* an intermediate surface so our children don't inherit our opacity
* 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:
BasicShadowLayerManager* BasicManager()
@ -2955,7 +3086,7 @@ BasicShadowImageLayer::Swap(const SharedImage& aNewFront,
}
void
BasicShadowImageLayer::Paint(gfxContext* aContext)
BasicShadowImageLayer::Paint(gfxContext* aContext, Layer* aMaskLayer)
{
if (!IsSurfaceDescriptorValid(mFrontBuffer)) {
return;
@ -2971,7 +3102,8 @@ BasicShadowImageLayer::Paint(gfxContext* aContext)
AutoSetOperator setOperator(aContext, GetOperator());
BasicImageLayer::PaintContext(pat,
nsIntRegion(nsIntRect(0, 0, mSize.width, mSize.height)),
GetEffectiveOpacity(), aContext);
GetEffectiveOpacity(), aContext,
aMaskLayer);
}
class BasicShadowColorLayer : public ShadowColorLayer,
@ -2988,10 +3120,11 @@ public:
MOZ_COUNT_DTOR(BasicShadowColorLayer);
}
virtual void Paint(gfxContext* aContext)
virtual void Paint(gfxContext* aContext, Layer* aMaskLayer)
{
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:
BasicShadowLayerManager* BasicManager()
@ -3074,7 +3207,7 @@ BasicShadowCanvasLayer::Swap(const CanvasSurface& aNewFront, bool needYFlip,
}
void
BasicShadowCanvasLayer::Paint(gfxContext* aContext)
BasicShadowCanvasLayer::Paint(gfxContext* aContext, Layer* aMaskLayer)
{
NS_ASSERTION(BasicManager()->InDrawing(),
"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
aContext->Rectangle(r);
aContext->SetPattern(pat);
//TODO[nrc] masking
aContext->FillWithOpacity(GetEffectiveOpacity());
if (mNeedsYFlip) {

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

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

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

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