Backed out changeset 0c763c30594d (bug 1409871)
This commit is contained in:
@@ -35,20 +35,6 @@ using namespace gfx;
|
||||
|
||||
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
|
||||
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);
|
||||
}
|
||||
|
||||
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>
|
||||
SourceRotatedBuffer::GetSourceSurface(ContextSource aSource) const
|
||||
{
|
||||
@@ -329,6 +197,15 @@ SourceRotatedBuffer::GetSourceSurface(ContextSource aSource) const
|
||||
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
|
||||
RotatedContentBuffer::DrawTo(PaintedLayer* aLayer,
|
||||
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
|
||||
RotatedContentBuffer::BufferContentType()
|
||||
{
|
||||
@@ -782,9 +748,7 @@ RotatedContentBuffer::BorrowDrawTargetForRecording(PaintState& aPaintState,
|
||||
DrawIterator* aIter,
|
||||
bool aSetTransform)
|
||||
{
|
||||
if (aPaintState.mMode == SurfaceMode::SURFACE_NONE ||
|
||||
!EnsureBuffer() ||
|
||||
(HaveBufferOnWhite() && !EnsureBufferOnWhite())) {
|
||||
if (aPaintState.mMode == SurfaceMode::SURFACE_NONE) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
@@ -29,25 +29,6 @@ typedef bool (*PrepDrawTargetForPaintingCallback)(CapturedPaintState*);
|
||||
class TextureClient;
|
||||
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
|
||||
* causes the layer's visible region to move. We want to keep
|
||||
@@ -63,8 +44,7 @@ protected:
|
||||
* at row H-N on the screen.
|
||||
* mBufferRotation.y would be N in this example.
|
||||
*/
|
||||
class RotatedBuffer : public BorrowDrawTarget
|
||||
{
|
||||
class RotatedBuffer {
|
||||
public:
|
||||
typedef gfxContentType ContentType;
|
||||
|
||||
@@ -78,18 +58,6 @@ public:
|
||||
: mDidSelfCopy(false)
|
||||
{ }
|
||||
|
||||
struct DrawIterator {
|
||||
friend class RotatedBuffer;
|
||||
DrawIterator()
|
||||
: mCount(0)
|
||||
{}
|
||||
|
||||
nsIntRegion mDrawRegion;
|
||||
|
||||
private:
|
||||
uint32_t mCount;
|
||||
};
|
||||
|
||||
/*
|
||||
* Which buffer should be drawn to/read from.
|
||||
*/
|
||||
@@ -106,9 +74,6 @@ public:
|
||||
gfx::SourceSurface* aMask = nullptr,
|
||||
const gfx::Matrix* aMaskTransform = nullptr) const;
|
||||
|
||||
void UpdateDestinationFrom(const RotatedBuffer& aSource,
|
||||
const nsIntRegion& aUpdateRegion);
|
||||
|
||||
/**
|
||||
* |BufferRect()| is the rect of device pixels that this
|
||||
* RotatedBuffer covers. That is what DrawBufferWithRotation()
|
||||
@@ -124,9 +89,6 @@ public:
|
||||
|
||||
protected:
|
||||
|
||||
virtual gfx::DrawTarget* GetDTBuffer() const = 0;
|
||||
virtual gfx::DrawTarget* GetDTBufferOnWhite() const = 0;
|
||||
|
||||
enum XSide {
|
||||
LEFT, RIGHT
|
||||
};
|
||||
@@ -149,27 +111,6 @@ protected:
|
||||
gfx::SourceSurface* aMask,
|
||||
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 */
|
||||
gfx::IntRect mBufferRect;
|
||||
/**
|
||||
@@ -204,20 +145,36 @@ public:
|
||||
virtual bool HaveBuffer() const { return !!mSource; }
|
||||
virtual bool HaveBufferOnWhite() const { return !!mSourceOnWhite; }
|
||||
|
||||
protected:
|
||||
virtual gfx::DrawTarget* GetDTBuffer() const { return nullptr; }
|
||||
virtual gfx::DrawTarget* GetDTBufferOnWhite() const { return nullptr; }
|
||||
|
||||
private:
|
||||
RefPtr<gfx::SourceSurface> mSource;
|
||||
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,
|
||||
* i.e., the contents of the layer's GetVisibleRegion().
|
||||
*/
|
||||
class RotatedContentBuffer : public RotatedBuffer
|
||||
, public BorrowDrawTarget
|
||||
{
|
||||
public:
|
||||
typedef gfxContentType ContentType;
|
||||
@@ -315,6 +272,18 @@ public:
|
||||
PaintState BeginPaint(PaintedLayer* aLayer,
|
||||
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
|
||||
* this. See notes on BorrowDrawTargetForQuadrantUpdate.
|
||||
@@ -362,6 +331,14 @@ public:
|
||||
CreateBuffer(ContentType aType, const gfx::IntRect& aRect, uint32_t aFlags,
|
||||
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;
|
||||
|
||||
/**
|
||||
@@ -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:
|
||||
/**
|
||||
* Return the buffer's content type. Requires a valid buffer or
|
||||
@@ -418,14 +418,6 @@ protected:
|
||||
// Flush our buffers if they are mapped.
|
||||
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
|
||||
* mapped currently).
|
||||
|
||||
@@ -636,11 +636,6 @@ ContentClientDoubleBuffered::FinalizeFrame(const nsIntRegion& aRegionToDraw)
|
||||
return;
|
||||
}
|
||||
|
||||
if (!EnsureBuffer() ||
|
||||
(HaveBufferOnWhite() && !EnsureBufferOnWhite())) {
|
||||
return;
|
||||
}
|
||||
|
||||
// We need to ensure that we lock these two buffers in the same
|
||||
// order as the compositor to prevent deadlocks.
|
||||
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 mozilla
|
||||
|
||||
@@ -363,6 +363,8 @@ protected:
|
||||
virtual void DestroyFrontBuffer() override;
|
||||
|
||||
private:
|
||||
void UpdateDestinationFrom(const RotatedBuffer& aSource,
|
||||
const nsIntRegion& aUpdateRegion);
|
||||
|
||||
virtual void AbortTextureClientCreation() override
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user