Bug 880676 - Replace a couple of Rect scaling functions with strongly typed operators. r=BenWa
authorKartikaya Gupta <kgupta@mozilla.com>
Fri, 14 Jun 2013 16:11:31 -0400
changeset 135121 1e0c4309ec6aa835bddf52d7109972e649e38f2e
parent 135120 6e2cfc657c74f6b6af36a47dfdfab0d78ace4392
child 135122 8050296faa271ea6adea360104624129c0cf3fea
push id24825
push userryanvm@gmail.com
push dateSat, 15 Jun 2013 01:40:31 +0000
treeherdermozilla-central@05d9196b27a1 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersBenWa
bugs880676
milestone24.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 880676 - Replace a couple of Rect scaling functions with strongly typed operators. r=BenWa
gfx/layers/client/ClientLayerManager.cpp
gfx/layers/composite/AsyncCompositionManager.cpp
gfx/layers/composite/ThebesLayerComposite.cpp
layout/base/Units.h
widget/android/AndroidJavaWrappers.cpp
--- a/gfx/layers/client/ClientLayerManager.cpp
+++ b/gfx/layers/client/ClientLayerManager.cpp
@@ -390,26 +390,25 @@ ClientLayerManager::ProgressiveUpdateCal
 #ifdef MOZ_WIDGET_ANDROID
   Layer* primaryScrollable = GetPrimaryScrollableLayer();
   if (primaryScrollable) {
     const FrameMetrics& metrics = primaryScrollable->AsContainerLayer()->GetFrameMetrics();
 
     // This is derived from the code in
     // gfx/layers/ipc/CompositorParent.cpp::TransformShadowTree.
     const gfx3DMatrix& rootTransform = GetRoot()->GetTransform();
-    float devPixelRatioX = 1 / rootTransform.GetXScale();
-    float devPixelRatioY = 1 / rootTransform.GetYScale();
+    CSSToLayerScale paintScale = LayerToCSSScale(rootTransform.GetXScale(),
+                                                 rootTransform.GetYScale()).Inverse();
     const CSSRect& metricsDisplayPort =
       (aDrawingCritical && !metrics.mCriticalDisplayPort.IsEmpty()) ?
         metrics.mCriticalDisplayPort : metrics.mDisplayPort;
-    LayerRect displayPort = LayerRect::FromCSSRect(metricsDisplayPort + metrics.mScrollOffset,
-                                                   devPixelRatioX, devPixelRatioY);
+    LayerRect displayPort = (metricsDisplayPort + metrics.mScrollOffset) * paintScale;
 
     return AndroidBridge::Bridge()->ProgressiveUpdateCallback(
-      aHasPendingNewThebesContent, displayPort, devPixelRatioX, aDrawingCritical,
+      aHasPendingNewThebesContent, displayPort, paintScale.scale, aDrawingCritical,
       aViewport, aScaleX, aScaleY);
   }
 #endif
 
   return false;
 }
 
 ClientLayer::~ClientLayer()
--- a/gfx/layers/composite/AsyncCompositionManager.cpp
+++ b/gfx/layers/composite/AsyncCompositionManager.cpp
@@ -399,103 +399,95 @@ AsyncCompositionManager::TransformScroll
 
   const FrameMetrics& metrics = container->GetFrameMetrics();
   // We must apply the resolution scale before a pan/zoom transform, so we call
   // GetTransform here.
   const gfx3DMatrix& currentTransform = aLayer->GetTransform();
 
   gfx3DMatrix treeTransform;
 
-  float layerPixelRatioX = 1 / aRootTransform.GetXScale(),
-        layerPixelRatioY = 1 / aRootTransform.GetYScale();
+  CSSToLayerScale geckoZoom = LayerToCSSScale(aRootTransform.GetXScale(),
+                                              aRootTransform.GetYScale()).Inverse();
 
-  LayerIntPoint scrollOffsetLayerPixels = LayerIntPoint::FromCSSPointRounded(
-    metrics.mScrollOffset, layerPixelRatioX, layerPixelRatioY);
+  LayerIntPoint scrollOffsetLayerPixels = RoundedToInt(metrics.mScrollOffset * geckoZoom);
 
   if (mIsFirstPaint) {
     mContentRect = metrics.mScrollableRect;
     SetFirstPaintViewport(scrollOffsetLayerPixels,
-                          layerPixelRatioX,
+                          geckoZoom.scale,
                           mContentRect);
     mIsFirstPaint = false;
   } else if (!metrics.mScrollableRect.IsEqualEdges(mContentRect)) {
     mContentRect = metrics.mScrollableRect;
     SetPageRect(mContentRect);
   }
 
   // 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
