Bug 783368 - Uncouple low precision updates from standard. r=bgirard

Allow low precision updates to happen regardless of the state of the unscaled
tile buffer.
This commit is contained in:
Chris Lord 2012-11-21 19:16:53 +00:00
parent 960993b01b
commit 561141a84b

View File

@ -484,8 +484,12 @@ BasicTiledThebesLayer::PaintThebes(gfxContext* aContext,
transform.Invert();
nsIntRect layerDisplayPort;
nsIntRegion lowPrecisionInvalidRegion;
const gfx::Rect& criticalDisplayPort = GetParent()->GetFrameMetrics().mCriticalDisplayPort;
if (!criticalDisplayPort.IsEmpty()) {
// Calculate the invalid region for the low precision buffer
lowPrecisionInvalidRegion.Sub(mVisibleRegion, mLowPrecisionValidRegion);
// Find the critical display port in layer space.
gfxRect transformedCriticalDisplayPort = transform.TransformBounds(
gfxRect(criticalDisplayPort.x, criticalDisplayPort.y,
@ -498,8 +502,9 @@ BasicTiledThebesLayer::PaintThebes(gfxContext* aContext,
// Clip the invalid region to the critical display-port
invalidRegion.And(invalidRegion, layerDisplayPort);
if (invalidRegion.IsEmpty())
if (invalidRegion.IsEmpty() && lowPrecisionInvalidRegion.IsEmpty()) {
return;
}
}
gfxSize resolution(1, 1);
@ -525,61 +530,66 @@ BasicTiledThebesLayer::PaintThebes(gfxContext* aContext,
transformedViewport.width, transformedViewport.height);
}
// Only draw progressively when the resolution is unchanged.
if (gfxPlatform::UseProgressiveTilePainting() &&
!BasicManager()->HasShadowTarget() &&
mTiledBuffer.GetFrameResolution() == resolution) {
// Store the old valid region, then clear it before painting.
// We clip the old valid region to the visible region, as it only gets
// used to decide stale content (currently valid and previously visible)
nsIntRegion oldValidRegion = mTiledBuffer.GetValidRegion();
oldValidRegion.And(oldValidRegion, mVisibleRegion);
if (!layerDisplayPort.IsEmpty()) {
oldValidRegion.And(oldValidRegion, layerDisplayPort);
}
if (!invalidRegion.IsEmpty()) {
bool updatedBuffer = false;
// Only draw progressively when the resolution is unchanged.
if (gfxPlatform::UseProgressiveTilePainting() &&
!BasicManager()->HasShadowTarget() &&
mTiledBuffer.GetFrameResolution() == resolution) {
// Store the old valid region, then clear it before painting.
// We clip the old valid region to the visible region, as it only gets
// used to decide stale content (currently valid and previously visible)
nsIntRegion oldValidRegion = mTiledBuffer.GetValidRegion();
oldValidRegion.And(oldValidRegion, mVisibleRegion);
if (!layerDisplayPort.IsEmpty()) {
oldValidRegion.And(oldValidRegion, layerDisplayPort);
}
// Make sure that tiles that fall outside of the visible region are
// discarded on the first update.
if (!BasicManager()->IsRepeatTransaction()) {
mValidRegion.And(mValidRegion, mVisibleRegion);
// Make sure that tiles that fall outside of the visible region are
// discarded on the first update.
if (!BasicManager()->IsRepeatTransaction()) {
mValidRegion.And(mValidRegion, mVisibleRegion);
if (!layerDisplayPort.IsEmpty()) {
mValidRegion.And(mValidRegion, layerDisplayPort);
}
}
updatedBuffer =
ProgressiveUpdate(mTiledBuffer, mValidRegion, invalidRegion,
oldValidRegion, transform, compositionBounds,
scrollOffset, resolution, aCallback, aCallbackData);
} else {
updatedBuffer = true;
mTiledBuffer.SetFrameResolution(resolution);
mValidRegion = mVisibleRegion;
if (!layerDisplayPort.IsEmpty()) {
mValidRegion.And(mValidRegion, layerDisplayPort);
}
mTiledBuffer.PaintThebes(this, mValidRegion, invalidRegion, aCallback, aCallbackData);
}
if (!ProgressiveUpdate(mTiledBuffer, mValidRegion, invalidRegion,
oldValidRegion, transform, compositionBounds,
scrollOffset, resolution, aCallback, aCallbackData))
return;
} else {
mTiledBuffer.SetFrameResolution(resolution);
mValidRegion = mVisibleRegion;
if (!layerDisplayPort.IsEmpty()) {
mValidRegion.And(mValidRegion, layerDisplayPort);
if (updatedBuffer) {
mTiledBuffer.ReadLock();
// Only paint the mask layer on the first transaction.
if (aMaskLayer && !BasicManager()->IsRepeatTransaction()) {
static_cast<BasicImplData*>(aMaskLayer->ImplData())
->Paint(aContext, nullptr);
}
// Create a heap copy owned and released by the compositor. This is needed
// since we're sending this over an async message and content needs to be
// be able to modify the tiled buffer in the next transaction.
// TODO: Remove me once Bug 747811 lands.
BasicTiledLayerBuffer *heapCopy = new BasicTiledLayerBuffer(mTiledBuffer);
BasicManager()->PaintedTiledLayerBuffer(BasicManager()->Hold(this), heapCopy);
mTiledBuffer.ClearPaintedRegion();
}
mTiledBuffer.PaintThebes(this, mValidRegion, invalidRegion, aCallback, aCallbackData);
}
mTiledBuffer.ReadLock();
// Only paint the mask layer on the first transaction.
if (aMaskLayer && !BasicManager()->IsRepeatTransaction()) {
static_cast<BasicImplData*>(aMaskLayer->ImplData())
->Paint(aContext, nullptr);
}
// Create a heap copy owned and released by the compositor. This is needed
// since we're sending this over an async message and content needs to be
// be able to modify the tiled buffer in the next transaction.
// TODO: Remove me once Bug 747811 lands.
BasicTiledLayerBuffer *heapCopy = new BasicTiledLayerBuffer(mTiledBuffer);
BasicManager()->PaintedTiledLayerBuffer(BasicManager()->Hold(this), heapCopy);
mTiledBuffer.ClearPaintedRegion();
// If we have a critical display-port defined, render the full display-port
// progressively in the low-precision tiled buffer.
bool clearedLowPrecision = false;
bool updatedLowPrecision = false;
if (!criticalDisplayPort.IsEmpty() &&
!nsIntRegion(layerDisplayPort).Contains(mVisibleRegion)) {
@ -589,7 +599,7 @@ BasicTiledThebesLayer::PaintThebes(gfxContext* aContext,
// If the frame resolution has changed, invalidate the buffer
if (mLowPrecisionTiledBuffer.GetFrameResolution() != resolution) {
if (!mLowPrecisionValidRegion.IsEmpty()) {
clearedLowPrecision = true;
updatedLowPrecision = true;
}
oldValidRegion.SetEmpty();
mLowPrecisionValidRegion.SetEmpty();
@ -601,9 +611,6 @@ BasicTiledThebesLayer::PaintThebes(gfxContext* aContext,
mLowPrecisionValidRegion.And(mLowPrecisionValidRegion, mVisibleRegion);
}
nsIntRegion lowPrecisionInvalidRegion;
lowPrecisionInvalidRegion.Sub(mVisibleRegion, mLowPrecisionValidRegion);
// Remove the valid high-precision region from the invalid low-precision
// region. We don't want to spend time drawing things twice.
nsIntRegion invalidHighPrecisionIntersect;
@ -623,7 +630,7 @@ BasicTiledThebesLayer::PaintThebes(gfxContext* aContext,
lowPrecisionInvalidRegion.Or(lowPrecisionInvalidRegion, invalidHighPrecisionIntersect);
} else if (!mLowPrecisionValidRegion.IsEmpty()) {
// Clear the low precision tiled buffer
clearedLowPrecision = true;
updatedLowPrecision = true;
mLowPrecisionValidRegion.SetEmpty();
mLowPrecisionTiledBuffer.PaintThebes(this, mLowPrecisionValidRegion,
mLowPrecisionValidRegion, aCallback,
@ -633,7 +640,7 @@ BasicTiledThebesLayer::PaintThebes(gfxContext* aContext,
// We send a Painted callback if we clear the valid region of the low
// precision buffer, so that the shadow buffer's valid region can be updated
// and the associated resources can be freed.
if (clearedLowPrecision || updatedLowPrecision) {
if (updatedLowPrecision) {
mLowPrecisionTiledBuffer.ReadLock();
BasicTiledLayerBuffer *heapCopy = new BasicTiledLayerBuffer(mLowPrecisionTiledBuffer);