Bug 933549. Change PaintState to use a DrawTarget instead of a gfxContext. r=mattwoodrow

This commit is contained in:
Nicholas Cameron 2014-01-08 10:09:34 +13:00
parent a44e014503
commit 100d053c89
8 changed files with 204 additions and 101 deletions

View File

@ -11,10 +11,8 @@
#include "BufferUnrotate.h" // for BufferUnrotate
#include "GeckoProfiler.h" // for PROFILER_LABEL
#include "Layers.h" // for ThebesLayer, Layer, etc
#include "gfxContext.h" // for gfxContext, etc
#include "gfxMatrix.h" // for gfxMatrix
#include "gfxPlatform.h" // for gfxPlatform
#include "gfxPoint.h" // for gfxPoint
#include "gfxUtils.h" // for gfxUtils
#include "mozilla/ArrayUtils.h" // for ArrayLength
#include "mozilla/gfx/BasePoint.h" // for BasePoint
@ -178,18 +176,19 @@ RotatedBuffer::DrawBufferWithRotation(gfx::DrawTarget *aTarget, ContextSource aS
}
/* static */ bool
RotatedContentBuffer::IsClippingCheap(gfxContext* aTarget, const nsIntRegion& aRegion)
RotatedContentBuffer::IsClippingCheap(DrawTarget* aTarget, const nsIntRegion& aRegion)
{
// Assume clipping is cheap if the context just has an integer
// Assume clipping is cheap if the draw target just has an integer
// translation, and the visible region is simple.
return !aTarget->CurrentMatrix().HasNonIntegerTranslation() &&
return !aTarget->GetTransform().HasNonIntegerTranslation() &&
aRegion.GetNumRects() <= 1;
}
void
RotatedContentBuffer::DrawTo(ThebesLayer* aLayer,
gfxContext* aTarget,
DrawTarget* aTarget,
float aOpacity,
CompositionOp aOp,
gfxASurface* aMask,
const gfxMatrix* aMaskTransform)
{
@ -197,8 +196,6 @@ RotatedContentBuffer::DrawTo(ThebesLayer* aLayer,
return;
}
RefPtr<DrawTarget> dt = aTarget->GetDrawTarget();
MOZ_ASSERT(dt, "Did you pass a non-Azure gfxContext?");
bool clipped = false;
// If the entire buffer is valid, we can just draw the whole thing,
@ -214,13 +211,13 @@ RotatedContentBuffer::DrawTo(ThebesLayer* aLayer,
// Bug 599189 if there is a non-integer-translation transform in aTarget,
// we might sample pixels outside GetEffectiveVisibleRegion(), which is wrong
// and may cause gray lines.
gfxUtils::ClipToRegionSnapped(dt, aLayer->GetEffectiveVisibleRegion());
gfxUtils::ClipToRegionSnapped(aTarget, aLayer->GetEffectiveVisibleRegion());
clipped = true;
}
RefPtr<gfx::SourceSurface> mask;
if (aMask) {
mask = gfxPlatform::GetPlatform()->GetSourceSurfaceForSurface(dt, aMask);
mask = gfxPlatform::GetPlatform()->GetSourceSurfaceForSurface(aTarget, aMask);
}
Matrix maskTransform;
@ -228,38 +225,35 @@ RotatedContentBuffer::DrawTo(ThebesLayer* aLayer,
maskTransform = ToMatrix(*aMaskTransform);
}
CompositionOp op = CompositionOpForOp(aTarget->CurrentOperator());
DrawBufferWithRotation(dt, BUFFER_BLACK, aOpacity, op, mask, &maskTransform);
DrawBufferWithRotation(aTarget, BUFFER_BLACK, aOpacity, aOp, mask, &maskTransform);
if (clipped) {
dt->PopClip();
aTarget->PopClip();
}
}
already_AddRefed<gfxContext>
RotatedContentBuffer::GetContextForQuadrantUpdate(const nsIntRect& aBounds,
ContextSource aSource,
nsIntPoint *aTopLeft)
DrawTarget*
RotatedContentBuffer::BorrowDrawTargetForQuadrantUpdate(const nsIntRect& aBounds,
ContextSource aSource)
{
if (!EnsureBuffer()) {
return nullptr;
}
nsRefPtr<gfxContext> ctx;
MOZ_ASSERT(!mLoanedDrawTarget, "draw target has been borrowed and not returned");
if (aSource == BUFFER_BOTH && HaveBufferOnWhite()) {
if (!EnsureBufferOnWhite()) {
return nullptr;
}
MOZ_ASSERT(mDTBuffer && mDTBufferOnWhite);
RefPtr<DrawTarget> dualDT = Factory::CreateDualDrawTarget(mDTBuffer, mDTBufferOnWhite);
ctx = new gfxContext(dualDT);
mLoanedDrawTarget = Factory::CreateDualDrawTarget(mDTBuffer, mDTBufferOnWhite);
} else if (aSource == BUFFER_WHITE) {
if (!EnsureBufferOnWhite()) {
return nullptr;
}
ctx = new gfxContext(mDTBufferOnWhite);
mLoanedDrawTarget = mDTBufferOnWhite;
} else {
// BUFFER_BLACK, or BUFFER_BOTH with a single buffer.
ctx = new gfxContext(mDTBuffer);
mLoanedDrawTarget = mDTBuffer;
}
// Figure out which quadrant to draw in
@ -269,13 +263,22 @@ RotatedContentBuffer::GetContextForQuadrantUpdate(const nsIntRect& aBounds,
YSide sideY = aBounds.YMost() <= yBoundary ? BOTTOM : TOP;
nsIntRect quadrantRect = GetQuadrantRectangle(sideX, sideY);
NS_ASSERTION(quadrantRect.Contains(aBounds), "Messed up quadrants");
ctx->Translate(-gfxPoint(quadrantRect.x, quadrantRect.y));
if (aTopLeft) {
*aTopLeft = nsIntPoint(quadrantRect.x, quadrantRect.y);
}
mLoanedTransform = mLoanedDrawTarget->GetTransform();
mLoanedTransform.Translate(-quadrantRect.x, -quadrantRect.y);
mLoanedDrawTarget->SetTransform(mLoanedTransform);
mLoanedTransform.Translate(quadrantRect.x, quadrantRect.y);
return ctx.forget();
return mLoanedDrawTarget;
}
void
BorrowDrawTarget::ReturnDrawTarget(gfx::DrawTarget*& aReturned)
{
MOZ_ASSERT(aReturned == mLoanedDrawTarget);
mLoanedDrawTarget->SetTransform(mLoanedTransform);
mLoanedDrawTarget = nullptr;
aReturned = nullptr;
}
gfxContentType
@ -309,6 +312,7 @@ RotatedContentBuffer::BufferSizeOkFor(const nsIntSize& aSize)
bool
RotatedContentBuffer::EnsureBuffer()
{
NS_ASSERTION(!mLoanedDrawTarget, "Loaned draw target must be returned");
if (!mDTBuffer) {
if (mDeprecatedBufferProvider) {
mDTBuffer = mDeprecatedBufferProvider->LockDrawTarget();
@ -324,6 +328,7 @@ RotatedContentBuffer::EnsureBuffer()
bool
RotatedContentBuffer::EnsureBufferOnWhite()
{
NS_ASSERTION(!mLoanedDrawTarget, "Loaned draw target must be returned");
if (!mDTBufferOnWhite) {
if (mDeprecatedBufferProviderOnWhite) {
mDTBufferOnWhite = mDeprecatedBufferProviderOnWhite->LockDrawTarget();
@ -644,8 +649,7 @@ RotatedContentBuffer::BeginPaint(ThebesLayer* aLayer, ContentType aContentType,
invalidate.Sub(aLayer->GetValidRegion(), destBufferRect);
result.mRegionToInvalidate.Or(result.mRegionToInvalidate, invalidate);
nsIntPoint topLeft;
result.mContext = GetContextForQuadrantUpdate(drawBounds, BUFFER_BOTH, &topLeft);
result.mTarget = BorrowDrawTargetForQuadrantUpdate(drawBounds, BUFFER_BOTH);
result.mClip = CLIP_DRAW_SNAPPED;
if (mode == Layer::SURFACE_COMPONENT_ALPHA) {
@ -662,7 +666,7 @@ RotatedContentBuffer::BeginPaint(ThebesLayer* aLayer, ContentType aContentType,
nsIntRegionRectIterator iter(result.mRegionToDraw);
const nsIntRect *iterRect;
while ((iterRect = iter.Next())) {
result.mContext->GetDrawTarget()->ClearRect(Rect(iterRect->x, iterRect->y, iterRect->width, iterRect->height));
result.mTarget->ClearRect(Rect(iterRect->x, iterRect->y, iterRect->width, iterRect->height));
}
}

View File

@ -8,7 +8,6 @@
#include <stdint.h> // for uint32_t
#include "gfxASurface.h" // for gfxASurface, etc
#include "gfxContext.h" // for gfxContext
#include "mozilla/Assertions.h" // for MOZ_ASSERT, etc
#include "mozilla/RefPtr.h" // for RefPtr, TemporaryRef
#include "mozilla/gfx/2D.h" // for DrawTarget, etc
@ -137,11 +136,27 @@ protected:
bool mDidSelfCopy;
};
// Mixin class for classes which need logic for loaning out a draw target.
// See comments on BorrowDrawTargetForQuadrantUpdate.
class BorrowDrawTarget
{
protected:
void ReturnDrawTarget(gfx::DrawTarget*& aReturned);
// The draw target loaned by BorrowDrawTargetForQuadrantUpdate. It should not
// be used, we just keep a reference to ensure it is kept alive and so we can
// correctly restore state when it is returned.
RefPtr<gfx::DrawTarget> mLoanedDrawTarget;
gfx::Matrix mLoanedTransform;
};
/**
* This class encapsulates the buffer used to retain ThebesLayer contents,
* i.e., the contents of the layer's GetVisibleRegion().
*/
class RotatedContentBuffer : public RotatedBuffer {
class RotatedContentBuffer : public RotatedBuffer
, public BorrowDrawTarget
{
public:
typedef gfxContentType ContentType;
@ -187,7 +202,7 @@ public:
}
/**
* This is returned by BeginPaint. The caller should draw into mContext.
* This is returned by BeginPaint. The caller should draw into mTarget.
* mRegionToDraw must be drawn. mRegionToInvalidate has been invalidated
* by RotatedContentBuffer and must be redrawn on the screen.
* mRegionToInvalidate is set when the buffer has changed from
@ -197,14 +212,15 @@ public:
*/
struct PaintState {
PaintState()
: mDidSelfCopy(false)
: mTarget(nullptr)
, mDidSelfCopy(false)
{}
nsRefPtr<gfxContext> mContext;
gfx::DrawTarget* mTarget;
nsIntRegion mRegionToDraw;
nsIntRegion mRegionToInvalidate;
bool mDidSelfCopy;
DrawRegionClip mClip;
bool mDidSelfCopy;
};
enum {
@ -215,7 +231,7 @@ public:
* Start a drawing operation. This returns a PaintState describing what
* needs to be drawn to bring the buffer up to date in the visible region.
* This queries aLayer to get the currently valid and visible regions.
* The returned mContext may be null if mRegionToDraw is empty.
* The returned mTarget may be null if mRegionToDraw is empty.
* Otherwise it must not be null.
* mRegionToInvalidate will contain mRegionToDraw.
* @param aFlags when PAINT_WILL_RESAMPLE is passed, this indicates that
@ -260,8 +276,12 @@ public:
* drawn before this is called. The contents of the buffer are drawn
* to aTarget.
*/
void DrawTo(ThebesLayer* aLayer, gfxContext* aTarget, float aOpacity,
gfxASurface* aMask, const gfxMatrix* aMaskTransform);
void DrawTo(ThebesLayer* aLayer,
gfx::DrawTarget* aTarget,
float aOpacity,
gfx::CompositionOp aOp,
gfxASurface* aMask,
const gfxMatrix* aMaskTransform);
protected:
TemporaryRef<gfx::DrawTarget>
@ -345,15 +365,24 @@ protected:
}
/**
* Get a context at the specified resolution for updating |aBounds|,
* Get a draw target at the specified resolution for updating |aBounds|,
* which must be contained within a single quadrant.
*
* Optionally returns the TopLeft coordinate of the quadrant being drawn to.
* The result should only be held temporarily by the caller (it will be kept
* alive by this). Once used it should be returned using ReturnDrawTarget.
* BorrowDrawTargetForQuadrantUpdate may not be called more than once without
* first calling ReturnDrawTarget.
*
* ReturnDrawTarget will restore the transform on the draw target. But it is
* the callers responsibility to restore the clip. The caller should flush the
* draw target, if necessary.
*/
already_AddRefed<gfxContext>
GetContextForQuadrantUpdate(const nsIntRect& aBounds, ContextSource aSource, nsIntPoint* aTopLeft = nullptr);
gfx::DrawTarget*
BorrowDrawTargetForQuadrantUpdate(const nsIntRect& aBounds,
ContextSource aSource);
void ReturnDrawTarget(gfx::DrawTarget* aReturned);
static bool IsClippingCheap(gfxContext* aTarget, const nsIntRegion& aRegion);
static bool IsClippingCheap(gfx::DrawTarget* aTarget, const nsIntRegion& aRegion);
protected:
/**

View File

@ -27,6 +27,7 @@
#include "nsRect.h" // for nsIntRect
#include "nsTArray.h" // for nsTArray, nsTArray_Impl
#include "AutoMaskData.h"
#include "gfx2DGlue.h"
struct gfxMatrix;
@ -132,8 +133,9 @@ BasicThebesLayer::PaintThebes(gfxContext* aContext,
}
if (!IsHidden() && !clipExtents.IsEmpty()) {
AutoSetOperator setOperator(aContext, GetOperator());
mContentClient->DrawTo(this, aContext, opacity, maskSurface, maskTransform);
mContentClient->DrawTo(this, aContext->GetDrawTarget(), opacity,
CompositionOpForOp(GetOperator()),
maskSurface, maskTransform);
}
for (uint32_t i = 0; i < readbackUpdates.Length(); ++i) {
@ -145,7 +147,9 @@ BasicThebesLayer::PaintThebes(gfxContext* aContext,
if (ctx) {
NS_ASSERTION(opacity == 1.0, "Should only read back opaque layers");
ctx->Translate(gfxPoint(offset.x, offset.y));
mContentClient->DrawTo(this, ctx, 1.0, maskSurface, maskTransform);
mContentClient->DrawTo(this, ctx->GetDrawTarget(), 1.0,
CompositionOpForOp(ctx->CurrentOperator()),
maskSurface, maskTransform);
update.mLayer->GetSink()->EndUpdate(ctx, update.mUpdateRect + offset);
}
}
@ -188,7 +192,7 @@ BasicThebesLayer::Validate(LayerManager::DrawThebesLayerCallback aCallback,
mContentClient->BeginPaintBuffer(this, contentType, flags);
mValidRegion.Sub(mValidRegion, state.mRegionToInvalidate);
if (state.mContext) {
if (state.mTarget) {
// The area that became invalid and is visible needs to be repainted
// (this could be the whole visible area if our buffer switched
// from RGB to RGBA, because we might need to repaint with
@ -196,17 +200,20 @@ BasicThebesLayer::Validate(LayerManager::DrawThebesLayerCallback aCallback,
state.mRegionToInvalidate.And(state.mRegionToInvalidate,
GetEffectiveVisibleRegion());
nsIntRegion extendedDrawRegion = state.mRegionToDraw;
SetAntialiasingFlags(this, state.mContext);
SetAntialiasingFlags(this, state.mTarget);
RenderTraceInvalidateStart(this, "FFFF00", state.mRegionToDraw.GetBounds());
PaintBuffer(state.mContext,
nsRefPtr<gfxContext> ctx = gfxContext::ContextForDrawTarget(state.mTarget);
PaintBuffer(ctx,
state.mRegionToDraw, extendedDrawRegion, state.mRegionToInvalidate,
state.mDidSelfCopy,
state.mClip,
aCallback, aCallbackData);
MOZ_LAYERS_LOG_IF_SHADOWABLE(this, ("Layer::Mutated(%p) PaintThebes", this));
Mutated();
ctx = nullptr;
mContentClient->ReturnDrawTarget(state.mTarget);
RenderTraceInvalidateEnd(this, "FFFF00");
} else {

View File

@ -22,6 +22,7 @@
#include "nsCOMPtr.h" // for already_AddRefed
#include "nsISupportsImpl.h" // for Layer::AddRef, etc
#include "nsRect.h" // for nsIntRect
#include "gfx2DGlue.h"
using namespace mozilla::gfx;
@ -61,7 +62,7 @@ ClientThebesLayer::PaintThebes()
mContentClient->BeginPaintBuffer(this, contentType, flags);
mValidRegion.Sub(mValidRegion, state.mRegionToInvalidate);
if (state.mContext) {
if (state.mTarget) {
// The area that became invalid and is visible needs to be repainted
// (this could be the whole visible area if our buffer switched
// from RGB to RGBA, because we might need to repaint with
@ -69,13 +70,16 @@ ClientThebesLayer::PaintThebes()
state.mRegionToInvalidate.And(state.mRegionToInvalidate,
GetEffectiveVisibleRegion());
nsIntRegion extendedDrawRegion = state.mRegionToDraw;
SetAntialiasingFlags(this, state.mContext);
SetAntialiasingFlags(this, state.mTarget);
PaintBuffer(state.mContext,
nsRefPtr<gfxContext> ctx = gfxContext::ContextForDrawTarget(state.mTarget);
PaintBuffer(ctx,
state.mRegionToDraw, extendedDrawRegion, state.mRegionToInvalidate,
state.mDidSelfCopy, state.mClip);
MOZ_LAYERS_LOG_IF_SHADOWABLE(this, ("Layer::Mutated(%p) PaintThebes", this));
Mutated();
ctx = nullptr;
mContentClient->ReturnDrawTarget(state.mTarget);
} else {
// It's possible that state.mRegionToInvalidate is nonempty here,
// if we are shrinking the valid region to nothing. So use mRegionToDraw

View File

@ -608,29 +608,35 @@ void
ContentClientDoubleBuffered::UpdateDestinationFrom(const RotatedBuffer& aSource,
const nsIntRegion& aUpdateRegion)
{
nsRefPtr<gfxContext> destCtx =
GetContextForQuadrantUpdate(aUpdateRegion.GetBounds(), BUFFER_BLACK);
destCtx->SetOperator(gfxContext::OPERATOR_SOURCE);
DrawTarget* destDT =
BorrowDrawTargetForQuadrantUpdate(aUpdateRegion.GetBounds(), BUFFER_BLACK);
bool isClippingCheap = IsClippingCheap(destCtx, aUpdateRegion);
bool isClippingCheap = IsClippingCheap(destDT, aUpdateRegion);
if (isClippingCheap) {
gfxUtils::ClipToRegion(destCtx, aUpdateRegion);
gfxUtils::ClipToRegion(destDT, aUpdateRegion);
}
aSource.DrawBufferWithRotation(destCtx->GetDrawTarget(), BUFFER_BLACK, 1.0, OP_SOURCE);
aSource.DrawBufferWithRotation(destDT, BUFFER_BLACK, 1.0, OP_SOURCE);
if (isClippingCheap) {
destDT->PopClip();
}
ReturnDrawTarget(destDT);
if (aSource.HaveBufferOnWhite()) {
MOZ_ASSERT(HaveBufferOnWhite());
nsRefPtr<gfxContext> destCtx =
GetContextForQuadrantUpdate(aUpdateRegion.GetBounds(), BUFFER_WHITE);
destCtx->SetOperator(gfxContext::OPERATOR_SOURCE);
DrawTarget* destDT =
BorrowDrawTargetForQuadrantUpdate(aUpdateRegion.GetBounds(), BUFFER_WHITE);
bool isClippingCheap = IsClippingCheap(destCtx, aUpdateRegion);
bool isClippingCheap = IsClippingCheap(destDT, aUpdateRegion);
if (isClippingCheap) {
gfxUtils::ClipToRegion(destCtx, aUpdateRegion);
gfxUtils::ClipToRegion(destDT, aUpdateRegion);
}
aSource.DrawBufferWithRotation(destCtx->GetDrawTarget(), BUFFER_WHITE, 1.0, OP_SOURCE);
aSource.DrawBufferWithRotation(destDT, BUFFER_WHITE, 1.0, OP_SOURCE);
if (isClippingCheap) {
destDT->PopClip();
}
ReturnDrawTarget(destDT);
}
}
@ -817,32 +823,38 @@ void
DeprecatedContentClientDoubleBuffered::UpdateDestinationFrom(const RotatedBuffer& aSource,
const nsIntRegion& aUpdateRegion)
{
nsRefPtr<gfxContext> destCtx =
GetContextForQuadrantUpdate(aUpdateRegion.GetBounds(), BUFFER_BLACK);
if (!destCtx) {
DrawTarget* destDT =
BorrowDrawTargetForQuadrantUpdate(aUpdateRegion.GetBounds(), BUFFER_BLACK);
if (!destDT) {
return;
}
destCtx->SetOperator(gfxContext::OPERATOR_SOURCE);
bool isClippingCheap = IsClippingCheap(destCtx, aUpdateRegion);
bool isClippingCheap = IsClippingCheap(destDT, aUpdateRegion);
if (isClippingCheap) {
gfxUtils::ClipToRegion(destCtx, aUpdateRegion);
gfxUtils::ClipToRegion(destDT, aUpdateRegion);
}
aSource.DrawBufferWithRotation(destCtx->GetDrawTarget(), BUFFER_BLACK, 1.0, OP_SOURCE);
aSource.DrawBufferWithRotation(destDT, BUFFER_BLACK, 1.0, OP_SOURCE);
if (isClippingCheap) {
destDT->PopClip();
}
ReturnDrawTarget(destDT);
if (aSource.HaveBufferOnWhite()) {
MOZ_ASSERT(HaveBufferOnWhite());
nsRefPtr<gfxContext> destCtx =
GetContextForQuadrantUpdate(aUpdateRegion.GetBounds(), BUFFER_WHITE);
destCtx->SetOperator(gfxContext::OPERATOR_SOURCE);
DrawTarget* destDT =
BorrowDrawTargetForQuadrantUpdate(aUpdateRegion.GetBounds(), BUFFER_WHITE);
bool isClippingCheap = IsClippingCheap(destCtx, aUpdateRegion);
bool isClippingCheap = IsClippingCheap(destDT, aUpdateRegion);
if (isClippingCheap) {
gfxUtils::ClipToRegion(destCtx, aUpdateRegion);
gfxUtils::ClipToRegion(destDT, aUpdateRegion);
}
aSource.DrawBufferWithRotation(destCtx->GetDrawTarget(), BUFFER_WHITE, 1.0, OP_SOURCE);
aSource.DrawBufferWithRotation(destDT, BUFFER_WHITE, 1.0, OP_SOURCE);
if (isClippingCheap) {
destDT->PopClip();
}
ReturnDrawTarget(destDT);
}
}
@ -1135,6 +1147,8 @@ ContentClientIncremental::BeginPaintBuffer(ThebesLayer* aLayer,
invalidate.Sub(aLayer->GetValidRegion(), destBufferRect);
result.mRegionToInvalidate.Or(result.mRegionToInvalidate, invalidate);
MOZ_ASSERT(!mLoanedDrawTarget);
// BeginUpdate is allowed to modify the given region,
// if it wants more to be repainted than we request.
if (mode == Layer::SURFACE_COMPONENT_ALPHA) {
@ -1149,22 +1163,25 @@ ContentClientIncremental::BeginPaintBuffer(ThebesLayer* aLayer,
MOZ_ASSERT(gfxPlatform::GetPlatform()->SupportsAzureContent());
RefPtr<DrawTarget> onBlackDT = gfxPlatform::GetPlatform()->CreateDrawTargetForUpdateSurface(onBlack, onBlack->GetSize().ToIntSize());
RefPtr<DrawTarget> onWhiteDT = gfxPlatform::GetPlatform()->CreateDrawTargetForUpdateSurface(onWhite, onWhite->GetSize().ToIntSize());
RefPtr<DrawTarget> dt = Factory::CreateDualDrawTarget(onBlackDT, onWhiteDT);
result.mContext = new gfxContext(dt);
mLoanedDrawTarget = Factory::CreateDualDrawTarget(onBlackDT, onWhiteDT);
} else {
result.mContext = nullptr;
mLoanedDrawTarget = nullptr;
}
} else {
nsRefPtr<gfxASurface> surf = GetUpdateSurface(BUFFER_BLACK, result.mRegionToDraw);
MOZ_ASSERT(gfxPlatform::GetPlatform()->SupportsAzureContent());
RefPtr<DrawTarget> dt = gfxPlatform::GetPlatform()->CreateDrawTargetForUpdateSurface(surf, surf->GetSize().ToIntSize());
result.mContext = new gfxContext(dt);
mLoanedDrawTarget = gfxPlatform::GetPlatform()->CreateDrawTargetForUpdateSurface(surf, surf->GetSize());
}
if (!result.mContext) {
if (!mLoanedDrawTarget) {
NS_WARNING("unable to get context for update");
return result;
}
result.mContext->Translate(-gfxPoint(drawBounds.x, drawBounds.y));
result.mTarget = mLoanedDrawTarget;
mLoanedTransform = mLoanedDrawTarget->GetTransform();
mLoanedTransform.Translate(-drawBounds.x, -drawBounds.y);
result.mTarget->SetTransform(mLoanedTransform);
mLoanedTransform.Translate(drawBounds.x, drawBounds.y);
// If we do partial updates, we have to clip drawing to the regionToDraw.
// If we don't clip, background images will be fillrect'd to the region correctly,
@ -1176,11 +1193,9 @@ ContentClientIncremental::BeginPaintBuffer(ThebesLayer* aLayer,
result.mClip = CLIP_DRAW;
if (mContentType == GFX_CONTENT_COLOR_ALPHA) {
result.mContext->Save();
gfxUtils::ClipToRegion(result.mContext, result.mRegionToDraw);
result.mContext->SetOperator(gfxContext::OPERATOR_CLEAR);
result.mContext->Paint();
result.mContext->Restore();
gfxUtils::ClipToRegion(result.mTarget, result.mRegionToDraw);
nsIntRect bounds = result.mRegionToDraw.GetBounds();
result.mTarget->ClearRect(Rect(bounds.x, bounds.y, bounds.width, bounds.height));
}
return result;

View File

@ -97,6 +97,7 @@ public:
virtual RotatedContentBuffer::PaintState BeginPaintBuffer(ThebesLayer* aLayer,
RotatedContentBuffer::ContentType aContentType,
uint32_t aFlags) = 0;
virtual void ReturnDrawTarget(gfx::DrawTarget* aReturned) = 0;
// Sync front/back buffers content
// After executing, the new back buffer has the same (interesting) pixels as
@ -140,16 +141,25 @@ public:
typedef RotatedContentBuffer::ContentType ContentType;
virtual void Clear() { RotatedContentBuffer::Clear(); }
PaintState BeginPaintBuffer(ThebesLayer* aLayer, ContentType aContentType,
uint32_t aFlags)
virtual PaintState BeginPaintBuffer(ThebesLayer* aLayer, ContentType aContentType,
uint32_t aFlags) MOZ_OVERRIDE
{
return RotatedContentBuffer::BeginPaint(aLayer, aContentType, aFlags);
}
void DrawTo(ThebesLayer* aLayer, gfxContext* aTarget, float aOpacity,
gfxASurface* aMask, const gfxMatrix* aMaskTransform)
virtual void ReturnDrawTarget(gfx::DrawTarget* aReturned) MOZ_OVERRIDE
{
RotatedContentBuffer::DrawTo(aLayer, aTarget, aOpacity, aMask, aMaskTransform);
BorrowDrawTarget::ReturnDrawTarget(aReturned);
}
void DrawTo(ThebesLayer* aLayer,
gfx::DrawTarget* aTarget,
float aOpacity,
gfx::CompositionOp aOp,
gfxASurface* aMask,
const gfxMatrix* aMaskTransform)
{
RotatedContentBuffer::DrawTo(aLayer, aTarget, aOpacity, aOp,
aMask, aMaskTransform);
}
virtual void CreateBuffer(ContentType aType, const nsIntRect& aRect, uint32_t aFlags,
@ -195,11 +205,16 @@ public:
typedef RotatedContentBuffer::ContentType ContentType;
virtual void Clear() { RotatedContentBuffer::Clear(); }
PaintState BeginPaintBuffer(ThebesLayer* aLayer, ContentType aContentType,
uint32_t aFlags)
virtual PaintState BeginPaintBuffer(ThebesLayer* aLayer, ContentType aContentType,
uint32_t aFlags) MOZ_OVERRIDE
{
return RotatedContentBuffer::BeginPaint(aLayer, aContentType, aFlags);
}
virtual void ReturnDrawTarget(gfx::DrawTarget* aReturned) MOZ_OVERRIDE
{
BorrowDrawTarget::ReturnDrawTarget(aReturned);
}
/**
* Begin/End Paint map a gfxASurface from the texture client
@ -295,11 +310,16 @@ public:
typedef RotatedContentBuffer::ContentType ContentType;
virtual void Clear() { RotatedContentBuffer::Clear(); }
PaintState BeginPaintBuffer(ThebesLayer* aLayer, ContentType aContentType,
uint32_t aFlags)
virtual PaintState BeginPaintBuffer(ThebesLayer* aLayer, ContentType aContentType,
uint32_t aFlags) MOZ_OVERRIDE
{
return RotatedContentBuffer::BeginPaint(aLayer, aContentType, aFlags);
}
virtual void ReturnDrawTarget(gfx::DrawTarget* aReturned) MOZ_OVERRIDE
{
BorrowDrawTarget::ReturnDrawTarget(aReturned);
}
/**
* Begin/End Paint map a gfxASurface from the texture client
@ -496,6 +516,7 @@ protected:
* new ones each frame.
*/
class ContentClientIncremental : public ContentClientRemote
, public BorrowDrawTarget
{
public:
ContentClientIncremental(CompositableForwarder* aFwd)
@ -521,9 +542,14 @@ public:
mHasBuffer = false;
mHasBufferOnWhite = false;
}
virtual RotatedContentBuffer::PaintState BeginPaintBuffer(ThebesLayer* aLayer,
RotatedContentBuffer::ContentType aContentType,
uint32_t aFlags);
uint32_t aFlags) MOZ_OVERRIDE;
virtual void ReturnDrawTarget(gfx::DrawTarget* aReturned) MOZ_OVERRIDE
{
BorrowDrawTarget::ReturnDrawTarget(aReturned);
}
virtual void Updated(const nsIntRegion& aRegionToDraw,
const nsIntRegion& aVisibleRegion,

View File

@ -115,6 +115,15 @@ gfxContext::gfxContext(DrawTarget *aTarget)
mDT->SetTransform(Matrix());
}
/* static */ already_AddRefed<gfxContext>
gfxContext::ContextForDrawTarget(DrawTarget* aTarget)
{
Matrix transform = aTarget->GetTransform();
nsRefPtr<gfxContext> result = new gfxContext(aTarget);
result->SetMatrix(ThebesMatrix(transform));
return result.forget();
}
gfxContext::~gfxContext()
{
if (mCairo) {

View File

@ -48,11 +48,20 @@ public:
/**
* Initialize this context from a DrawTarget.
* Strips any transform from aTarget.
* aTarget will be flushed in the gfxContext's destructor.
*/
gfxContext(mozilla::gfx::DrawTarget *aTarget);
~gfxContext();
/**
* Create a new gfxContext wrapping aTarget and preserving aTarget's
* transform. Note that the transform is moved from aTarget to the resulting
* gfxContext, aTarget will no longer have its transform.
*/
static already_AddRefed<gfxContext> ContextForDrawTarget(mozilla::gfx::DrawTarget* aTarget);
/**
* Return the surface that this gfxContext was created with
*/