diff --git a/gfx/layers/basic/BasicTiledThebesLayer.cpp b/gfx/layers/basic/BasicTiledThebesLayer.cpp index 6b013242ec0d..f172f7bbeedf 100644 --- a/gfx/layers/basic/BasicTiledThebesLayer.cpp +++ b/gfx/layers/basic/BasicTiledThebesLayer.cpp @@ -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(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(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);