diff --git a/gfx/layers/basic/BasicLayerManager.cpp b/gfx/layers/basic/BasicLayerManager.cpp index 947638b41766..9eee33767087 100644 --- a/gfx/layers/basic/BasicLayerManager.cpp +++ b/gfx/layers/basic/BasicLayerManager.cpp @@ -1311,10 +1311,12 @@ BasicShadowLayerManager::ProgressiveUpdateCallback(bool aHasPendingNewThebesCont const gfx3DMatrix& rootTransform = GetRoot()->GetTransform(); float devPixelRatioX = 1 / rootTransform.GetXScale(); float devPixelRatioY = 1 / rootTransform.GetYScale(); - gfx::Rect displayPort((metrics.mDisplayPort.x + metrics.mScrollOffset.x) * devPixelRatioX, - (metrics.mDisplayPort.y + metrics.mScrollOffset.y) * devPixelRatioY, - metrics.mDisplayPort.width * devPixelRatioX, - metrics.mDisplayPort.height * devPixelRatioY); + const gfx::Rect& metricsDisplayPort = metrics.mCriticalDisplayPort.IsEmpty() ? + metrics.mDisplayPort : metrics.mCriticalDisplayPort; + gfx::Rect displayPort((metricsDisplayPort.x + metrics.mScrollOffset.x) * devPixelRatioX, + (metricsDisplayPort.y + metrics.mScrollOffset.y) * devPixelRatioY, + metricsDisplayPort.width * devPixelRatioX, + metricsDisplayPort.height * devPixelRatioY); return AndroidBridge::Bridge()->ProgressiveUpdateCallback( aHasPendingNewThebesContent, displayPort, devPixelRatioX, diff --git a/gfx/layers/basic/BasicTiledThebesLayer.cpp b/gfx/layers/basic/BasicTiledThebesLayer.cpp index cacc1551bfea..94de90961c5d 100644 --- a/gfx/layers/basic/BasicTiledThebesLayer.cpp +++ b/gfx/layers/basic/BasicTiledThebesLayer.cpp @@ -388,6 +388,37 @@ BasicTiledThebesLayer::PaintThebes(gfxContext* aContext, if (invalidRegion.IsEmpty()) return; + // Calculate the transform required to convert screen space into layer space + gfx3DMatrix transform = GetEffectiveTransform(); + // XXX Not sure if this code for intermediate surfaces is correct. + // It rarely gets hit though, and shouldn't have terrible consequences + // even if it is wrong. + for (ContainerLayer* parent = GetParent(); parent; parent = parent->GetParent()) { + if (parent->UseIntermediateSurface()) { + transform.PreMultiply(parent->GetEffectiveTransform()); + } + } + transform.Invert(); + + nsIntRect layerDisplayPort; + const gfx::Rect& criticalDisplayPort = GetParent()->GetFrameMetrics().mCriticalDisplayPort; + if (!criticalDisplayPort.IsEmpty()) { + // Find the critical display port in layer space. + gfxRect transformedCriticalDisplayPort = transform.TransformBounds( + gfxRect(criticalDisplayPort.x, criticalDisplayPort.y, + criticalDisplayPort.width, criticalDisplayPort.height)); + transformedCriticalDisplayPort.RoundOut(); + layerDisplayPort = nsIntRect(transformedCriticalDisplayPort.x, + transformedCriticalDisplayPort.y, + transformedCriticalDisplayPort.width, + transformedCriticalDisplayPort.height); + + // Clip the invalid region to the critical display-port + invalidRegion.And(invalidRegion, layerDisplayPort); + if (invalidRegion.IsEmpty()) + return; + } + gfxSize resolution(1, 1); for (ContainerLayer* parent = GetParent(); parent; parent = parent->GetParent()) { const FrameMetrics& metrics = parent->GetFrameMetrics(); @@ -399,29 +430,23 @@ BasicTiledThebesLayer::PaintThebes(gfxContext* aContext, if (gfxPlatform::UseProgressiveTilePainting() && !BasicManager()->HasShadowTarget() && mTiledBuffer.GetResolution() == resolution) { - // Calculate the transform required to convert screen space into layer space - gfx3DMatrix transform = GetEffectiveTransform(); - // XXX Not sure if this code for intermediate surfaces is correct. - // It rarely gets hit though, and shouldn't have terrible consequences - // even if it is wrong. - for (ContainerLayer* parent = GetParent(); parent; parent = parent->GetParent()) { - if (parent->UseIntermediateSurface()) { - transform.PreMultiply(parent->GetEffectiveTransform()); - } - } - transform.Invert(); - // 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); + } mTiledBuffer.ClearPaintedRegion(); // 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); + } } // Calculate the scroll offset since the last transaction. @@ -472,6 +497,9 @@ BasicTiledThebesLayer::PaintThebes(gfxContext* aContext, mTiledBuffer.ClearPaintedRegion(); mTiledBuffer.SetResolution(resolution); mValidRegion = mVisibleRegion; + if (!layerDisplayPort.IsEmpty()) { + mValidRegion.And(mValidRegion, layerDisplayPort); + } mTiledBuffer.PaintThebes(this, mValidRegion, invalidRegion, aCallback, aCallbackData); } diff --git a/gfx/layers/ipc/CompositorParent.cpp b/gfx/layers/ipc/CompositorParent.cpp index ab125205c740..5623c48cc3af 100644 --- a/gfx/layers/ipc/CompositorParent.cpp +++ b/gfx/layers/ipc/CompositorParent.cpp @@ -875,7 +875,8 @@ CompositorParent::TransformShadowTree(TimeStamp aCurrentFrame) // We synchronise the viewport information with Java after sending the above // notifications, so that Java can take these into account in its response. // Calculate the absolute display port to send to Java - gfx::Rect displayPortLayersPixels(metrics.mDisplayPort); + gfx::Rect displayPortLayersPixels(metrics.mCriticalDisplayPort.IsEmpty() ? + metrics.mDisplayPort : metrics.mCriticalDisplayPort); nsIntRect displayPortDevPixels( NS_lround(displayPortLayersPixels.x * devPixelRatioX), NS_lround(displayPortLayersPixels.y * devPixelRatioY),