Bug 859929 - Make AsyncPanZoomController work with progressive tile painting on Fennec. r=kats
authorBotond Ballo <botond@mozilla.com>
Mon, 22 Jul 2013 22:33:05 -0400
changeset 151820 ab5069084abd33984e2e85aa39630ab02d23caa4
parent 151819 d33324fd225144cc30aef26857e7d4ff03ce1776
child 151821 bdceed7037666e3133b84c5fa7856fb6710814a1
push id2859
push userakeybl@mozilla.com
push dateMon, 16 Sep 2013 19:14:59 +0000
treeherdermozilla-beta@87d3c51cd2bf [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskats
bugs859929
milestone25.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 859929 - Make AsyncPanZoomController work with progressive tile painting on Fennec. r=kats
gfx/layers/ipc/AsyncPanZoomController.cpp
gfx/layers/ipc/AsyncPanZoomController.h
mobile/android/base/gfx/GeckoLayerClient.java
mobile/android/base/gfx/JavaPanZoomController.java
mobile/android/base/gfx/NativePanZoomController.java
mobile/android/base/gfx/PanZoomController.java
mozglue/android/jni-stubs.inc
widget/android/AndroidJNI.cpp
--- a/gfx/layers/ipc/AsyncPanZoomController.cpp
+++ b/gfx/layers/ipc/AsyncPanZoomController.cpp
@@ -1152,16 +1152,20 @@ bool AsyncPanZoomController::SampleConte
 }
 
 void AsyncPanZoomController::NotifyLayersUpdated(const FrameMetrics& aViewportFrame, bool aIsFirstPaint) {
   MonitorAutoLock monitor(mMonitor);
 
   mLastContentPaintMetrics = aViewportFrame;
 
   mFrameMetrics.mMayHaveTouchListeners = aViewportFrame.mMayHaveTouchListeners;
+
+  // TODO: Once a mechanism for calling UpdateScrollOffset() when content does
+  //       a scrollTo() is implemented for B2G (bug 895905), this block can be removed.
+#ifndef MOZ_WIDGET_ANDROID
   if (!mPaintThrottler.IsOutstanding()) {
     // No paint was requested, but we got one anyways. One possible cause of this
     // is that content could have fired a scrollTo(). In this case, we should take
     // the new scroll offset. Document/viewport changes are handled elsewhere.
     // Also note that, since NotifyLayersUpdated() is called whenever there's a
     // layers update, we didn't necessarily get a new scroll offset, but we're
     // updating our local copy of it anyways just in case.
     switch (mState) {
@@ -1171,16 +1175,17 @@ void AsyncPanZoomController::NotifyLayer
     case WAITING_LISTENERS:
       mFrameMetrics.mScrollOffset = aViewportFrame.mScrollOffset;
       break;
     // Don't clobber if we're in other states.
     default:
       break;
     }
   }
+#endif
 
   mPaintThrottler.TaskComplete(GetFrameTime());
   bool needContentRepaint = false;
   if (aViewportFrame.mCompositionBounds.width == mFrameMetrics.mCompositionBounds.width &&
       aViewportFrame.mCompositionBounds.height == mFrameMetrics.mCompositionBounds.height) {
     // Remote content has sync'd up to the composition geometry
     // change, so we can accept the viewport it's calculated.
     CSSToScreenScale previousResolution = mFrameMetrics.CalculateResolution();
@@ -1468,10 +1473,16 @@ void AsyncPanZoomController::GetAPZCAtPo
 {
   *aApzcOut = nullptr;
 
   gfxPoint point(aPoint.x, aPoint.y);
 
   GetAPZCAtPointOnSubtree(aLayerTree, point, aApzcOut, aRelativePointOut);
 }
 
+void AsyncPanZoomController::UpdateScrollOffset(CSSPoint aScrollOffset)
+{
+  MonitorAutoLock monitor(mMonitor);
+  mFrameMetrics.mScrollOffset = aScrollOffset;
+}
+
 }
 }
