Bug 790505, part 2: Add a GetLayerTransformForFrame() helper for computing a frame's layer transform outside a proper transaction, and mark frames that have been fully prerendered. r=roc
authorChris Jones <jones.chris.g@gmail.com>
Tue, 02 Oct 2012 22:55:50 -0700
changeset 115500 d333cf74425fc2890ca822bcf9d10ed8c733377d
parent 115499 e0907e4af12baf20477f38fb21c429f9d5e6a9df
child 115501 f3d44e273f4e6cdb2563b021c74355ab7c6b5d1b
push id1708
push userakeybl@mozilla.com
push dateMon, 19 Nov 2012 21:10:21 +0000
treeherdermozilla-beta@27b14fe50103 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersroc
bugs790505
milestone18.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 790505, part 2: Add a GetLayerTransformForFrame() helper for computing a frame's layer transform outside a proper transaction, and mark frames that have been fully prerendered. r=roc
layout/base/nsLayoutUtils.cpp
layout/base/nsLayoutUtils.h
layout/generic/nsIFrame.h
layout/generic/nsPageContentFrame.h
layout/generic/nsSimplePageSequence.h
--- a/layout/base/nsLayoutUtils.cpp
+++ b/layout/base/nsLayoutUtils.cpp
@@ -1307,16 +1307,51 @@ nsLayoutUtils::GetTransformToAncestor(ns
     if (!parent->Preserves3DChildren()) {
       ctm.ProjectTo2D();
     }
     ctm = ctm * parent->GetTransformMatrix(aAncestor, &parent);
   }
   return ctm;
 }
 
+bool
+nsLayoutUtils::GetLayerTransformForFrame(nsIFrame* aFrame,
+                                         gfx3DMatrix* aTransform)
+{
+  // FIXME/bug 796690: we can sometimes compute a transform in these
+  // cases, it just increases complexity considerably.  Punt for now.
+  if (aFrame->Preserves3DChildren() || aFrame->HasTransformGetter()) {
+    return false;
+  }
+
+  nsIFrame* root = nsLayoutUtils::GetDisplayRootFrame(aFrame);
+  if (root->HasAnyStateBits(NS_FRAME_UPDATE_LAYER_TREE)) {
+    // Content may have been invalidated, so we can't reliably compute
+    // the "layer transform" in general.
+    return false;
+  }
+  // If the caller doesn't care about the value, early-return to skip
+  // overhead below.
+  if (!aTransform) {
+    return true;
+  }
+
+  nsDisplayListBuilder builder(root, nsDisplayListBuilder::OTHER,
+                               false/*don't build caret*/);
+  nsDisplayList list;  
+  nsDisplayTransform* item =
+    new (&builder) nsDisplayTransform(&builder, aFrame, &list);
+
+  *aTransform =
+    item->GetTransform(aFrame->PresContext()->AppUnitsPerDevPixel());
+  list.DeleteAll();
+
+  return true;
+}
+
 static gfxPoint
 TransformGfxPointFromAncestor(nsIFrame *aFrame,
                               const gfxPoint &aPoint,
                               nsIFrame *aAncestor)
 {
   gfx3DMatrix ctm = nsLayoutUtils::GetTransformToAncestor(aFrame, aAncestor);
   return ctm.Inverse().ProjectPoint(aPoint);
 }
--- a/layout/base/nsLayoutUtils.h
+++ b/layout/base/nsLayoutUtils.h
@@ -532,16 +532,25 @@ public:
 
   /**
    * Gets the transform for aFrame relative to aAncestor. Pass null for aAncestor
    * to go up to the root frame.
    */
   static gfx3DMatrix GetTransformToAncestor(nsIFrame *aFrame, const nsIFrame *aAncestor);
 
   /**
+   * Return true if a "layer transform" could be computed for aFrame,
+   * and optionally return the computed transform.  The returned
+   * transform is what would be set on the layer currently if a layers
+   * transaction were opened at the time this helper is called.
+   */
+  static bool GetLayerTransformForFrame(nsIFrame* aFrame,
+                                        gfx3DMatrix* aTransform);
+
+  /**
    * Given a point in the global coordinate space, returns that point expressed
    * in the coordinate system of aFrame.  This effectively inverts all transforms
    * between this point and the root frame.
    *
    * @param aFrame The frame that acts as the coordinate space container.
    * @param aPoint The point, in the global space, to get in the frame-local space.
    * @return aPoint, expressed in aFrame's canonical coordinate space.
    */
