Backing out 99f6b3acc464 (bug 618975). Bug This caused a reftest crash. a=bustage
authorDoug Turner <dougt@dougt.org>
Tue, 08 Mar 2011 22:02:50 -0800
changeset 63361 3268032022693d48024c06c721ab88add032e1cb
parent 63360 99f6b3acc464b2ca1d519de7a8c381def4005463
child 63362 d205dbeada8c3bc3c6ff1649a6f1020d9b58e282
push idunknown
push userunknown
push dateunknown
reviewersbustage
bugs618975
milestone2.0b13pre
Backing out 99f6b3acc464 (bug 618975). Bug This caused a reftest crash. a=bustage
content/base/src/nsGkAtomList.h
dom/base/nsDOMWindowUtils.cpp
dom/interfaces/base/nsIDOMWindowUtils.idl
layout/base/FrameLayerBuilder.cpp
layout/base/FrameLayerBuilder.h
layout/base/nsDisplayList.cpp
layout/base/nsDisplayList.h
layout/base/nsIPresShell.h
layout/base/nsLayoutUtils.cpp
layout/base/nsLayoutUtils.h
layout/base/nsPresShell.cpp
layout/generic/nsGfxScrollFrame.cpp
layout/generic/nsSubDocumentFrame.cpp
--- a/content/base/src/nsGkAtomList.h
+++ b/content/base/src/nsGkAtomList.h
@@ -1744,17 +1744,16 @@ GK_ATOM(Unicode, "x-unicode")
 // Names for editor transactions
 GK_ATOM(TypingTxnName, "Typing")
 GK_ATOM(IMETxnName, "IME")
 GK_ATOM(DeleteTxnName, "Deleting")
 
 // IPC stuff
 GK_ATOM(Remote, "remote")
 GK_ATOM(RemoteId, "_remote_id")
-GK_ATOM(DisplayPort, "_displayport")
 
 // Names for system metrics
 GK_ATOM(scrollbar_start_backward, "scrollbar-start-backward")
 GK_ATOM(scrollbar_start_forward, "scrollbar-start-forward")
 GK_ATOM(scrollbar_end_backward, "scrollbar-end-backward")
 GK_ATOM(scrollbar_end_forward, "scrollbar-end-forward")
 GK_ATOM(scrollbar_thumb_proportional, "scrollbar-thumb-proportional")
 GK_ATOM(images_in_menus, "images-in-menus")
--- a/dom/base/nsDOMWindowUtils.cpp
+++ b/dom/base/nsDOMWindowUtils.cpp
@@ -43,17 +43,16 @@
 #include "nsIPrivateDOMEvent.h"
 #include "nsDOMWindowUtils.h"
 #include "nsQueryContentEventResult.h"
 #include "nsGlobalWindow.h"
 #include "nsIDocument.h"
 #include "nsFocusManager.h"
 #include "nsIEventStateManager.h"
 #include "nsEventStateManager.h"
-#include "nsFrameManager.h"
 
 #include "nsIScrollableFrame.h"
 
 #include "nsContentUtils.h"
 #include "nsLayoutUtils.h"
 
 #include "nsIFrame.h"
 #include "nsIWidget.h"
@@ -254,101 +253,36 @@ nsDOMWindowUtils::SetCSSViewport(float a
   nscoord width = nsPresContext::CSSPixelsToAppUnits(aWidthPx);
   nscoord height = nsPresContext::CSSPixelsToAppUnits(aHeightPx);
 
   presShell->ResizeReflowOverride(width, height);
 
   return NS_OK;
 }
 
