From 755b86ca3a2a1e38ff0a75b7cbcecd9ffab2f9bb Mon Sep 17 00:00:00 2001 From: Botond Ballo Date: Fri, 19 Dec 2014 18:53:05 -0500 Subject: [PATCH] Bug 1076241 - Get rid of the nontransient async transform. r=kats --- dom/ipc/TabChild.cpp | 2 +- gfx/layers/apz/src/AsyncPanZoomController.cpp | 22 +------ gfx/layers/apz/src/AsyncPanZoomController.h | 7 -- gfx/layers/apz/util/APZCCallbackHelper.cpp | 2 +- gfx/layers/client/ClientTiledPaintedLayer.cpp | 4 +- gfx/layers/client/TiledContentClient.cpp | 25 ++------ .../composite/AsyncCompositionManager.cpp | 64 +++++++++++-------- .../gtest/TestAsyncPanZoomController.cpp | 12 ++-- mobile/android/chrome/content/browser.js | 6 +- 9 files changed, 57 insertions(+), 87 deletions(-) diff --git a/dom/ipc/TabChild.cpp b/dom/ipc/TabChild.cpp index 2553102ce465..46448393b18f 100644 --- a/dom/ipc/TabChild.cpp +++ b/dom/ipc/TabChild.cpp @@ -435,7 +435,7 @@ TabChildBase::HandlePossibleViewportChange(const ScreenIntSize& aOldScreenSize) // This is the root layer, so the cumulative resolution is the same // as the resolution. metrics.mPresShellResolution = metrics.GetCumulativeResolution().scale; - utils->SetResolution(metrics.mPresShellResolution, metrics.mPresShellResolution); + utils->SetResolutionAndScaleTo(metrics.mPresShellResolution, metrics.mPresShellResolution); CSSSize scrollPort = metrics.CalculateCompositedSizeInCssPixels(); utils->SetScrollPositionClampingScrollPortSize(scrollPort.width, scrollPort.height); diff --git a/gfx/layers/apz/src/AsyncPanZoomController.cpp b/gfx/layers/apz/src/AsyncPanZoomController.cpp index 51e346a604b9..11e9340198b7 100644 --- a/gfx/layers/apz/src/AsyncPanZoomController.cpp +++ b/gfx/layers/apz/src/AsyncPanZoomController.cpp @@ -2639,19 +2639,10 @@ ViewTransform AsyncPanZoomController::GetCurrentAsyncTransform() const { } } - LayerToParentLayerScale scale(mFrameMetrics.mPresShellResolution // non-transient portion - * mFrameMetrics.GetAsyncZoom().scale); // transient portion ParentLayerPoint translation = (currentScrollOffset - lastPaintScrollOffset) * mFrameMetrics.GetZoom(); - return ViewTransform(scale, -translation); -} - -Matrix4x4 AsyncPanZoomController::GetNontransientAsyncTransform() const { - ReentrantMonitorAutoEnter lock(mMonitor); - return Matrix4x4::Scaling(mLastContentPaintMetrics.mPresShellResolution, - mLastContentPaintMetrics.mPresShellResolution, - 1.0f); + return ViewTransform(mFrameMetrics.GetAsyncZoom(), -translation); } Matrix4x4 AsyncPanZoomController::GetTransformToLastDispatchedPaint() const { @@ -2660,16 +2651,7 @@ Matrix4x4 AsyncPanZoomController::GetTransformToLastDispatchedPaint() const { LayerPoint scrollChange = (mLastContentPaintMetrics.GetScrollOffset() - mLastDispatchedPaintMetrics.GetScrollOffset()) * mLastContentPaintMetrics.GetDevPixelsPerCSSPixel() - * mLastContentPaintMetrics.GetCumulativeResolution() - // This transform ("LD" in the terminology of the comment above - // GetScreenToApzcTransform() in APZCTreeManager.h) is applied in a - // coordinate space that includes the APZC's CSS transform ("LC"). - // This CSS transform is the identity unless this APZC sets a pres-shell - // resolution, in which case the transform has a post-scale that cancels - // out the pres-shell resolution. We simulate applying the "LC" transform - // by dividing by the pres-shell resolution. This will go away once - // bug 1076192 is fixed. - / mLastContentPaintMetrics.mPresShellResolution; + * mLastContentPaintMetrics.GetCumulativeResolution(); float zoomChange = mLastContentPaintMetrics.GetZoom().scale / mLastDispatchedPaintMetrics.GetZoom().scale; diff --git a/gfx/layers/apz/src/AsyncPanZoomController.h b/gfx/layers/apz/src/AsyncPanZoomController.h index 8fcb5aa58c6e..356572c86e6e 100644 --- a/gfx/layers/apz/src/AsyncPanZoomController.h +++ b/gfx/layers/apz/src/AsyncPanZoomController.h @@ -217,13 +217,6 @@ public: */ ViewTransform GetCurrentAsyncTransform() const; - /** - * Returns the part of the async transform that will remain once Gecko does a - * repaint at the desired metrics. That is, in the steady state: - * Matrix4x4(GetCurrentAsyncTransform()) === GetNontransientAsyncTransform() - */ - Matrix4x4 GetNontransientAsyncTransform() const; - /** * Returns the transform to take something from the coordinate space of the * last thing we know gecko painted, to the coordinate space of the last thing diff --git a/gfx/layers/apz/util/APZCCallbackHelper.cpp b/gfx/layers/apz/util/APZCCallbackHelper.cpp index 8dfede7c20a4..e8990717e840 100644 --- a/gfx/layers/apz/util/APZCCallbackHelper.cpp +++ b/gfx/layers/apz/util/APZCCallbackHelper.cpp @@ -145,7 +145,7 @@ APZCCallbackHelper::UpdateRootFrame(nsIDOMWindowUtils* aUtils, // last paint. float presShellResolution = aMetrics.mPresShellResolution * aMetrics.GetAsyncZoom().scale; - aUtils->SetResolution(presShellResolution, presShellResolution); + aUtils->SetResolutionAndScaleTo(presShellResolution, presShellResolution); // Finally, we set the displayport. nsCOMPtr content = nsLayoutUtils::FindContentFor(aMetrics.GetScrollId()); diff --git a/gfx/layers/client/ClientTiledPaintedLayer.cpp b/gfx/layers/client/ClientTiledPaintedLayer.cpp index c219fa354a17..c5e599affa71 100644 --- a/gfx/layers/client/ClientTiledPaintedLayer.cpp +++ b/gfx/layers/client/ClientTiledPaintedLayer.cpp @@ -72,8 +72,8 @@ GetTransformToAncestorsParentLayer(Layer* aStart, const LayerMetricsWrapper& aAn ancestorParent ? iter != ancestorParent : iter.IsValid(); iter = iter.GetParent()) { transform = transform * iter.GetTransform(); - // If the layer has a non-transient async transform then we need to apply it here - // because it will get applied by the APZ in the compositor as well + // If the layer has a pres shell resolution, the compositor will apply + // a scale to scale to this transform. Apply it here too. const FrameMetrics& metrics = iter.Metrics(); transform.PostScale(metrics.mPresShellResolution, metrics.mPresShellResolution, 1.f); } diff --git a/gfx/layers/client/TiledContentClient.cpp b/gfx/layers/client/TiledContentClient.cpp index a4df3c0d8d1c..4c698692372e 100644 --- a/gfx/layers/client/TiledContentClient.cpp +++ b/gfx/layers/client/TiledContentClient.cpp @@ -151,11 +151,9 @@ ComputeViewTransform(const FrameMetrics& aContentMetrics, const FrameMetrics& aC // but with aContentMetrics used in place of mLastContentPaintMetrics, because they // should be equivalent, modulo race conditions while transactions are inflight. - LayerToParentLayerScale scale(aCompositorMetrics.mPresShellResolution - * aCompositorMetrics.GetAsyncZoom().scale); ParentLayerPoint translation = (aCompositorMetrics.GetScrollOffset() - aContentMetrics.GetScrollOffset()) * aCompositorMetrics.GetZoom(); - return ViewTransform(scale, -translation); + return ViewTransform(aCompositorMetrics.GetAsyncZoom(), -translation); } bool @@ -1318,8 +1316,7 @@ ClientTiledLayerBuffer::ValidateTile(TileClient aTile, * (which was generated in GetTransformToAncestorsParentLayer), and * modifies it with the ViewTransform from the compositor side so that * it reflects what the compositor is actually rendering. This operation - * basically replaces the nontransient async transform that was injected - * in GetTransformToAncestorsParentLayer with the complete async transform. + * basically adds in the layer's async transform. * This function then returns the scroll ancestor's composition bounds, * transformed into the painted layer's LayerPixel coordinates, accounting * for the compositor state. @@ -1329,22 +1326,8 @@ GetCompositorSideCompositionBounds(const LayerMetricsWrapper& aScrollAncestor, const Matrix4x4& aTransformToCompBounds, const ViewTransform& aAPZTransform) { - Matrix4x4 nonTransientAPZUntransform = Matrix4x4::Scaling( - aScrollAncestor.Metrics().mPresShellResolution, - aScrollAncestor.Metrics().mPresShellResolution, - 1.f); - nonTransientAPZUntransform.Invert(); - - // Take off the last "term" of aTransformToCompBounds, which - // is the APZ's nontransient async transform. Replace it with - // the APZ's async transform (this includes the nontransient - // component as well). - Matrix4x4 transform = aTransformToCompBounds - * nonTransientAPZUntransform - * Matrix4x4(aAPZTransform); - transform.Invert(); - - return TransformTo(transform, + Matrix4x4 transform = aTransformToCompBounds * Matrix4x4(aAPZTransform); + return TransformTo(transform.Inverse(), aScrollAncestor.Metrics().mCompositionBounds); } diff --git a/gfx/layers/composite/AsyncCompositionManager.cpp b/gfx/layers/composite/AsyncCompositionManager.cpp index 31f0bce106c2..ed6bae96424a 100644 --- a/gfx/layers/composite/AsyncCompositionManager.cpp +++ b/gfx/layers/composite/AsyncCompositionManager.cpp @@ -695,17 +695,15 @@ ApplyAsyncTransformToScrollbarForContent(Layer* aScrollbar, AsyncPanZoomController* apzc = aContent.GetApzc(); Matrix4x4 asyncTransform = apzc->GetCurrentAsyncTransform(); - Matrix4x4 nontransientTransform = apzc->GetNontransientAsyncTransform(); - Matrix4x4 transientTransform = nontransientTransform.Inverse() * asyncTransform; - // |transientTransform| represents the amount by which we have scrolled and + // |asyncTransform| represents the amount by which we have scrolled and // zoomed since the last paint. Because the scrollbar was sized and positioned based - // on the painted content, we need to adjust it based on transientTransform so that + // on the painted content, we need to adjust it based on asyncTransform so that // it reflects what the user is actually seeing now. // - The scroll thumb needs to be scaled in the direction of scrolling by the inverse - // of the transientTransform scale (representing the zoom). This is because zooming + // of the asyncTransform scale (representing the zoom). This is because zooming // in decreases the fraction of the whole scrollable rect that is in view. - // - It needs to be translated in opposite direction of the transientTransform + // - It needs to be translated in opposite direction of the asyncTransform // translation (representing the scroll). This is because scrolling down, which // translates the layer content up, should result in moving the scroll thumb down. // The amount of the translation to the scroll thumb should be such that the ratio @@ -719,41 +717,57 @@ ApplyAsyncTransformToScrollbarForContent(Layer* aScrollbar, // scrollbar gets painted at the same resolution as the content. Since the // coordinate space we apply this transform in includes the resolution, we // need to adjust for it as well here. Note that in another - // aScrollbarIsDescendant hunk below we unapply the entire async - // transform, which includes the nontransientasync transform and would - // normally account for the resolution. + // aScrollbarIsDescendant hunk below we apply a resolution-cancelling + // transform which ensures the scroll thumb isn't actually rendered + // at a larger scale. scale *= metrics.mPresShellResolution; } - scrollbarTransform.PostScale(1.f, 1.f / transientTransform._22, 1.f); - scrollbarTransform.PostTranslate(0, -transientTransform._42 * scale, 0); + scrollbarTransform.PostScale(1.f, 1.f / asyncTransform._22, 1.f); + scrollbarTransform.PostTranslate(0, -asyncTransform._42 * scale, 0); } if (aScrollbar->GetScrollbarDirection() == Layer::HORIZONTAL) { float scale = metrics.CalculateCompositedSizeInCssPixels().width / metrics.GetScrollableRect().width; if (aScrollbarIsDescendant) { scale *= metrics.mPresShellResolution; } - scrollbarTransform.PostScale(1.f / transientTransform._11, 1.f, 1.f); - scrollbarTransform.PostTranslate(-transientTransform._41 * scale, 0, 0); + scrollbarTransform.PostScale(1.f / asyncTransform._11, 1.f, 1.f); + scrollbarTransform.PostTranslate(-asyncTransform._41 * scale, 0, 0); } Matrix4x4 transform = scrollbarTransform * aScrollbar->GetTransform(); if (aScrollbarIsDescendant) { - // If the scrollbar layer is a child of the content it is a scrollbar for, then we - // need to do an extra untransform to cancel out the async transform on - // the content. This is needed because layout positions and sizes the - // scrollbar on the assumption that there is no async transform, and without - // this code the scrollbar will end up in the wrong place. + // If the scrollbar layer is a child of the content it is a scrollbar for, + // then we need to make a couple of adjustments to the scrollbar's transform. // - // Since the async transform is applied on top of the content's regular - // transform, we need to make sure to unapply the async transform in the - // same coordinate space. This requires applying the content transform and - // then unapplying it after unapplying the async transform. + // - First, the content's resolution applies to the scrollbar as well. + // Since we don't actually want the scroll thumb's size to vary with + // the zoom (other than its length reflecting the fraction of the + // scrollable length that's in view, which is taken care of above), + // we apply a transform to cancel out this resolution. + // + // - Second, if there is any async transform (including an overscroll + // transform) on the content, this needs to be cancelled out because + // layout positions and sizes the scrollbar on the assumption that there + // is no async transform, and without this adjustment the scrollbar will + // end up in the wrong place. + // + // Note that since the async transform is applied on top of the content's + // regular transform, we need to make sure to unapply the async transform + // in the same coordinate space. This requires applying the content + // transform and then unapplying it after unapplying the async transform. + Matrix4x4 resolutionCancellingTransform = + Matrix4x4::Scaling(metrics.mPresShellResolution, + metrics.mPresShellResolution, + 1.0f).Inverse(); Matrix4x4 asyncUntransform = (asyncTransform * apzc->GetOverscrollTransform()).Inverse(); Matrix4x4 contentTransform = aContent.GetTransform(); Matrix4x4 contentUntransform = contentTransform.Inverse(); - Matrix4x4 compensation = contentTransform * asyncUntransform * contentUntransform; + Matrix4x4 compensation = resolutionCancellingTransform + * contentTransform + * asyncUntransform + * contentUntransform; transform = transform * compensation; // We also need to make a corresponding change on the clip rect of all the @@ -894,10 +908,8 @@ AsyncCompositionManager::TransformScrollableLayer(Layer* aLayer) } LayerToParentLayerScale asyncZoom = userZoom / metrics.LayersPixelsPerCSSPixel(); - LayerToParentLayerScale scale(metrics.mPresShellResolution - * asyncZoom.scale); ParentLayerPoint translation = userScroll - geckoScroll; - Matrix4x4 treeTransform = ViewTransform(scale, -translation); + Matrix4x4 treeTransform = ViewTransform(asyncZoom, -translation); SetShadowTransform(aLayer, oldTransform * treeTransform); NS_ASSERTION(!aLayer->AsLayerComposite()->GetShadowTransformSetByAnimation(), diff --git a/gfx/tests/gtest/TestAsyncPanZoomController.cpp b/gfx/tests/gtest/TestAsyncPanZoomController.cpp index 1204401dd2b3..e5c5c0e97174 100644 --- a/gfx/tests/gtest/TestAsyncPanZoomController.cpp +++ b/gfx/tests/gtest/TestAsyncPanZoomController.cpp @@ -841,39 +841,39 @@ TEST_F(APZCBasicTester, ComplexTransform) { apzc->SetFrameMetrics(metrics); apzc->NotifyLayersUpdated(metrics, true); apzc->SampleContentTransformForFrame(testStartTime, &viewTransformOut, pointOut); - EXPECT_EQ(ViewTransform(LayerToParentLayerScale(2), ParentLayerPoint()), viewTransformOut); + EXPECT_EQ(ViewTransform(LayerToParentLayerScale(1), ParentLayerPoint()), viewTransformOut); EXPECT_EQ(ParentLayerPoint(60, 60), pointOut); childApzc->SetFrameMetrics(childMetrics); childApzc->NotifyLayersUpdated(childMetrics, true); childApzc->SampleContentTransformForFrame(testStartTime, &viewTransformOut, pointOut); - EXPECT_EQ(ViewTransform(LayerToParentLayerScale(2), ParentLayerPoint()), viewTransformOut); + EXPECT_EQ(ViewTransform(LayerToParentLayerScale(1), ParentLayerPoint()), viewTransformOut); EXPECT_EQ(ParentLayerPoint(60, 60), pointOut); // do an async scroll by 5 pixels and check the transform metrics.ScrollBy(CSSPoint(5, 0)); apzc->SetFrameMetrics(metrics); apzc->SampleContentTransformForFrame(testStartTime, &viewTransformOut, pointOut); - EXPECT_EQ(ViewTransform(LayerToParentLayerScale(2), ParentLayerPoint(-30, 0)), viewTransformOut); + EXPECT_EQ(ViewTransform(LayerToParentLayerScale(1), ParentLayerPoint(-30, 0)), viewTransformOut); EXPECT_EQ(ParentLayerPoint(90, 60), pointOut); childMetrics.ScrollBy(CSSPoint(5, 0)); childApzc->SetFrameMetrics(childMetrics); childApzc->SampleContentTransformForFrame(testStartTime, &viewTransformOut, pointOut); - EXPECT_EQ(ViewTransform(LayerToParentLayerScale(2), ParentLayerPoint(-30, 0)), viewTransformOut); + EXPECT_EQ(ViewTransform(LayerToParentLayerScale(1), ParentLayerPoint(-30, 0)), viewTransformOut); EXPECT_EQ(ParentLayerPoint(90, 60), pointOut); // do an async zoom of 1.5x and check the transform metrics.ZoomBy(1.5f); apzc->SetFrameMetrics(metrics); apzc->SampleContentTransformForFrame(testStartTime, &viewTransformOut, pointOut); - EXPECT_EQ(ViewTransform(LayerToParentLayerScale(3), ParentLayerPoint(-45, 0)), viewTransformOut); + EXPECT_EQ(ViewTransform(LayerToParentLayerScale(1.5), ParentLayerPoint(-45, 0)), viewTransformOut); EXPECT_EQ(ParentLayerPoint(135, 90), pointOut); childMetrics.ZoomBy(1.5f); childApzc->SetFrameMetrics(childMetrics); childApzc->SampleContentTransformForFrame(testStartTime, &viewTransformOut, pointOut); - EXPECT_EQ(ViewTransform(LayerToParentLayerScale(3), ParentLayerPoint(-45, 0)), viewTransformOut); + EXPECT_EQ(ViewTransform(LayerToParentLayerScale(1.5), ParentLayerPoint(-45, 0)), viewTransformOut); EXPECT_EQ(ParentLayerPoint(135, 90), pointOut); } diff --git a/mobile/android/chrome/content/browser.js b/mobile/android/chrome/content/browser.js index 0ac2c977e6d5..1b7654419258 100644 --- a/mobile/android/chrome/content/browser.js +++ b/mobile/android/chrome/content/browser.js @@ -3634,7 +3634,7 @@ Tab.prototype = { if (BrowserApp.selectedTab == this) { if (resolution != this._drawZoom) { this._drawZoom = resolution; - cwu.setResolution(resolution / window.devicePixelRatio, resolution / window.devicePixelRatio); + cwu.setResolutionAndScaleTo(resolution / window.devicePixelRatio, resolution / window.devicePixelRatio); } } else if (!fuzzyEquals(resolution, zoom)) { dump("Warning: setDisplayPort resolution did not match zoom for background tab! (" + resolution + " != " + zoom + ")"); @@ -3758,7 +3758,7 @@ Tab.prototype = { if (BrowserApp.selectedTab == this) { let cwu = this.browser.contentWindow.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils); this._drawZoom = aZoom; - cwu.setResolution(aZoom / window.devicePixelRatio, aZoom / window.devicePixelRatio); + cwu.setResolutionAndScaleTo(aZoom / window.devicePixelRatio, aZoom / window.devicePixelRatio); } } }, @@ -4523,7 +4523,7 @@ Tab.prototype = { saveSessionZoom: function(aZoom) { let cwu = this.browser.contentWindow.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils); - cwu.setResolution(aZoom / window.devicePixelRatio, aZoom / window.devicePixelRatio); + cwu.setResolutionAndScaleTo(aZoom / window.devicePixelRatio, aZoom / window.devicePixelRatio); }, restoredSessionZoom: function() {