Bug 528323: Improve zooming perf and fix zoom for some sites [r=mark.finkle]
authorBenjamin Stover <bstover@mozilla.com>
Thu, 12 Nov 2009 23:41:45 -0500
changeset 65789 380e1d11715d28274932c2f8579c4c3db6c7d05e
parent 65788 46237cde937fcacd67cf1a61f68baa6b7a176ec4
child 65790 62802ec0300e2926ff412a8a8c0869e164c09c41
push id1
push userroot
push dateTue, 26 Apr 2011 22:38:44 +0000
treeherdermozilla-beta@bfdb6e623a36 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmark
bugs528323
Bug 528323: Improve zooming perf and fix zoom for some sites [r=mark.finkle]
mobile/chrome/content/TileManager.js.in
mobile/chrome/content/browser.js
--- a/mobile/chrome/content/TileManager.js.in
+++ b/mobile/chrome/content/TileManager.js.in
@@ -290,17 +290,17 @@ TileManager.prototype = {
 
       //dump("  render, append, hold: " + (Date.now() - start) + "\n");
     }
 
     //dump(" paint: " + (Date.now() - start) + "\n");
   },
 
   beginCriticalMove: function beginCriticalMove(destCriticalRect) {
-    if (destCriticalRect) {
+    if (!destCriticalRect.isEmpty()) {
       let tc = this._tileCache;
 
       BEGIN_FOREACH_IN_RECT(destCriticalRect, tc, tile)
 
       if (!tile.isDirty())
         this._appendTileSafe(tile);
 
       END_FOREACH_IN_RECT
--- a/mobile/chrome/content/browser.js
+++ b/mobile/chrome/content/browser.js
@@ -1012,57 +1012,76 @@ var Browser = {
     let bv = Browser._browserView;
     let vis = bv.getVisibleRect();
     x = bv.browserToViewport(x);
     y = bv.browserToViewport(y);
 
     zoomLevel = Math.min(kBrowserViewZoomLevelMax, zoomLevel);
     let zoomRatio = zoomLevel / bv.getZoomLevel();
     let newVisW = vis.width / zoomRatio, newVisH = vis.height / zoomRatio;
-    let result = new Rect(x - newVisW / 2, y - newVisH / 2, newVisW, newVisH).expandToIntegers();
+    let result = new Rect(x - newVisW / 2, y - newVisH / 2, newVisW, newVisH);
 
     // Make sure rectangle doesn't poke out of viewport
     return result.translateInside(bv._browserViewportState.viewportRect);
   },
 
   setVisibleRect: function setVisibleRect(rect) {
     let bv = Browser._browserView;
     let vis = bv.getVisibleRect();
     let zoomRatio = vis.width / rect.width;
     let zoomLevel = bv.getZoomLevel() * zoomRatio;
     let scrollX = rect.left * zoomRatio;
     let scrollY = rect.top * zoomRatio;
 
+    // The order of operations below is important for artifacting and for performance. Important
+    // side effects of functions are noted below.
+
+    // Hardware scrolling happens immediately when scrollTo is called.  Hide to prevent artifacts.
     bv.beginOffscreenOperation();
 
+    // We must scroll to the correct area before TileManager is informed of the change
+    // so that only one render is done. Ensures setZoomLevel puts it off.
+    bv.beginBatchOperation();
+
+    // Critical rect changes when controls are hidden. Must hide before tilemanager viewport.
     Browser.hideSidebars();
     Browser.hideTitlebar();
     bv.setZoomLevel(zoomLevel);
-    bv.forceViewportChange();  // ensure container is resized for scrollTo
+
+    // Ensure container is big enough for scroll values.
+    bv.forceContainerResize();
     Browser.forceChromeReflow();
     Browser.contentScrollboxScroller.scrollTo(scrollX, scrollY);
     bv.onAfterVisibleMove();
-    bv.renderNow();  // during loading, make sure new zoom level is rendered
-
+
+    // Inform tile manager, which happens to render new tiles too. Must call in case a batch
+    // operation was in progress before zoom.
+    bv.forceViewportChange();
+
+    bv.commitBatchOperation();
     bv.commitOffscreenOperation();
   },
 
   zoomToPoint: function zoomToPoint(cX, cY) {
     let [elementX, elementY] = Browser.transformClientToBrowser(cX, cY);
 
     let element = Browser.elementFromPoint(elementX, elementY);
     if (!element)
       return false;
 
+    let defaultZoomLevel = this._browserView.getZoomForPage();
+    let oldZoomLevel = this._browserView.getZoomLevel();
     let zoomLevel = this._getZoomLevelForElement(element);
-
-    // Don't zoom in a marginal amount
+    let zoomRatio = oldZoomLevel / zoomLevel;
+
+    // Don't zoom in a marginal amount, but be more lenient for the first zoom.
     // > 2/3 means operation increases the zoom level by less than 1.5
-    let zoomRatio = this._browserView.getZoomLevel() / zoomLevel;
-    if (zoomRatio >= .6666)
+    // > 9/10 means operation increases the zoom level by less than 1.1
+    let zoomTolerance = (oldZoomLevel == defaultZoomLevel) ? .9 : .6666;
+    if (zoomRatio >= zoomTolerance)
        return false;
 
     let elRect = Browser.getBoundingContentRect(element);
     let zoomRect = this._getZoomRectForPoint(elRect.center().x, elementY, zoomLevel);
 
     this.setVisibleRect(zoomRect);
     return true;
   },