mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-14 22:05:44 +00:00
Bug 599359, part 2: When we allocate a new front/back buffer pair, pre-fill the new front buffer with what we painted into the back buffer to stabilize the first Swap(). r=vlad a=blocking-fennec
This commit is contained in:
parent
6bee72a35f
commit
374601de26
@ -1432,6 +1432,10 @@ private:
|
||||
// copy of the descriptor here so that we can call
|
||||
// DestroySharedSurface() on the descriptor.
|
||||
SurfaceDescriptor mBackBuffer;
|
||||
// When we allocate a new front buffer, we keep a temporary record
|
||||
// of it until reach PaintBuffer(). Then we pre-fill back->front
|
||||
// and destroy our record.
|
||||
SurfaceDescriptor mNewFrontBuffer;
|
||||
nsIntSize mBufferSize;
|
||||
};
|
||||
|
||||
@ -1449,8 +1453,39 @@ BasicShadowableThebesLayer::PaintBuffer(gfxContext* aContext,
|
||||
NS_ABORT_IF_FALSE(IsSurfaceDescriptorValid(mBackBuffer),
|
||||
"should have a back buffer by now");
|
||||
|
||||
nsIntRegion updatedRegion = aRegionToDraw;
|
||||
if (IsSurfaceDescriptorValid(mNewFrontBuffer)) {
|
||||
// We just allocated a new buffer pair. We want to "pre-fill"
|
||||
// the new front buffer by copying to it what we just painted
|
||||
// into the back buffer. This starts off our Swap()s from a
|
||||
// stable base: the first swap will return the same valid region
|
||||
// as our new back buffer. Thereafter, we only need to
|
||||
// invalidate what was painted into the back buffer.
|
||||
nsRefPtr<gfxASurface> frontBuffer =
|
||||
BasicManager()->OpenDescriptor(mNewFrontBuffer);
|
||||
nsRefPtr<gfxASurface> backBuffer =
|
||||
BasicManager()->OpenDescriptor(mBackBuffer);
|
||||
|
||||
nsRefPtr<gfxContext> ctx = new gfxContext(frontBuffer);
|
||||
ctx->SetOperator(gfxContext::OPERATOR_SOURCE);
|
||||
ctx->DrawSurface(backBuffer, backBuffer->GetSize());
|
||||
|
||||
BasicManager()->CreatedThebesBuffer(BasicManager()->Hold(this),
|
||||
mValidRegion,
|
||||
mXResolution,
|
||||
mYResolution,
|
||||
mBuffer.BufferRect(),
|
||||
mNewFrontBuffer);
|
||||
|
||||
// Clear temporary record of new front buffer
|
||||
mNewFrontBuffer = SurfaceDescriptor();
|
||||
// And pretend that we didn't update anything, in order to
|
||||
// stabilize the first swap.
|
||||
updatedRegion.SetEmpty();
|
||||
}
|
||||
|
||||
BasicManager()->PaintedThebesBuffer(BasicManager()->Hold(this),
|
||||
aRegionToDraw,
|
||||
updatedRegion,
|
||||
mBuffer.BufferRect(),
|
||||
mBuffer.BufferRotation(),
|
||||
mBackBuffer);
|
||||
@ -1471,19 +1506,15 @@ BasicShadowableThebesLayer::CreateBuffer(Buffer::ContentType aType,
|
||||
mBackBuffer = SurfaceDescriptor();
|
||||
}
|
||||
|
||||
SurfaceDescriptor tmpFront;
|
||||
// XXX error handling
|
||||
NS_ABORT_IF_FALSE(!IsSurfaceDescriptorValid(mNewFrontBuffer),
|
||||
"Bad! Did we create a buffer twice without painting?");
|
||||
if (!BasicManager()->AllocDoubleBuffer(gfxIntSize(aSize.width, aSize.height),
|
||||
aType,
|
||||
&tmpFront,
|
||||
&mNewFrontBuffer,
|
||||
&mBackBuffer))
|
||||
NS_RUNTIMEABORT("creating ThebesLayer 'back buffer' failed!");
|
||||
mBufferSize = aSize;
|
||||
|
||||
nsIntRect bufRect = mVisibleRegion.GetBounds();
|
||||
BasicManager()->CreatedThebesBuffer(BasicManager()->Hold(this),
|
||||
bufRect,
|
||||
tmpFront);
|
||||
return BasicManager()->OpenDescriptor(mBackBuffer);
|
||||
}
|
||||
|
||||
@ -1769,6 +1800,10 @@ public:
|
||||
MOZ_COUNT_DTOR(BasicShadowThebesLayer);
|
||||
}
|
||||
|
||||
virtual void SetFrontBuffer(const ThebesBuffer& aNewFront,
|
||||
const nsIntRegion& aValidRegion,
|
||||
float aXResolution, float aYResolution);
|
||||
|
||||
virtual void SetValidRegion(const nsIntRegion& aRegion)
|
||||
{
|
||||
mOldValidRegion = mValidRegion;
|
||||
@ -1829,6 +1864,25 @@ private:
|
||||
float mOldYResolution;
|
||||
};
|
||||
|
||||
void
|
||||
BasicShadowThebesLayer::SetFrontBuffer(const ThebesBuffer& aNewFront,
|
||||
const nsIntRegion& aValidRegion,
|
||||
float aXResolution, float aYResolution)
|
||||
{
|
||||
mValidRegion = mOldValidRegion = aValidRegion;
|
||||
mXResolution = mOldXResolution = aXResolution;
|
||||
mYResolution = mOldYResolution = aYResolution;
|
||||
nsRefPtr<gfxASurface> newFrontBuffer =
|
||||
BasicManager()->OpenDescriptor(aNewFront.buffer());
|
||||
|
||||
nsRefPtr<gfxASurface> unused;
|
||||
nsIntRect unusedRect;
|
||||
nsIntPoint unusedRotation;
|
||||
mFrontBuffer.Swap(newFrontBuffer, aNewFront.rect(), aNewFront.rotation(),
|
||||
getter_AddRefs(unused), &unusedRect, &unusedRotation);
|
||||
mFrontBufferDescriptor = aNewFront.buffer();
|
||||
}
|
||||
|
||||
void
|
||||
BasicShadowThebesLayer::Swap(const ThebesBuffer& aNewFront,
|
||||
const nsIntRegion& aUpdatedRegion,
|
||||
|
@ -82,10 +82,18 @@ union SurfaceDescriptor {
|
||||
SurfaceDescriptorX11;
|
||||
};
|
||||
|
||||
struct ThebesBuffer {
|
||||
SurfaceDescriptor buffer;
|
||||
nsIntRect rect;
|
||||
nsIntPoint rotation;
|
||||
};
|
||||
|
||||
struct OpCreateThebesBuffer {
|
||||
PLayer layer;
|
||||
nsIntRect bufferRect;
|
||||
SurfaceDescriptor initialFront;
|
||||
ThebesBuffer initialFront;
|
||||
nsIntRegion frontValidRegion;
|
||||
float xResolution;
|
||||
float yResolution;
|
||||
};
|
||||
struct OpDestroyThebesFrontBuffer { PLayer layer; };
|
||||
|
||||
@ -152,11 +160,6 @@ struct OpRemoveChild { PLayer container; PLayer childLayer; };
|
||||
|
||||
|
||||
// Paint (buffer update)
|
||||
struct ThebesBuffer {
|
||||
SurfaceDescriptor buffer;
|
||||
nsIntRect rect;
|
||||
nsIntPoint rotation;
|
||||
};
|
||||
struct OpPaintThebesBuffer {
|
||||
PLayer layer;
|
||||
ThebesBuffer newFrontBuffer;
|
||||
|
@ -183,12 +183,19 @@ ShadowLayerForwarder::CreatedCanvasLayer(ShadowableLayer* aCanvas)
|
||||
|
||||
void
|
||||
ShadowLayerForwarder::CreatedThebesBuffer(ShadowableLayer* aThebes,
|
||||
nsIntRect aBufferRect,
|
||||
const nsIntRegion& aFrontValidRegion,
|
||||
float aXResolution,
|
||||
float aYResolution,
|
||||
const nsIntRect& aBufferRect,
|
||||
const SurfaceDescriptor& aTempFrontBuffer)
|
||||
{
|
||||
mTxn->AddEdit(OpCreateThebesBuffer(NULL, Shadow(aThebes),
|
||||
aBufferRect,
|
||||
aTempFrontBuffer));
|
||||
ThebesBuffer(aTempFrontBuffer,
|
||||
aBufferRect,
|
||||
nsIntPoint(0, 0)),
|
||||
aFrontValidRegion,
|
||||
aXResolution,
|
||||
aYResolution));
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -143,13 +143,16 @@ public:
|
||||
*
|
||||
* It is expected that Created*Buffer() will be followed by a
|
||||
* Painted*Buffer() in the same transaction, so that
|
||||
* |aInitialFrontBuffer| is never actually drawn to screen.
|
||||
* |aInitialFrontBuffer| is never actually drawn to screen. It is
|
||||
* OK if it is drawn though.
|
||||
*/
|
||||
/**
|
||||
* |aBufferRect| is the screen rect covered by |aInitialFrontBuffer|.
|
||||
*/
|
||||
void CreatedThebesBuffer(ShadowableLayer* aThebes,
|
||||
nsIntRect aBufferRect,
|
||||
const nsIntRegion& aFrontValidRegion,
|
||||
float aXResolution, float aYResolution,
|
||||
const nsIntRect& aBufferRect,
|
||||
const SurfaceDescriptor& aInitialFrontBuffer);
|
||||
/**
|
||||
* For the next two methods, |aSize| is the size of
|
||||
@ -394,6 +397,16 @@ public:
|
||||
mAllocator = aParent;
|
||||
}
|
||||
|
||||
/**
|
||||
* CONSTRUCTION PHASE ONLY
|
||||
*
|
||||
* Override the front buffer and its valid region with the specified
|
||||
* values. This is called when a new buffer has been created.
|
||||
*/
|
||||
virtual void SetFrontBuffer(const ThebesBuffer& aNewFront,
|
||||
const nsIntRegion& aValidRegion,
|
||||
float aXResolution, float aYResolution) = 0;
|
||||
|
||||
virtual void InvalidateRegion(const nsIntRegion& aRegion)
|
||||
{
|
||||
NS_RUNTIMEABORT("ShadowThebesLayers can't fill invalidated regions");
|
||||
|
@ -195,12 +195,8 @@ ShadowLayersParent::RecvUpdate(const nsTArray<Edit>& cset,
|
||||
ShadowThebesLayer* thebes = static_cast<ShadowThebesLayer*>(
|
||||
AsShadowLayer(otb)->AsLayer());
|
||||
|
||||
ThebesBuffer unusedBuffer;
|
||||
nsIntRegion unusedRegion; float unusedXRes, unusedYRes;
|
||||
thebes->Swap(
|
||||
ThebesBuffer(otb.initialFront(), otb.bufferRect(), nsIntPoint(0, 0)),
|
||||
unusedRegion,
|
||||
&unusedBuffer, &unusedRegion, &unusedXRes, &unusedYRes);
|
||||
thebes->SetFrontBuffer(otb.initialFront(), otb.frontValidRegion(),
|
||||
otb.xResolution(), otb.yResolution());
|
||||
|
||||
break;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user