--- a/layout/generic/nsIFrame.h
+++ b/layout/generic/nsIFrame.h
@@ -1266,16 +1266,21 @@ public:
    * Returns true if this frame is transformed (e.g. has CSS or SVG transforms)
    * or if its parent is an SVG frame that has children-only transforms (e.g.
    * an SVG viewBox attribute).
    */
   bool IsTransformed() const;
   
   bool HasOpacity() const;
 
+   /**
+   * Return true if this frame might be using a transform getter.
+   */
+  virtual bool HasTransformGetter() const { return false; }
+
   /**
    * Returns true if this frame is an SVG frame that has SVG transforms applied
    * to it, or if its parent frame is an SVG frame that has children-only
    * transforms (e.g. an SVG viewBox attribute).
    * If aOwnTransforms is non-null and the frame has its own SVG transforms,
    * aOwnTransforms will be set to these transforms. If aFromParentTransforms
    * is non-null and the frame has an SVG parent with children-only transforms,
    * then aFromParentTransforms will be set to these transforms.
@@ -2220,17 +2225,17 @@ public:
   void InvalidateFrameSubtree(uint32_t aDisplayItemKey = 0);
 
   /**
    * Called when a frame is about to be removed and needs to be invalidated.
    * Normally does nothing since DLBI handles removed frames.
    * 
    */
   virtual void InvalidateFrameForRemoval() {}
-  
+
   /**
    * Checks if a frame has had InvalidateFrame() called on it since the
    * last paint.
    *
    * If true, then the invalid rect is returned in aRect, with an
    * empty rect meaning all pixels drawn by this frame should be
    * invalidated.
    * If false, aRect is left unchanged.
--- a/layout/generic/nsPageContentFrame.h
+++ b/layout/generic/nsPageContentFrame.h
@@ -37,16 +37,18 @@ public:
    *  Computes page size based on shared page data; SetSharedPageData must be
    *  given valid data first.
    */
   virtual nsSize ComputeSize(nsRenderingContext *aRenderingContext,
                              nsSize aCBSize, nscoord aAvailableWidth,
                              nsSize aMargin, nsSize aBorder, nsSize aPadding,
                              uint32_t aFlags) MOZ_OVERRIDE;
 
+  virtual bool HasTransformGetter() const MOZ_OVERRIDE { return true; }
+
   /**
    * Get the "type" of the frame
    *
    * @see nsGkAtoms::pageContentFrame
    */
   virtual nsIAtom* GetType() const MOZ_OVERRIDE;
   
 #ifdef DEBUG
--- a/layout/generic/nsSimplePageSequence.h
+++ b/layout/generic/nsSimplePageSequence.h
@@ -86,16 +86,18 @@ public:
   NS_IMETHOD IsDoingPrintRange(bool* aDoing) MOZ_OVERRIDE;
   NS_IMETHOD GetPrintRange(int32_t* aFromPage, int32_t* aToPage) MOZ_OVERRIDE;
   NS_IMETHOD DoPageEnd() MOZ_OVERRIDE;
 
   // We must allow Print Preview UI to have a background, no matter what the
   // user's settings
   virtual bool HonorPrintBackgroundSettings() { return false; }
 
+  virtual bool HasTransformGetter() const MOZ_OVERRIDE { return true; }
+
   /**
    * Get the "type" of the frame
    *
    * @see nsGkAtoms::sequenceFrame
    */
   virtual nsIAtom* GetType() const;
 
 #ifdef DEBUG