-  LayerIntRect displayPort =
-    LayerIntRect::FromCSSRectRounded(metrics.mCriticalDisplayPort.IsEmpty()
-                                       ? metrics.mDisplayPort
-                                       : metrics.mCriticalDisplayPort,
-                                     layerPixelRatioX, layerPixelRatioY);
+  LayerIntRect displayPort = RoundedToInt(
+    (metrics.mCriticalDisplayPort.IsEmpty()
+      ? metrics.mDisplayPort
+      : metrics.mCriticalDisplayPort
+    ) * geckoZoom);
   displayPort += scrollOffsetLayerPixels;
 
   gfx::Margin fixedLayerMargins(0, 0, 0, 0);
   ScreenPoint offset(0, 0);
-  ScreenPoint scrollOffset(0, 0);
-  float scaleX = 1.0,
-        scaleY = 1.0;
-  SyncViewportInfo(displayPort, layerPixelRatioX, mLayersUpdated,
-                   scrollOffset, scaleX, scaleY, fixedLayerMargins,
+  ScreenPoint userScroll(0, 0);
+  CSSToScreenScale userZoom;
+  SyncViewportInfo(displayPort, geckoZoom.scale, mLayersUpdated,
+                   userScroll, userZoom.scale, userZoom.scale, fixedLayerMargins,
                    offset);
   mLayersUpdated = false;
 
   // Apply the render offset
   mLayerManager->GetCompositor()->SetScreenRenderOffset(offset);
 
   // Handle transformations for asynchronous panning and zooming. We determine the
   // zoom used by Gecko from the transformation set on the root layer, and we
   // determine the scroll offset used by Gecko from the frame metrics of the
-  // primary scrollable layer. We compare this to the desired zoom and scroll
+  // primary scrollable layer. We compare this to the user zoom and scroll
   // offset in the view transform we obtained from Java in order to compute the
   // transformation we need to apply.
-  float tempScaleDiffX = aRootTransform.GetXScale() * scaleX;
-  float tempScaleDiffY = aRootTransform.GetYScale() * scaleY;
+  LayerToScreenScale zoomAdjust = userZoom / geckoZoom;
 
-  LayerIntPoint metricsScrollOffset(0, 0);
+  LayerIntPoint geckoScroll(0, 0);
   if (metrics.IsScrollable()) {
-    metricsScrollOffset = scrollOffsetLayerPixels;
+    geckoScroll = scrollOffsetLayerPixels;
   }
 
-  LayerPoint scrollCompensation(
-    (scrollOffset.x / tempScaleDiffX - metricsScrollOffset.x),
-    (scrollOffset.y / tempScaleDiffY - metricsScrollOffset.y));
-  treeTransform = gfx3DMatrix(ViewTransform(-scrollCompensation,
-                                            CSSToScreenScale(scaleX, scaleY)));
+  LayerPoint translation = (userScroll / zoomAdjust) - geckoScroll;
+  treeTransform = gfx3DMatrix(ViewTransform(-translation, userZoom));
 
   // Translate fixed position layers so that they stay in the correct position
-  // when scrollOffset and metricsScrollOffset differ.
+  // when userScroll and geckoScroll differ.
   gfxPoint fixedOffset;
   gfxSize scaleDiff;
 
-  LayerRect content = LayerRect::FromCSSRect(mContentRect,
-                                             1 / aRootTransform.GetXScale(),
-                                             1 / aRootTransform.GetYScale());
+  LayerRect content = mContentRect * geckoZoom;
   // If the contents can fit entirely within the widget area on a particular
   // dimension, we need to translate and scale so that the fixed layers remain
   // within the page boundaries.
-  if (mContentRect.width * scaleX < metrics.mCompositionBounds.width) {
-    fixedOffset.x = -metricsScrollOffset.x;
+  if (mContentRect.width * userZoom.scale < metrics.mCompositionBounds.width) {
+    fixedOffset.x = -geckoScroll.x;
     scaleDiff.width = std::min(1.0f, metrics.mCompositionBounds.width / content.width);
   } else {
-    fixedOffset.x = clamped(scrollOffset.x / tempScaleDiffX, content.x,
-        content.XMost() - metrics.mCompositionBounds.width / tempScaleDiffX) - metricsScrollOffset.x;
-    scaleDiff.width = tempScaleDiffX;
+    fixedOffset.x = clamped(userScroll.x / zoomAdjust.scale, content.x,
+        content.XMost() - metrics.mCompositionBounds.width / zoomAdjust.scale) - geckoScroll.x;
+    scaleDiff.width = zoomAdjust.scale;
   }
 
-  if (mContentRect.height * scaleY < metrics.mCompositionBounds.height) {
-    fixedOffset.y = -metricsScrollOffset.y;
+  if (mContentRect.height * userZoom.scale < metrics.mCompositionBounds.height) {
+    fixedOffset.y = -geckoScroll.y;
     scaleDiff.height = std::min(1.0f, metrics.mCompositionBounds.height / content.height);
   } else {
-    fixedOffset.y = clamped(scrollOffset.y / tempScaleDiffY, content.y,
-        content.YMost() - metrics.mCompositionBounds.height / tempScaleDiffY) - metricsScrollOffset.y;
-    scaleDiff.height = tempScaleDiffY;
+    fixedOffset.y = clamped(userScroll.y / zoomAdjust.scale, content.y,
+        content.YMost() - metrics.mCompositionBounds.height / zoomAdjust.scale) - geckoScroll.y;
+    scaleDiff.height = zoomAdjust.scale;
   }
 
   // The transform already takes the resolution scale into account.  Since we
   // will apply the resolution scale again when computing the effective
   // transform, we must apply the inverse resolution scale here.
   gfx3DMatrix computedTransform = treeTransform * currentTransform;
   computedTransform.Scale(1.0f/container->GetPreXScale(),
                           1.0f/container->GetPreYScale(),
--- a/gfx/layers/composite/ThebesLayerComposite.cpp
+++ b/gfx/layers/composite/ThebesLayerComposite.cpp
@@ -241,27 +241,25 @@ ThebesLayerComposite::GetCompositionBoun
                                   parentMetrics.mCompositionBounds.y,
                                   parentMetrics.mCompositionBounds.width,
                                   parentMetrics.mCompositionBounds.height);
 
       // Calculate the scale transform applied to the root layer to determine
       // the content resolution.
       Layer* rootLayer = Manager()->GetRoot();
       const gfx3DMatrix& rootTransform = rootLayer->GetTransform();
-      float scaleX = rootTransform.GetXScale();
-      float scaleY = rootTransform.GetYScale();
+      LayerToCSSScale scale(rootTransform.GetXScale(),
+                            rootTransform.GetYScale());
 
       // Get the content document bounds, in screen-space.
       const FrameMetrics& metrics = scrollableLayer->GetFrameMetrics();
-      const LayerIntRect content = LayerIntRect::FromCSSRectRounded(metrics.mScrollableRect,
-                                                                    1 / scaleX,
-                                                                    1 / scaleY);
+      const LayerIntRect content = RoundedToInt(metrics.mScrollableRect / scale);
       gfx::Point scrollOffset =
-        gfx::Point((metrics.mScrollOffset.x * metrics.LayersPixelsPerCSSPixel().width) / scaleX,
-                   (metrics.mScrollOffset.y * metrics.LayersPixelsPerCSSPixel().height) / scaleY);
+        gfx::Point((metrics.mScrollOffset.x * metrics.LayersPixelsPerCSSPixel().width) / scale.scale,
+                   (metrics.mScrollOffset.y * metrics.LayersPixelsPerCSSPixel().height) / scale.scale);
       const nsIntPoint contentOrigin(
         content.x - NS_lround(scrollOffset.x),
         content.y - NS_lround(scrollOffset.y));
       gfxRect contentRect = gfxRect(contentOrigin.x, contentOrigin.y,
                                     content.width, content.height);
       gfxRect contentBounds = scrollableLayer->GetEffectiveTransform().
         TransformBounds(contentRect);
 
--- a/layout/base/Units.h
+++ b/layout/base/Units.h
@@ -101,34 +101,16 @@ struct CSSPixel {
  * The pixels that layout rasterizes and delivers to the graphics code.
  * These are generally referred to as "device pixels" in layout code. Layer
  * pixels are affected by:
  * 1) the "display resolution" (see nsIPresShell::SetResolution)
  * 2) the "full zoom" (see nsPresContext::SetFullZoom)
  * 3) the "widget scale" (nsIWidget::GetDefaultScale)
  */
 struct LayerPixel {
-
-  // Conversions from CSS units
-
-  static LayerIntPoint FromCSSPointRounded(const CSSPoint& aPoint, float aResolutionX, float aResolutionY) {
-    return LayerIntPoint(NS_lround(aPoint.x * aResolutionX),
-                         NS_lround(aPoint.y * aResolutionY));
-  }
-
-  static LayerRect FromCSSRect(const CSSRect& aRect, float aResolutionX, float aResolutionY) {
-    return LayerRect(aRect.x * aResolutionX,
-                     aRect.y * aResolutionY,
-                     aRect.width * aResolutionX,
-                     aRect.height * aResolutionY);
-  }
-
-  static LayerIntRect FromCSSRectRounded(const CSSRect& aRect, float aResolutionX, float aResolutionY) {
-    return gfx::RoundedToInt(FromCSSRect(aRect, aResolutionX, aResolutionY));
-  }
 };
 
 /*
  * The pixels that are displayed on the screen.
  * On non-OMTC platforms this should be equivalent to LayerPixel units.
  * On OMTC platforms these may diverge from LayerPixel units temporarily,
  * while an asynchronous zoom is happening, but should eventually converge
  * back to LayerPixel units. Some variables (such as those representing
@@ -141,25 +123,41 @@ struct ScreenPixel {
 
   static CSSIntRect ToCSSIntRectRoundIn(const ScreenIntRect& aRect, float aResolutionX, float aResolutionY) {
     CSSIntRect ret(aRect.x, aRect.y, aRect.width, aRect.height);
     ret.ScaleInverseRoundIn(aResolutionX, aResolutionY);
     return ret;
   }
 };
 
-// Operators to apply ScaleFactors directly to Points
+// Operators to apply ScaleFactors directly to Points and Rects
 
 template<class src, class dst>
 gfx::PointTyped<dst> operator*(const gfx::PointTyped<src>& aPoint, const gfx::ScaleFactor<src, dst>& aScale) {
   return gfx::PointTyped<dst>(aPoint.x * aScale.scale,
                               aPoint.y * aScale.scale);
 }
 
 template<class src, class dst>
 gfx::PointTyped<dst> operator/(const gfx::PointTyped<src>& aPoint, const gfx::ScaleFactor<dst, src>& aScale) {
   return gfx::PointTyped<dst>(aPoint.x / aScale.scale,
                               aPoint.y / aScale.scale);
 }
 
+template<class src, class dst>
+gfx::RectTyped<dst> operator*(const gfx::RectTyped<src>& aRect, const gfx::ScaleFactor<src, dst>& aScale) {
+  return gfx::RectTyped<dst>(aRect.x * aScale.scale,
+                             aRect.y * aScale.scale,
+                             aRect.width * aScale.scale,
+                             aRect.height * aScale.scale);
+}
+
+template<class src, class dst>
+gfx::RectTyped<dst> operator/(const gfx::RectTyped<src>& aRect, const gfx::ScaleFactor<dst, src>& aScale) {
+  return gfx::RectTyped<dst>(aRect.x / aScale.scale,
+                             aRect.y / aScale.scale,
+                             aRect.width / aScale.scale,
+                             aRect.height / aScale.scale);
+}
+
 };
 
 #endif
--- a/widget/android/AndroidJavaWrappers.cpp
+++ b/widget/android/AndroidJavaWrappers.cpp
@@ -932,17 +932,17 @@ AndroidGeckoLayerClient::SyncFrameMetric
     NS_ASSERTION(!isNull(), "SyncFrameMetrics called on null layer client!");
     JNIEnv *env = GetJNIForThread();    // this is called on the compositor thread
     if (!env)
         return;
 
     AutoLocalJNIFrame jniFrame(env);
 
     // convert the displayport rect from scroll-relative CSS pixels to document-relative device pixels
-    LayerRect dpUnrounded = LayerRect::FromCSSRect(aDisplayPort, aDisplayResolution, aDisplayResolution);
+    LayerRect dpUnrounded = aDisplayPort * CSSToLayerScale(aDisplayResolution);
     dpUnrounded += LayerPoint::FromUnknownPoint(aScrollOffset.ToUnknownPoint());
     LayerIntRect dp = gfx::RoundedToInt(dpUnrounded);
 
     jobject viewTransformJObj = env->CallObjectMethod(wrapped_obj, jSyncFrameMetricsMethod,
             aScrollOffset.x, aScrollOffset.y, aZoom,
             aCssPageRect.x, aCssPageRect.y, aCssPageRect.XMost(), aCssPageRect.YMost(),
             aLayersUpdated, dp.x, dp.y, dp.width, dp.height, aDisplayResolution,
             aIsFirstPaint);