--- a/gfx/layers/ipc/AsyncPanZoomController.h
+++ b/gfx/layers/ipc/AsyncPanZoomController.h
@@ -79,17 +79,17 @@ public:
   /**
    * Shut down the controller/UI thread state and prepare to be
    * deleted (which may happen from any thread).
    */
   void Destroy();
 
   /**
    * General handler for incoming input events. Manipulates the frame metrics
-   * basde on what type of input it is. For example, a PinchGestureEvent will
+   * based on what type of input it is. For example, a PinchGestureEvent will
    * cause scaling. This should only be called externally to this class.
    * HandleInputEvent() should be used internally.
    */
   nsEventStatus ReceiveInputEvent(const InputData& aEvent);
 
   /**
    * Special handler for nsInputEvents. Also sets |aOutEvent| (which is assumed
    * to be an already-existing instance of an nsInputEvent which may be an
@@ -247,16 +247,23 @@ public:
    * aRelativePointOut Return the point transformed into the layer coordinates
    * relative to the scroll origin for this layer.
    */
   static void GetAPZCAtPoint(const ContainerLayer& aLayerTree,
                              const ScreenIntPoint& aPoint,
                              AsyncPanZoomController** aApzcOut,
                              LayerIntPoint* aRelativePointOut);
 
+  /**
+   * Update mFrameMetrics.mScrollOffset to the given offset.
+   * This is necessary in cases where a scroll is not caused by user
+   * input (for example, a content scrollTo()).
+   */
+  void UpdateScrollOffset(CSSPoint aScrollOffset);
+
 protected:
   /**
    * Helper method for touches beginning. Sets everything up for panning and any
    * multitouch gestures.
    */
   nsEventStatus OnTouchStart(const MultiTouchInput& aEvent);
 
   /**
--- a/mobile/android/base/gfx/GeckoLayerClient.java
+++ b/mobile/android/base/gfx/GeckoLayerClient.java
@@ -375,16 +375,19 @@ public class GeckoLayerClient implements
             switch (type) {
             default:
             case UPDATE:
                 // Keep the old viewport size
                 newMetrics = messageMetrics.setViewportSize(oldMetrics.getWidth(), oldMetrics.getHeight());
                 if (!oldMetrics.fuzzyEquals(newMetrics)) {
                     abortPanZoomAnimation();
                 }
+                mPanZoomController.updateScrollOffset(
+                		messageMetrics.viewportRectLeft / messageMetrics.zoomFactor,
+                		messageMetrics.viewportRectTop / messageMetrics.zoomFactor);
                 break;
             case PAGE_SIZE:
                 // adjust the page dimensions to account for differences in zoom
                 // between the rendered content (which is what Gecko tells us)
                 // and our zoom level (which may have diverged).
                 float scaleFactor = oldMetrics.zoomFactor / messageMetrics.zoomFactor;
                 newMetrics = oldMetrics.setPageRect(RectUtils.scale(messageMetrics.getPageRect(), scaleFactor), messageMetrics.getCssPageRect());
                 break;
--- a/mobile/android/base/gfx/JavaPanZoomController.java
+++ b/mobile/android/base/gfx/JavaPanZoomController.java
@@ -1352,9 +1352,14 @@ class JavaPanZoomController
         mX.setOverScrollMode(overscrollMode);
         mY.setOverScrollMode(overscrollMode);
     }
 
     @Override
     public int getOverScrollMode() {
         return mX.getOverScrollMode();
     }
+
+    @Override
+    public void updateScrollOffset(float cssX, float cssY) {
+        // Nothing to update, this class doesn't store the scroll offset locally.
+    }
 }
--- a/mobile/android/base/gfx/NativePanZoomController.java
+++ b/mobile/android/base/gfx/NativePanZoomController.java
@@ -98,9 +98,11 @@ class NativePanZoomController implements
         @Override
         public void run() {
             long nextDelay = runDelayedCallback();
             if (nextDelay >= 0) {
                 mTarget.postDelayed(this, nextDelay);
             }
         }
     }
+
+    public native void updateScrollOffset(float cssX, float cssY);
 }
--- a/mobile/android/base/gfx/PanZoomController.java
+++ b/mobile/android/base/gfx/PanZoomController.java
@@ -35,9 +35,11 @@ public interface PanZoomController {
     public PointF getVelocityVector();
 
     public void pageRectUpdated();
     public void abortPanning();
     public void abortAnimation();
 
     public void setOverScrollMode(int overscrollMode);
     public int getOverScrollMode();
+
+    public void updateScrollOffset(float cssX, float cssY);
 }
--- a/mozglue/android/jni-stubs.inc
+++ b/mozglue/android/jni-stubs.inc
@@ -490,16 +490,35 @@ Java_org_mozilla_gecko_gfx_NativePanZoom
 #endif
 
 #ifdef JNI_BINDINGS
   xul_dlsym("Java_org_mozilla_gecko_gfx_NativePanZoomController_getOverScrollMode", &f_Java_org_mozilla_gecko_gfx_NativePanZoomController_getOverScrollMode);
 #endif
 
 #ifdef JNI_STUBS
 
+typedef void (*Java_org_mozilla_gecko_gfx_NativePanZoomController_updateScrollOffset_t)(JNIEnv *, jobject, jfloat, jfloat);
+static Java_org_mozilla_gecko_gfx_NativePanZoomController_updateScrollOffset_t f_Java_org_mozilla_gecko_gfx_NativePanZoomController_updateScrollOffset;
+extern "C" NS_EXPORT void JNICALL
+Java_org_mozilla_gecko_gfx_NativePanZoomController_updateScrollOffset(JNIEnv * arg0, jobject arg1, jfloat arg2, jfloat arg3) {
+    if (!f_Java_org_mozilla_gecko_gfx_NativePanZoomController_updateScrollOffset) {
+        arg0->ThrowNew(arg0->FindClass("java/lang/UnsupportedOperationException"),
+                       "JNI Function called before it was loaded");
+        return ;
+    }
+     f_Java_org_mozilla_gecko_gfx_NativePanZoomController_updateScrollOffset(arg0, arg1, arg2, arg3);
+}
+#endif
+
+#ifdef JNI_BINDINGS
+  xul_dlsym("Java_org_mozilla_gecko_gfx_NativePanZoomController_updateScrollOffset", &f_Java_org_mozilla_gecko_gfx_NativePanZoomController_updateScrollOffset);
+#endif
+
+#ifdef JNI_STUBS
+
 typedef jboolean (*Java_org_mozilla_gecko_ANRReporter_requestNativeStack_t)(JNIEnv *, jclass);
 static Java_org_mozilla_gecko_ANRReporter_requestNativeStack_t f_Java_org_mozilla_gecko_ANRReporter_requestNativeStack;
 extern "C" NS_EXPORT jboolean JNICALL
 Java_org_mozilla_gecko_ANRReporter_requestNativeStack(JNIEnv * arg0, jclass arg1) {
     if (!f_Java_org_mozilla_gecko_ANRReporter_requestNativeStack) {
         arg0->ThrowNew(arg0->FindClass("java/lang/UnsupportedOperationException"),
                        "JNI Function called before it was loaded");
         return false;
--- a/widget/android/AndroidJNI.cpp
+++ b/widget/android/AndroidJNI.cpp
@@ -916,16 +916,25 @@ Java_org_mozilla_gecko_gfx_NativePanZoom
 
 NS_EXPORT jint JNICALL
 Java_org_mozilla_gecko_gfx_NativePanZoomController_getOverScrollMode(JNIEnv* env, jobject instance)
 {
     // FIXME implement this
     return 0;
 }
 
+NS_EXPORT void JNICALL
+Java_org_mozilla_gecko_gfx_NativePanZoomController_updateScrollOffset(JNIEnv* env, jobject instance, jfloat cssX, jfloat cssY)
+{
+    AsyncPanZoomController* controller = nsWindow::GetPanZoomController();
+    if (controller) {
+        controller->UpdateScrollOffset(CSSPoint(cssX, cssY));
+    }
+}
+
 NS_EXPORT jboolean JNICALL
 Java_org_mozilla_gecko_ANRReporter_requestNativeStack(JNIEnv*, jclass)
 {
     if (profiler_is_active()) {
         // Don't proceed if profiler is already running
         return JNI_FALSE;
     }
     // WARNING: we are on the ANR reporter thread at this point and it is