-static void DestroyNsRect(void* aObject, nsIAtom* aPropertyName,
-                          void* aPropertyValue, void* aData)
-{
-  nsRect* rect = static_cast<nsRect*>(aPropertyValue);
-  delete rect;
-}
-
 NS_IMETHODIMP
 nsDOMWindowUtils::SetDisplayPort(float aXPx, float aYPx,
                                  float aWidthPx, float aHeightPx)
 {
-  NS_ABORT_IF_FALSE(false, "This interface is deprecated.");
-  return NS_ERROR_FAILURE;
-}
-
-NS_IMETHODIMP
-nsDOMWindowUtils::SetDisplayPortForElement(float aXPx, float aYPx,
-                                           float aWidthPx, float aHeightPx,
-                                           nsIDOMElement* aElement)
-{
   if (!IsUniversalXPConnectCapable()) {
     return NS_ERROR_DOM_SECURITY_ERR;
   }
 
   nsIPresShell* presShell = GetPresShell();
   if (!presShell) {
     return NS_ERROR_FAILURE;
   } 
 
   nsRect displayport(nsPresContext::CSSPixelsToAppUnits(aXPx),
                      nsPresContext::CSSPixelsToAppUnits(aYPx),
                      nsPresContext::CSSPixelsToAppUnits(aWidthPx),
                      nsPresContext::CSSPixelsToAppUnits(aHeightPx));
-
-  if (!aElement) {
-    return NS_ERROR_INVALID_ARG;
-  }
-
-  nsCOMPtr<nsIContent> content = do_QueryInterface(aElement);
-
-  if (!content) {
-    return NS_ERROR_INVALID_ARG;
-  }
-
-  nsRect lastDisplayPort;
-  if (nsLayoutUtils::GetDisplayPort(content, &lastDisplayPort) &&
-      displayport == lastDisplayPort) {
-    return NS_OK;
-  }
-
-  content->SetProperty(nsGkAtoms::DisplayPort, new nsRect(displayport),
-                       DestroyNsRect);
+  presShell->SetDisplayPort(displayport);
 
-  nsIFrame* rootScrollFrame = presShell->GetRootScrollFrame();
-  if (rootScrollFrame) {
-    if (content == rootScrollFrame->GetContent()) {
-      // We are setting the root displayport. The pres context needs a special
-      // flag to be set.
-      presShell->SetIgnoreViewportScrolling(PR_TRUE);
-    }
-  }
-
-  // FIXME (Bug 593243 should fix this.)
-  //
-  // Invalidated content does not pay any attention to the displayport, so
-  // invalidating the subdocument's root frame could end up not repainting
-  // visible content.
-  //
-  // For instance, imagine the iframe is located at y=1000. Even though the
-  // displayport may intersect the iframe's viewport, the visual overflow
-  // rect of the root content could be (0, 0, 800, 500). Since the dirty region
-  // does not intersect the visible overflow rect, the display list for the
-  // iframe will not even be generated.
-  //
-  // Here, we find the very top presShell and use its root frame for
-  // invalidation instead.
-  //
-  nsPresContext* rootPresContext = GetPresContext()->GetRootPresContext();
-  if (rootPresContext) {
-    nsIPresShell* rootPresShell = rootPresContext->GetPresShell();
-    nsIFrame* rootFrame = rootPresShell->FrameManager()->GetRootFrame();
-    if (rootFrame) {
-      rootFrame->InvalidateFrameSubtree();
-    }
-  }
+  presShell->SetIgnoreViewportScrolling(PR_TRUE);
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDOMWindowUtils::SetResolution(float aXResolution, float aYResolution)
 {
   if (!IsUniversalXPConnectCapable()) {
--- a/dom/interfaces/base/nsIDOMWindowUtils.idl
+++ b/dom/interfaces/base/nsIDOMWindowUtils.idl
@@ -124,17 +124,40 @@ interface nsIDOMWindowUtils : nsISupport
    * This will trigger reflow.
    *
    * The caller of this method must have UniversalXPConnect
    * privileges.
    */
   void setCSSViewport(in float aWidthPx, in float aHeightPx);
 
   /**
-   * @DEPRECATED See nsIDOMWindowUtils_MOZILLA_2_0_BRANCH.
+   * Set the "displayport" to be <xPx, yPx, widthPx, heightPx> in
+   * units of CSS pixels, regardless of the size of the enclosing
+   * widget/view.  This will *not* trigger reflow.
+   *
+   * <x, y> is relative to the top-left of the CSS viewport.  This
+   * means that the pixels rendered to the displayport take scrolling
+   * into account, for example.
+   *
+   * The displayport will be used as the window's visible region for
+   * the purposes of invalidation and painting.  The displayport can
+   * approximately be thought of as a "persistent" drawWindow()
+   * (albeit with coordinates relative to the CSS viewport): the
+   * bounds are remembered by the platform, and layer pixels are
+   * retained and updated inside the viewport bounds.
+   *
+   * It's legal to set a displayport that extends beyond the CSS
+   * viewport in any direction (left/right/top/bottom).
+   * 
+   * It's also legal to set a displayport that extends beyond the
+   * document's bounds.  The value of the pixels rendered outside the
+   * document bounds is not yet defined.
+   *
+   * The caller of this method must have UniversalXPConnect
+   * privileges.
    */
   void setDisplayPort(in float aXPx, in float aYPx,
                       in float aWidthPx, in float aHeightPx);
 
   /**
    * Get/set the resolution at which rescalable web content is drawn.
    * Currently this is only (some) thebes content.
    *
@@ -796,61 +819,31 @@ interface nsIDOMWindowUtils : nsISupport
   double computeAnimationDistance(in nsIDOMElement element,
                                   in AString property,
                                   in AString value1,
                                   in AString value2);
 };
 
 typedef unsigned long long nsViewID;
 
-[scriptable, uuid(7ad49829-e631-4cdd-a237-95847d9bcbe6)]
+[scriptable, uuid(be2e28c8-64f8-4100-906d-8a451ddd6835)]
 interface nsIDOMWindowUtils_MOZILLA_2_0_BRANCH : nsISupports {
   /**
    * Get the type of the currently focused html input, if any.
    */
   readonly attribute string focusedInputType;
 
   /**
    * Given a view ID from the compositor process, retrieve the element
    * associated with a view. For scrollpanes for documents, the root
    * element of the document is returned.
    */
   nsIDOMElement findElementWithViewId(in nsViewID aId);
 
   /**
-   * For any scrollable element, this allows you to override the
-   * visible region and draw more than what is visible, which is
-   * useful for asynchronous drawing. The "displayport" will be
-   * <xPx, yPx, widthPx, heightPx> in units of CSS pixels,
-   * regardless of the size of the enclosing container.  This
-   * will *not* trigger reflow.
-   *
-   * For the root scroll area, pass in the root document element.
-   * For scrollable elements, pass in the container element (for
-   * instance, the element with overflow: scroll).
-   *
-   * <x, y> is relative to the top-left of what would normally be
-   * the visible area of the element. This means that the pixels
-   * rendered to the displayport take scrolling into account,
-   * for example.
-   *
-   * It's legal to set a displayport that extends beyond the overflow
-   * area in any direction (left/right/top/bottom).
-   * 
-   * It's also legal to set a displayport that extends beyond the
-   * area's bounds.  No pixels are rendered outside the area bounds.
-   *
-   * The caller of this method must have UniversalXPConnect
-   * privileges.
-   */
-  void setDisplayPortForElement(in float aXPx, in float aYPx,
-                                in float aWidthPx, in float aHeightPx,
-                                in nsIDOMElement aElement);
-
-  /**
    * Same as enterModalState, but returns the window associated with the
    * current JS context.
    */
   nsIDOMWindow enterModalStateWithWindow();
 
   /**
    * Same as leaveModalState, but takes a window associated with the active
    * context when enterModalStateWithWindow was called. The currently context
--- a/layout/base/FrameLayerBuilder.cpp
+++ b/layout/base/FrameLayerBuilder.cpp
@@ -1247,18 +1247,17 @@ ContainerState::ProcessDisplayItems(cons
       itemContent.IntersectRect(aClip.mClipRect, itemContent);
     }
     mBounds.UnionRect(mBounds, itemContent);
     nsIntRect itemDrawRect = itemContent.ToOutsidePixels(appUnitsPerDevPixel);
     nsDisplayItem::LayerState layerState =
       item->GetLayerState(mBuilder, mManager);
 
     // Assign the item to a layer
-    if (layerState == LAYER_ACTIVE_FORCE ||
-        layerState == LAYER_ACTIVE && (aClip.mRoundedClipRects.IsEmpty() ||
+    if (layerState == LAYER_ACTIVE && (aClip.mRoundedClipRects.IsEmpty() ||
         // We can use the visible rect here only because the item has its own
         // layer, like the comment below.
         !aClip.IsRectClippedByRoundedCorner(item->GetVisibleRect()))) {
       // If the item would have its own layer but is invisible, just hide it.
       // Note that items without their own layers can't be skipped this
       // way, since their ThebesLayer may decide it wants to draw them
       // into its buffer even if they're currently covered.
       if (itemVisibleRect.IsEmpty()) {
--- a/layout/base/FrameLayerBuilder.h
+++ b/layout/base/FrameLayerBuilder.h
@@ -51,20 +51,17 @@ class nsDisplayItem;
 class gfxContext;
 class nsRootPresContext;
 
 namespace mozilla {
 
 enum LayerState {
   LAYER_NONE,
   LAYER_INACTIVE,
-  LAYER_ACTIVE,
-  // Force an active layer even if it causes incorrect rendering, e.g.
-  // when the layer has rounded rect clips.
-  LAYER_ACTIVE_FORCE
+  LAYER_ACTIVE
 };
 
 /**
  * The FrameLayerBuilder belongs to an nsDisplayListBuilder and is
  * responsible for converting display lists into layer trees.
  * 
  * The most important API in this class is BuildContainerLayerFor. This
  * method takes a display list as input and constructs a ContainerLayer
--- a/layout/base/nsDisplayList.cpp
+++ b/layout/base/nsDisplayList.cpp
@@ -144,48 +144,47 @@ static void UnmarkFrameForDisplay(nsIFra
        f = nsLayoutUtils::GetParentOrPlaceholderFor(frameManager, f)) {
     if (!(f->GetStateBits() & NS_FRAME_FORCE_DISPLAY_LIST_DESCEND_INTO))
       return;
     f->RemoveStateBits(NS_FRAME_FORCE_DISPLAY_LIST_DESCEND_INTO);
   }
 }
 
 static void RecordFrameMetrics(nsIFrame* aForFrame,
-                               nsIFrame* aViewportFrame,
                                ContainerLayer* aRoot,
                                nsRect aVisibleRect,
                                nsRect aViewport,
-                               nsRect aDisplayPort,
                                ViewID aScrollId) {
   nsPresContext* presContext = aForFrame->PresContext();
+  nsIPresShell* presShell = presContext->GetPresShell();
 
   nsIntRect visible = aVisibleRect.ToNearestPixels(presContext->AppUnitsPerDevPixel());
   aRoot->SetVisibleRegion(nsIntRegion(visible));
 
   FrameMetrics metrics;
 
   PRInt32 auPerDevPixel = presContext->AppUnitsPerDevPixel();
   metrics.mViewport = aViewport.ToNearestPixels(auPerDevPixel);
-  if (aViewport != aDisplayPort) {
-    metrics.mDisplayPort = aDisplayPort.ToNearestPixels(auPerDevPixel);
+  if (presShell->UsingDisplayPort()) {
+    metrics.mDisplayPort =
+      presShell->GetDisplayPort().ToNearestPixels(auPerDevPixel);
   }
 
-  nsIScrollableFrame* scrollableFrame = NULL;
-  if (aViewportFrame)
-    scrollableFrame = aViewportFrame->GetScrollTargetFrame();
-
-  if (scrollableFrame) {
-    nsSize contentSize =
-      scrollableFrame->GetScrollRange().Size() +
-      scrollableFrame->GetScrollPortRect().Size();
+  nsIScrollableFrame* rootScrollableFrame =
+    presShell->GetRootScrollFrameAsScrollable();
+  if (rootScrollableFrame) {
+    nsSize contentSize = 
+      rootScrollableFrame->GetScrollRange().Size() +
+      rootScrollableFrame->GetScrollPortRect().Size();
     metrics.mContentSize = nsIntSize(NSAppUnitsToIntPixels(contentSize.width, auPerDevPixel),
                                      NSAppUnitsToIntPixels(contentSize.height, auPerDevPixel));
 
     metrics.mViewportScrollOffset =
-      scrollableFrame->GetScrollPosition().ToNearestPixels(auPerDevPixel);
+      rootScrollableFrame->GetScrollPosition().ToNearestPixels(auPerDevPixel);
+    
   }
   else {
     nsSize contentSize = aForFrame->GetSize();
     metrics.mContentSize = nsIntSize(NSAppUnitsToIntPixels(contentSize.width, auPerDevPixel),
                                      NSAppUnitsToIntPixels(contentSize.height, auPerDevPixel));
   }
 
   metrics.mScrollId = aScrollId;
@@ -519,28 +518,17 @@ void nsDisplayList::PaintForFrame(nsDisp
     return;
 
   nsPresContext* presContext = aForFrame->PresContext();
   nsIPresShell* presShell = presContext->GetPresShell();
 
   ViewID id = presContext->IsRootContentDocument() ? FrameMetrics::ROOT_SCROLL_ID
                                                    : FrameMetrics::NULL_SCROLL_ID;
 
-  nsIFrame* rootScrollFrame = presShell->GetRootScrollFrame();
-  nsRect visibleRect = mVisibleRect;
-  if (rootScrollFrame) {
-    nsIContent* content = rootScrollFrame->GetContent();
-    if (content) {
-      // If there is a displayport defined for the root content element,
-      // it will be stored in visibleRect.
-      nsLayoutUtils::GetDisplayPort(content, &visibleRect);
-    }
-  }
-  RecordFrameMetrics(aForFrame, presShell->GetRootScrollFrame(),
-                     root, mVisibleRect, mVisibleRect, visibleRect, id);
+  RecordFrameMetrics(aForFrame, root, mVisibleRect, mVisibleRect, id);
 
   // If the layer manager supports resolution scaling, set that up
   if (LayerManager::LAYERS_BASIC == layerManager->GetBackendType()) {
     BasicLayerManager* basicManager =
       static_cast<BasicLayerManager*>(layerManager.get());
     // This is free if both resolutions are 1.0, or neither resolution
     // has changed since the last transaction
     basicManager->SetResolution(presShell->GetXResolution(),
@@ -1701,21 +1689,19 @@ nsDisplayOwnLayer::BuildLayer(nsDisplayL
   return layer.forget();
 }
 
 #ifdef MOZ_IPC
 
 nsDisplayScrollLayer::nsDisplayScrollLayer(nsDisplayListBuilder* aBuilder,
                                            nsDisplayList* aList,
                                            nsIFrame* aForFrame,
-                                           nsIFrame* aViewportFrame,
-                                           const nsRect& aDisplayPort)
+                                           nsIFrame* aViewportFrame)
   : nsDisplayOwnLayer(aBuilder, aForFrame, aList)
   , mViewportFrame(aViewportFrame)
-  , mDisplayPort(aDisplayPort)
 {
 #ifdef NS_BUILD_REFCNT_LOGGING
   MOZ_COUNT_CTOR(nsDisplayScrollLayer);
 #endif
 
   NS_ASSERTION(mFrame && mFrame->GetContent(),
                "Need a child frame with content");
 }
@@ -1730,40 +1716,36 @@ nsDisplayScrollLayer::BuildLayer(nsDispl
   // Or, if not set, generate a new ID.
   nsIContent* content = mFrame->GetContent();
   ViewID scrollId = nsLayoutUtils::FindIDFor(content);
 
   nsRect viewport = mViewportFrame->GetRect() -
                     mViewportFrame->GetPosition() +
                     aBuilder->ToReferenceFrame(mViewportFrame);
 
-  RecordFrameMetrics(mFrame, mViewportFrame, layer, mVisibleRect, viewport,
-                     mDisplayPort, scrollId);
+  RecordFrameMetrics(mFrame, layer, mVisibleRect, viewport, scrollId);
 
   return layer.forget();
 }
 
 PRBool
 nsDisplayScrollLayer::ComputeVisibility(nsDisplayListBuilder* aBuilder,
                                         nsRegion* aVisibleRegion,
                                         const nsRect& aAllowVisibleRegionExpansion,
                                         PRBool& aContainsRootContentDocBG)
 {
   nsPresContext* presContext = mFrame->PresContext();
+  nsIPresShell* presShell = presContext->GetPresShell();
 
-  nsRect viewport = mViewportFrame->GetRect() -
-                    mViewportFrame->GetPosition() +
-                    aBuilder->ToReferenceFrame(mViewportFrame);
-
-  if (mDisplayPort != viewport) {
+  if (presShell->UsingDisplayPort()) {
     // The visible region for the children may be much bigger than the hole we
     // are viewing the children from, so that the compositor process has enough
     // content to asynchronously pan while content is being refreshed.
 
-    nsRegion childVisibleRegion = mDisplayPort + aBuilder->ToReferenceFrame(mViewportFrame);
+    nsRegion childVisibleRegion = presShell->GetDisplayPort() + aBuilder->ToReferenceFrame(mViewportFrame);
 
     nsRect boundedRect;
     boundedRect.IntersectRect(childVisibleRegion.GetBounds(), mList.GetBounds(aBuilder));
     nsRect allowExpansion;
     allowExpansion.IntersectRect(allowExpansion, boundedRect);
     PRBool visible = mList.ComputeVisibilityForSublist(
       aBuilder, &childVisibleRegion, boundedRect, allowExpansion, aContainsRootContentDocBG);
     mVisibleRect = boundedRect;
--- a/layout/base/nsDisplayList.h
+++ b/layout/base/nsDisplayList.h
@@ -1785,46 +1785,35 @@ public:
  */
 class nsDisplayScrollLayer : public nsDisplayOwnLayer
 {
 public:
   /**
    * @param aForFrame This will determine what the displayport is. It should be
    *                  the root content frame of the scrolled area.
    * @param aViewportFrame The viewport frame you see this content through.
-   * @param aDisplayPort Overrides the visibility of the child items if it
-   *                     is not equal to the visible area.
    */
   nsDisplayScrollLayer(nsDisplayListBuilder* aBuilder, nsDisplayList* aList,
-                       nsIFrame* aForFrame, nsIFrame* aViewportFrame,
-                       const nsRect& aDisplayPort);
+                       nsIFrame* aForFrame, nsIFrame* aViewportFrame);
   NS_DISPLAY_DECL_NAME("ScrollLayer", TYPE_SCROLL_LAYER)
 
 #ifdef NS_BUILD_REFCNT_LOGGING
   virtual ~nsDisplayScrollLayer();
 #endif
 
   virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
                                              LayerManager* aManager);
 
   virtual PRBool ComputeVisibility(nsDisplayListBuilder* aBuilder,
                                    nsRegion* aVisibleRegion,
                                    const nsRect& aAllowVisibleRegionExpansion,
                                    PRBool& aContainsRootContentDocBG);
 
-  virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
-                                   LayerManager* aManager)
-  {
-    // Force this as a layer so we can scroll asynchronously.
-    // This causes incorrect rendering for rounded clips!
-    return mozilla::LAYER_ACTIVE_FORCE;
-  }
 private:
   nsIFrame* mViewportFrame;
-  nsRect mDisplayPort;
 };
 #endif
 
 /**
  * nsDisplayClip can clip a list of items, but we take a single item
  * initially and then later merge other items into it when we merge
  * adjacent matching nsDisplayClips
  */
