mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-27 06:43:32 +00:00
Bug 570625, part 1: Only use back/front buffers for BasicThebesLayer and update back->front in the compositor process. r=roc sr=shaver
This commit is contained in:
parent
f5894e967e
commit
7e002c08ab
@ -155,6 +155,18 @@ protected:
|
||||
void DrawBufferWithRotation(gfxContext* aTarget, float aOpacity,
|
||||
float aXRes, float aYRes);
|
||||
|
||||
/**
|
||||
* |BufferRect()| is the rect of device pixels that this
|
||||
* ThebesLayerBuffer covers. That is what DrawBufferWithRotation()
|
||||
* will paint when it's called.
|
||||
*
|
||||
* |BufferDims()| is the actual dimensions of the underlying surface
|
||||
* maintained by this, also in device pixels. It is *not*
|
||||
* necessarily true that |BufferRect().Size() == BufferDims()|.
|
||||
* They may differ if a ThebesLayer is drawn at a non-1.0
|
||||
* resolution.
|
||||
*/
|
||||
const nsIntSize& BufferDims() const { return mBufferDims; }
|
||||
const nsIntRect& BufferRect() const { return mBufferRect; }
|
||||
const nsIntPoint& BufferRotation() const { return mBufferRotation; }
|
||||
|
||||
|
@ -261,6 +261,22 @@ public:
|
||||
virtual already_AddRefed<gfxASurface>
|
||||
CreateBuffer(ContentType aType, const nsIntSize& aSize);
|
||||
|
||||
/**
|
||||
* Swap out the old backing buffer for |aBuffer|.
|
||||
*
|
||||
* CAVEAT EMPTOR: |aBuffer| must have the same dimensions and pixels
|
||||
* as the previous buffer. If not, rendering glitches will occur.
|
||||
* This is a rather dangerous and low-level interface added in bug
|
||||
* 570625 as an intermediate step to a better interface.
|
||||
*/
|
||||
void SetBackingBuffer(gfxASurface* aBuffer)
|
||||
{
|
||||
gfxIntSize prevSize = gfxIntSize(BufferDims().width, BufferDims().height);
|
||||
NS_ABORT_IF_FALSE(aBuffer->GetSize() == prevSize,
|
||||
"Swapped-in buffer size doesn't match old buffer's!");
|
||||
SetBuffer(aBuffer, BufferDims(), BufferRect(), BufferRotation());
|
||||
}
|
||||
|
||||
private:
|
||||
BasicThebesLayer* mLayer;
|
||||
};
|
||||
@ -1343,6 +1359,7 @@ public:
|
||||
virtual void SetBackBuffer(gfxSharedImageSurface* aBuffer)
|
||||
{
|
||||
mBackBuffer = aBuffer;
|
||||
mBuffer.SetBackingBuffer(aBuffer);
|
||||
}
|
||||
|
||||
virtual void Disconnect()
|
||||
@ -1367,6 +1384,8 @@ private:
|
||||
NS_OVERRIDE virtual already_AddRefed<gfxASurface>
|
||||
CreateBuffer(Buffer::ContentType aType, const nsIntSize& aSize);
|
||||
|
||||
// We give a ref to this buffer to our ThebesLayerBuffer, and keep
|
||||
// this ref here that we can destroy its underlying shmem segment.
|
||||
nsRefPtr<gfxSharedImageSurface> mBackBuffer;
|
||||
nsIntSize mBufferSize;
|
||||
};
|
||||
@ -1384,11 +1403,6 @@ BasicShadowableThebesLayer::PaintBuffer(gfxContext* aContext,
|
||||
if (HasShadow()) {
|
||||
NS_ABORT_IF_FALSE(!!mBackBuffer, "should have a back buffer by now");
|
||||
|
||||
nsRefPtr<gfxContext> tmpCtx = new gfxContext(mBackBuffer);
|
||||
tmpCtx->SetOperator(gfxContext::OPERATOR_SOURCE);
|
||||
tmpCtx->DrawSurface(aContext->OriginalSurface(),
|
||||
gfxIntSize(mBufferSize.width, mBufferSize.height));
|
||||
|
||||
BasicManager()->PaintedThebesBuffer(BasicManager()->Hold(this),
|
||||
mBuffer.BufferRect(),
|
||||
mBuffer.BufferRotation(),
|
||||
@ -1400,31 +1414,35 @@ already_AddRefed<gfxASurface>
|
||||
BasicShadowableThebesLayer::CreateBuffer(Buffer::ContentType aType,
|
||||
const nsIntSize& aSize)
|
||||
{
|
||||
if (HasShadow()) {
|
||||
if (mBackBuffer) {
|
||||
BasicManager()->ShadowLayerForwarder::DestroySharedSurface(mBackBuffer);
|
||||
mBackBuffer = nsnull;
|
||||
|
||||
BasicManager()->DestroyedThebesBuffer(BasicManager()->Hold(this));
|
||||
}
|
||||
|
||||
nsRefPtr<gfxSharedImageSurface> tmpFront;
|
||||
// XXX error handling
|
||||
if (!BasicManager()->AllocDoubleBuffer(gfxIntSize(aSize.width, aSize.height),
|
||||
gfxASurface::ImageFormatARGB32,
|
||||
getter_AddRefs(tmpFront),
|
||||
getter_AddRefs(mBackBuffer)))
|
||||
NS_RUNTIMEABORT("creating ThebesLayer 'back buffer' failed!");
|
||||
mBufferSize = aSize;
|
||||
|
||||
BasicManager()->CreatedThebesBuffer(BasicManager()->Hold(this),
|
||||
// only |aSize| really matters
|
||||
// here, since Painted() soon
|
||||
// follows
|
||||
nsIntRect(nsIntPoint(0, 0), aSize),
|
||||
tmpFront);
|
||||
if (!HasShadow()) {
|
||||
return BasicThebesLayer::CreateBuffer(aType, aSize);
|
||||
}
|
||||
return Base::CreateBuffer(aType, aSize);
|
||||
|
||||
if (mBackBuffer) {
|
||||
BasicManager()->DestroyedThebesBuffer(BasicManager()->Hold(this),
|
||||
mBackBuffer);
|
||||
mBackBuffer = nsnull;
|
||||
}
|
||||
|
||||
gfxASurface::gfxImageFormat format = (aType == gfxASurface::CONTENT_COLOR) ?
|
||||
gfxASurface::ImageFormatRGB24 :
|
||||
gfxASurface::ImageFormatARGB32;
|
||||
nsRefPtr<gfxSharedImageSurface> tmpFront;
|
||||
// XXX error handling
|
||||
if (!BasicManager()->AllocDoubleBuffer(gfxIntSize(aSize.width, aSize.height),
|
||||
format,
|
||||
getter_AddRefs(tmpFront),
|
||||
getter_AddRefs(mBackBuffer)))
|
||||
NS_RUNTIMEABORT("creating ThebesLayer 'back buffer' failed!");
|
||||
mBufferSize = aSize;
|
||||
|
||||
BasicManager()->CreatedThebesBuffer(BasicManager()->Hold(this),
|
||||
// only |aSize| really matters
|
||||
// here, since Painted() soon
|
||||
// follows
|
||||
nsIntRect(nsIntPoint(0, 0), aSize),
|
||||
tmpFront);
|
||||
return nsRefPtr<gfxASurface>(mBackBuffer).forget();
|
||||
}
|
||||
|
||||
|
||||
@ -1671,6 +1689,15 @@ public:
|
||||
nsRefPtr<gfxASurface> newBackBuffer = SetBuffer(aNewFrontBuffer,
|
||||
aBufferDims,
|
||||
aBufferRect, aRotation);
|
||||
if (newBackBuffer && aNewFrontBuffer) {
|
||||
// Copy the new pixels in the new front buffer to our previous
|
||||
// front buffer. This is intended to be optimized! Many
|
||||
// factors are involved.
|
||||
nsRefPtr<gfxContext> tmpCtx = new gfxContext(newBackBuffer);
|
||||
tmpCtx->SetOperator(gfxContext::OPERATOR_SOURCE);
|
||||
tmpCtx->DrawSurface(aNewFrontBuffer,
|
||||
gfxIntSize(aBufferDims.width, aBufferDims.height));
|
||||
}
|
||||
return static_cast<gfxSharedImageSurface*>(newBackBuffer.forget().get());
|
||||
}
|
||||
|
||||
@ -1717,7 +1744,7 @@ public:
|
||||
virtual void DestroyFrontBuffer()
|
||||
{
|
||||
nsRefPtr<gfxSharedImageSurface> frontBuffer =
|
||||
mFrontBuffer.Swap(0, nsIntSize(), nsIntRect());
|
||||
mFrontBuffer.Swap(nsnull, nsIntSize(), nsIntRect());
|
||||
if (frontBuffer) {
|
||||
BasicManager()->ShadowLayerManager::DestroySharedSurface(frontBuffer);
|
||||
}
|
||||
|
@ -52,6 +52,7 @@
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
|
||||
typedef nsTArray<nsRefPtr<gfxSharedImageSurface> > BufferArray;
|
||||
typedef std::vector<Edit> EditVector;
|
||||
typedef std::set<ShadowableLayer*> ShadowableLayerSet;
|
||||
|
||||
@ -72,10 +73,16 @@ public:
|
||||
NS_ABORT_IF_FALSE(!Finished(), "forgot BeginTransaction?");
|
||||
mMutants.insert(aLayer);
|
||||
}
|
||||
void AddBufferToDestroy(gfxSharedImageSurface* aBuffer)
|
||||
{
|
||||
NS_ABORT_IF_FALSE(!Finished(), "forgot BeginTransaction?");
|
||||
mDyingBuffers.AppendElement(aBuffer);
|
||||
}
|
||||
|
||||
void End()
|
||||
{
|
||||
mCset.clear();
|
||||
mDyingBuffers.Clear();
|
||||
mMutants.clear();
|
||||
mOpen = PR_FALSE;
|
||||
}
|
||||
@ -84,6 +91,7 @@ public:
|
||||
PRBool Finished() const { return !mOpen && Empty(); }
|
||||
|
||||
EditVector mCset;
|
||||
BufferArray mDyingBuffers;
|
||||
ShadowableLayerSet mMutants;
|
||||
|
||||
private:
|
||||
@ -188,9 +196,11 @@ ShadowLayerForwarder::CreatedCanvasBuffer(ShadowableLayer* aCanvas,
|
||||
}
|
||||
|
||||
void
|
||||
ShadowLayerForwarder::DestroyedThebesBuffer(ShadowableLayer* aThebes)
|
||||
ShadowLayerForwarder::DestroyedThebesBuffer(ShadowableLayer* aThebes,
|
||||
gfxSharedImageSurface* aBackBufferToDestroy)
|
||||
{
|
||||
mTxn->AddEdit(OpDestroyThebesFrontBuffer(NULL, Shadow(aThebes)));
|
||||
mTxn->AddBufferToDestroy(aBackBufferToDestroy);
|
||||
}
|
||||
|
||||
void
|
||||
@ -277,6 +287,12 @@ ShadowLayerForwarder::EndTransaction(nsTArray<EditReply>* aReplies)
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
MOZ_LAYERS_LOG(("[LayersForwarder] destroying buffers..."));
|
||||
|
||||
for (PRUint32 i = 0; i < mTxn->mDyingBuffers.Length(); ++i) {
|
||||
DestroySharedSurface(mTxn->mDyingBuffers[i]);
|
||||
}
|
||||
|
||||
MOZ_LAYERS_LOG(("[LayersForwarder] sending transaction..."));
|
||||
|
||||
for (ShadowableLayerSet::const_iterator it = mTxn->mMutants.begin();
|
||||
|
@ -161,11 +161,15 @@ public:
|
||||
gfxSharedImageSurface* aInitialFrontSurface);
|
||||
|
||||
/**
|
||||
* The specified layer should destroy its front buffer. This can
|
||||
* happen when a new front/back buffer pair have been created
|
||||
* because of a layer resize, e.g.
|
||||
* The specified layer is destroying its buffers.
|
||||
* |aBackBufferToDestroy| is deallocated when this transaction is
|
||||
* posted to the parent. During the parent-side transaction, the
|
||||
* shadow is told to destroy its front buffer. This can happen when
|
||||
* a new front/back buffer pair have been created because of a layer
|
||||
* resize, e.g.
|
||||
*/
|
||||
void DestroyedThebesBuffer(ShadowableLayer* aThebes);
|
||||
void DestroyedThebesBuffer(ShadowableLayer* aThebes,
|
||||
gfxSharedImageSurface* aBackBufferToDestroy);
|
||||
void DestroyedImageBuffer(ShadowableLayer* aImage);
|
||||
void DestroyedCanvasBuffer(ShadowableLayer* aCanvas);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user