Backed out changeset 0c763c30594d (bug 1409871)
This commit is contained in:
@@ -35,20 +35,6 @@ using namespace gfx;
|
|||||||
|
|
||||||
namespace layers {
|
namespace layers {
|
||||||
|
|
||||||
void
|
|
||||||
BorrowDrawTarget::ReturnDrawTarget(gfx::DrawTarget*& aReturned)
|
|
||||||
{
|
|
||||||
MOZ_ASSERT(mLoanedDrawTarget);
|
|
||||||
MOZ_ASSERT(aReturned == mLoanedDrawTarget);
|
|
||||||
if (mLoanedDrawTarget) {
|
|
||||||
if (mSetTransform) {
|
|
||||||
mLoanedDrawTarget->SetTransform(mLoanedTransform);
|
|
||||||
}
|
|
||||||
mLoanedDrawTarget = nullptr;
|
|
||||||
}
|
|
||||||
aReturned = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
IntRect
|
IntRect
|
||||||
RotatedBuffer::GetQuadrantRectangle(XSide aXSide, YSide aYSide) const
|
RotatedBuffer::GetQuadrantRectangle(XSide aXSide, YSide aYSide) const
|
||||||
{
|
{
|
||||||
@@ -196,124 +182,6 @@ RotatedBuffer::DrawBufferWithRotation(gfx::DrawTarget *aTarget, ContextSource aS
|
|||||||
DrawBufferQuadrant(aTarget, RIGHT, BOTTOM, aSource, aOpacity, aOperator,aMask, aMaskTransform);
|
DrawBufferQuadrant(aTarget, RIGHT, BOTTOM, aSource, aOpacity, aOperator,aMask, aMaskTransform);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IsClippingCheap(gfx::DrawTarget* aTarget, const nsIntRegion& aRegion)
|
|
||||||
{
|
|
||||||
// Assume clipping is cheap if the draw target just has an integer
|
|
||||||
// translation, and the visible region is simple.
|
|
||||||
return !aTarget->GetTransform().HasNonIntegerTranslation() &&
|
|
||||||
aRegion.GetNumRects() <= 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
RotatedBuffer::UpdateDestinationFrom(const RotatedBuffer& aSource,
|
|
||||||
const nsIntRegion& aUpdateRegion)
|
|
||||||
{
|
|
||||||
DrawIterator iter;
|
|
||||||
while (DrawTarget* destDT =
|
|
||||||
BorrowDrawTargetForQuadrantUpdate(aUpdateRegion.GetBounds(), BUFFER_BLACK, &iter)) {
|
|
||||||
bool isClippingCheap = IsClippingCheap(destDT, iter.mDrawRegion);
|
|
||||||
if (isClippingCheap) {
|
|
||||||
gfxUtils::ClipToRegion(destDT, iter.mDrawRegion);
|
|
||||||
}
|
|
||||||
|
|
||||||
aSource.DrawBufferWithRotation(destDT, BUFFER_BLACK, 1.0, CompositionOp::OP_SOURCE);
|
|
||||||
if (isClippingCheap) {
|
|
||||||
destDT->PopClip();
|
|
||||||
}
|
|
||||||
// Flush the destination before the sources become inaccessible (Unlock).
|
|
||||||
destDT->Flush();
|
|
||||||
ReturnDrawTarget(destDT);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (aSource.HaveBufferOnWhite()) {
|
|
||||||
MOZ_ASSERT(HaveBufferOnWhite());
|
|
||||||
DrawIterator whiteIter;
|
|
||||||
while (DrawTarget* destDT =
|
|
||||||
BorrowDrawTargetForQuadrantUpdate(aUpdateRegion.GetBounds(), BUFFER_WHITE, &whiteIter)) {
|
|
||||||
bool isClippingCheap = IsClippingCheap(destDT, whiteIter.mDrawRegion);
|
|
||||||
if (isClippingCheap) {
|
|
||||||
gfxUtils::ClipToRegion(destDT, whiteIter.mDrawRegion);
|
|
||||||
}
|
|
||||||
|
|
||||||
aSource.DrawBufferWithRotation(destDT, BUFFER_WHITE, 1.0, CompositionOp::OP_SOURCE);
|
|
||||||
if (isClippingCheap) {
|
|
||||||
destDT->PopClip();
|
|
||||||
}
|
|
||||||
// Flush the destination before the sources become inaccessible (Unlock).
|
|
||||||
destDT->Flush();
|
|
||||||
ReturnDrawTarget(destDT);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
DrawTarget*
|
|
||||||
RotatedBuffer::BorrowDrawTargetForQuadrantUpdate(const IntRect& aBounds,
|
|
||||||
ContextSource aSource,
|
|
||||||
DrawIterator* aIter,
|
|
||||||
bool aSetTransform,
|
|
||||||
Matrix* aOutMatrix)
|
|
||||||
{
|
|
||||||
IntRect bounds = aBounds;
|
|
||||||
if (aIter) {
|
|
||||||
// If an iterator was provided, then BeginPaint must have been run with
|
|
||||||
// PAINT_CAN_DRAW_ROTATED, and the draw region might cover multiple quadrants.
|
|
||||||
// Iterate over each of them, and return an appropriate buffer each time we find
|
|
||||||
// one that intersects the draw region. The iterator mCount value tracks which
|
|
||||||
// quadrants we have considered across multiple calls to this function.
|
|
||||||
aIter->mDrawRegion.SetEmpty();
|
|
||||||
while (aIter->mCount < 4) {
|
|
||||||
IntRect quadrant = GetQuadrantRectangle((aIter->mCount & 1) ? LEFT : RIGHT,
|
|
||||||
(aIter->mCount & 2) ? TOP : BOTTOM);
|
|
||||||
aIter->mDrawRegion.And(aBounds, quadrant);
|
|
||||||
aIter->mCount++;
|
|
||||||
if (!aIter->mDrawRegion.IsEmpty()) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (aIter->mDrawRegion.IsEmpty()) {
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
bounds = aIter->mDrawRegion.GetBounds();
|
|
||||||
}
|
|
||||||
|
|
||||||
gfx::DrawTarget* dtBuffer = GetDTBuffer();
|
|
||||||
gfx::DrawTarget* dtBufferOnWhite = GetDTBufferOnWhite();
|
|
||||||
|
|
||||||
MOZ_ASSERT(!mLoanedDrawTarget, "draw target has been borrowed and not returned");
|
|
||||||
if (aSource == BUFFER_BOTH && HaveBufferOnWhite()) {
|
|
||||||
MOZ_ASSERT(dtBuffer && dtBuffer->IsValid() && dtBufferOnWhite && dtBufferOnWhite->IsValid());
|
|
||||||
mLoanedDrawTarget = Factory::CreateDualDrawTarget(dtBuffer, dtBufferOnWhite);
|
|
||||||
} else if (aSource == BUFFER_WHITE) {
|
|
||||||
mLoanedDrawTarget = dtBufferOnWhite;
|
|
||||||
} else {
|
|
||||||
// BUFFER_BLACK, or BUFFER_BOTH with a single buffer.
|
|
||||||
mLoanedDrawTarget = dtBuffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Figure out which quadrant to draw in
|
|
||||||
int32_t xBoundary = mBufferRect.XMost() - mBufferRotation.x;
|
|
||||||
int32_t yBoundary = mBufferRect.YMost() - mBufferRotation.y;
|
|
||||||
XSide sideX = bounds.XMost() <= xBoundary ? RIGHT : LEFT;
|
|
||||||
YSide sideY = bounds.YMost() <= yBoundary ? BOTTOM : TOP;
|
|
||||||
IntRect quadrantRect = GetQuadrantRectangle(sideX, sideY);
|
|
||||||
NS_ASSERTION(quadrantRect.Contains(bounds), "Messed up quadrants");
|
|
||||||
|
|
||||||
if (aSetTransform) {
|
|
||||||
mLoanedTransform = mLoanedDrawTarget->GetTransform();
|
|
||||||
Matrix transform = Matrix(mLoanedTransform)
|
|
||||||
.PreTranslate(-quadrantRect.x,
|
|
||||||
-quadrantRect.y);
|
|
||||||
mLoanedDrawTarget->SetTransform(transform);
|
|
||||||
mSetTransform = true;
|
|
||||||
} else {
|
|
||||||
MOZ_ASSERT(aOutMatrix);
|
|
||||||
*aOutMatrix = Matrix::Translation(-quadrantRect.x, -quadrantRect.y);
|
|
||||||
mSetTransform = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return mLoanedDrawTarget;
|
|
||||||
}
|
|
||||||
|
|
||||||
already_AddRefed<SourceSurface>
|
already_AddRefed<SourceSurface>
|
||||||
SourceRotatedBuffer::GetSourceSurface(ContextSource aSource) const
|
SourceRotatedBuffer::GetSourceSurface(ContextSource aSource) const
|
||||||
{
|
{
|
||||||
@@ -329,6 +197,15 @@ SourceRotatedBuffer::GetSourceSurface(ContextSource aSource) const
|
|||||||
return surf.forget();
|
return surf.forget();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* static */ bool
|
||||||
|
RotatedContentBuffer::IsClippingCheap(DrawTarget* aTarget, const nsIntRegion& aRegion)
|
||||||
|
{
|
||||||
|
// Assume clipping is cheap if the draw target just has an integer
|
||||||
|
// translation, and the visible region is simple.
|
||||||
|
return !aTarget->GetTransform().HasNonIntegerTranslation() &&
|
||||||
|
aRegion.GetNumRects() <= 1;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
RotatedContentBuffer::DrawTo(PaintedLayer* aLayer,
|
RotatedContentBuffer::DrawTo(PaintedLayer* aLayer,
|
||||||
DrawTarget* aTarget,
|
DrawTarget* aTarget,
|
||||||
@@ -366,6 +243,95 @@ RotatedContentBuffer::DrawTo(PaintedLayer* aLayer,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DrawTarget*
|
||||||
|
RotatedContentBuffer::BorrowDrawTargetForQuadrantUpdate(const IntRect& aBounds,
|
||||||
|
ContextSource aSource,
|
||||||
|
DrawIterator* aIter,
|
||||||
|
bool aSetTransform,
|
||||||
|
Matrix* aOutMatrix)
|
||||||
|
{
|
||||||
|
IntRect bounds = aBounds;
|
||||||
|
if (aIter) {
|
||||||
|
// If an iterator was provided, then BeginPaint must have been run with
|
||||||
|
// PAINT_CAN_DRAW_ROTATED, and the draw region might cover multiple quadrants.
|
||||||
|
// Iterate over each of them, and return an appropriate buffer each time we find
|
||||||
|
// one that intersects the draw region. The iterator mCount value tracks which
|
||||||
|
// quadrants we have considered across multiple calls to this function.
|
||||||
|
aIter->mDrawRegion.SetEmpty();
|
||||||
|
while (aIter->mCount < 4) {
|
||||||
|
IntRect quadrant = GetQuadrantRectangle((aIter->mCount & 1) ? LEFT : RIGHT,
|
||||||
|
(aIter->mCount & 2) ? TOP : BOTTOM);
|
||||||
|
aIter->mDrawRegion.And(aBounds, quadrant);
|
||||||
|
aIter->mCount++;
|
||||||
|
if (!aIter->mDrawRegion.IsEmpty()) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (aIter->mDrawRegion.IsEmpty()) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
bounds = aIter->mDrawRegion.GetBounds();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!EnsureBuffer()) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
MOZ_ASSERT(!mLoanedDrawTarget, "draw target has been borrowed and not returned");
|
||||||
|
if (aSource == BUFFER_BOTH && HaveBufferOnWhite()) {
|
||||||
|
if (!EnsureBufferOnWhite()) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
MOZ_ASSERT(mDTBuffer && mDTBuffer->IsValid() && mDTBufferOnWhite && mDTBufferOnWhite->IsValid());
|
||||||
|
mLoanedDrawTarget = Factory::CreateDualDrawTarget(mDTBuffer, mDTBufferOnWhite);
|
||||||
|
} else if (aSource == BUFFER_WHITE) {
|
||||||
|
if (!EnsureBufferOnWhite()) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
mLoanedDrawTarget = mDTBufferOnWhite;
|
||||||
|
} else {
|
||||||
|
// BUFFER_BLACK, or BUFFER_BOTH with a single buffer.
|
||||||
|
mLoanedDrawTarget = mDTBuffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Figure out which quadrant to draw in
|
||||||
|
int32_t xBoundary = mBufferRect.XMost() - mBufferRotation.x;
|
||||||
|
int32_t yBoundary = mBufferRect.YMost() - mBufferRotation.y;
|
||||||
|
XSide sideX = bounds.XMost() <= xBoundary ? RIGHT : LEFT;
|
||||||
|
YSide sideY = bounds.YMost() <= yBoundary ? BOTTOM : TOP;
|
||||||
|
IntRect quadrantRect = GetQuadrantRectangle(sideX, sideY);
|
||||||
|
NS_ASSERTION(quadrantRect.Contains(bounds), "Messed up quadrants");
|
||||||
|
|
||||||
|
if (aSetTransform) {
|
||||||
|
mLoanedTransform = mLoanedDrawTarget->GetTransform();
|
||||||
|
Matrix transform = Matrix(mLoanedTransform)
|
||||||
|
.PreTranslate(-quadrantRect.x,
|
||||||
|
-quadrantRect.y);
|
||||||
|
mLoanedDrawTarget->SetTransform(transform);
|
||||||
|
mSetTransform = true;
|
||||||
|
} else {
|
||||||
|
MOZ_ASSERT(aOutMatrix);
|
||||||
|
*aOutMatrix = Matrix::Translation(-quadrantRect.x, -quadrantRect.y);
|
||||||
|
mSetTransform = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return mLoanedDrawTarget;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
BorrowDrawTarget::ReturnDrawTarget(gfx::DrawTarget*& aReturned)
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(mLoanedDrawTarget);
|
||||||
|
MOZ_ASSERT(aReturned == mLoanedDrawTarget);
|
||||||
|
if (mLoanedDrawTarget) {
|
||||||
|
if (mSetTransform) {
|
||||||
|
mLoanedDrawTarget->SetTransform(mLoanedTransform);
|
||||||
|
}
|
||||||
|
mLoanedDrawTarget = nullptr;
|
||||||
|
}
|
||||||
|
aReturned = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
gfxContentType
|
gfxContentType
|
||||||
RotatedContentBuffer::BufferContentType()
|
RotatedContentBuffer::BufferContentType()
|
||||||
{
|
{
|
||||||
@@ -782,9 +748,7 @@ RotatedContentBuffer::BorrowDrawTargetForRecording(PaintState& aPaintState,
|
|||||||
DrawIterator* aIter,
|
DrawIterator* aIter,
|
||||||
bool aSetTransform)
|
bool aSetTransform)
|
||||||
{
|
{
|
||||||
if (aPaintState.mMode == SurfaceMode::SURFACE_NONE ||
|
if (aPaintState.mMode == SurfaceMode::SURFACE_NONE) {
|
||||||
!EnsureBuffer() ||
|
|
||||||
(HaveBufferOnWhite() && !EnsureBufferOnWhite())) {
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -29,25 +29,6 @@ typedef bool (*PrepDrawTargetForPaintingCallback)(CapturedPaintState*);
|
|||||||
class TextureClient;
|
class TextureClient;
|
||||||
class PaintedLayer;
|
class PaintedLayer;
|
||||||
|
|
||||||
// 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 flag denotes whether or not a transform was already applied
|
|
||||||
// to mLoanedDrawTarget and thus needs to be reset to mLoanedTransform
|
|
||||||
// upon returning the drawtarget.
|
|
||||||
bool mSetTransform;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is a cairo/Thebes surface, but with a literal twist. Scrolling
|
* This is a cairo/Thebes surface, but with a literal twist. Scrolling
|
||||||
* causes the layer's visible region to move. We want to keep
|
* causes the layer's visible region to move. We want to keep
|
||||||
@@ -63,8 +44,7 @@ protected:
|
|||||||
* at row H-N on the screen.
|
* at row H-N on the screen.
|
||||||
* mBufferRotation.y would be N in this example.
|
* mBufferRotation.y would be N in this example.
|
||||||
*/
|
*/
|
||||||
class RotatedBuffer : public BorrowDrawTarget
|
class RotatedBuffer {
|
||||||
{
|
|
||||||
public:
|
public:
|
||||||
typedef gfxContentType ContentType;
|
typedef gfxContentType ContentType;
|
||||||
|
|
||||||
@@ -78,18 +58,6 @@ public:
|
|||||||
: mDidSelfCopy(false)
|
: mDidSelfCopy(false)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
struct DrawIterator {
|
|
||||||
friend class RotatedBuffer;
|
|
||||||
DrawIterator()
|
|
||||||
: mCount(0)
|
|
||||||
{}
|
|
||||||
|
|
||||||
nsIntRegion mDrawRegion;
|
|
||||||
|
|
||||||
private:
|
|
||||||
uint32_t mCount;
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Which buffer should be drawn to/read from.
|
* Which buffer should be drawn to/read from.
|
||||||
*/
|
*/
|
||||||
@@ -106,9 +74,6 @@ public:
|
|||||||
gfx::SourceSurface* aMask = nullptr,
|
gfx::SourceSurface* aMask = nullptr,
|
||||||
const gfx::Matrix* aMaskTransform = nullptr) const;
|
const gfx::Matrix* aMaskTransform = nullptr) const;
|
||||||
|
|
||||||
void UpdateDestinationFrom(const RotatedBuffer& aSource,
|
|
||||||
const nsIntRegion& aUpdateRegion);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* |BufferRect()| is the rect of device pixels that this
|
* |BufferRect()| is the rect of device pixels that this
|
||||||
* RotatedBuffer covers. That is what DrawBufferWithRotation()
|
* RotatedBuffer covers. That is what DrawBufferWithRotation()
|
||||||
@@ -124,9 +89,6 @@ public:
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
virtual gfx::DrawTarget* GetDTBuffer() const = 0;
|
|
||||||
virtual gfx::DrawTarget* GetDTBufferOnWhite() const = 0;
|
|
||||||
|
|
||||||
enum XSide {
|
enum XSide {
|
||||||
LEFT, RIGHT
|
LEFT, RIGHT
|
||||||
};
|
};
|
||||||
@@ -149,27 +111,6 @@ protected:
|
|||||||
gfx::SourceSurface* aMask,
|
gfx::SourceSurface* aMask,
|
||||||
const gfx::Matrix* aMaskTransform) const;
|
const gfx::Matrix* aMaskTransform) const;
|
||||||
|
|
||||||
/**
|
|
||||||
* Get a draw target at the specified resolution for updating |aBounds|,
|
|
||||||
* which must be contained within a single quadrant.
|
|
||||||
*
|
|
||||||
* 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 by default 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.
|
|
||||||
* If aSetTransform is false, the required transform will be set in aOutTransform.
|
|
||||||
*/
|
|
||||||
gfx::DrawTarget*
|
|
||||||
BorrowDrawTargetForQuadrantUpdate(const gfx::IntRect& aBounds,
|
|
||||||
ContextSource aSource,
|
|
||||||
DrawIterator* aIter,
|
|
||||||
bool aSetTransform = true,
|
|
||||||
gfx::Matrix* aOutTransform = nullptr);
|
|
||||||
|
|
||||||
/** The area of the PaintedLayer that is covered by the buffer as a whole */
|
/** The area of the PaintedLayer that is covered by the buffer as a whole */
|
||||||
gfx::IntRect mBufferRect;
|
gfx::IntRect mBufferRect;
|
||||||
/**
|
/**
|
||||||
@@ -204,20 +145,36 @@ public:
|
|||||||
virtual bool HaveBuffer() const { return !!mSource; }
|
virtual bool HaveBuffer() const { return !!mSource; }
|
||||||
virtual bool HaveBufferOnWhite() const { return !!mSourceOnWhite; }
|
virtual bool HaveBufferOnWhite() const { return !!mSourceOnWhite; }
|
||||||
|
|
||||||
protected:
|
|
||||||
virtual gfx::DrawTarget* GetDTBuffer() const { return nullptr; }
|
|
||||||
virtual gfx::DrawTarget* GetDTBufferOnWhite() const { return nullptr; }
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
RefPtr<gfx::SourceSurface> mSource;
|
RefPtr<gfx::SourceSurface> mSource;
|
||||||
RefPtr<gfx::SourceSurface> mSourceOnWhite;
|
RefPtr<gfx::SourceSurface> mSourceOnWhite;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 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 flag denotes whether or not a transform was already applied
|
||||||
|
// to mLoanedDrawTarget and thus needs to be reset to mLoanedTransform
|
||||||
|
// upon returning the drawtarget.
|
||||||
|
bool mSetTransform;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class encapsulates the buffer used to retain PaintedLayer contents,
|
* This class encapsulates the buffer used to retain PaintedLayer contents,
|
||||||
* i.e., the contents of the layer's GetVisibleRegion().
|
* i.e., the contents of the layer's GetVisibleRegion().
|
||||||
*/
|
*/
|
||||||
class RotatedContentBuffer : public RotatedBuffer
|
class RotatedContentBuffer : public RotatedBuffer
|
||||||
|
, public BorrowDrawTarget
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
typedef gfxContentType ContentType;
|
typedef gfxContentType ContentType;
|
||||||
@@ -315,6 +272,18 @@ public:
|
|||||||
PaintState BeginPaint(PaintedLayer* aLayer,
|
PaintState BeginPaint(PaintedLayer* aLayer,
|
||||||
uint32_t aFlags);
|
uint32_t aFlags);
|
||||||
|
|
||||||
|
struct DrawIterator {
|
||||||
|
friend class RotatedContentBuffer;
|
||||||
|
DrawIterator()
|
||||||
|
: mCount(0)
|
||||||
|
{}
|
||||||
|
|
||||||
|
nsIntRegion mDrawRegion;
|
||||||
|
|
||||||
|
private:
|
||||||
|
uint32_t mCount;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fetch a DrawTarget for rendering. The DrawTarget remains owned by
|
* Fetch a DrawTarget for rendering. The DrawTarget remains owned by
|
||||||
* this. See notes on BorrowDrawTargetForQuadrantUpdate.
|
* this. See notes on BorrowDrawTargetForQuadrantUpdate.
|
||||||
@@ -362,6 +331,14 @@ public:
|
|||||||
CreateBuffer(ContentType aType, const gfx::IntRect& aRect, uint32_t aFlags,
|
CreateBuffer(ContentType aType, const gfx::IntRect& aRect, uint32_t aFlags,
|
||||||
RefPtr<gfx::DrawTarget>* aBlackDT, RefPtr<gfx::DrawTarget>* aWhiteDT) = 0;
|
RefPtr<gfx::DrawTarget>* aBlackDT, RefPtr<gfx::DrawTarget>* aWhiteDT) = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the underlying buffer, if any. This is useful because we can pass
|
||||||
|
* in the buffer as the default "reference surface" if there is one.
|
||||||
|
* Don't use it for anything else!
|
||||||
|
*/
|
||||||
|
gfx::DrawTarget* GetDTBuffer() { return mDTBuffer; }
|
||||||
|
gfx::DrawTarget* GetDTBufferOnWhite() { return mDTBufferOnWhite; }
|
||||||
|
|
||||||
virtual already_AddRefed<gfx::SourceSurface> GetSourceSurface(ContextSource aSource) const;
|
virtual already_AddRefed<gfx::SourceSurface> GetSourceSurface(ContextSource aSource) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -402,6 +379,29 @@ protected:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a draw target at the specified resolution for updating |aBounds|,
|
||||||
|
* which must be contained within a single quadrant.
|
||||||
|
*
|
||||||
|
* 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 by default 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.
|
||||||
|
* If aSetTransform is false, the required transform will be set in aOutTransform.
|
||||||
|
*/
|
||||||
|
gfx::DrawTarget*
|
||||||
|
BorrowDrawTargetForQuadrantUpdate(const gfx::IntRect& aBounds,
|
||||||
|
ContextSource aSource,
|
||||||
|
DrawIterator* aIter,
|
||||||
|
bool aSetTransform = true,
|
||||||
|
gfx::Matrix* aOutTransform = nullptr);
|
||||||
|
|
||||||
|
static bool IsClippingCheap(gfx::DrawTarget* aTarget, const nsIntRegion& aRegion);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
/**
|
/**
|
||||||
* Return the buffer's content type. Requires a valid buffer or
|
* Return the buffer's content type. Requires a valid buffer or
|
||||||
@@ -418,14 +418,6 @@ protected:
|
|||||||
// Flush our buffers if they are mapped.
|
// Flush our buffers if they are mapped.
|
||||||
void FlushBuffers();
|
void FlushBuffers();
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the underlying buffer, if any. This is useful because we can pass
|
|
||||||
* in the buffer as the default "reference surface" if there is one.
|
|
||||||
* Don't use it for anything else!
|
|
||||||
*/
|
|
||||||
virtual gfx::DrawTarget* GetDTBuffer() const { return mDTBuffer; }
|
|
||||||
virtual gfx::DrawTarget* GetDTBufferOnWhite() const { return mDTBufferOnWhite; }
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* True if we have a buffer where we can get it (but not necessarily
|
* True if we have a buffer where we can get it (but not necessarily
|
||||||
* mapped currently).
|
* mapped currently).
|
||||||
|
|||||||
@@ -636,11 +636,6 @@ ContentClientDoubleBuffered::FinalizeFrame(const nsIntRegion& aRegionToDraw)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!EnsureBuffer() ||
|
|
||||||
(HaveBufferOnWhite() && !EnsureBufferOnWhite())) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// We need to ensure that we lock these two buffers in the same
|
// We need to ensure that we lock these two buffers in the same
|
||||||
// order as the compositor to prevent deadlocks.
|
// order as the compositor to prevent deadlocks.
|
||||||
TextureClientAutoLock frontLock(mFrontClient, OpenMode::OPEN_READ_ONLY);
|
TextureClientAutoLock frontLock(mFrontClient, OpenMode::OPEN_READ_ONLY);
|
||||||
@@ -686,5 +681,47 @@ ContentClientDoubleBuffered::EnsureBackBufferIfFrontBuffer()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ContentClientDoubleBuffered::UpdateDestinationFrom(const RotatedBuffer& aSource,
|
||||||
|
const nsIntRegion& aUpdateRegion)
|
||||||
|
{
|
||||||
|
DrawIterator iter;
|
||||||
|
while (DrawTarget* destDT =
|
||||||
|
BorrowDrawTargetForQuadrantUpdate(aUpdateRegion.GetBounds(), BUFFER_BLACK, &iter)) {
|
||||||
|
bool isClippingCheap = IsClippingCheap(destDT, iter.mDrawRegion);
|
||||||
|
if (isClippingCheap) {
|
||||||
|
gfxUtils::ClipToRegion(destDT, iter.mDrawRegion);
|
||||||
|
}
|
||||||
|
|
||||||
|
aSource.DrawBufferWithRotation(destDT, BUFFER_BLACK, 1.0, CompositionOp::OP_SOURCE);
|
||||||
|
if (isClippingCheap) {
|
||||||
|
destDT->PopClip();
|
||||||
|
}
|
||||||
|
// Flush the destination before the sources become inaccessible (Unlock).
|
||||||
|
destDT->Flush();
|
||||||
|
ReturnDrawTargetToBuffer(destDT);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (aSource.HaveBufferOnWhite()) {
|
||||||
|
MOZ_ASSERT(HaveBufferOnWhite());
|
||||||
|
DrawIterator whiteIter;
|
||||||
|
while (DrawTarget* destDT =
|
||||||
|
BorrowDrawTargetForQuadrantUpdate(aUpdateRegion.GetBounds(), BUFFER_WHITE, &whiteIter)) {
|
||||||
|
bool isClippingCheap = IsClippingCheap(destDT, whiteIter.mDrawRegion);
|
||||||
|
if (isClippingCheap) {
|
||||||
|
gfxUtils::ClipToRegion(destDT, whiteIter.mDrawRegion);
|
||||||
|
}
|
||||||
|
|
||||||
|
aSource.DrawBufferWithRotation(destDT, BUFFER_WHITE, 1.0, CompositionOp::OP_SOURCE);
|
||||||
|
if (isClippingCheap) {
|
||||||
|
destDT->PopClip();
|
||||||
|
}
|
||||||
|
// Flush the destination before the sources become inaccessible (Unlock).
|
||||||
|
destDT->Flush();
|
||||||
|
ReturnDrawTargetToBuffer(destDT);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace layers
|
} // namespace layers
|
||||||
} // namespace mozilla
|
} // namespace mozilla
|
||||||
|
|||||||
@@ -363,6 +363,8 @@ protected:
|
|||||||
virtual void DestroyFrontBuffer() override;
|
virtual void DestroyFrontBuffer() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void UpdateDestinationFrom(const RotatedBuffer& aSource,
|
||||||
|
const nsIntRegion& aUpdateRegion);
|
||||||
|
|
||||||
virtual void AbortTextureClientCreation() override
|
virtual void AbortTextureClientCreation() override
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user