Bug 975931. Part 1: Add nsDOMWindowUtils API to add an extra scroll offset in the AsyncPanZoomController when compositing. r=kats
authorRobert O'Callahan <robert@ocallahan.org>
Fri, 14 Feb 2014 21:59:23 +1300
changeset 190974 00d4459b6380a87cbd7faefe05cf411198dfd75f
parent 190973 7de39a071ca6202971d48a614c0a28b389739ef4
child 190975 0bb890f82f1eb68abc3319be5b5a772d6f178c23
push id474
push userasasaki@mozilla.com
push dateMon, 02 Jun 2014 21:01:02 +0000
treeherdermozilla-release@967f4cf1b31c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskats
bugs975931
milestone30.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 975931. Part 1: Add nsDOMWindowUtils API to add an extra scroll offset in the AsyncPanZoomController when compositing. r=kats
dom/base/nsDOMWindowUtils.cpp
dom/interfaces/base/nsIDOMWindowUtils.idl
gfx/layers/ipc/AsyncPanZoomController.cpp
gfx/layers/ipc/AsyncPanZoomController.h
gfx/layers/ipc/LayerTransactionParent.cpp
gfx/layers/ipc/LayerTransactionParent.h
gfx/layers/ipc/PLayerTransaction.ipdl
layout/base/nsDisplayItemTypesList.h
--- a/dom/base/nsDOMWindowUtils.cpp
+++ b/dom/base/nsDOMWindowUtils.cpp
@@ -2596,16 +2596,65 @@ nsDOMWindowUtils::GetIsTestControllingRe
   nsPresContext* pc = GetPresContext();
   *aResult =
     pc ? pc->RefreshDriver()->IsTestControllingRefreshesEnabled() : false;
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
+nsDOMWindowUtils::SetAsyncScrollOffset(nsIDOMNode* aNode,
+                                       int32_t aX, int32_t aY)
+{
+  nsCOMPtr<Element> element = do_QueryInterface(aNode);
+  if (!element) {
+    return NS_ERROR_INVALID_ARG;
+  }
+  nsIFrame* frame = element->GetPrimaryFrame();
+  if (!frame) {
+    return NS_ERROR_UNEXPECTED;
+  }
+  nsIScrollableFrame* scrollable = do_QueryFrame(frame);
+  nsPresContext* presContext = frame->PresContext();
+  nsIFrame* rootScrollFrame = presContext->PresShell()->GetRootScrollFrame();
+  if (!scrollable) {
+    if (rootScrollFrame && rootScrollFrame->GetContent() == element) {
+      frame = rootScrollFrame;
+      scrollable = do_QueryFrame(frame);
+    }
+  }
+  if (!scrollable) {
+    return NS_ERROR_UNEXPECTED;
+  }
+  Layer* layer = FrameLayerBuilder::GetDedicatedLayer(scrollable->GetScrolledFrame(),
+    nsDisplayItem::TYPE_SCROLL_LAYER);
+  if (!layer) {
+    if (rootScrollFrame == frame && !presContext->GetParentPresContext()) {
+      nsIWidget* widget = GetWidget();
+      if (widget) {
+        LayerManager* manager = widget->GetLayerManager();
+        if (manager) {
+          layer = manager->GetRoot();
+        }
+      }
+    }
+    if (!layer) {
+      return NS_ERROR_UNEXPECTED;
+    }
+  }
+  ShadowLayerForwarder* forwarder = layer->Manager()->AsShadowForwarder();
+  if (!forwarder || !forwarder->HasShadowManager()) {
+    return NS_ERROR_UNEXPECTED;
+  }
+  forwarder->GetShadowManager()->SendSetAsyncScrollOffset(
+    layer->AsShadowableLayer()->GetShadow(), aX, aY);
+  return NS_OK;
+}
+
+NS_IMETHODIMP
 nsDOMWindowUtils::ComputeAnimationDistance(nsIDOMElement* aElement,
                                            const nsAString& aProperty,
                                            const nsAString& aValue1,
                                            const nsAString& aValue2,
                                            double* aResult)
 {
   if (!nsContentUtils::IsCallerChrome()) {
     return NS_ERROR_DOM_SECURITY_ERR;
--- a/dom/interfaces/base/nsIDOMWindowUtils.idl
+++ b/dom/interfaces/base/nsIDOMWindowUtils.idl
@@ -38,17 +38,17 @@ interface nsIDOMFile;
 interface nsIFile;
 interface nsIDOMTouch;
 interface nsIDOMClientRect;
 interface nsIURI;
 interface nsIDOMEventTarget;
 interface nsIRunnable;
 interface nsICompositionStringSynthesizer;
 
-[scriptable, uuid(c378a808-7474-403a-8e5c-7d9ff052b0c1)]
+[scriptable, uuid(17fccbaa-9cef-4217-9c98-3275d9a6c6de)]
 interface nsIDOMWindowUtils : nsISupports {
 
   /**
    * Image animation mode of the window. When this attribute's value
    * is changed, the implementation should set all images in the window
    * to the given value. That is, when set to kDontAnimMode, all images
    * will stop animating. The attribute's value must be one of the
    * animationMode values from imgIContainer.
@@ -1289,16 +1289,23 @@ interface nsIDOMWindowUtils : nsISupport
 
   /**
    * Reports whether the current state is test-controlled refreshes
    * (see advanceTimeAndRefresh and restoreNormalRefresh above).
    */
   readonly attribute bool isTestControllingRefreshes;
 
   /**
+   * Set async scroll offset on an element. The next composite will render
+   * with that offset if async scrolling is enabled, and then the offset
+   * will be removed. Only call this while test-controlled refreshes is enabled.
+   */
+  void setAsyncScrollOffset(in nsIDOMNode aNode, in int32_t aX, in int32_t aY);
+
+  /**
    * Method for testing nsStyleAnimation::ComputeDistance.
    *
    * Returns the distance between the two values as reported by
    * nsStyleAnimation::ComputeDistance for the given element and
    * property.
    */
   double computeAnimationDistance(in nsIDOMElement element,
                                   in AString property,
--- a/gfx/layers/ipc/AsyncPanZoomController.cpp
+++ b/gfx/layers/ipc/AsyncPanZoomController.cpp
@@ -1566,17 +1566,18 @@ bool AsyncPanZoomController::SampleConte
 ViewTransform AsyncPanZoomController::GetCurrentAsyncTransform() {
   ReentrantMonitorAutoEnter lock(mMonitor);
 
   CSSPoint lastPaintScrollOffset;
   if (mLastContentPaintMetrics.IsScrollable()) {
     lastPaintScrollOffset = mLastContentPaintMetrics.mScrollOffset;
   }
 
-  CSSPoint currentScrollOffset = mFrameMetrics.mScrollOffset;
+  CSSPoint currentScrollOffset = mFrameMetrics.mScrollOffset +
+    mTestAsyncScrollOffset;
 
   // If checkerboarding has been disallowed, clamp the scroll position to stay
   // within rendered content.
   if (!gAllowCheckerboarding &&
       !mLastContentPaintMetrics.mDisplayPort.IsEmpty()) {
     CSSRect compositedRect = mLastContentPaintMetrics.CalculateCompositedRectInCssPixels();
     CSSPoint maxScrollOffset = lastPaintScrollOffset +
       CSSPoint(mLastContentPaintMetrics.mDisplayPort.XMost() - compositedRect.width,
--- a/gfx/layers/ipc/AsyncPanZoomController.h
+++ b/gfx/layers/ipc/AsyncPanZoomController.h
@@ -330,16 +330,24 @@ public:
   /**
    * Returns whether this APZC is for an element marked with the 'scrollgrab'
    * attribute.
    */
   bool HasScrollgrab() const { return mFrameMetrics.mHasScrollgrab; }
 
   void FlushRepaintForOverscrollHandoff();
 
+  /**
+   * Set an extra offset for testing async scrolling.
+   */
+  void SetTestAsyncScrollOffset(const CSSPoint& aPoint)
+  {
+    mTestAsyncScrollOffset = aPoint;
+  }
+
 protected:
   /**
    * Helper method for touches beginning. Sets everything up for panning and any
    * multitouch gestures.
    */
   nsEventStatus OnTouchStart(const MultiTouchInput& aEvent);
 
   /**
@@ -718,16 +726,19 @@ private:
 
   // Flag used to specify that content prevented the default behavior of the current
   // touch events block.
   bool mPreventDefault;
 
   // Specifies whether mPreventDefault property is set for current touch events block.
   bool mPreventDefaultSet;
 
+  // Extra offset to add in SampleContentTransformForFrame for testing
+  CSSPoint mTestAsyncScrollOffset;
+
   RefPtr<AsyncPanZoomAnimation> mAnimation;
 
   friend class Axis;
 
   /* The functions and members in this section are used to build a tree
    * structure out of APZC instances. This tree can only be walked or
    * manipulated while holding the lock in the associated APZCTreeManager
    * instance.
--- a/gfx/layers/ipc/LayerTransactionParent.cpp
+++ b/gfx/layers/ipc/LayerTransactionParent.cpp
@@ -36,16 +36,17 @@
 #include "nsISupportsImpl.h"            // for Layer::Release, etc
 #include "nsLayoutUtils.h"              // for nsLayoutUtils
 #include "nsMathUtils.h"                // for NS_round
 #include "nsPoint.h"                    // for nsPoint
 #include "nsTArray.h"                   // for nsTArray, nsTArray_Impl, etc
 #include "GeckoProfiler.h"
 #include "mozilla/layers/TextureHost.h"
 #include "mozilla/layers/AsyncCompositionManager.h"
+#include "AsyncPanZoomController.h"
 
 typedef std::vector<mozilla::layers::EditReply> EditReplyVector;
 
 using mozilla::layout::RenderFrameParent;
 
 namespace mozilla {
 namespace layers {
 
@@ -640,16 +641,36 @@ LayerTransactionParent::RecvGetAnimation
   transform._42 *= devPerCss;
   transform._43 *= devPerCss;
 
   *aTransform = transform;
   return true;
 }
 
 bool
+LayerTransactionParent::RecvSetAsyncScrollOffset(PLayerParent* aLayer,
+                                                 const int32_t& aX, const int32_t& aY)
+{
+  if (mDestroyed || !layer_manager() || layer_manager()->IsDestroyed()) {
+    return false;
+  }
+
+  ContainerLayer* layer = cast(aLayer)->AsLayer()->AsContainerLayer();
+  if (!layer) {
+    return true;
+  }
+  AsyncPanZoomController* controller = layer->GetAsyncPanZoomController();
+  if (!controller) {
+    return true;
+  }
+  controller->SetTestAsyncScrollOffset(CSSPoint(aX, aY));
+  return true;
+}
+
+bool
 LayerTransactionParent::Attach(ShadowLayerParent* aLayerParent,
                                CompositableParent* aCompositable,
                                bool aIsAsyncVideo)
 {
   Layer* baselayer = aLayerParent->AsLayer();
   if (!baselayer) {
     return false;
   }
--- a/gfx/layers/ipc/LayerTransactionParent.h
+++ b/gfx/layers/ipc/LayerTransactionParent.h
@@ -93,16 +93,18 @@ protected:
 
   virtual bool RecvClearCachedResources() MOZ_OVERRIDE;
   virtual bool RecvForceComposite() MOZ_OVERRIDE;
   virtual bool RecvGetOpacity(PLayerParent* aParent,
                               float* aOpacity) MOZ_OVERRIDE;
   virtual bool RecvGetAnimationTransform(PLayerParent* aParent,
                                          MaybeTransform* aTransform)
                                          MOZ_OVERRIDE;
+  virtual bool RecvSetAsyncScrollOffset(PLayerParent* aLayer,
+                                        const int32_t& aX, const int32_t& aY) MOZ_OVERRIDE;
 
   virtual PGrallocBufferParent*
   AllocPGrallocBufferParent(const IntSize& aSize,
                             const uint32_t& aFormat, const uint32_t& aUsage,
                             MaybeMagicGrallocBufferHandle* aOutHandle) MOZ_OVERRIDE;
   virtual bool
   DeallocPGrallocBufferParent(PGrallocBufferParent* actor) MOZ_OVERRIDE;
 
--- a/gfx/layers/ipc/PLayerTransaction.ipdl
+++ b/gfx/layers/ipc/PLayerTransaction.ipdl
@@ -76,25 +76,31 @@ parent:
   async PCompositable(TextureInfo aTextureInfo);
   async PTexture(SurfaceDescriptor aSharedData, uint32_t aTextureFlags);
 
   // The isFirstPaint flag can be used to indicate that this is the first update
   // for a particular document.
   sync Update(Edit[] cset, TargetConfig targetConfig, bool isFirstPaint, bool scheduleComposite)
     returns (EditReply[] reply);
 
+  // Testing APIs
   sync GetOpacity(PLayer layer) returns (float opacity);
 
   // Returns the value of the transform applied to the layer by animation after
   // factoring out translation components introduced to account for the offset
   // of the corresponding frame and transform origin and after converting to CSS
   // pixels. If the layer is not transformed by animation, the return value will
   // be void_t.
   sync GetAnimationTransform(PLayer layer) returns (MaybeTransform transform);
 
+  // The next time this layer is composited, add this async scroll offset in
+  // CSS pixels.
+  // Useful for testing rendering of async scrolling.
+  async SetAsyncScrollOffset(PLayer layer, int32_t x, int32_t y);
+
   // We don't need to send a sync transaction if
   // no transaction operate require a swap.
   async UpdateNoSwap(Edit[] cset, TargetConfig targetConfig, bool isFirstPaint, bool scheduleComposite);
 
   // Drop any front buffers that might be retained on the compositor
   // side.
   async ClearCachedResources();
   
--- a/layout/base/nsDisplayItemTypesList.h
+++ b/layout/base/nsDisplayItemTypesList.h
@@ -20,17 +20,16 @@ DECLARE_DISPLAY_ITEM_TYPE(CARET)
 DECLARE_DISPLAY_ITEM_TYPE(CHECKED_CHECKBOX)
 DECLARE_DISPLAY_ITEM_TYPE(CHECKED_RADIOBUTTON)
 DECLARE_DISPLAY_ITEM_TYPE(COLUMN_RULE)
 DECLARE_DISPLAY_ITEM_TYPE(COMBOBOX_FOCUS)
 DECLARE_DISPLAY_ITEM_TYPE(EVENT_RECEIVER)
 DECLARE_DISPLAY_ITEM_TYPE(LAYER_EVENT_REGIONS)
 DECLARE_DISPLAY_ITEM_TYPE(FIELDSET_BORDER_BACKGROUND)
 DECLARE_DISPLAY_ITEM_TYPE(STICKY_POSITION)
-DECLARE_DISPLAY_ITEM_TYPE(FORCEPAINTONSCROLL)
 DECLARE_DISPLAY_ITEM_TYPE(FRAMESET_BORDER)
 DECLARE_DISPLAY_ITEM_TYPE(FRAMESET_BLANK)
 DECLARE_DISPLAY_ITEM_TYPE(HEADER_FOOTER)
 DECLARE_DISPLAY_ITEM_TYPE(IMAGE)
 DECLARE_DISPLAY_ITEM_TYPE(LIST_FOCUS)
 DECLARE_DISPLAY_ITEM_TYPE(MIX_BLEND_MODE)
 DECLARE_DISPLAY_ITEM_TYPE(OPACITY)
 DECLARE_DISPLAY_ITEM_TYPE(OPTION_EVENT_GRABBER)