зеркало из https://github.com/mozilla/pjs.git
Backout bug 629866 and bug 647560.
This commit is contained in:
Родитель
45110d1301
Коммит
bac56e54f3
|
@ -92,7 +92,7 @@ class ShadowableLayer;
|
|||
*/
|
||||
class BasicImplData {
|
||||
public:
|
||||
BasicImplData() : mHidden(PR_FALSE), mOperator(gfxContext::OPERATOR_OVER)
|
||||
BasicImplData()
|
||||
{
|
||||
MOZ_COUNT_CTOR(BasicImplData);
|
||||
}
|
||||
|
@ -136,45 +136,16 @@ public:
|
|||
virtual void ClearCachedResources() {}
|
||||
|
||||
/**
|
||||
* This variable is set by MarkLayersHidden() before painting. It indicates
|
||||
* that the layer should not be composited during this transaction.
|
||||
* This variable is used by layer manager in order to
|
||||
* MarkLeafLayersCoveredByOpaque() before painting.
|
||||
* We keep it here for now. Once we need to cull completely covered
|
||||
* non-Basic layers, mCoveredByOpaque should be moved to Layer.
|
||||
*/
|
||||
void SetHidden(PRBool aCovered) { mHidden = aCovered; }
|
||||
PRBool IsHidden() const { return PR_FALSE; }
|
||||
/**
|
||||
* This variable is set by MarkLayersHidden() before painting. This is
|
||||
* the operator to be used when compositing the layer in this transaction. It must
|
||||
* be OVER or SOURCE.
|
||||
*/
|
||||
void SetOperator(gfxContext::GraphicsOperator aOperator)
|
||||
{
|
||||
NS_ASSERTION(aOperator == gfxContext::OPERATOR_OVER ||
|
||||
aOperator == gfxContext::OPERATOR_SOURCE,
|
||||
"Bad composition operator");
|
||||
mOperator = aOperator;
|
||||
}
|
||||
gfxContext::GraphicsOperator GetOperator() const { return mOperator; }
|
||||
void SetCoveredByOpaque(PRBool aCovered) { mCoveredByOpaque = aCovered; }
|
||||
PRBool IsCoveredByOpaque() const { return mCoveredByOpaque; }
|
||||
|
||||
protected:
|
||||
PRPackedBool mHidden;
|
||||
gfxContext::GraphicsOperator mOperator;
|
||||
};
|
||||
|
||||
class AutoSetOperator {
|
||||
public:
|
||||
AutoSetOperator(gfxContext* aContext, gfxContext::GraphicsOperator aOperator) {
|
||||
if (aOperator != gfxContext::OPERATOR_OVER) {
|
||||
aContext->SetOperator(aOperator);
|
||||
mContext = aContext;
|
||||
}
|
||||
}
|
||||
~AutoSetOperator() {
|
||||
if (mContext) {
|
||||
mContext->SetOperator(gfxContext::OPERATOR_OVER);
|
||||
}
|
||||
}
|
||||
private:
|
||||
nsRefPtr<gfxContext> mContext;
|
||||
PRPackedBool mCoveredByOpaque;
|
||||
};
|
||||
|
||||
static BasicImplData*
|
||||
|
@ -188,7 +159,7 @@ static void ContainerInsertAfter(Layer* aChild, Layer* aAfter, Container* aConta
|
|||
template<class Container>
|
||||
static void ContainerRemoveChild(Layer* aChild, Container* aContainer);
|
||||
|
||||
class BasicContainerLayer : public ContainerLayer, public BasicImplData {
|
||||
class BasicContainerLayer : public ContainerLayer, BasicImplData {
|
||||
template<class Container>
|
||||
friend void ContainerInsertAfter(Layer* aChild, Layer* aAfter, Container* aContainer);
|
||||
template<class Container>
|
||||
|
@ -242,23 +213,6 @@ public:
|
|||
mUseIntermediateSurface = GetEffectiveOpacity() != 1.0 && HasMultipleChildren();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true when:
|
||||
* a) no (non-hidden) childrens' visible areas overlap in
|
||||
* (aInRect intersected with this layer's visible region).
|
||||
* b) the (non-hidden) childrens' visible areas cover
|
||||
* (aInRect intersected with this layer's visible region).
|
||||
* c) this layer and all (non-hidden) children have transforms that are translations
|
||||
* by integers.
|
||||
* aInRect is in the root coordinate system.
|
||||
* Child layers with opacity do not contribute to the covered area in check b).
|
||||
* This method can be conservative; it's OK to return false under any
|
||||
* circumstances.
|
||||
*/
|
||||
PRBool ChildrenPartitionVisibleRegion(const nsIntRect& aInRect);
|
||||
|
||||
void ForceIntermediateSurface() { mUseIntermediateSurface = PR_TRUE; }
|
||||
|
||||
protected:
|
||||
BasicLayerManager* BasicManager()
|
||||
{
|
||||
|
@ -275,43 +229,6 @@ BasicContainerLayer::~BasicContainerLayer()
|
|||
MOZ_COUNT_DTOR(BasicContainerLayer);
|
||||
}
|
||||
|
||||
PRBool
|
||||
BasicContainerLayer::ChildrenPartitionVisibleRegion(const nsIntRect& aInRect)
|
||||
{
|
||||
gfxMatrix transform;
|
||||
if (!GetEffectiveTransform().Is2D(&transform) ||
|
||||
transform.HasNonIntegerTranslation())
|
||||
return PR_FALSE;
|
||||
|
||||
nsIntPoint offset(PRInt32(transform.x0), PRInt32(transform.y0));
|
||||
nsIntRect rect = aInRect.Intersect(GetEffectiveVisibleRegion().GetBounds() + offset);
|
||||
nsIntRegion covered;
|
||||
|
||||
for (Layer* l = mFirstChild; l; l = l->GetNextSibling()) {
|
||||
if (ToData(l)->IsHidden())
|
||||
continue;
|
||||
|
||||
gfxMatrix childTransform;
|
||||
if (!l->GetEffectiveTransform().Is2D(&childTransform) ||
|
||||
childTransform.HasNonIntegerTranslation() ||
|
||||
l->GetEffectiveOpacity() != 1.0)
|
||||
return PR_FALSE;
|
||||
nsIntRegion childRegion = l->GetEffectiveVisibleRegion();
|
||||
childRegion.MoveBy(PRInt32(childTransform.x0), PRInt32(childTransform.y0));
|
||||
childRegion.And(childRegion, rect);
|
||||
if (l->GetClipRect()) {
|
||||
childRegion.And(childRegion, *l->GetClipRect() + offset);
|
||||
}
|
||||
nsIntRegion intersection;
|
||||
intersection.And(covered, childRegion);
|
||||
if (!intersection.IsEmpty())
|
||||
return PR_FALSE;
|
||||
covered.Or(covered, childRegion);
|
||||
}
|
||||
|
||||
return covered.Contains(rect);
|
||||
}
|
||||
|
||||
template<class Container>
|
||||
static void
|
||||
ContainerInsertAfter(Layer* aChild, Layer* aAfter, Container* aContainer)
|
||||
|
@ -444,7 +361,7 @@ private:
|
|||
BasicThebesLayer* mLayer;
|
||||
};
|
||||
|
||||
class BasicThebesLayer : public ThebesLayer, public BasicImplData {
|
||||
class BasicThebesLayer : public ThebesLayer, BasicImplData {
|
||||
public:
|
||||
typedef BasicThebesLayerBuffer Buffer;
|
||||
|
||||
|
@ -583,16 +500,15 @@ SetAntialiasingFlags(Layer* aLayer, gfxContext* aTarget)
|
|||
aTarget->UserToDevice(gfxRect(bounds.x, bounds.y, bounds.width, bounds.height))));
|
||||
}
|
||||
|
||||
already_AddRefed<gfxContext>
|
||||
BasicLayerManager::PushGroupForLayer(gfxContext* aContext, Layer* aLayer,
|
||||
const nsIntRegion& aRegion,
|
||||
PRBool* aNeedsClipToVisibleRegion)
|
||||
static PRBool
|
||||
PushGroupForLayer(gfxContext* aContext, Layer* aLayer, const nsIntRegion& aRegion)
|
||||
{
|
||||
// If we need to call PushGroup, we should clip to the smallest possible
|
||||
// area first to minimize the size of the temporary surface.
|
||||
PRBool didCompleteClip = ClipToContain(aContext, aRegion.GetBounds());
|
||||
|
||||
nsRefPtr<gfxContext> result;
|
||||
gfxASurface::gfxContentType contentType = gfxASurface::CONTENT_COLOR_ALPHA;
|
||||
PRBool needsClipToVisibleRegion = PR_FALSE;
|
||||
if (aLayer->CanUseOpaqueSurface() &&
|
||||
((didCompleteClip && aRegion.GetNumRects() == 1) ||
|
||||
!aContext->CurrentMatrix().HasNonIntegerTranslation())) {
|
||||
|
@ -600,14 +516,11 @@ BasicLayerManager::PushGroupForLayer(gfxContext* aContext, Layer* aLayer,
|
|||
// group. We need to make sure that only pixels inside the layer's visible
|
||||
// region are copied back to the destination. Remember if we've already
|
||||
// clipped precisely to the visible region.
|
||||
*aNeedsClipToVisibleRegion = !didCompleteClip || aRegion.GetNumRects() > 1;
|
||||
result = PushGroupWithCachedSurface(aContext, gfxASurface::CONTENT_COLOR);
|
||||
} else {
|
||||
*aNeedsClipToVisibleRegion = PR_FALSE;
|
||||
result = aContext;
|
||||
aContext->PushGroupAndCopyBackground(gfxASurface::CONTENT_COLOR_ALPHA);
|
||||
needsClipToVisibleRegion = !didCompleteClip || aRegion.GetNumRects() > 1;
|
||||
contentType = gfxASurface::CONTENT_COLOR;
|
||||
}
|
||||
return result.forget();
|
||||
aContext->PushGroupAndCopyBackground(contentType);
|
||||
return needsClipToVisibleRegion;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -640,8 +553,8 @@ BasicThebesLayer::PaintThebes(gfxContext* aContext,
|
|||
mValidRegion.SetEmpty();
|
||||
mBuffer.Clear();
|
||||
|
||||
nsIntRegion toDraw = IntersectWithClip(GetEffectiveVisibleRegion(), aContext);
|
||||
if (!toDraw.IsEmpty() && !IsHidden()) {
|
||||
nsIntRegion toDraw = IntersectWithClip(mVisibleRegion, aContext);
|
||||
if (!toDraw.IsEmpty()) {
|
||||
if (!aCallback) {
|
||||
BasicManager()->SetTransactionIncomplete();
|
||||
return;
|
||||
|
@ -650,27 +563,16 @@ BasicThebesLayer::PaintThebes(gfxContext* aContext,
|
|||
aContext->Save();
|
||||
|
||||
PRBool needsClipToVisibleRegion = PR_FALSE;
|
||||
PRBool needsGroup =
|
||||
opacity != 1.0 || GetOperator() != gfxContext::OPERATOR_OVER;
|
||||
nsRefPtr<gfxContext> groupContext;
|
||||
if (needsGroup) {
|
||||
groupContext =
|
||||
BasicManager()->PushGroupForLayer(aContext, this, toDraw,
|
||||
&needsClipToVisibleRegion);
|
||||
if (GetOperator() != gfxContext::OPERATOR_OVER) {
|
||||
needsClipToVisibleRegion = PR_TRUE;
|
||||
}
|
||||
} else {
|
||||
groupContext = aContext;
|
||||
if (opacity != 1.0) {
|
||||
needsClipToVisibleRegion = PushGroupForLayer(aContext, this, toDraw);
|
||||
}
|
||||
SetAntialiasingFlags(this, groupContext);
|
||||
aCallback(this, groupContext, toDraw, nsIntRegion(), aCallbackData);
|
||||
if (needsGroup) {
|
||||
BasicManager()->PopGroupToSourceWithCachedSurface(aContext, groupContext);
|
||||
SetAntialiasingFlags(this, aContext);
|
||||
aCallback(this, aContext, toDraw, nsIntRegion(), aCallbackData);
|
||||
if (opacity != 1.0) {
|
||||
aContext->PopGroupToSource();
|
||||
if (needsClipToVisibleRegion) {
|
||||
gfxUtils::ClipToRegion(aContext, toDraw);
|
||||
}
|
||||
AutoSetOperator setOperator(aContext, GetOperator());
|
||||
aContext->Paint(opacity);
|
||||
}
|
||||
|
||||
|
@ -699,8 +601,7 @@ BasicThebesLayer::PaintThebes(gfxContext* aContext,
|
|||
// (this could be the whole visible area if our buffer switched
|
||||
// from RGB to RGBA, because we might need to repaint with
|
||||
// subpixel AA)
|
||||
state.mRegionToInvalidate.And(state.mRegionToInvalidate,
|
||||
GetEffectiveVisibleRegion());
|
||||
state.mRegionToInvalidate.And(state.mRegionToInvalidate, mVisibleRegion);
|
||||
nsIntRegion extendedDrawRegion = state.mRegionToDraw;
|
||||
extendedDrawRegion.ExtendForScaling(paintXRes, paintYRes);
|
||||
mXResolution = paintXRes;
|
||||
|
@ -719,10 +620,7 @@ BasicThebesLayer::PaintThebes(gfxContext* aContext,
|
|||
}
|
||||
}
|
||||
|
||||
if (!IsHidden()) {
|
||||
AutoSetOperator setOperator(aContext, GetOperator());
|
||||
mBuffer.DrawTo(this, aContext, opacity);
|
||||
}
|
||||
mBuffer.DrawTo(this, aContext, opacity);
|
||||
|
||||
for (PRUint32 i = 0; i < readbackUpdates.Length(); ++i) {
|
||||
ReadbackProcessor::Update& update = readbackUpdates[i];
|
||||
|
@ -758,13 +656,13 @@ BasicThebesLayerBuffer::DrawTo(ThebesLayer* aLayer,
|
|||
// no need to clip. But we'll still clip if clipping is cheap ---
|
||||
// that might let us copy a smaller region of the buffer.
|
||||
if (!aLayer->GetValidRegion().Contains(BufferRect()) ||
|
||||
IsClippingCheap(aTarget, aLayer->GetEffectiveVisibleRegion())) {
|
||||
IsClippingCheap(aTarget, aLayer->GetVisibleRegion())) {
|
||||
// We don't want to draw invalid stuff, so we need to clip. Might as
|
||||
// well clip to the smallest area possible --- the visible region.
|
||||
// Bug 599189 if there is a non-integer-translation transform in aTarget,
|
||||
// we might sample pixels outside GetEffectiveVisibleRegion(), which is wrong
|
||||
// we might sample pixels outside GetVisibleRegion(), which is wrong
|
||||
// and may cause gray lines.
|
||||
gfxUtils::ClipToRegionSnapped(aTarget, aLayer->GetEffectiveVisibleRegion());
|
||||
gfxUtils::ClipToRegionSnapped(aTarget, aLayer->GetVisibleRegion());
|
||||
}
|
||||
DrawBufferWithRotation(aTarget, aOpacity,
|
||||
aLayer->GetXResolution(), aLayer->GetYResolution());
|
||||
|
@ -797,7 +695,7 @@ BasicThebesLayerBuffer::SetBackingBufferAndUpdateFrom(
|
|||
srcBuffer.DrawBufferWithRotation(destCtx, 1.0, aXResolution, aYResolution);
|
||||
}
|
||||
|
||||
class BasicImageLayer : public ImageLayer, public BasicImplData {
|
||||
class BasicImageLayer : public ImageLayer, BasicImplData {
|
||||
public:
|
||||
BasicImageLayer(BasicLayerManager* aLayerManager) :
|
||||
ImageLayer(aLayerManager, static_cast<BasicImplData*>(this)),
|
||||
|
@ -841,8 +739,6 @@ protected:
|
|||
void
|
||||
BasicImageLayer::Paint(gfxContext* aContext)
|
||||
{
|
||||
if (IsHidden())
|
||||
return;
|
||||
nsRefPtr<gfxPattern> dontcare =
|
||||
GetAndPaintCurrentImage(aContext, GetEffectiveOpacity());
|
||||
}
|
||||
|
@ -872,7 +768,6 @@ BasicImageLayer::GetAndPaintCurrentImage(gfxContext* aContext,
|
|||
// tiling, we don't want to draw into that area, so just draw within
|
||||
// the image bounds.
|
||||
const nsIntRect* tileSrcRect = GetTileSourceRect();
|
||||
AutoSetOperator setOperator(aContext, GetOperator());
|
||||
PaintContext(pat,
|
||||
tileSrcRect ? GetVisibleRegion() : nsIntRegion(nsIntRect(0, 0, mSize.width, mSize.height)),
|
||||
tileSrcRect,
|
||||
|
@ -934,7 +829,7 @@ BasicImageLayer::PaintContext(gfxPattern* aPattern,
|
|||
aPattern->SetExtend(extend);
|
||||
}
|
||||
|
||||
class BasicColorLayer : public ColorLayer, public BasicImplData {
|
||||
class BasicColorLayer : public ColorLayer, BasicImplData {
|
||||
public:
|
||||
BasicColorLayer(BasicLayerManager* aLayerManager) :
|
||||
ColorLayer(aLayerManager, static_cast<BasicImplData*>(this))
|
||||
|
@ -955,9 +850,6 @@ public:
|
|||
|
||||
virtual void Paint(gfxContext* aContext)
|
||||
{
|
||||
if (IsHidden())
|
||||
return;
|
||||
AutoSetOperator setOperator(aContext, GetOperator());
|
||||
PaintColorTo(mColor, GetEffectiveOpacity(), aContext);
|
||||
}
|
||||
|
||||
|
@ -980,7 +872,7 @@ BasicColorLayer::PaintColorTo(gfxRGBA aColor, float aOpacity,
|
|||
}
|
||||
|
||||
class BasicCanvasLayer : public CanvasLayer,
|
||||
public BasicImplData
|
||||
BasicImplData
|
||||
{
|
||||
public:
|
||||
BasicCanvasLayer(BasicLayerManager* aLayerManager) :
|
||||
|
@ -1102,8 +994,6 @@ BasicCanvasLayer::UpdateSurface()
|
|||
void
|
||||
BasicCanvasLayer::Paint(gfxContext* aContext)
|
||||
{
|
||||
if (IsHidden())
|
||||
return;
|
||||
UpdateSurface();
|
||||
FireDidTransactionCallback();
|
||||
PaintWithOpacity(aContext, GetEffectiveOpacity());
|
||||
|
@ -1128,7 +1018,6 @@ BasicCanvasLayer::PaintWithOpacity(gfxContext* aContext,
|
|||
aContext->Scale(1.0, -1.0);
|
||||
}
|
||||
|
||||
AutoSetOperator setOperator(aContext, GetOperator());
|
||||
aContext->NewPath();
|
||||
// No need to snap here; our transform is already set up to snap our rect
|
||||
aContext->Rectangle(gfxRect(0, 0, mBounds.width, mBounds.height));
|
||||
|
@ -1141,7 +1030,7 @@ BasicCanvasLayer::PaintWithOpacity(gfxContext* aContext,
|
|||
}
|
||||
|
||||
class BasicReadbackLayer : public ReadbackLayer,
|
||||
public BasicImplData
|
||||
BasicImplData
|
||||
{
|
||||
public:
|
||||
BasicReadbackLayer(BasicLayerManager* aLayerManager) :
|
||||
|
@ -1184,6 +1073,64 @@ ToInsideIntRect(const gfxRect& aRect)
|
|||
return nsIntRect(r.X(), r.Y(), r.Width(), r.Height());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns false if there is at most one leaf layer overlapping aBounds
|
||||
* and that layer is opaque.
|
||||
* aDirtyVisibleRegionInContainer is filled in only if we return false.
|
||||
* It contains the union of the visible regions of leaf layers under aLayer.
|
||||
*/
|
||||
static PRBool
|
||||
MayHaveOverlappingOrTransparentLayers(Layer* aLayer,
|
||||
const nsIntRect& aBounds,
|
||||
nsIntRegion* aDirtyVisibleRegionInContainer)
|
||||
{
|
||||
if (!(aLayer->GetContentFlags() & Layer::CONTENT_OPAQUE)) {
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
gfxMatrix matrix;
|
||||
if (!aLayer->GetTransform().Is2D(&matrix) ||
|
||||
matrix.HasNonIntegerTranslation()) {
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
nsIntPoint translation = nsIntPoint(PRInt32(matrix.x0), PRInt32(matrix.y0));
|
||||
nsIntRect bounds = aBounds - translation;
|
||||
|
||||
nsIntRect clippedDirtyRect = bounds;
|
||||
const nsIntRect* clipRect = aLayer->GetClipRect();
|
||||
if (clipRect) {
|
||||
clippedDirtyRect.IntersectRect(clippedDirtyRect, *clipRect - translation);
|
||||
}
|
||||
aDirtyVisibleRegionInContainer->And(aLayer->GetVisibleRegion(), clippedDirtyRect);
|
||||
aDirtyVisibleRegionInContainer->MoveBy(translation);
|
||||
|
||||
/* Ignore layers outside the clip rect */
|
||||
if (aDirtyVisibleRegionInContainer->IsEmpty()) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
nsIntRegion region;
|
||||
|
||||
for (Layer* child = aLayer->GetFirstChild(); child;
|
||||
child = child->GetNextSibling()) {
|
||||
nsIntRegion childRegion;
|
||||
if (MayHaveOverlappingOrTransparentLayers(child, bounds, &childRegion)) {
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
nsIntRegion tmp;
|
||||
tmp.And(region, childRegion);
|
||||
if (!tmp.IsEmpty()) {
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
region.Or(region, childRegion);
|
||||
}
|
||||
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
BasicLayerManager::BasicLayerManager(nsIWidget* aWidget) :
|
||||
#ifdef DEBUG
|
||||
mPhase(PHASE_NONE),
|
||||
|
@ -1192,7 +1139,6 @@ BasicLayerManager::BasicLayerManager(nsIWidget* aWidget) :
|
|||
, mYResolution(1.0)
|
||||
, mWidget(aWidget)
|
||||
, mDoubleBuffering(BUFFER_NONE), mUsingDefaultTarget(PR_FALSE)
|
||||
, mCachedSurfaceInUse(PR_FALSE)
|
||||
, mTransactionIncomplete(false)
|
||||
{
|
||||
MOZ_COUNT_CTOR(BasicLayerManager);
|
||||
|
@ -1239,15 +1185,9 @@ BasicLayerManager::BeginTransaction()
|
|||
|
||||
already_AddRefed<gfxContext>
|
||||
BasicLayerManager::PushGroupWithCachedSurface(gfxContext *aTarget,
|
||||
gfxASurface::gfxContentType aContent)
|
||||
gfxASurface::gfxContentType aContent,
|
||||
gfxPoint *aSavedOffset)
|
||||
{
|
||||
if (mCachedSurfaceInUse) {
|
||||
aTarget->PushGroup(aContent);
|
||||
nsRefPtr<gfxContext> result = aTarget;
|
||||
return result.forget();
|
||||
}
|
||||
mCachedSurfaceInUse = PR_TRUE;
|
||||
|
||||
gfxContextMatrixAutoSaveRestore saveMatrix(aTarget);
|
||||
aTarget->IdentityMatrix();
|
||||
|
||||
|
@ -1255,26 +1195,29 @@ BasicLayerManager::PushGroupWithCachedSurface(gfxContext *aTarget,
|
|||
gfxRect clip = aTarget->GetClipExtents();
|
||||
clip.RoundOut();
|
||||
|
||||
nsRefPtr<gfxContext> ctx = mCachedSurface.Get(aContent, clip, currentSurf);
|
||||
nsRefPtr<gfxContext> ctx =
|
||||
mCachedSurface.Get(aContent,
|
||||
gfxIntSize(clip.Width(), clip.Height()),
|
||||
currentSurf);
|
||||
/* Align our buffer for the original surface */
|
||||
ctx->SetMatrix(saveMatrix.Matrix());
|
||||
ctx->Translate(-clip.TopLeft());
|
||||
*aSavedOffset = clip.TopLeft();
|
||||
ctx->Multiply(saveMatrix.Matrix());
|
||||
return ctx.forget();
|
||||
}
|
||||
|
||||
void
|
||||
BasicLayerManager::PopGroupToSourceWithCachedSurface(gfxContext *aTarget, gfxContext *aPushed)
|
||||
BasicLayerManager::PopGroupWithCachedSurface(gfxContext *aTarget,
|
||||
const gfxPoint& aSavedOffset)
|
||||
{
|
||||
if (!aTarget)
|
||||
if (!mTarget)
|
||||
return;
|
||||
nsRefPtr<gfxASurface> current = aPushed->CurrentSurface();
|
||||
if (mCachedSurface.IsSurface(current)) {
|
||||
gfxContextMatrixAutoSaveRestore saveMatrix(aTarget);
|
||||
aTarget->IdentityMatrix();
|
||||
aTarget->SetSource(current);
|
||||
mCachedSurfaceInUse = PR_FALSE;
|
||||
} else {
|
||||
aTarget->PopGroupToSource();
|
||||
}
|
||||
|
||||
gfxContextMatrixAutoSaveRestore saveMatrix(aTarget);
|
||||
aTarget->IdentityMatrix();
|
||||
|
||||
aTarget->SetSource(mTarget->OriginalSurface(), aSavedOffset);
|
||||
aTarget->Paint();
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -1301,36 +1244,25 @@ TransformIntRect(nsIntRect& aRect, const gfxMatrix& aMatrix,
|
|||
aRect = (*aRoundMethod)(gr);
|
||||
}
|
||||
|
||||
/**
|
||||
* This function assumes that GetEffectiveTransform transforms
|
||||
* all layers to the same coordinate system (the "root coordinate system").
|
||||
* It can't be used as is by accelerated layers because of intermediate surfaces.
|
||||
* This must set the hidden flag to true or false on *all* layers in the subtree.
|
||||
* It also sets the operator for all layers to "OVER".
|
||||
* @param aClipRect the cliprect, in the root coordinate system. We assume
|
||||
* that any layer drawing is clipped to this rect. It is therefore not
|
||||
* allowed to add to the opaque region outside that rect.
|
||||
* @param aDirtyRect the dirty rect that will be painted, in the root
|
||||
* coordinate system. Layers outside this rect should be hidden.
|
||||
* @param aOpaqueRegion the opaque region covering aLayer, in the
|
||||
* root coordinate system.
|
||||
*/
|
||||
enum {
|
||||
ALLOW_OPAQUE = 0x01,
|
||||
};
|
||||
// This implementation assumes that GetEffectiveTransform transforms
|
||||
// all layers to the same coordinate system. It can't be used as is
|
||||
// by accelerated layers because of intermediate surfaces.
|
||||
// aClipRect and aRegion are in that global coordinate system.
|
||||
static void
|
||||
MarkLayersHidden(Layer* aLayer, const nsIntRect& aClipRect,
|
||||
const nsIntRect& aDirtyRect,
|
||||
nsIntRegion& aOpaqueRegion,
|
||||
PRUint32 aFlags)
|
||||
MarkLeafLayersCoveredByOpaque(Layer* aLayer, const nsIntRect& aClipRect,
|
||||
nsIntRegion& aRegion)
|
||||
{
|
||||
Layer* child = aLayer->GetLastChild();
|
||||
BasicImplData* data = ToData(aLayer);
|
||||
data->SetCoveredByOpaque(PR_FALSE);
|
||||
|
||||
nsIntRect newClipRect(aClipRect);
|
||||
PRUint32 newFlags = aFlags;
|
||||
|
||||
// Allow aLayer or aLayer's descendants to cover underlying layers
|
||||
// only if it's opaque.
|
||||
// only if it's opaque. GetEffectiveOpacity() could be used instead,
|
||||
// but it does extra passes from descendant to ancestor.
|
||||
if (aLayer->GetOpacity() != 1.0f) {
|
||||
newFlags &= ~ALLOW_OPAQUE;
|
||||
newClipRect.SetRect(0, 0, 0, 0);
|
||||
}
|
||||
|
||||
{
|
||||
|
@ -1342,8 +1274,6 @@ MarkLayersHidden(Layer* aLayer, const nsIntRect& aClipRect,
|
|||
if (aLayer->GetParent()) {
|
||||
gfxMatrix tr;
|
||||
if (aLayer->GetParent()->GetEffectiveTransform().Is2D(&tr)) {
|
||||
// Clip rect is applied after aLayer's transform, i.e., in the coordinate
|
||||
// system of aLayer's parent.
|
||||
TransformIntRect(cr, tr, ToInsideIntRect);
|
||||
} else {
|
||||
cr.SetRect(0, 0, 0, 0);
|
||||
|
@ -1353,102 +1283,36 @@ MarkLayersHidden(Layer* aLayer, const nsIntRect& aClipRect,
|
|||
}
|
||||
}
|
||||
|
||||
BasicImplData* data = ToData(aLayer);
|
||||
data->SetOperator(gfxContext::OPERATOR_OVER);
|
||||
|
||||
if (!aLayer->AsContainerLayer()) {
|
||||
if (!child) {
|
||||
gfxMatrix transform;
|
||||
if (!aLayer->GetEffectiveTransform().Is2D(&transform)) {
|
||||
data->SetHidden(PR_FALSE);
|
||||
return;
|
||||
}
|
||||
|
||||
nsIntRegion region = aLayer->GetEffectiveVisibleRegion();
|
||||
nsIntRect r = region.GetBounds();
|
||||
TransformIntRect(r, transform, ToOutsideIntRect);
|
||||
r.IntersectRect(r, aDirtyRect);
|
||||
data->SetHidden(aOpaqueRegion.Contains(r));
|
||||
data->SetCoveredByOpaque(aRegion.Contains(r));
|
||||
|
||||
// Allow aLayer to cover underlying layers only if aLayer's
|
||||
// content is opaque
|
||||
if ((aLayer->GetContentFlags() & Layer::CONTENT_OPAQUE) &&
|
||||
(newFlags & ALLOW_OPAQUE)) {
|
||||
nsIntRegionRectIterator it(region);
|
||||
while (const nsIntRect* sr = it.Next()) {
|
||||
r = *sr;
|
||||
TransformIntRect(r, transform, ToInsideIntRect);
|
||||
if (!(aLayer->GetContentFlags() & Layer::CONTENT_OPAQUE)) {
|
||||
return;
|
||||
}
|
||||
|
||||
r.IntersectRect(r, newClipRect);
|
||||
aOpaqueRegion.Or(aOpaqueRegion, r);
|
||||
nsIntRegionRectIterator it(region);
|
||||
while (const nsIntRect* sr = it.Next()) {
|
||||
r = *sr;
|
||||
TransformIntRect(r, transform, ToInsideIntRect);
|
||||
|
||||
r.IntersectRect(r, newClipRect);
|
||||
if (!r.IsEmpty()) {
|
||||
aRegion.Or(aRegion, r);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Layer* child = aLayer->GetLastChild();
|
||||
PRBool allHidden = PR_TRUE;
|
||||
for (; child; child = child->GetPrevSibling()) {
|
||||
MarkLayersHidden(child, newClipRect, aDirtyRect, aOpaqueRegion, newFlags);
|
||||
if (!ToData(child)->IsHidden()) {
|
||||
allHidden = PR_FALSE;
|
||||
}
|
||||
}
|
||||
data->SetHidden(allHidden);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This function assumes that GetEffectiveTransform transforms
|
||||
* all layers to the same coordinate system (the "root coordinate system").
|
||||
* MarkLayersHidden must be called before calling this.
|
||||
* @param aVisibleRect the rectangle of aLayer that is visible (i.e. not
|
||||
* clipped and in the dirty rect), in the root coordinate system.
|
||||
*/
|
||||
static void
|
||||
ApplyDoubleBuffering(Layer* aLayer, const nsIntRect& aVisibleRect)
|
||||
{
|
||||
BasicImplData* data = ToData(aLayer);
|
||||
if (data->IsHidden())
|
||||
return;
|
||||
|
||||
nsIntRect newVisibleRect(aVisibleRect);
|
||||
|
||||
{
|
||||
const nsIntRect* clipRect = aLayer->GetEffectiveClipRect();
|
||||
if (clipRect) {
|
||||
nsIntRect cr = *clipRect;
|
||||
// clipRect is in the container's coordinate system. Get it into the
|
||||
// global coordinate system.
|
||||
if (aLayer->GetParent()) {
|
||||
gfxMatrix tr;
|
||||
if (aLayer->GetParent()->GetEffectiveTransform().Is2D(&tr)) {
|
||||
NS_ASSERTION(!tr.HasNonIntegerTranslation(),
|
||||
"Parent can only have an integer translation");
|
||||
cr += nsIntPoint(PRInt32(tr.x0), PRInt32(tr.y0));
|
||||
} else {
|
||||
NS_ERROR("Parent can only have an integer translation");
|
||||
}
|
||||
}
|
||||
newVisibleRect.IntersectRect(newVisibleRect, cr);
|
||||
}
|
||||
}
|
||||
|
||||
BasicContainerLayer* container =
|
||||
static_cast<BasicContainerLayer*>(aLayer->AsContainerLayer());
|
||||
// Layers that act as their own backbuffers should be drawn to the destination
|
||||
// using OPERATOR_SOURCE to ensure that alpha values in a transparent window
|
||||
// are cleared. This can also be faster than OPERATOR_OVER.
|
||||
if (!container) {
|
||||
data->SetOperator(gfxContext::OPERATOR_SOURCE);
|
||||
} else {
|
||||
if (container->UseIntermediateSurface() ||
|
||||
!container->ChildrenPartitionVisibleRegion(newVisibleRect)) {
|
||||
// We need to double-buffer this container.
|
||||
data->SetOperator(gfxContext::OPERATOR_SOURCE);
|
||||
container->ForceIntermediateSurface();
|
||||
} else {
|
||||
for (Layer* child = aLayer->GetFirstChild(); child;
|
||||
child = child->GetNextSibling()) {
|
||||
ApplyDoubleBuffering(child, newVisibleRect);
|
||||
}
|
||||
MarkLeafLayersCoveredByOpaque(child, newClipRect, aRegion);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1477,39 +1341,50 @@ BasicLayerManager::EndTransactionInternal(DrawThebesLayerCallback aCallback,
|
|||
mTransactionIncomplete = false;
|
||||
|
||||
if (mTarget && mRoot) {
|
||||
nsIntRect clipRect;
|
||||
if (HasShadowManager()) {
|
||||
// If this has a shadow manager, the clip extents of mTarget are meaningless.
|
||||
// So instead just use the root layer's visible region bounds.
|
||||
const nsIntRect& bounds = mRoot->GetVisibleRegion().GetBounds();
|
||||
gfxRect deviceRect =
|
||||
mTarget->UserToDevice(gfxRect(bounds.x, bounds.y, bounds.width, bounds.height));
|
||||
clipRect = ToOutsideIntRect(deviceRect);
|
||||
} else {
|
||||
gfxContextMatrixAutoSaveRestore save(mTarget);
|
||||
mTarget->SetMatrix(gfxMatrix());
|
||||
clipRect = ToOutsideIntRect(mTarget->GetClipExtents());
|
||||
nsRefPtr<gfxContext> finalTarget = mTarget;
|
||||
gfxPoint cachedSurfaceOffset;
|
||||
|
||||
nsIntRegion rootRegion;
|
||||
PRBool useDoubleBuffering = mUsingDefaultTarget &&
|
||||
mDoubleBuffering != BUFFER_NONE &&
|
||||
MayHaveOverlappingOrTransparentLayers(mRoot,
|
||||
ToOutsideIntRect(mTarget->GetClipExtents()),
|
||||
&rootRegion);
|
||||
if (useDoubleBuffering) {
|
||||
nsRefPtr<gfxASurface> targetSurface = mTarget->CurrentSurface();
|
||||
mTarget = PushGroupWithCachedSurface(mTarget, targetSurface->GetContentType(),
|
||||
&cachedSurfaceOffset);
|
||||
}
|
||||
|
||||
// Need to do this before we call ApplyDoubleBuffering,
|
||||
// which depends on correct effective transforms
|
||||
mSnapEffectiveTransforms =
|
||||
!(mTarget->GetFlags() & gfxContext::FLAG_DISABLE_SNAPPING);
|
||||
mRoot->ComputeEffectiveTransforms(gfx3DMatrix::From2D(mTarget->CurrentMatrix()));
|
||||
|
||||
if (IsRetained()) {
|
||||
nsIntRegion region;
|
||||
MarkLayersHidden(mRoot, clipRect, clipRect, region, ALLOW_OPAQUE);
|
||||
if (mUsingDefaultTarget && mDoubleBuffering != BUFFER_NONE) {
|
||||
ApplyDoubleBuffering(mRoot, clipRect);
|
||||
}
|
||||
}
|
||||
nsIntRegion region;
|
||||
MarkLeafLayersCoveredByOpaque(mRoot,
|
||||
mRoot->GetEffectiveVisibleRegion().GetBounds(),
|
||||
region);
|
||||
PaintLayer(mRoot, aCallback, aCallbackData, nsnull);
|
||||
|
||||
PaintLayer(mTarget, mRoot, aCallback, aCallbackData, nsnull);
|
||||
// If we're doing manual double-buffering, we need to avoid drawing
|
||||
// the results of an incomplete transaction to the destination surface.
|
||||
// If the transaction is incomplete and we're not double-buffering then
|
||||
// either the system is double-buffering our window (in which case the
|
||||
// followup EndTransaction will be drawn over the top of our incomplete
|
||||
// transaction before the system updates the window), or we have no
|
||||
// overlapping or transparent layers in the update region, in which case
|
||||
// our partial transaction drawing will look fine.
|
||||
if (useDoubleBuffering && !mTransactionIncomplete) {
|
||||
finalTarget->SetOperator(gfxContext::OPERATOR_SOURCE);
|
||||
PopGroupWithCachedSurface(finalTarget, cachedSurfaceOffset);
|
||||
}
|
||||
|
||||
if (!mTransactionIncomplete) {
|
||||
// Clear out target if we have a complete transaction.
|
||||
mTarget = nsnull;
|
||||
} else {
|
||||
// If we don't have a complete transaction set back to the old mTarget.
|
||||
mTarget = finalTarget;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1558,36 +1433,30 @@ BasicLayerManager::SetRoot(Layer* aLayer)
|
|||
}
|
||||
|
||||
void
|
||||
BasicLayerManager::PaintLayer(gfxContext* aTarget,
|
||||
Layer* aLayer,
|
||||
BasicLayerManager::PaintLayer(Layer* aLayer,
|
||||
DrawThebesLayerCallback aCallback,
|
||||
void* aCallbackData,
|
||||
ReadbackProcessor* aReadback)
|
||||
{
|
||||
const nsIntRect* clipRect = aLayer->GetEffectiveClipRect();
|
||||
const gfx3DMatrix& effectiveTransform = aLayer->GetEffectiveTransform();
|
||||
BasicContainerLayer* container = static_cast<BasicContainerLayer*>(aLayer);
|
||||
PRBool needsGroup = aLayer->GetFirstChild() &&
|
||||
container->UseIntermediateSurface();
|
||||
NS_ASSERTION(needsGroup || !aLayer->GetFirstChild() ||
|
||||
container->GetOperator() == gfxContext::OPERATOR_OVER,
|
||||
"non-OVER operator should have forced UseIntermediateSurface");
|
||||
|
||||
static_cast<BasicContainerLayer*>(aLayer)->UseIntermediateSurface();
|
||||
// If needsSaveRestore is false, we should still save and restore
|
||||
// the CTM
|
||||
PRBool needsSaveRestore = needsGroup || clipRect;
|
||||
|
||||
gfxMatrix savedMatrix;
|
||||
if (needsSaveRestore) {
|
||||
aTarget->Save();
|
||||
mTarget->Save();
|
||||
|
||||
if (clipRect) {
|
||||
aTarget->NewPath();
|
||||
aTarget->Rectangle(gfxRect(clipRect->x, clipRect->y, clipRect->width, clipRect->height), PR_TRUE);
|
||||
aTarget->Clip();
|
||||
mTarget->NewPath();
|
||||
mTarget->Rectangle(gfxRect(clipRect->x, clipRect->y, clipRect->width, clipRect->height), PR_TRUE);
|
||||
mTarget->Clip();
|
||||
}
|
||||
} else {
|
||||
savedMatrix = aTarget->CurrentMatrix();
|
||||
savedMatrix = mTarget->CurrentMatrix();
|
||||
}
|
||||
|
||||
gfxMatrix transform;
|
||||
|
@ -1596,11 +1465,11 @@ BasicLayerManager::PaintLayer(gfxContext* aTarget,
|
|||
NS_ASSERTION(effectiveTransform.Is2D(),
|
||||
"Only 2D transforms supported currently");
|
||||
effectiveTransform.Is2D(&transform);
|
||||
aTarget->SetMatrix(transform);
|
||||
mTarget->SetMatrix(transform);
|
||||
|
||||
PRBool pushedTargetOpaqueRect = PR_FALSE;
|
||||
const nsIntRegion& visibleRegion = aLayer->GetEffectiveVisibleRegion();
|
||||
nsRefPtr<gfxASurface> currentSurface = aTarget->CurrentSurface();
|
||||
nsRefPtr<gfxASurface> currentSurface = mTarget->CurrentSurface();
|
||||
const gfxRect& targetOpaqueRect = currentSurface->GetOpaqueRect();
|
||||
|
||||
// Try to annotate currentSurface with a region of pixels that have been
|
||||
|
@ -1610,17 +1479,14 @@ BasicLayerManager::PaintLayer(gfxContext* aTarget,
|
|||
!transform.HasNonAxisAlignedTransform()) {
|
||||
const nsIntRect& bounds = visibleRegion.GetBounds();
|
||||
currentSurface->SetOpaqueRect(
|
||||
aTarget->UserToDevice(gfxRect(bounds.x, bounds.y, bounds.width, bounds.height)));
|
||||
mTarget->UserToDevice(gfxRect(bounds.x, bounds.y, bounds.width, bounds.height)));
|
||||
pushedTargetOpaqueRect = PR_TRUE;
|
||||
}
|
||||
|
||||
PRBool needsClipToVisibleRegion = PR_FALSE;
|
||||
nsRefPtr<gfxContext> groupTarget;
|
||||
if (needsGroup) {
|
||||
groupTarget = PushGroupForLayer(aTarget, aLayer, aLayer->GetEffectiveVisibleRegion(),
|
||||
&needsClipToVisibleRegion);
|
||||
} else {
|
||||
groupTarget = aTarget;
|
||||
needsClipToVisibleRegion =
|
||||
PushGroupForLayer(mTarget, aLayer, aLayer->GetEffectiveVisibleRegion());
|
||||
}
|
||||
|
||||
/* Only paint ourself, or our children - This optimization relies on this! */
|
||||
|
@ -1629,12 +1495,14 @@ BasicLayerManager::PaintLayer(gfxContext* aTarget,
|
|||
BasicImplData* data = ToData(aLayer);
|
||||
#ifdef MOZ_LAYERS_HAVE_LOG
|
||||
MOZ_LAYERS_LOG(("%s (0x%p) is covered: %i\n", __FUNCTION__,
|
||||
(void*)aLayer, data->IsHidden()));
|
||||
(void*)aLayer, data->IsCoveredByOpaque()));
|
||||
#endif
|
||||
if (aLayer->AsThebesLayer()) {
|
||||
data->PaintThebes(groupTarget, aCallback, aCallbackData, aReadback);
|
||||
} else {
|
||||
data->Paint(groupTarget);
|
||||
if (!data->IsCoveredByOpaque()) {
|
||||
if (aLayer->AsThebesLayer()) {
|
||||
data->PaintThebes(mTarget, aCallback, aCallbackData, aReadback);
|
||||
} else {
|
||||
data->Paint(mTarget);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
ReadbackProcessor readback;
|
||||
|
@ -1644,30 +1512,18 @@ BasicLayerManager::PaintLayer(gfxContext* aTarget,
|
|||
}
|
||||
|
||||
for (; child; child = child->GetNextSibling()) {
|
||||
PaintLayer(groupTarget, child, aCallback, aCallbackData, &readback);
|
||||
PaintLayer(child, aCallback, aCallbackData, &readback);
|
||||
if (mTransactionIncomplete)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (needsGroup) {
|
||||
PopGroupToSourceWithCachedSurface(aTarget, groupTarget);
|
||||
// If we're doing our own double-buffering, we need to avoid drawing
|
||||
// the results of an incomplete transaction to the destination surface ---
|
||||
// that could cause flicker. Double-buffering is implemented using a
|
||||
// temporary surface for one or more container layers, so we need to stop
|
||||
// those temporary surfaces from being composited to aTarget.
|
||||
// ApplyDoubleBuffering guarantees that this container layer can't
|
||||
// intersect any other leaf layers, so if the transaction is not yet marked
|
||||
// incomplete, the contents of this container layer are the final contents
|
||||
// for the window.
|
||||
if (!mTransactionIncomplete) {
|
||||
if (needsClipToVisibleRegion) {
|
||||
gfxUtils::ClipToRegion(aTarget, aLayer->GetEffectiveVisibleRegion());
|
||||
}
|
||||
AutoSetOperator setOperator(aTarget, container->GetOperator());
|
||||
aTarget->Paint(aLayer->GetEffectiveOpacity());
|
||||
mTarget->PopGroupToSource();
|
||||
if (needsClipToVisibleRegion) {
|
||||
gfxUtils::ClipToRegion(mTarget, aLayer->GetEffectiveVisibleRegion());
|
||||
}
|
||||
mTarget->Paint(aLayer->GetEffectiveOpacity());
|
||||
}
|
||||
|
||||
if (pushedTargetOpaqueRect) {
|
||||
|
@ -1675,9 +1531,9 @@ BasicLayerManager::PaintLayer(gfxContext* aTarget,
|
|||
}
|
||||
|
||||
if (needsSaveRestore) {
|
||||
aTarget->Restore();
|
||||
mTarget->Restore();
|
||||
} else {
|
||||
aTarget->SetMatrix(savedMatrix);
|
||||
mTarget->SetMatrix(savedMatrix);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2438,7 +2294,7 @@ protected:
|
|||
};
|
||||
|
||||
|
||||
class BasicShadowThebesLayer : public ShadowThebesLayer, public BasicImplData {
|
||||
class BasicShadowThebesLayer : public ShadowThebesLayer, BasicImplData {
|
||||
public:
|
||||
BasicShadowThebesLayer(BasicShadowLayerManager* aLayerManager)
|
||||
: ShadowThebesLayer(aLayerManager, static_cast<BasicImplData*>(this))
|
||||
|
@ -2612,7 +2468,7 @@ BasicShadowThebesLayer::PaintThebes(gfxContext* aContext,
|
|||
mFrontBuffer.DrawTo(this, target, GetEffectiveOpacity());
|
||||
}
|
||||
|
||||
class BasicShadowContainerLayer : public ShadowContainerLayer, public BasicImplData {
|
||||
class BasicShadowContainerLayer : public ShadowContainerLayer, BasicImplData {
|
||||
template<class Container>
|
||||
friend void ContainerInsertAfter(Layer* aChild, Layer* aAfter, Container* aContainer);
|
||||
template<class Container>
|
||||
|
@ -2658,7 +2514,7 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
class BasicShadowImageLayer : public ShadowImageLayer, public BasicImplData {
|
||||
class BasicShadowImageLayer : public ShadowImageLayer, BasicImplData {
|
||||
public:
|
||||
BasicShadowImageLayer(BasicShadowLayerManager* aLayerManager) :
|
||||
ShadowImageLayer(aLayerManager, static_cast<BasicImplData*>(this))
|
||||
|
@ -2731,7 +2587,6 @@ BasicShadowImageLayer::Paint(gfxContext* aContext)
|
|||
// tiling, we don't want to draw into that area, so just draw within
|
||||
// the image bounds.
|
||||
const nsIntRect* tileSrcRect = GetTileSourceRect();
|
||||
AutoSetOperator setOperator(aContext, GetOperator());
|
||||
BasicImageLayer::PaintContext(pat,
|
||||
tileSrcRect ? GetEffectiveVisibleRegion() : nsIntRegion(nsIntRect(0, 0, mSize.width, mSize.height)),
|
||||
tileSrcRect,
|
||||
|
@ -2739,7 +2594,7 @@ BasicShadowImageLayer::Paint(gfxContext* aContext)
|
|||
}
|
||||
|
||||
class BasicShadowColorLayer : public ShadowColorLayer,
|
||||
public BasicImplData
|
||||
BasicImplData
|
||||
{
|
||||
public:
|
||||
BasicShadowColorLayer(BasicShadowLayerManager* aLayerManager) :
|
||||
|
@ -2754,13 +2609,12 @@ public:
|
|||
|
||||
virtual void Paint(gfxContext* aContext)
|
||||
{
|
||||
AutoSetOperator setOperator(aContext, GetOperator());
|
||||
BasicColorLayer::PaintColorTo(mColor, GetEffectiveOpacity(), aContext);
|
||||
}
|
||||
};
|
||||
|
||||
class BasicShadowCanvasLayer : public ShadowCanvasLayer,
|
||||
public BasicImplData
|
||||
BasicImplData
|
||||
{
|
||||
public:
|
||||
BasicShadowCanvasLayer(BasicShadowLayerManager* aLayerManager) :
|
||||
|
|
|
@ -180,16 +180,7 @@ public:
|
|||
|
||||
void SetTransactionIncomplete() { mTransactionIncomplete = true; }
|
||||
|
||||
already_AddRefed<gfxContext> PushGroupForLayer(gfxContext* aContext, Layer* aLayer,
|
||||
const nsIntRegion& aRegion,
|
||||
PRBool* aNeedsClipToVisibleRegion);
|
||||
already_AddRefed<gfxContext> PushGroupWithCachedSurface(gfxContext *aTarget,
|
||||
gfxASurface::gfxContentType aContent);
|
||||
void PopGroupToSourceWithCachedSurface(gfxContext *aTarget, gfxContext *aPushed);
|
||||
|
||||
virtual PRBool IsCompositingCheap() { return PR_FALSE; }
|
||||
virtual bool HasShadowManagerInternal() const { return false; }
|
||||
bool HasShadowManager() const { return HasShadowManagerInternal(); }
|
||||
|
||||
protected:
|
||||
#ifdef DEBUG
|
||||
|
@ -200,8 +191,7 @@ protected:
|
|||
#endif
|
||||
|
||||
// Paints aLayer to mTarget.
|
||||
void PaintLayer(gfxContext* aTarget,
|
||||
Layer* aLayer,
|
||||
void PaintLayer(Layer* aLayer,
|
||||
DrawThebesLayerCallback aCallback,
|
||||
void* aCallbackData,
|
||||
ReadbackProcessor* aReadback);
|
||||
|
@ -209,6 +199,12 @@ protected:
|
|||
// Clear the contents of a layer
|
||||
void ClearLayer(Layer* aLayer);
|
||||
|
||||
already_AddRefed<gfxContext> PushGroupWithCachedSurface(gfxContext *aTarget,
|
||||
gfxASurface::gfxContentType aContent,
|
||||
gfxPoint *aSavedOffset);
|
||||
void PopGroupWithCachedSurface(gfxContext *aTarget,
|
||||
const gfxPoint& aSavedOffset);
|
||||
|
||||
bool EndTransactionInternal(DrawThebesLayerCallback aCallback,
|
||||
void* aCallbackData);
|
||||
|
||||
|
@ -229,7 +225,6 @@ protected:
|
|||
|
||||
BufferMode mDoubleBuffering;
|
||||
PRPackedBool mUsingDefaultTarget;
|
||||
PRPackedBool mCachedSurfaceInUse;
|
||||
bool mTransactionIncomplete;
|
||||
};
|
||||
|
||||
|
@ -265,7 +260,6 @@ public:
|
|||
|
||||
ShadowableLayer* Hold(Layer* aLayer);
|
||||
|
||||
bool HasShadowManager() const { return ShadowLayerForwarder::HasShadowManager(); }
|
||||
PLayersChild* GetShadowManager() const { return mShadowManager; }
|
||||
|
||||
void SetShadowManager(PLayersChild* aShadowManager)
|
||||
|
@ -274,7 +268,6 @@ public:
|
|||
}
|
||||
|
||||
virtual PRBool IsCompositingCheap();
|
||||
virtual bool HasShadowManagerInternal() const { return HasShadowManager(); }
|
||||
|
||||
private:
|
||||
/**
|
||||
|
|
|
@ -98,12 +98,12 @@ gfxCachedTempSurface::~gfxCachedTempSurface()
|
|||
|
||||
already_AddRefed<gfxContext>
|
||||
gfxCachedTempSurface::Get(gfxASurface::gfxContentType aContentType,
|
||||
const gfxRect& aRect,
|
||||
const gfxIntSize& aSize,
|
||||
gfxASurface* aSimilarTo)
|
||||
{
|
||||
if (mSurface) {
|
||||
/* Verify the current buffer is valid for this purpose */
|
||||
if (mSize.width < aRect.width || mSize.height < aRect.height
|
||||
if (mSize.width < aSize.width || mSize.height < aSize.height
|
||||
|| mSurface->GetContentType() != aContentType) {
|
||||
mSurface = nsnull;
|
||||
} else {
|
||||
|
@ -114,8 +114,8 @@ gfxCachedTempSurface::Get(gfxASurface::gfxContentType aContentType,
|
|||
|
||||
PRBool cleared = PR_FALSE;
|
||||
if (!mSurface) {
|
||||
mSize = gfxIntSize(PRInt32(NS_ceil(aRect.width)), PRInt32(NS_ceil(aRect.height)));
|
||||
mSurface = aSimilarTo->CreateSimilarSurface(aContentType, mSize);
|
||||
mSize = aSize;
|
||||
mSurface = aSimilarTo->CreateSimilarSurface(aContentType, aSize);
|
||||
if (!mSurface)
|
||||
return nsnull;
|
||||
|
||||
|
@ -124,10 +124,9 @@ gfxCachedTempSurface::Get(gfxASurface::gfxContentType aContentType,
|
|||
mType = aSimilarTo->GetType();
|
||||
#endif
|
||||
}
|
||||
mSurface->SetDeviceOffset(-aRect.TopLeft());
|
||||
|
||||
nsRefPtr<gfxContext> ctx = new gfxContext(mSurface);
|
||||
ctx->Rectangle(aRect);
|
||||
ctx->Rectangle(gfxRect(0, 0, aSize.width, aSize.height));
|
||||
ctx->Clip();
|
||||
if (!cleared && aContentType != gfxASurface::CONTENT_COLOR) {
|
||||
ctx->SetOperator(gfxContext::OPERATOR_CLEAR);
|
||||
|
|
|
@ -71,15 +71,13 @@ public:
|
|||
* different format.
|
||||
*/
|
||||
already_AddRefed<gfxContext> Get(gfxASurface::gfxContentType aContentType,
|
||||
const gfxRect& aRect,
|
||||
const gfxIntSize& aSize,
|
||||
gfxASurface* aSimilarTo);
|
||||
|
||||
void Expire() { mSurface = nsnull; }
|
||||
nsExpirationState* GetExpirationState() { return &mExpirationState; }
|
||||
~gfxCachedTempSurface();
|
||||
|
||||
PRBool IsSurface(gfxASurface* aSurface) { return mSurface == aSurface; }
|
||||
|
||||
private:
|
||||
nsRefPtr<gfxASurface> mSurface;
|
||||
gfxIntSize mSize;
|
||||
|
|
Загрузка…
Ссылка в новой задаче