--- a/layout/base/nsIPresShell.h
+++ b/layout/base/nsIPresShell.h
@@ -1149,31 +1149,29 @@ public:
   virtual void SetIgnoreViewportScrolling(PRBool aIgnore) = 0;
   PRBool IgnoringViewportScrolling() const
   { return mRenderFlags & STATE_IGNORING_VIEWPORT_SCROLLING; }
 
   /**
    * Set up a "displayport", which overrides what everything else thinks
    * is the visible region of this document with the specified
    * displayport rect.
-   * @DEPRECATED Use nsLayoutUtils displayport methods
    */
   virtual void SetDisplayPort(const nsRect& aDisplayPort) = 0;
   PRBool UsingDisplayPort() const
-  { NS_ABORT_IF_FALSE(false, "UsingDisplayPort is deprecated"); return false; }
+  { return mRenderFlags & STATE_USING_DISPLAYPORT; }
 
   /**
    * Return the displayport being used.  |UsingDisplayPort()| must be
    * true.
-   * @DEPRECATED Use nsLayoutUtils displayport methods
    */
   nsRect GetDisplayPort()
   {
-    NS_ABORT_IF_FALSE(false, "GetDisplayPort is deprecated");
-    return nsRect();
+    NS_ABORT_IF_FALSE(UsingDisplayPort(), "no displayport defined!");
+    return mDisplayPort;
   }
 
    /**
    * Set a "resolution" for the document, which if not 1.0 will
    * allocate more or fewer pixels for rescalable content by a factor
    * of |resolution| in both dimensions.  Return NS_OK iff the
    * resolution bounds are sane, and the resolution of this was
    * actually updated.
--- a/layout/base/nsLayoutUtils.cpp
+++ b/layout/base/nsLayoutUtils.cpp
@@ -138,20 +138,16 @@ static ContentMap& GetContentMap() {
 static void DestroyViewID(void* aObject, nsIAtom* aPropertyName,
                           void* aPropertyValue, void* aData)
 {
   ViewID* id = static_cast<ViewID*>(aPropertyValue);
   GetContentMap().Remove(*id);
   delete id;
 }
 
-/**
- * A namespace class for static layout utilities.
- */
-
 ViewID
 nsLayoutUtils::FindIDFor(nsIContent* aContent)
 {
   ViewID scrollId;
 
   void* scrollIdProperty = aContent->GetProperty(nsGkAtoms::RemoteId);
   if (scrollIdProperty) {
     scrollId = *static_cast<ViewID*>(scrollIdProperty);
@@ -176,29 +172,19 @@ nsLayoutUtils::FindContentFor(ViewID aId
 
   if (exists) {
     return content;
   } else {
     return nsnull;
   }
 }
 
-bool
-nsLayoutUtils::GetDisplayPort(nsIContent* aContent, nsRect *aResult)
-{
-  void* property = aContent->GetProperty(nsGkAtoms::DisplayPort);
-  if (!property) {
-    return false;
-  }
-
-  if (aResult) {
-    *aResult = *static_cast<nsRect*>(property);
-  }
-  return true;
-}
+/**
+ * A namespace class for static layout utilities.
+ */
 
 nsIFrame*
 nsLayoutUtils::GetLastContinuationWithChild(nsIFrame* aFrame)
 {
   NS_PRECONDITION(aFrame, "NULL frame pointer");
   aFrame = aFrame->GetLastContinuation();
   while (!aFrame->GetFirstChild(nsnull) &&
          aFrame->GetPrevContinuation()) {
@@ -1377,39 +1363,29 @@ nsLayoutUtils::PaintFrame(nsIRenderingCo
       aFlags &= ~PAINT_WIDGET_LAYERS;
       NS_ASSERTION(aRenderingContext, "need a rendering context");
     }
   }
 
   nsPresContext* presContext = aFrame->PresContext();
   nsIPresShell* presShell = presContext->PresShell();
 
-  nsIFrame* rootScrollFrame = presShell->GetRootScrollFrame();
-  bool usingDisplayPort = false;
-  nsRect displayport;
-  if (rootScrollFrame) {
-    nsIContent* content = rootScrollFrame->GetContent();
-    if (content) {
-      usingDisplayPort = nsLayoutUtils::GetDisplayPort(content, &displayport);
-    }
-  }
-
   PRBool ignoreViewportScrolling = presShell->IgnoringViewportScrolling();
   nsRegion visibleRegion;
   if (aFlags & PAINT_WIDGET_LAYERS) {
     // This layer tree will be reused, so we'll need to calculate it
     // for the whole "visible" area of the window
     // 
     // |ignoreViewportScrolling| and |usingDisplayPort| are persistent
     // document-rendering state.  We rely on PresShell to flush
     // retained layers as needed when that persistent state changes.
-    if (!usingDisplayPort) {
+    if (!presShell->UsingDisplayPort()) {
       visibleRegion = aFrame->GetVisualOverflowRectRelativeToSelf();
     } else {
-      visibleRegion = displayport;
+      visibleRegion = presShell->GetDisplayPort();
     }
   } else {
     visibleRegion = aDirtyRegion;
   }
 
   // If we're going to display something different from what we'd normally
   // paint in a window then we will flush out any retained layer trees before
   // *and after* we draw.
--- a/layout/base/nsLayoutUtils.h
+++ b/layout/base/nsLayoutUtils.h
@@ -90,21 +90,16 @@ public:
   static ViewID FindIDFor(nsIContent* aContent);
 
   /**
    * Find content for given ID.
    */
   static nsIContent* FindContentFor(ViewID aId);
 
   /**
-   * Get display port for the given element.
-   */
-  static bool GetDisplayPort(nsIContent* aContent, nsRect *aResult);
-
-  /**
    * Use heuristics to figure out the name of the child list that
    * aChildFrame is currently in.
    */
   static nsIAtom* GetChildListNameFor(nsIFrame* aChildFrame);
 
   /**
    * GetBeforeFrame returns the outermost :before frame of the given frame, if
    * one exists.  This is typically O(1).  The frame passed in must be
--- a/layout/base/nsPresShell.cpp
+++ b/layout/base/nsPresShell.cpp
@@ -1032,33 +1032,36 @@ protected:
                                PRUint32    aFlags);
 
   friend struct AutoRenderingStateSaveRestore;
   friend struct RenderingState;
 
   struct RenderingState {
     RenderingState(PresShell* aPresShell) 
       : mRenderFlags(aPresShell->mRenderFlags)
+      , mDisplayPort(aPresShell->mDisplayPort)
       , mXResolution(aPresShell->mXResolution)
       , mYResolution(aPresShell->mYResolution)
     { }
     PRUint32 mRenderFlags;
+    nsRect mDisplayPort;
     float mXResolution;
     float mYResolution;
   };
 
   struct AutoSaveRestoreRenderingState {
     AutoSaveRestoreRenderingState(PresShell* aPresShell)
       : mPresShell(aPresShell)
       , mOldState(aPresShell)
     {}
 
     ~AutoSaveRestoreRenderingState()
     {
       mPresShell->mRenderFlags = mOldState.mRenderFlags;
+      mPresShell->mDisplayPort = mOldState.mDisplayPort;
       mPresShell->mXResolution = mOldState.mXResolution;
       mPresShell->mYResolution = mOldState.mYResolution;
     }
 
     PresShell* mPresShell;
     RenderingState mOldState;
   };
 
@@ -6009,17 +6012,24 @@ void PresShell::SetIgnoreViewportScrolli
   RenderingState state(this);
   state.mRenderFlags = ChangeFlag(state.mRenderFlags, aIgnore,
                                   STATE_IGNORING_VIEWPORT_SCROLLING);
   SetRenderingState(state);
 }
 
 void PresShell::SetDisplayPort(const nsRect& aDisplayPort)
 {
-  NS_ABORT_IF_FALSE(false, "SetDisplayPort is deprecated");
+  if (UsingDisplayPort() && mDisplayPort == aDisplayPort) {
+    return;
+  }
+  RenderingState state(this);
+  state.mRenderFlags = ChangeFlag(mRenderFlags, PR_TRUE,
+                                  STATE_USING_DISPLAYPORT);
+  state.mDisplayPort = aDisplayPort;
+  SetRenderingState(state);
 }
 
 nsresult PresShell::SetResolution(float aXResolution, float aYResolution)
 {
   if (!(aXResolution > 0.0 && aXResolution > 0.0)) {
     return NS_ERROR_ILLEGAL_VALUE;
   }
   if (aXResolution == mXResolution && aYResolution == mYResolution) {
@@ -6039,18 +6049,47 @@ void PresShell::SetRenderingState(const 
     // retained layers we might already have.
     LayerManager* manager = GetLayerManager();
     if (manager) {
       FrameLayerBuilder::InvalidateAllLayers(manager);
     }
   }
 
   mRenderFlags = aState.mRenderFlags;
+  if (UsingDisplayPort()) {
+    mDisplayPort = aState.mDisplayPort;
+  } else {
+    mDisplayPort = nsRect();
+  }
   mXResolution = aState.mXResolution;
   mYResolution = aState.mYResolution;
+
+  // FIXME (Bug 593243 should fix this.)
+  //
+  // Invalidated content does not pay any attention to the displayport, so
+  // invalidating the subdocument's root frame could end up not repainting
+  // visible content.
+  //
+  // For instance, imagine the iframe is located at y=1000. Even though the
+  // displayport may intersect the iframe's viewport, the visual overflow
+  // rect of the root content could be (0, 0, 800, 500). Since the dirty region
+  // does not intersect the visible overflow rect, the display list for the
+  // iframe will not even be generated.
+  //
+  // Here, we find the very top presShell and use its root frame for
+  // invalidation instead.
+  //
+  nsPresContext* rootPresContext = mPresContext->GetRootPresContext();
+  if (rootPresContext) {
+    nsIPresShell* rootPresShell = rootPresContext->GetPresShell();
+    nsIFrame* rootFrame = rootPresShell->FrameManager()->GetRootFrame();
+    if (rootFrame) {
+      rootFrame->InvalidateFrameSubtree();
+    }
+  }
 }
 
 void PresShell::SynthesizeMouseMove(PRBool aFromScroll)
 {
   if (mViewManager && !mPaintingSuppressed && mIsActive) {
     mViewManager->SynthesizeMouseMove(aFromScroll);
   }
 }
--- a/layout/generic/nsGfxScrollFrame.cpp
+++ b/layout/generic/nsGfxScrollFrame.cpp
@@ -1858,95 +1858,41 @@ nsGfxScrollFrameInner::BuildDisplayList(
     // Now display the scrollbars and scrollcorner. These parts are drawn
     // in the border-background layer, on top of our own background and
     // borders and underneath borders and backgrounds of later elements
     // in the tree.
     AppendScrollPartsTo(aBuilder, aDirtyRect, aLists,
                         scrollParts, createLayersForScrollbars);
   }
 
-  nsRect displayport;
-  PRBool usingDisplayPort = nsLayoutUtils::GetDisplayPort(mOuter->GetContent(),
-                                                        &displayport);
-  if (!usingDisplayPort) {
-    displayport = mScrollPort;
-  }
+  nsIPresShell* presShell = mOuter->PresContext()->GetPresShell();
+  nsRect scrollPort = (mIsRoot && presShell->UsingDisplayPort()) ?
+                      (presShell->GetDisplayPort()) : mScrollPort;
 
   // Overflow clipping can never clip frames outside our subtree, so there
   // is no need to worry about whether we are a moving frame that might clip
   // non-moving frames.
   nsRect dirtyRect;
   // Not all our descendants will be clipped by overflow clipping, but all
   // the ones that aren't clipped will be out of flow frames that have already
   // had dirty rects saved for them by their parent frames calling
   // MarkOutOfFlowChildrenForDisplayList, so it's safe to restrict our
   // dirty rect here.
-  dirtyRect.IntersectRect(aDirtyRect, mScrollPort);
-
-  if (usingDisplayPort) {
-    dirtyRect = displayport;
-  }
+  dirtyRect.IntersectRect(aDirtyRect, scrollPort);
 
   nsDisplayListCollection set;
-
-  nsPresContext* presContext = mOuter->PresContext();
-  PRInt32 appUnitsPerDevPixel = presContext->AppUnitsPerDevPixel();
-
-#ifdef MOZ_IPC
-  // Since making new layers is expensive, only use nsDisplayScrollLayer
-  // if the area is scrollable.
-  //
-  // Scroll frames can be generated with a scroll range that is 0, 0.
-  // Furthermore, it is not worth the memory tradeoff to allow asynchronous
-  // scrolling of small scroll frames. We use an arbitrary minimum scroll
-  // range of 20 pixels to eliminate many gfx scroll frames from becoming a
-  // layer.
-  //
-  nsRect scrollRange = GetScrollRange();
-  PRBool buildingLayer =
-     (XRE_GetProcessType() == GeckoProcessType_Content &&
-     (scrollRange.width >= NSIntPixelsToAppUnits(20, appUnitsPerDevPixel) ||
-     scrollRange.height >= NSIntPixelsToAppUnits(20, appUnitsPerDevPixel))) &&
-     (!mIsRoot || !mOuter->PresContext()->IsRootContentDocument());
-
-#else
-  PRBool buildingLayer = false;
-#endif
-
-  if (buildingLayer) {
-    // Note that using StackingContext breaks z order, so the resulting
-    // rendering can be incorrect for weird edge cases!
-
-    rv = mScrolledFrame->BuildDisplayListForStackingContext(
-      aBuilder,
-      dirtyRect + mOuter->GetOffsetTo(mScrolledFrame),
-      set.Content()
-    );
-
-    nsDisplayScrollLayer* layerItem = new (aBuilder) nsDisplayScrollLayer(
-      aBuilder,
-      set.Content(),
-      mScrolledFrame,
-      mOuter,
-      displayport
-    );
-    set.Content()->AppendNewToTop(layerItem);
-  } else {
-    rv = mOuter->BuildDisplayListForChild(aBuilder, mScrolledFrame, dirtyRect, set);
-  }
-
+  rv = mOuter->BuildDisplayListForChild(aBuilder, mScrolledFrame, dirtyRect, set);
   NS_ENSURE_SUCCESS(rv, rv);
   nsRect clip;
-  clip = mScrollPort + aBuilder->ToReferenceFrame(mOuter);
+  clip = scrollPort + aBuilder->ToReferenceFrame(mOuter);
 
   nscoord radii[8];
   // Our override of GetBorderRadii ensures we never have a radius at
   // the corners where we have a scrollbar.
   mOuter->GetPaddingBoxBorderRadii(radii);
-
   // mScrolledFrame may have given us a background, e.g., the scrolled canvas
   // frame below the viewport. If so, we want it to be clipped. We also want
   // to end up on our BorderBackground list.
   // If we are the viewport scrollframe, then clip all our descendants (to ensure
   // that fixed-pos elements get clipped by us).
   rv = mOuter->OverflowClip(aBuilder, set, aLists, clip, radii,
                             PR_TRUE, mIsRoot);
   NS_ENSURE_SUCCESS(rv, rv);
--- a/layout/generic/nsSubDocumentFrame.cpp
+++ b/layout/generic/nsSubDocumentFrame.cpp
@@ -335,22 +335,42 @@ nsSubDocumentFrame::BuildDisplayList(nsD
 
   nsPresContext* presContext = presShell->GetPresContext();
 
   nsDisplayList childItems;
 
   PRInt32 parentAPD = PresContext()->AppUnitsPerDevPixel();
   PRInt32 subdocAPD = presContext->AppUnitsPerDevPixel();
 
+  nsIFrame* subdocRootScrollFrame = presShell->GetRootScrollFrame();
+
   nsRect dirty;
   if (subdocRootFrame) {
-    // get the dirty rect relative to the root frame of the subdoc
-    dirty = aDirtyRect + GetOffsetToCrossDoc(subdocRootFrame);
-    // and convert into the appunits of the subdoc
-    dirty = dirty.ConvertAppUnitsRoundOut(parentAPD, subdocAPD);
+    if (presShell->UsingDisplayPort() && subdocRootScrollFrame) {
+      dirty = presShell->GetDisplayPort();
+
+      // The visual overflow rect of our viewport frame unfortunately may not
+      // intersect with the displayport of that frame. For example, the scroll
+      // offset of the frame may be (0, 0) so that the visual overflow rect
+      // is (0, 0, 800px, 500px) while the display port may have its top-left
+      // corner below y=500px.
+      //
+      // We have to force the frame to have a little faith and build a display
+      // list anyway. (see nsIFrame::BuildDisplayListForChild for the short-
+      // circuit code we are evading here).
+      //
+      subdocRootScrollFrame->AddStateBits(
+        NS_FRAME_FORCE_DISPLAY_LIST_DESCEND_INTO);
+
+    } else {
+      // get the dirty rect relative to the root frame of the subdoc
+      dirty = aDirtyRect + GetOffsetToCrossDoc(subdocRootFrame);
+      // and convert into the appunits of the subdoc
+      dirty = dirty.ConvertAppUnitsRoundOut(parentAPD, subdocAPD);
+    }
 
     aBuilder->EnterPresShell(subdocRootFrame, dirty);
   }
 
   // The subdocView's bounds are in appunits of the subdocument, so adjust
   // them.
   nsRect subdocBoundsInParentUnits =
     subdocView->GetBounds().ConvertAppUnitsRoundOut(subdocAPD, parentAPD);
@@ -400,16 +420,42 @@ nsSubDocumentFrame::BuildDisplayList(nsD
              bounds, NS_RGBA(0,0,0,0), flags);
     }
   }
 
   if (NS_SUCCEEDED(rv)) {
 
     bool addedLayer = false;
 
+#ifdef MOZ_IPC
+    // Make a scrollable layer in the child process so it can be manipulated
+    // with transforms in the parent process.
+    if (XRE_GetProcessType() == GeckoProcessType_Content) {
+      nsIScrollableFrame* scrollFrame = presShell->GetRootScrollFrameAsScrollable();
+
+      if (scrollFrame) {
+        NS_ASSERTION(subdocRootFrame, "Root scroll frame should be non-null");
+        nsRect scrollRange = scrollFrame->GetScrollRange();
+        
+        // Since making new layers is expensive, only use nsDisplayScrollLayer
+        // if the area is scrollable.
+        if (scrollRange.width != 0 || scrollRange.height != 0) {
+          addedLayer = true;
+          nsDisplayScrollLayer* layerItem = new (aBuilder) nsDisplayScrollLayer(
+            aBuilder,
+            &childItems,
+            subdocRootScrollFrame,
+            subdocRootFrame
+          );
+          childItems.AppendToTop(layerItem);
+        }
+      }
+    }
+#endif
+
     if (subdocRootFrame && parentAPD != subdocAPD) {
       NS_WARN_IF_FALSE(!addedLayer,
                        "Two container layers have been added. "
                        "Performance may suffer.");
       addedLayer = true;
 
       nsDisplayZoom* zoomItem =
         new (aBuilder) nsDisplayZoom(aBuilder, subdocRootFrame, &childItems,