Backout 61fd66629c4f, 7c8121f8d3af & 2a2e9cf8fd41 (bug 539356), e31a5e6545d3 (bug 761884), 85fa80bd9792, a284ccb25b83, 2865904db9fc, 34e07b09c426, e9b3d41e0360, cef00ebcd6c8, f943b729ac14 & 783f298401b6 (bug 539356), 330a086f1570 (bug 741682), d80219c8842c (bug 739671), e8c96b4fd4da, 313af486e68d, 0adc41ff56dc, 0cd288a38085, f1d43208825c, 4859876972f3, eec8ef3ebe48, f7f29fcd1845, 6079b229d306, f23c3a7e7ce0, 9824458a41e2 & 6748b5496059 (bug 539356) for mochitest-4 orange & talos regressions on multiple platforms
authorEd Morley <emorley@mozilla.com>
Mon, 11 Jun 2012 10:08:32 +0100
changeset 101196 f08886a8cf22a6ceb6d96b68f8c9aad020a1fd92
parent 101195 a430a3d30163393ed5bdc18ec1a274be1abfc2f5
child 101197 8060c5ce574daf35c2bb77b348d6851e658c9548
push idunknown
push userunknown
push dateunknown
bugs539356, 761884, 741682, 739671
milestone16.0a1
backs out61fd66629c4f21f56d797d4c934a9347129beabc
Backout 61fd66629c4f, 7c8121f8d3af & 2a2e9cf8fd41 (bug 539356), e31a5e6545d3 (bug 761884), 85fa80bd9792, a284ccb25b83, 2865904db9fc, 34e07b09c426, e9b3d41e0360, cef00ebcd6c8, f943b729ac14 & 783f298401b6 (bug 539356), 330a086f1570 (bug 741682), d80219c8842c (bug 739671), e8c96b4fd4da, 313af486e68d, 0adc41ff56dc, 0cd288a38085, f1d43208825c, 4859876972f3, eec8ef3ebe48, f7f29fcd1845, 6079b229d306, f23c3a7e7ce0, 9824458a41e2 & 6748b5496059 (bug 539356) for mochitest-4 orange & talos regressions on multiple platforms
browser/components/tabview/content.js
browser/devtools/layoutview/LayoutView.jsm
content/base/src/nsFrameLoader.cpp
content/base/src/nsObjectLoadingContent.cpp
content/events/src/nsDOMNotifyPaintEvent.cpp
content/events/src/nsPaintRequest.cpp
content/events/test/Makefile.in
content/events/test/bug426082.html
content/events/test/bug656379-1.html
content/events/test/test_bug426082.html
content/events/test/test_bug656379-1.html
content/html/content/src/nsHTMLCanvasElement.cpp
content/media/VideoFrameContainer.cpp
dom/base/nsDOMWindowUtils.cpp
dom/plugins/base/nsPluginInstanceOwner.cpp
dom/plugins/test/mochitest/test_painting.html
editor/libeditor/html/crashtests/crashtests.list
editor/reftests/reftest.list
editor/reftests/spellcheck-textarea-focused-notreadonly.html
editor/reftests/spellcheck-textarea-ref2.html
gfx/2d/UserData.h
gfx/layers/ImageLayers.h
gfx/layers/LayerTreeInvalidation.cpp
gfx/layers/LayerTreeInvalidation.h
gfx/layers/Layers.h
gfx/layers/Makefile.in
gfx/layers/basic/BasicImplData.h
gfx/layers/basic/BasicLayers.cpp
gfx/layers/basic/BasicLayers.h
gfx/layers/basic/BasicTiledThebesLayer.h
gfx/layers/d3d10/LayerManagerD3D10.cpp
gfx/layers/d3d10/LayerManagerD3D10.h
gfx/layers/d3d10/ThebesLayerD3D10.cpp
gfx/layers/d3d9/CanvasLayerD3D9.cpp
gfx/layers/d3d9/ColorLayerD3D9.cpp
gfx/layers/d3d9/ContainerLayerD3D9.cpp
gfx/layers/d3d9/ImageLayerD3D9.cpp
gfx/layers/d3d9/LayerManagerD3D9.cpp
gfx/layers/d3d9/LayerManagerD3D9.h
gfx/layers/d3d9/ThebesLayerD3D9.cpp
gfx/layers/opengl/CanvasLayerOGL.cpp
gfx/layers/opengl/ColorLayerOGL.cpp
gfx/layers/opengl/ContainerLayerOGL.cpp
gfx/layers/opengl/ImageLayerOGL.cpp
gfx/layers/opengl/LayerManagerOGL.cpp
gfx/layers/opengl/LayerManagerOGL.h
gfx/layers/opengl/ThebesLayerOGL.cpp
gfx/thebes/gfx3DMatrix.cpp
gfx/thebes/gfx3DMatrix.h
gfx/thebes/gfxASurface.cpp
image/test/mochitest/test_animSVGImage.html
layout/base/FrameLayerBuilder.cpp
layout/base/FrameLayerBuilder.h
layout/base/Makefile.in
layout/base/nsCSSFrameConstructor.cpp
layout/base/nsCaret.cpp
layout/base/nsCaret.h
layout/base/nsDisplayList.cpp
layout/base/nsDisplayList.h
layout/base/nsDisplayListInvalidation.h
layout/base/nsDocumentViewer.cpp
layout/base/nsFrameManager.cpp
layout/base/nsFrameManager.h
layout/base/nsIPresShell.h
layout/base/nsImageLoader.cpp
layout/base/nsLayoutDebugger.cpp
layout/base/nsLayoutUtils.cpp
layout/base/nsLayoutUtils.h
layout/base/nsPresContext.cpp
layout/base/nsPresContext.h
layout/base/nsPresShell.cpp
layout/base/nsPresShell.h
layout/base/nsRefreshDriver.cpp
layout/base/nsRefreshDriver.h
layout/base/tests/Makefile.in
layout/base/tests/bug450930.xhtml
layout/base/tests/chrome/Makefile.in
layout/base/tests/chrome/test_transformed_scrolling_repaints.html
layout/base/tests/chrome/test_transformed_scrolling_repaints_2.html
layout/base/tests/test_after_paint_pref.html
layout/base/tests/test_bug450930.xhtml
layout/forms/nsButtonFrameRenderer.cpp
layout/forms/nsComboboxControlFrame.cpp
layout/forms/nsFieldSetFrame.cpp
layout/forms/nsListControlFrame.cpp
layout/forms/nsListControlFrame.h
layout/forms/nsMeterFrame.cpp
layout/forms/nsProgressFrame.cpp
layout/generic/crashtests/crashtests.list
layout/generic/nsAbsoluteContainingBlock.cpp
layout/generic/nsBlockFrame.cpp
layout/generic/nsBlockFrame.h
layout/generic/nsBlockReflowState.cpp
layout/generic/nsBulletFrame.cpp
layout/generic/nsCanvasFrame.cpp
layout/generic/nsCanvasFrame.h
layout/generic/nsColumnSetFrame.cpp
layout/generic/nsContainerFrame.cpp
layout/generic/nsFrame.cpp
layout/generic/nsFrame.h
layout/generic/nsGfxScrollFrame.cpp
layout/generic/nsGfxScrollFrame.h
layout/generic/nsHTMLCanvasFrame.cpp
layout/generic/nsIFrame.h
layout/generic/nsImageFrame.cpp
layout/generic/nsImageMap.cpp
layout/generic/nsObjectFrame.cpp
layout/generic/nsPlaceholderFrame.cpp
layout/generic/nsSubDocumentFrame.cpp
layout/generic/nsTextFrame.h
layout/generic/nsTextFrameThebes.cpp
layout/generic/nsVideoFrame.cpp
layout/generic/nsViewportFrame.cpp
layout/generic/nsViewportFrame.h
layout/inspector/src/inFlasher.cpp
layout/ipc/RenderFrameParent.cpp
layout/ipc/RenderFrameParent.h
layout/mathml/nsMathMLChar.cpp
layout/reftests/bidi/reftest.list
layout/reftests/bugs/reftest.list
layout/reftests/font-inflation/reftest.list
layout/reftests/forms/placeholder/reftest.list
layout/reftests/layers/reftest.list
layout/reftests/reftest-sanity/invalidation.html
layout/reftests/scrolling/fixed-text-1.html
layout/reftests/svg/reftest.list
layout/reftests/svg/smil/sort/reftest.list
layout/reftests/svg/smil/transform/reftest.list
layout/reftests/text/reftest.list
layout/svg/base/src/nsSVGEffects.cpp
layout/svg/base/src/nsSVGForeignObjectFrame.cpp
layout/svg/base/src/nsSVGForeignObjectFrame.h
layout/svg/base/src/nsSVGIntegrationUtils.cpp
layout/svg/base/src/nsSVGIntegrationUtils.h
layout/svg/base/src/nsSVGOuterSVGFrame.cpp
layout/svg/base/src/nsSVGOuterSVGFrame.h
layout/svg/base/src/nsSVGUtils.cpp
layout/tables/nsTableCellFrame.cpp
layout/tables/nsTableCellFrame.h
layout/tables/nsTableColFrame.cpp
layout/tables/nsTableColFrame.h
layout/tables/nsTableColGroupFrame.cpp
layout/tables/nsTableColGroupFrame.h
layout/tables/nsTableFrame.cpp
layout/tables/nsTableFrame.h
layout/tables/nsTableOuterFrame.cpp
layout/tables/nsTableRowFrame.cpp
layout/tables/nsTableRowFrame.h
layout/tables/nsTableRowGroupFrame.cpp
layout/tables/nsTableRowGroupFrame.h
layout/tables/test/Makefile.in
layout/tables/test/invalidation.html
layout/tables/test/test_invalidation.html
layout/tools/reftest/reftest-content.js
layout/tools/reftest/reftest.js
layout/xul/base/src/nsBox.cpp
layout/xul/base/src/nsDeckFrame.cpp
layout/xul/base/src/nsImageBoxFrame.cpp
layout/xul/base/src/nsListBoxLayout.cpp
layout/xul/base/src/nsMenuPopupFrame.cpp
layout/xul/base/src/nsMenuPopupFrame.h
layout/xul/base/src/nsSliderFrame.cpp
layout/xul/base/src/nsStackLayout.cpp
layout/xul/base/src/tree/src/nsTreeBodyFrame.cpp
modules/libpref/src/init/all.js
toolkit/content/tests/chrome/window_panel.xul
view/public/nsIViewManager.h
view/src/Makefile.in
view/src/nsView.cpp
view/src/nsView.h
view/src/nsViewManager.cpp
view/src/nsViewManager.h
widget/android/nsLookAndFeel.cpp
widget/android/nsWindow.cpp
widget/android/nsWindow.h
widget/cocoa/nsChildView.mm
widget/gtk2/nsNativeThemeGTK.cpp
widget/nsIWidget.h
widget/xpwidgets/nsNativeTheme.cpp
--- a/browser/components/tabview/content.js
+++ b/browser/components/tabview/content.js
@@ -36,19 +36,17 @@ let WindowEventHandler = {
     sendSyncMessage("Panorama:DOMWillOpenModalDialog");
   },
 
   // ----------
   // Function: onMozAfterPaint
   // Sends an asynchronous message when the "onMozAfterPaint" event
   // is fired.
   onMozAfterPaint: function WEH_onMozAfterPaint(event) {
-    if (event.clientRects.length > 0) {
-      sendAsyncMessage("Panorama:MozAfterPaint");
-    }
+    sendAsyncMessage("Panorama:MozAfterPaint");
   }
 };
 
 // add event listeners
 addEventListener("DOMWillOpenModalDialog", WindowEventHandler.onDOMWillOpenModalDialog, false);
 addEventListener("MozAfterPaint", WindowEventHandler.onMozAfterPaint, false);
 
 // ----------
--- a/browser/devtools/layoutview/LayoutView.jsm
+++ b/browser/devtools/layoutview/LayoutView.jsm
@@ -289,19 +289,17 @@ LayoutView.prototype = {
     if (!node || !this.documentReady) return;
 
     // First, we update the first part of the layout view, with
     // the size of the element.
 
     let clientRect = node.getBoundingClientRect();
     let width = Math.round(clientRect.width);
     let height = Math.round(clientRect.height);
-    if (this.doc.querySelector("#element-size").textContent !=  width + "x" + height) {
-      this.doc.querySelector("#element-size").textContent =  width + "x" + height;
-    }
+    this.doc.querySelector("#element-size").textContent =  width + "x" + height;
 
     // If the view is closed, no need to do anything more.
     if (!this.isOpen) return;
 
     // We compute and update the values of margins & co.
     let style = this.browser.contentWindow.getComputedStyle(node);;
 
     for (let i in this.map) {
--- a/content/base/src/nsFrameLoader.cpp
+++ b/content/base/src/nsFrameLoader.cpp
@@ -102,16 +102,24 @@ public:
     if (base_win) {
       base_win->Destroy();
     }
     return NS_OK;
   }
   nsRefPtr<nsIDocShell> mDocShell;
 };
 
+static void InvalidateFrame(nsIFrame* aFrame, PRUint32 aFlags)
+{
+  if (!aFrame)
+    return;
+  nsRect rect = nsRect(nsPoint(0, 0), aFrame->GetRect().Size());
+  aFrame->InvalidateWithFlags(rect, aFlags);
+}
+
 NS_IMPL_ISUPPORTS1(nsContentView, nsIContentView)
 
 bool
 nsContentView::IsRoot() const
 {
   return mScrollId == FrameMetrics::ROOT_SCROLL_ID;
 }
 
@@ -136,16 +144,23 @@ nsContentView::Update(const ViewConfig& 
       return NS_ERROR_NOT_AVAILABLE;
     }
   }
 
   if (RenderFrameParent* rfp = mFrameLoader->GetCurrentRemoteFrame()) {
     rfp->ContentViewScaleChanged(this);
   }
 
+  // XXX could be clever here and compute a smaller invalidation
+  // rect
+  // NB: we pass INVALIDATE_NO_THEBES_LAYERS here to keep view
+  // semantics the same for both in-process and out-of-process
+  // <browser>.  This is just a transform of the layer subtree in
+  // both.
+  InvalidateFrame(mFrameLoader->GetPrimaryFrameOfOwningContent(), nsIFrame::INVALIDATE_NO_THEBES_LAYERS);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsContentView::ScrollTo(float aXpx, float aYpx)
 {
   ViewConfig config(mConfig);
   config.mScrollOffset = nsPoint(nsPresContext::CSSPixelsToAppUnits(aXpx),
@@ -1703,16 +1718,21 @@ nsFrameLoader::GetRenderMode(PRUint32* a
 NS_IMETHODIMP
 nsFrameLoader::SetRenderMode(PRUint32 aRenderMode)
 {
   if (aRenderMode == mRenderMode) {
     return NS_OK;
   }
 
   mRenderMode = aRenderMode;
+  // NB: we pass INVALIDATE_NO_THEBES_LAYERS here to keep view
+  // semantics the same for both in-process and out-of-process
+  // <browser>.  This is just a transform of the layer subtree in
+  // both.
+  InvalidateFrame(GetPrimaryFrameOfOwningContent(), nsIFrame::INVALIDATE_NO_THEBES_LAYERS);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsFrameLoader::GetEventMode(PRUint32* aEventMode)
 {
   *aEventMode = mEventMode;
   return NS_OK;
@@ -1733,17 +1753,17 @@ nsFrameLoader::GetClipSubdocument(bool* 
 }
 
 NS_IMETHODIMP
 nsFrameLoader::SetClipSubdocument(bool aClip)
 {
   mClipSubdocument = aClip;
   nsIFrame* frame = GetPrimaryFrameOfOwningContent();
   if (frame) {
-    frame->InvalidateFrame();
+    InvalidateFrame(frame, 0);
     frame->PresContext()->PresShell()->
       FrameNeedsReflow(frame, nsIPresShell::eResize, NS_FRAME_IS_DIRTY);
     nsSubDocumentFrame* subdocFrame = do_QueryFrame(frame);
     if (subdocFrame) {
       nsIFrame* subdocRootFrame = subdocFrame->GetSubdocumentRootFrame();
       if (subdocRootFrame) {
         nsIFrame* subdocRootScrollFrame = subdocRootFrame->PresContext()->PresShell()->
           GetRootScrollFrame();
--- a/content/base/src/nsObjectLoadingContent.cpp
+++ b/content/base/src/nsObjectLoadingContent.cpp
@@ -500,18 +500,18 @@ nsresult nsObjectLoadingContent::IsPlugi
     rv = topWindow->GetDocument(getter_AddRefs(topDocument));
     NS_ENSURE_SUCCESS(rv, rv);
     nsCOMPtr<nsIDocument> topDoc = do_QueryInterface(topDocument);
     nsIURI* topUri = topDoc->GetDocumentURI();
 
     nsCOMPtr<nsIPermissionManager> permissionManager = do_GetService(NS_PERMISSIONMANAGER_CONTRACTID, &rv);
     NS_ENSURE_SUCCESS(rv, rv);
     PRUint32 permission;
-    rv = permissionManager->TestPermission(topUri,
-                                           "plugins",
+    rv = permissionManager->TestPermission(topUri,
+                                           "plugins",
                                            &permission);
     NS_ENSURE_SUCCESS(rv, rv);
     if (permission == nsIPermissionManager::ALLOW_ACTION) {
       mShouldPlay = true;
     } else {
       return NS_ERROR_PLUGIN_CLICKTOPLAY;
     }
   }
@@ -1095,17 +1095,17 @@ nsObjectLoadingContent::HasNewFrame(nsIO
   DisconnectFrame();
 
   // Set up relationship between instance owner and frame.
   nsObjectFrame *objFrame = static_cast<nsObjectFrame*>(aFrame);
   mInstanceOwner->SetFrame(objFrame);
 
   // Set up new frame to draw.
   objFrame->FixupWindow(objFrame->GetContentRectRelativeToSelf().Size());
-  objFrame->InvalidateFrame();
+  objFrame->Invalidate(objFrame->GetContentRectRelativeToSelf());
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsObjectLoadingContent::DisconnectFrame()
 {
   if (mInstanceOwner) {
--- a/content/events/src/nsDOMNotifyPaintEvent.cpp
+++ b/content/events/src/nsDOMNotifyPaintEvent.cpp
@@ -34,20 +34,22 @@ NS_INTERFACE_MAP_END_INHERITING(nsDOMEve
 
 NS_IMPL_ADDREF_INHERITED(nsDOMNotifyPaintEvent, nsDOMEvent)
 NS_IMPL_RELEASE_INHERITED(nsDOMNotifyPaintEvent, nsDOMEvent)
 
 nsRegion
 nsDOMNotifyPaintEvent::GetRegion()
 {
   nsRegion r;
-  if (!nsContentUtils::IsCallerTrustedForRead()) {
-    return r;
-  }
+  bool isTrusted = nsContentUtils::IsCallerTrustedForRead();
   for (PRUint32 i = 0; i < mInvalidateRequests.Length(); ++i) {
+    if (!isTrusted &&
+        (mInvalidateRequests[i].mFlags & nsIFrame::INVALIDATE_CROSS_DOC))
+      continue;
+
     r.Or(r, mInvalidateRequests[i].mRect);
     r.SimplifyOutward(10);
   }
   return r;
 }
 
 NS_IMETHODIMP
 nsDOMNotifyPaintEvent::GetBoundingClientRect(nsIDOMClientRect** aResult)
@@ -91,25 +93,27 @@ nsDOMNotifyPaintEvent::GetClientRects(ns
 NS_IMETHODIMP
 nsDOMNotifyPaintEvent::GetPaintRequests(nsIDOMPaintRequestList** aResult)
 {
   nsRefPtr<nsPaintRequestList> requests =
     new nsPaintRequestList(static_cast<nsDOMEvent*>(this));
   if (!requests)
     return NS_ERROR_OUT_OF_MEMORY;
 
-  if (nsContentUtils::IsCallerTrustedForRead()) {
-    for (PRUint32 i = 0; i < mInvalidateRequests.Length(); ++i) {
-      nsRefPtr<nsPaintRequest> r = new nsPaintRequest();
-      if (!r)
-        return NS_ERROR_OUT_OF_MEMORY;
- 
-      r->SetRequest(mInvalidateRequests[i]);
-      requests->Append(r);
-    }
+  bool isTrusted = nsContentUtils::IsCallerTrustedForRead();
+  for (PRUint32 i = 0; i < mInvalidateRequests.Length(); ++i) {
+    if (!isTrusted &&
+        (mInvalidateRequests[i].mFlags & nsIFrame::INVALIDATE_CROSS_DOC))
+      continue;
+
+    nsRefPtr<nsPaintRequest> r = new nsPaintRequest();
+    if (!r)
+      return NS_ERROR_OUT_OF_MEMORY;
+    r->SetRequest(mInvalidateRequests[i]);
+    requests->Append(r);
   }
 
   requests.forget(aResult);
   return NS_OK;
 }
 
 NS_IMETHODIMP_(void)
 nsDOMNotifyPaintEvent::Serialize(IPC::Message* aMsg,
--- a/content/events/src/nsPaintRequest.cpp
+++ b/content/events/src/nsPaintRequest.cpp
@@ -30,17 +30,27 @@ nsPaintRequest::GetClientRect(nsIDOMClie
   clientRect->SetLayoutRect(mRequest.mRect);
   clientRect.forget(aResult);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsPaintRequest::GetReason(nsAString& aResult)
 {
-  aResult.AssignLiteral("repaint");
+  switch (mRequest.mFlags & nsIFrame::INVALIDATE_REASON_MASK) {
+  case nsIFrame::INVALIDATE_REASON_SCROLL_BLIT:
+    aResult.AssignLiteral("scroll copy");
+    break;
+  case nsIFrame::INVALIDATE_REASON_SCROLL_REPAINT:
+    aResult.AssignLiteral("scroll repaint");
+    break;
+  default:
+    aResult.Truncate();
+    break;
+  }
   return NS_OK;
 }
 
 DOMCI_DATA(PaintRequestList, nsPaintRequestList)
 
 NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_1(nsPaintRequestList, mParent)
 
 NS_INTERFACE_TABLE_HEAD(nsPaintRequestList)
--- a/content/events/test/Makefile.in
+++ b/content/events/test/Makefile.in
@@ -31,17 +31,16 @@ include $(topsrcdir)/config/rules.mk
 		test_bug368835.html \
 		test_bug379120.html \
 		test_bug391568.xhtml \
 		test_bug402089.html \
 		test_bug405632.html \
 		test_bug409604.html \
 		test_bug412567.html \
 		test_bug426082.html \
-		bug426082.html \
 		test_bug427537.html \
 		test_bug432698.html \
 		test_bug443985.html \
 		test_bug447736.html \
 		test_bug448602.html \
 		test_bug450876.html \
 		test_bug456273.html \
 		test_bug457672.html \
@@ -66,17 +65,16 @@ include $(topsrcdir)/config/rules.mk
 		test_bug613634.html \
 		test_bug607464.html \
 		test_bug624127.html \
 		test_bug650493.html \
 		test_bug641477.html \
 		test_bug648573.html \
 		test_bug615597.html \
 		test_bug656379-1.html \
-		bug656379-1.html \
 		test_bug656379-2.html \
 		test_bug656954.html \
 		test_bug659350.html \
 		test_bug662678.html \
 		test_bug667919-1.html \
 		test_bug667919-2.html \
 		test_bug667612.html \
 		empty.js \
deleted file mode 100644
--- a/content/events/test/bug426082.html
+++ /dev/null
@@ -1,182 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=426082
--->
-<head>
-  <title>Test for Bug 426082</title>
-  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
-  <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
-  <script type="application/javascript" src="/tests/SimpleTest/WindowSnapshot.js"></script>
-  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
-  <style>
-    canvas {
-      display: none;
-    }
-  </style>
-</head>
-<body onload="runTests()">
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=426082">Mozilla Bug 426082</a>
-<p id="display"></p>
-<div id="content" style="display: none">
-  
-</div>
-<p><input type="button" value="Button" id="button"></p>
-<p><label for="button" id="label">Label</label></p>
-<p id="outside">Something under the label</p>
-<pre id="test">
-<script type="application/javascript;version=1.8">
-
-/** Test for Bug 426082 **/
-
-var normalButtonCanvas, pressedButtonCanvas, normalFocusedButtonCanvas,
-    pressedFocusedButtonCanvas, currentSnapshot, button, label, outside;
-
-function runTests() {
-  normalButtonCanvas = document.getElementById("normalButtonCanvas");
-  pressedButtonCanvas = document.getElementById("pressedButtonCanvas");
-  normalFocusedButtonCanvas = document.getElementById("normalFocusedButtonCanvas");
-  pressedFocusedButtonCanvas = document.getElementById("pressedFocusedButtonCanvas");
-  currentSnapshot = document.getElementById("currentSnapshot");
-  button = document.getElementById("button");
-  label = document.getElementById("label");
-  outside = document.getElementById("outside");
-  SimpleTest.executeSoon(executeTests);
-}
-
-function isRectContainedInRectFromRegion(rect, region) {
-  console.log("Button rect: " + rect.left + " " + rect.top + " " + rect.right + " " + rect.bottom);
-  return Array.some(region, function (r) {
-    console.log("Region rect: " + r.left + " " + r.top + " " + r.right + " " + r.bottom);
-    return rect.left >= r.left &&
-           rect.top >= r.top &&
-           rect.right <= r.right &&
-           rect.bottom <= r.bottom;
-  });
-}
-
-function paintListener(e) {
-  netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
-  console.log("paint");
-  if (isRectContainedInRectFromRegion(buttonRect(), e.clientRects)) {
-    console.log("painted");
-    gNeedsPaint = false;
-    takeSnapshot(currentSnapshot);
-  }
-}
-
-var gNeedsPaint = false;
-function executeTests() {
-  var testYielder = tests();
-  function execNext() {
-    try {
-      console.log("check painted");
-      if (!gNeedsPaint) {
-        testYielder.next();
-        button.getBoundingClientRect(); // Flush.
-        gNeedsPaint = true;
-      }
-      SimpleTest.executeSoon(execNext);
-    } catch (e) {}
-  }
-  execNext();
-}
-
-function tests() {
-  window.addEventListener("MozAfterPaint", paintListener, false);
-  takeSnapshot(normalButtonCanvas);
-  // Press the button.
-  sendMouseEvent("mousemove", button);
-  sendMouseEvent("mousedown", button);
-  yield;
-  takeSnapshot(pressedFocusedButtonCanvas);
-  compareSnapshots_(normalButtonCanvas, pressedFocusedButtonCanvas, false, "Pressed focused buttons should look different from normal buttons.");
-  // Release.
-  sendMouseEvent("mouseup", button);
-  yield;
-  // make sure the button is focused as this doesn't happen on click on Mac
-  button.focus();
-  takeSnapshot(normalFocusedButtonCanvas);
-  compareSnapshots_(normalFocusedButtonCanvas, pressedFocusedButtonCanvas, false, "Pressed focused buttons should look different from normal focused buttons.");
-  // Unfocus the button.
-  sendMouseEvent("mousedown", outside);
-  sendMouseEvent("mouseup", outside);
-  yield;
-
-  // Press the label.
-  sendMouseEvent("mousemove", label);
-  sendMouseEvent("mousedown", label);
-  yield;
-  compareSnapshots_(normalButtonCanvas, currentSnapshot, false, "Pressing the label should have pressed the button.");
-  takeSnapshot(pressedButtonCanvas);
-  // Move the mouse down from the label.
-  sendMouseEvent("mousemove", outside);
-  yield;
-  compareSnapshots_(normalButtonCanvas, currentSnapshot, true, "Moving the mouse down from the label should have unpressed the button.");
-  // ... and up again.
-  sendMouseEvent("mousemove", label);
-  yield;
-  compareSnapshots_(pressedButtonCanvas, currentSnapshot, true, "Moving the mouse back on top of the label should have pressed the button.");
-  // Release.
-  sendMouseEvent("mouseup", label);
-  yield;
-  compareSnapshots_(normalFocusedButtonCanvas, currentSnapshot, true, "Releasing the mouse over the label should have unpressed (and focused) the button.");
-  // Press the label and remove it.
-  sendMouseEvent("mousemove", label);
-  sendMouseEvent("mousedown", label);
-  yield;
-  label.parentNode.removeChild(label);
-  yield;
-  compareSnapshots_(normalButtonCanvas, currentSnapshot, true, "Removing the label should have unpressed the button.");
-  sendMouseEvent("mouseup", label);
-  window.removeEventListener("MozAfterPaint", paintListener, false);
-  window.opener.finishTests();
-}
-
-function sendMouseEvent(t, elem) {
-  var r = elem.getBoundingClientRect();
-  synthesizeMouse(elem, r.width / 2, r.height / 2, {type: t});
-}
-
-function compareSnapshots_(c1, c2, shouldBeIdentical, msg) {
-  var [correct, c1url, c2url] = compareSnapshots(c1, c2, shouldBeIdentical);
-  if (correct) {
-    if (shouldBeIdentical) {
-      window.opener.ok(true, msg + " - expected " + c1url);
-    } else {
-      window.opener.ok(true, msg + " - got " + c1url + " and " + c2url);
-    }
-  } else {
-    if (shouldBeIdentical) {
-      window.opener.ok(false, msg + " - expected " + c1url + " but got " + c2url);
-    } else {
-      window.opener.ok(false, msg + " - expected something other than " + c1url);
-    }
-  }
-}
-
-function takeSnapshot(canvas) {
-  var r = buttonRect();
-  var ctx = canvas.getContext("2d");
-  netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
-  canvas.width = r.width + 4;
-  canvas.height = r.height + 4;
-  ctx.clearRect(0, 0, canvas.width, canvas.height);
-  ctx.drawWindow(window, r.left - 2, r.top - 2, r.width + 4, r.height + 4, "#FFF");
-}
-
-function buttonRect() {
-  return button.getBoundingClientRect();
-}
-
-
-</script>
-</pre>
-
-<canvas id="normalButtonCanvas"></canvas>
-<canvas id="pressedButtonCanvas"></canvas>
-<canvas id="normalFocusedButtonCanvas"></canvas>
-<canvas id="pressedFocusedButtonCanvas"></canvas>
-<canvas id="currentSnapshot"></canvas>
-</body>
-</html>
deleted file mode 100644
--- a/content/events/test/bug656379-1.html
+++ /dev/null
@@ -1,208 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=656379
--->
-<head>
-  <title>Test for Bug 656379</title>
-  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
-  <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
-  <script type="application/javascript" src="/tests/SimpleTest/WindowSnapshot.js"></script>
-  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
-  <style>
-    canvas {
-      display: none;
-    }
-    input[type=button] {
-      -moz-appearance: none;
-      padding: 0;
-      border: none;
-      color: black;
-      background: white;
-    }
-    input[type=button]::-moz-focus-inner { border: none; }
-
-    /* Make sure that normal, focused, hover+active, focused+hover+active
-       buttons all have different styles so that the test keeps moving along. */
-    input[type=button]:hover:active {
-      background: red;
-    }
-    input[type=button]:focus {
-      background: green;
-    }
-    input[type=button]:focus:hover:active {
-      background: purple;
-    }
-  </style>
-</head>
-<body onload="runTests()">
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=656379">Mozilla Bug 656379</a>
-<p id="display"></p>
-<div id="content" style="display: none">
-  
-</div>
-<pre id="test">
-<script type="application/javascript;version=1.8">
-
-
-var normalButtonCanvas, pressedButtonCanvas, normalFocusedButtonCanvas,
-    pressedFocusedButtonCanvas, currentSnapshot, button, label, outside;
-
-function runTests() {
-  normalButtonCanvas = $("normalButtonCanvas");
-  pressedButtonCanvas = $("pressedButtonCanvas");
-  normalFocusedButtonCanvas = $("normalFocusedButtonCanvas");
-  pressedFocusedButtonCanvas = $("pressedFocusedButtonCanvas");
-  currentSnapshot = $("currentSnapshot");
-  button = $("button");
-  label = $("label");
-  outside = $("outside");
-  SimpleTest.executeSoon(executeTests);
-}
-
-function isRectContainedInRectFromRegion(rect, region) {
-  return Array.some(region, function (r) {
-    return rect.left >= r.left &&
-           rect.top >= r.top &&
-           rect.right <= r.right &&
-           rect.bottom <= r.bottom;
-  });
-}
-
-function paintListener(e) {
-  netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
-  window.opener.ok(true, "Paint");
-  if (isRectContainedInRectFromRegion(buttonRect(), e.clientRects)) {
-    window.opener.ok(true, "Painted button");
-    gNeedsPaint = false;
-    takeSnapshot(currentSnapshot);
-  }
-}
-
-var gNeedsPaint = false;
-function executeTests() {
-  var testYielder = tests();
-  function execNext() {
-    try {
-      if (!gNeedsPaint) {
-        testYielder.next();
-        button.getBoundingClientRect(); // Flush.
-        gNeedsPaint = true;
-      }
-      SimpleTest.executeSoon(execNext);
-    } catch (e) {}
-  }
-  execNext();
-}
-
-function tests() {
-  window.addEventListener("MozAfterPaint", paintListener, false);
-  takeSnapshot(normalButtonCanvas);
-  // Press the button.
-  sendMouseEvent("mousemove", button);
-  sendMouseEvent("mousedown", button);
-  yield;
-  window.opener.ok(true, "1");
-  takeSnapshot(pressedFocusedButtonCanvas);
-  compareSnapshots_(normalButtonCanvas, pressedFocusedButtonCanvas, false, "Pressed focused buttons should look different from normal buttons.");
-  // Release.
-  sendMouseEvent("mouseup", button);
-  yield;
-  window.opener.ok(true, "2");
-  // make sure the button is focused as this doesn't happen on click on Mac
-  button.focus();
-  takeSnapshot(normalFocusedButtonCanvas);
-  compareSnapshots_(normalFocusedButtonCanvas, pressedFocusedButtonCanvas, false, "Pressed focused buttons should look different from normal focused buttons.");
-  // Unfocus the button.
-  sendMouseEvent("mousedown", outside);
-  sendMouseEvent("mouseup", outside);
-  yield;
-  window.opener.ok(true, "3");
-
-  // Press the label.
-  sendMouseEvent("mousemove", label);
-  sendMouseEvent("mousedown", label);
-  yield;
-  window.opener.ok(true, "4");
-  compareSnapshots_(normalButtonCanvas, currentSnapshot, false, "Pressing the label should have pressed the button.");
-  takeSnapshot(pressedButtonCanvas);
-  // Move the mouse down from the label.
-  sendMouseEvent("mousemove", outside);
-  yield;
-  window.opener.ok(true, "5");
-  compareSnapshots_(normalButtonCanvas, currentSnapshot, true, "Moving the mouse down from the label should have unpressed the button.");
-  // ... and up again.
-  sendMouseEvent("mousemove", label);
-  yield;
-  window.opener.ok(true, "6");
-  compareSnapshots_(pressedButtonCanvas, currentSnapshot, true, "Moving the mouse back on top of the label should have pressed the button.");
-  // Release.
-  sendMouseEvent("mouseup", label);
-  yield;
-  window.opener.ok(true, "7");
-  compareSnapshots_(normalFocusedButtonCanvas, currentSnapshot, true, "Releasing the mouse over the label should have unpressed (and focused) the button.");
-  // Press the label and remove it.
-  sendMouseEvent("mousemove", label);
-  sendMouseEvent("mousedown", label);
-  yield;
-  window.opener.ok(true, "8");
-  label.parentNode.removeChild(label);
-  yield;
-  window.opener.ok(true, "9");
-  compareSnapshots_(normalButtonCanvas, currentSnapshot, true, "Removing the label should have unpressed the button.");
-  sendMouseEvent("mouseup", label);
-  window.removeEventListener("MozAfterPaint", paintListener, false);
-  window.opener.finishTests();
-}
-
-function sendMouseEvent(t, elem) {
-  var r = elem.getBoundingClientRect();
-  synthesizeMouse(elem, r.width / 2, r.height / 2, {type: t});
-}
-
-function compareSnapshots_(c1, c2, shouldBeIdentical, msg) {
-  var [correct, c1url, c2url] = compareSnapshots(c1, c2, shouldBeIdentical);
-  if (correct) {
-    if (shouldBeIdentical) {
-      window.opener.ok(true, msg + " - expected " + c1url);
-    } else {
-      window.opener.ok(true, msg + " - got " + c1url + " and " + c2url);
-    }
-  } else {
-    if (shouldBeIdentical) {
-      window.opener.ok(false, msg + " - expected " + c1url + " but got " + c2url);
-    } else {
-      window.opener.ok(false, msg + " - expected something other than " + c1url);
-    }
-  }
-}
-
-function takeSnapshot(canvas) {
-  var r = buttonRect();
-  var ctx = canvas.getContext("2d");
-  netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
-  canvas.width = r.width + 4;
-  canvas.height = r.height + 4;
-  ctx.clearRect(0, 0, canvas.width, canvas.height);
-  ctx.drawWindow(window, r.left - 2, r.top - 2, r.width + 4, r.height + 4, "#FFF");
-}
-
-function buttonRect() {
-  return button.getBoundingClientRect();
-}
-
-
-</script>
-</pre>
-<p><input type="button" value="Button" id="button"></p>
-<p><label for="button" id="label">Label</label></p>
-<p id="outside">Something under the label</p>
-
-<canvas id="normalButtonCanvas"></canvas>
-<canvas id="pressedButtonCanvas"></canvas>
-<canvas id="normalFocusedButtonCanvas"></canvas>
-<canvas id="pressedFocusedButtonCanvas"></canvas>
-<canvas id="currentSnapshot"></canvas>
-
-</body>
-</html>
--- a/content/events/test/test_bug426082.html
+++ b/content/events/test/test_bug426082.html
@@ -4,27 +4,175 @@
 https://bugzilla.mozilla.org/show_bug.cgi?id=426082
 -->
 <head>
   <title>Test for Bug 426082</title>
   <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
   <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
   <script type="application/javascript" src="/tests/SimpleTest/WindowSnapshot.js"></script>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+  <style>
+    canvas {
+      display: none;
+    }
+  </style>
 </head>
-<body>
-
+<body onload="runTests()">
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=426082">Mozilla Bug 426082</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+  
+</div>
 <pre id="test">
 <script type="application/javascript;version=1.8">
 
 /** Test for Bug 426082 **/
 SimpleTest.waitForExplicitFinish();
-var subwindow = window.open("./bug426082.html", "bug426082", "width=800,height=1000");
+
+var normalButtonCanvas, pressedButtonCanvas, normalFocusedButtonCanvas,
+    pressedFocusedButtonCanvas, currentSnapshot, button, label, outside;
+
+function runTests() {
+  normalButtonCanvas = $("normalButtonCanvas");
+  pressedButtonCanvas = $("pressedButtonCanvas");
+  normalFocusedButtonCanvas = $("normalFocusedButtonCanvas");
+  pressedFocusedButtonCanvas = $("pressedFocusedButtonCanvas");
+  currentSnapshot = $("currentSnapshot");
+  button = $("button");
+  label = $("label");
+  outside = $("outside");
+  SimpleTest.executeSoon(executeTests);
+}
+
+function isRectContainedInRectFromRegion(rect, region) {
+  return Array.some(region, function (r) {
+    return rect.left >= r.left &&
+           rect.top >= r.top &&
+           rect.right <= r.right &&
+           rect.bottom <= r.bottom;
+  });
+}
+
+function paintListener(e) {
+  if (isRectContainedInRectFromRegion(buttonRect(), e.clientRects)) {
+    gNeedsPaint = false;
+    takeSnapshot(currentSnapshot);
+  }
+}
+
+var gNeedsPaint = false;
+function executeTests() {
+  var testYielder = tests();
+  function execNext() {
+    try {
+      if (!gNeedsPaint) {
+        testYielder.next();
+        button.getBoundingClientRect(); // Flush.
+        gNeedsPaint = true;
+      }
+      SimpleTest.executeSoon(execNext);
+    } catch (e) {}
+  }
+  execNext();
+}
 
-function finishTests() {
-  subwindow.close();
+function tests() {
+  window.addEventListener("MozAfterPaint", paintListener, false);
+  takeSnapshot(normalButtonCanvas);
+  // Press the button.
+  sendMouseEvent("mousemove", button);
+  sendMouseEvent("mousedown", button);
+  yield;
+  takeSnapshot(pressedFocusedButtonCanvas);
+  compareSnapshots_(normalButtonCanvas, pressedFocusedButtonCanvas, false, "Pressed focused buttons should look different from normal buttons.");
+  // Release.
+  sendMouseEvent("mouseup", button);
+  yield;
+  // make sure the button is focused as this doesn't happen on click on Mac
+  button.focus();
+  takeSnapshot(normalFocusedButtonCanvas);
+  compareSnapshots_(normalFocusedButtonCanvas, pressedFocusedButtonCanvas, false, "Pressed focused buttons should look different from normal focused buttons.");
+  // Unfocus the button.
+  sendMouseEvent("mousedown", outside);
+  sendMouseEvent("mouseup", outside);
+  yield;
+
+  // Press the label.
+  sendMouseEvent("mousemove", label);
+  sendMouseEvent("mousedown", label);
+  yield;
+  compareSnapshots_(normalButtonCanvas, currentSnapshot, false, "Pressing the label should have pressed the button.");
+  takeSnapshot(pressedButtonCanvas);
+  // Move the mouse down from the label.
+  sendMouseEvent("mousemove", outside);
+  yield;
+  compareSnapshots_(normalButtonCanvas, currentSnapshot, true, "Moving the mouse down from the label should have unpressed the button.");
+  // ... and up again.
+  sendMouseEvent("mousemove", label);
+  yield;
+  compareSnapshots_(pressedButtonCanvas, currentSnapshot, true, "Moving the mouse back on top of the label should have pressed the button.");
+  // Release.
+  sendMouseEvent("mouseup", label);
+  yield;
+  compareSnapshots_(normalFocusedButtonCanvas, currentSnapshot, true, "Releasing the mouse over the label should have unpressed (and focused) the button.");
+  // Press the label and remove it.
+  sendMouseEvent("mousemove", label);
+  sendMouseEvent("mousedown", label);
+  yield;
+  label.parentNode.removeChild(label);
+  yield;
+  compareSnapshots_(normalButtonCanvas, currentSnapshot, true, "Removing the label should have unpressed the button.");
+  sendMouseEvent("mouseup", label);
+  window.removeEventListener("MozAfterPaint", paintListener, false);
   SimpleTest.finish();
 }
+
+function sendMouseEvent(t, elem) {
+  var r = elem.getBoundingClientRect();
+  synthesizeMouse(elem, r.width / 2, r.height / 2, {type: t});
+}
+
+function compareSnapshots_(c1, c2, shouldBeIdentical, msg) {
+  var [correct, c1url, c2url] = compareSnapshots(c1, c2, shouldBeIdentical);
+  if (correct) {
+    if (shouldBeIdentical) {
+      ok(true, msg + " - expected " + c1url);
+    } else {
+      ok(true, msg + " - got " + c1url + " and " + c2url);
+    }
+  } else {
+    if (shouldBeIdentical) {
+      ok(false, msg + " - expected " + c1url + " but got " + c2url);
+    } else {
+      ok(false, msg + " - expected something other than " + c1url);
+    }
+  }
+}
+
+function takeSnapshot(canvas) {
+  var r = buttonRect();
+  var ctx = canvas.getContext("2d");
+  netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
+  canvas.width = r.width + 4;
+  canvas.height = r.height + 4;
+  ctx.clearRect(0, 0, canvas.width, canvas.height);
+  ctx.drawWindow(window, r.left - 2, r.top - 2, r.width + 4, r.height + 4, "#FFF");
+}
+
+function buttonRect() {
+  return button.getBoundingClientRect();
+}
+
+
 </script>
 </pre>
+<p><input type="button" value="Button" id="button"></p>
+<p><label for="button" id="label">Label</label></p>
+<p id="outside">Something under the label</p>
+
+<canvas id="normalButtonCanvas"></canvas>
+<canvas id="pressedButtonCanvas"></canvas>
+<canvas id="normalFocusedButtonCanvas"></canvas>
+<canvas id="pressedFocusedButtonCanvas"></canvas>
+<canvas id="currentSnapshot"></canvas>
 
 </body>
 </html>
--- a/content/events/test/test_bug656379-1.html
+++ b/content/events/test/test_bug656379-1.html
@@ -4,27 +4,195 @@
 https://bugzilla.mozilla.org/show_bug.cgi?id=656379
 -->
 <head>
   <title>Test for Bug 656379</title>
   <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
   <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
   <script type="application/javascript" src="/tests/SimpleTest/WindowSnapshot.js"></script>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+  <style>
+    canvas {
+      display: none;
+    }
+    input[type=button] {
+      -moz-appearance: none;
+      padding: 0;
+      border: none;
+      color: black;
+      background: white;
+    }
+    input[type=button]::-moz-focus-inner { border: none; }
+
+    /* Make sure that normal, focused, hover+active, focused+hover+active
+       buttons all have different styles so that the test keeps moving along. */
+    input[type=button]:hover:active {
+      background: red;
+    }
+    input[type=button]:focus {
+      background: green;
+    }
+    input[type=button]:focus:hover:active {
+      background: purple;
+    }
+  </style>
 </head>
-<body>
-
+<body onload="runTests()">
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=426082">Mozilla Bug 426082</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+  
+</div>
 <pre id="test">
 <script type="application/javascript;version=1.8">
 
-/** Test for Bug 656379 **/
+/** Test for Bug 426082 **/
 SimpleTest.waitForExplicitFinish();
-var subwindow = window.open("./bug656379-1.html", "bug656379", "width=800,height=1000");
+
+var normalButtonCanvas, pressedButtonCanvas, normalFocusedButtonCanvas,
+    pressedFocusedButtonCanvas, currentSnapshot, button, label, outside;
+
+function runTests() {
+  normalButtonCanvas = $("normalButtonCanvas");
+  pressedButtonCanvas = $("pressedButtonCanvas");
+  normalFocusedButtonCanvas = $("normalFocusedButtonCanvas");
+  pressedFocusedButtonCanvas = $("pressedFocusedButtonCanvas");
+  currentSnapshot = $("currentSnapshot");
+  button = $("button");
+  label = $("label");
+  outside = $("outside");
+  SimpleTest.executeSoon(executeTests);
+}
+
+function isRectContainedInRectFromRegion(rect, region) {
+  return Array.some(region, function (r) {
+    return rect.left >= r.left &&
+           rect.top >= r.top &&
+           rect.right <= r.right &&
+           rect.bottom <= r.bottom;
+  });
+}
+
+function paintListener(e) {
+  if (isRectContainedInRectFromRegion(buttonRect(), e.clientRects)) {
+    gNeedsPaint = false;
+    takeSnapshot(currentSnapshot);
+  }
+}
+
+var gNeedsPaint = false;
+function executeTests() {
+  var testYielder = tests();
+  function execNext() {
+    try {
+      if (!gNeedsPaint) {
+        testYielder.next();
+        button.getBoundingClientRect(); // Flush.
+        gNeedsPaint = true;
+      }
+      SimpleTest.executeSoon(execNext);
+    } catch (e) {}
+  }
+  execNext();
+}
 
-function finishTests() {
-  subwindow.close();
+function tests() {
+  window.addEventListener("MozAfterPaint", paintListener, false);
+  takeSnapshot(normalButtonCanvas);
+  // Press the button.
+  sendMouseEvent("mousemove", button);
+  sendMouseEvent("mousedown", button);
+  yield;
+  takeSnapshot(pressedFocusedButtonCanvas);
+  compareSnapshots_(normalButtonCanvas, pressedFocusedButtonCanvas, false, "Pressed focused buttons should look different from normal buttons.");
+  // Release.
+  sendMouseEvent("mouseup", button);
+  yield;
+  // make sure the button is focused as this doesn't happen on click on Mac
+  button.focus();
+  takeSnapshot(normalFocusedButtonCanvas);
+  compareSnapshots_(normalFocusedButtonCanvas, pressedFocusedButtonCanvas, false, "Pressed focused buttons should look different from normal focused buttons.");
+  // Unfocus the button.
+  sendMouseEvent("mousedown", outside);
+  sendMouseEvent("mouseup", outside);
+  yield;
+
+  // Press the label.
+  sendMouseEvent("mousemove", label);
+  sendMouseEvent("mousedown", label);
+  yield;
+  compareSnapshots_(normalButtonCanvas, currentSnapshot, false, "Pressing the label should have pressed the button.");
+  takeSnapshot(pressedButtonCanvas);
+  // Move the mouse down from the label.
+  sendMouseEvent("mousemove", outside);
+  yield;
+  compareSnapshots_(normalButtonCanvas, currentSnapshot, true, "Moving the mouse down from the label should have unpressed the button.");
+  // ... and up again.
+  sendMouseEvent("mousemove", label);
+  yield;
+  compareSnapshots_(pressedButtonCanvas, currentSnapshot, true, "Moving the mouse back on top of the label should have pressed the button.");
+  // Release.
+  sendMouseEvent("mouseup", label);
+  yield;
+  compareSnapshots_(normalFocusedButtonCanvas, currentSnapshot, true, "Releasing the mouse over the label should have unpressed (and focused) the button.");
+  // Press the label and remove it.
+  sendMouseEvent("mousemove", label);
+  sendMouseEvent("mousedown", label);
+  yield;
+  label.parentNode.removeChild(label);
+  yield;
+  compareSnapshots_(normalButtonCanvas, currentSnapshot, true, "Removing the label should have unpressed the button.");
+  sendMouseEvent("mouseup", label);
+  window.removeEventListener("MozAfterPaint", paintListener, false);
   SimpleTest.finish();
 }
+
+function sendMouseEvent(t, elem) {
+  var r = elem.getBoundingClientRect();
+  synthesizeMouse(elem, r.width / 2, r.height / 2, {type: t});
+}
+
+function compareSnapshots_(c1, c2, shouldBeIdentical, msg) {
+  var [correct, c1url, c2url] = compareSnapshots(c1, c2, shouldBeIdentical);
+  if (correct) {
+    if (shouldBeIdentical) {
+      ok(true, msg + " - expected " + c1url);
+    } else {
+      ok(true, msg + " - got " + c1url + " and " + c2url);
+    }
+  } else {
+    if (shouldBeIdentical) {
+      ok(false, msg + " - expected " + c1url + " but got " + c2url);
+    } else {
+      ok(false, msg + " - expected something other than " + c1url);
+    }
+  }
+}
+
+function takeSnapshot(canvas) {
+  var r = buttonRect();
+  var ctx = canvas.getContext("2d");
+  netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
+  canvas.width = r.width + 4;
+  canvas.height = r.height + 4;
+  ctx.clearRect(0, 0, canvas.width, canvas.height);
+  ctx.drawWindow(window, r.left - 2, r.top - 2, r.width + 4, r.height + 4, "#FFF");
+}
+
+function buttonRect() {
+  return button.getBoundingClientRect();
+}
+
+
 </script>
 </pre>
+<p><input type="button" value="Button" id="button"></p>
+<p><label for="button" id="label">Label</label></p>
+<p id="outside">Something under the label</p>
+
+<canvas id="normalButtonCanvas"></canvas>
+<canvas id="pressedButtonCanvas"></canvas>
+<canvas id="normalFocusedButtonCanvas"></canvas>
+<canvas id="pressedFocusedButtonCanvas"></canvas>
+<canvas id="currentSnapshot"></canvas>
 
 </body>
 </html>
--- a/content/html/content/src/nsHTMLCanvasElement.cpp
+++ b/content/html/content/src/nsHTMLCanvasElement.cpp
@@ -645,47 +645,57 @@ nsHTMLCanvasElement::InvalidateCanvasCon
   // We don't need to flush anything here; if there's no frame or if
   // we plan to reframe we don't need to invalidate it anyway.
   nsIFrame *frame = GetPrimaryFrame();
   if (!frame)
     return;
 
   frame->MarkLayersActive(nsChangeHint(0));
 
-  Layer* layer;
+  nsRect invalRect;
+  nsRect contentArea = frame->GetContentRect();
   if (damageRect) {
     nsIntSize size = GetWidthHeight();
     if (size.width != 0 && size.height != 0) {
+
+      // damageRect and size are in CSS pixels; contentArea is in appunits
+      // We want a rect in appunits; so avoid doing pixels-to-appunits and
+      // vice versa conversion here.
       gfxRect realRect(*damageRect);
+      realRect.Scale(contentArea.width / gfxFloat(size.width),
+                     contentArea.height / gfxFloat(size.height));
       realRect.RoundOut();
 
-      nsIntRect invalRect(realRect.X(), realRect.Y(),
-                          realRect.Width(), realRect.Height());
+      // then make it a nsRect
+      invalRect = nsRect(realRect.X(), realRect.Y(),
+                         realRect.Width(), realRect.Height());
 
-      layer = frame->InvalidateLayer(nsDisplayItem::TYPE_CANVAS, &invalRect);
+      invalRect = invalRect.Intersect(nsRect(nsPoint(0,0), contentArea.Size()));
     }
   } else {
-    layer = frame->InvalidateLayer(nsDisplayItem::TYPE_CANVAS);
+    invalRect = nsRect(nsPoint(0, 0), contentArea.Size());
   }
+  invalRect.MoveBy(contentArea.TopLeft() - frame->GetPosition());
 
+  Layer* layer = frame->InvalidateLayer(invalRect, nsDisplayItem::TYPE_CANVAS);
   if (layer) {
     static_cast<CanvasLayer*>(layer)->Updated();
   }
 }
 
 void
 nsHTMLCanvasElement::InvalidateCanvas()
 {
   // We don't need to flush anything here; if there's no frame or if
   // we plan to reframe we don't need to invalidate it anyway.
   nsIFrame *frame = GetPrimaryFrame();
   if (!frame)
     return;
 
-  frame->InvalidateFrame();
+  frame->Invalidate(frame->GetContentRect() - frame->GetPosition());
 }
 
 PRInt32
 nsHTMLCanvasElement::CountContexts()
 {
   if (mCurrentContext)
     return 1;
 
--- a/content/media/VideoFrameContainer.cpp
+++ b/content/media/VideoFrameContainer.cpp
@@ -74,19 +74,20 @@ void VideoFrameContainer::Invalidate()
         presShell->FrameNeedsReflow(frame,
                                     nsIPresShell::eStyleChange,
                                     NS_FRAME_IS_DIRTY);
       }
     }
   }
 
   if (frame) {
+    nsRect contentRect = frame->GetContentRect() - frame->GetPosition();
     if (invalidateFrame) {
-      frame->InvalidateFrame();
+      frame->Invalidate(contentRect);
     } else {
-      frame->InvalidateLayer(nsDisplayItem::TYPE_VIDEO);
+      frame->InvalidateLayer(contentRect, nsDisplayItem::TYPE_VIDEO);
     }
   }
 
   nsSVGEffects::InvalidateDirectRenderingObservers(mElement);
 }
 
 }
--- a/dom/base/nsDOMWindowUtils.cpp
+++ b/dom/base/nsDOMWindowUtils.cpp
@@ -201,20 +201,22 @@ nsDOMWindowUtils::Redraw(PRUint32 aCount
 {
   if (aCount == 0)
     aCount = 1;
 
   if (nsIPresShell* presShell = GetPresShell()) {
     nsIFrame *rootFrame = presShell->GetRootFrame();
 
     if (rootFrame) {
+      nsRect r(nsPoint(0, 0), rootFrame->GetSize());
+
       PRIntervalTime iStart = PR_IntervalNow();
 
       for (PRUint32 i = 0; i < aCount; i++)
-        rootFrame->InvalidateFrame();
+        rootFrame->InvalidateWithFlags(r, nsIFrame::INVALIDATE_IMMEDIATE);
 
 #if defined(MOZ_X11) && defined(MOZ_WIDGET_GTK2)
       XSync(GDK_DISPLAY(), False);
 #endif
 
       *aDurationOut = PR_IntervalToMilliseconds(PR_IntervalNow() - iStart);
 
       return NS_OK;
@@ -349,17 +351,24 @@ nsDOMWindowUtils::SetDisplayPortForEleme
       // separate notification just for this change.
       nsPresContext* presContext = GetPresContext();
       MaybeReflowForInflationScreenWidthChange(presContext);
     }
   }
 
   nsIFrame* rootFrame = presShell->FrameManager()->GetRootFrame();
   if (rootFrame) {
-    rootFrame->InvalidateFrame();
+    nsIContent* rootContent =
+      rootScrollFrame ? rootScrollFrame->GetContent() : nsnull;
+    nsRect rootDisplayport;
+    bool usingDisplayport = rootContent &&
+      nsLayoutUtils::GetDisplayPort(rootContent, &rootDisplayport);
+    rootFrame->InvalidateWithFlags(
+      usingDisplayport ? rootDisplayport : rootFrame->GetVisualOverflowRect(),
+      nsIFrame::INVALIDATE_NO_THEBES_LAYERS);
 
     // If we are hiding something that is a display root then send empty paint
     // transaction in order to release retained layers because it won't get
     // any more paint requests when it is hidden.
     if (displayport.IsEmpty() &&
         rootFrame == nsLayoutUtils::GetDisplayRootFrame(rootFrame)) {
       nsCOMPtr<nsIWidget> widget = GetWidget();
       if (widget) {
--- a/dom/plugins/base/nsPluginInstanceOwner.cpp
+++ b/dom/plugins/base/nsPluginInstanceOwner.cpp
@@ -628,34 +628,46 @@ NS_IMETHODIMP nsPluginInstanceOwner::Inv
   if (mWidget) {
     mWidget->Invalidate(nsIntRect(invalidRect->left, invalidRect->top,
                                   invalidRect->right - invalidRect->left,
                                   invalidRect->bottom - invalidRect->top));
     return NS_OK;
   }
 #endif
 
-  nsIntRect rect(invalidRect->left,
-                 invalidRect->top,
-                 invalidRect->right - invalidRect->left,
-                 invalidRect->bottom - invalidRect->top);
-  mObjectFrame->InvalidateLayer(nsDisplayItem::TYPE_PLUGIN, &rect);
+  nsPresContext* presContext = mObjectFrame->PresContext();
+  nsRect rect(presContext->DevPixelsToAppUnits(invalidRect->left),
+              presContext->DevPixelsToAppUnits(invalidRect->top),
+              presContext->DevPixelsToAppUnits(invalidRect->right - invalidRect->left),
+              presContext->DevPixelsToAppUnits(invalidRect->bottom - invalidRect->top));
+  if (container) {
+    gfxIntSize newSize = container->GetCurrentSize();
+    if (newSize != oldSize) {
+      // The image size has changed - invalidate the old area too, bug 635405.
+      nsRect oldRect = nsRect(0, 0,
+                              presContext->DevPixelsToAppUnits(oldSize.width),
+                              presContext->DevPixelsToAppUnits(oldSize.height));
+      rect.UnionRect(rect, oldRect);
+    }
+  }
+  rect.MoveBy(mObjectFrame->GetContentRectRelativeToSelf().TopLeft());
+  mObjectFrame->InvalidateLayer(rect, nsDisplayItem::TYPE_PLUGIN);
   return NS_OK;
 }
 
 NS_IMETHODIMP nsPluginInstanceOwner::InvalidateRegion(NPRegion invalidRegion)
 {
   return NS_ERROR_NOT_IMPLEMENTED;
 }
  
 NS_IMETHODIMP
 nsPluginInstanceOwner::RedrawPlugin()
 {
   if (mObjectFrame) {
-    mObjectFrame->InvalidateLayer(nsDisplayItem::TYPE_PLUGIN);
+    mObjectFrame->InvalidateLayer(mObjectFrame->GetContentRectRelativeToSelf(), nsDisplayItem::TYPE_PLUGIN);
   }
   return NS_OK;
 }
 
 NS_IMETHODIMP nsPluginInstanceOwner::GetNetscapeWindow(void *value)
 {
   if (!mObjectFrame) {
     NS_WARNING("plugin owner has no owner in getting doc's window handle");
@@ -3747,17 +3759,17 @@ void nsPluginInstanceOwner::SetFrame(nsO
   if (mObjectFrame) {
     mObjectFrame->SetInstanceOwner(this);
     // Can only call PrepForDrawing on an object frame once. Don't do it here unless
     // widget creation is complete. Doesn't matter if we actually have a widget.
     if (mWidgetCreationComplete) {
       mObjectFrame->PrepForDrawing(mWidget);
     }
     mObjectFrame->FixupWindow(mObjectFrame->GetContentRectRelativeToSelf().Size());
-    mObjectFrame->InvalidateFrame();
+    mObjectFrame->Invalidate(mObjectFrame->GetContentRectRelativeToSelf());
 
     // Scroll position listening is only required for Carbon event model plugins on Mac OS X.
 #if defined(XP_MACOSX) && !defined(NP_NO_QUICKDRAW)
     // We need to register as a scroll position listener on every scrollable frame up to the top.
     if (GetEventModel() == NPEventModelCarbon) {
       for (nsIFrame* f = aFrame; f; f = nsLayoutUtils::GetCrossDocParentFrame(f)) {
         nsIScrollableFrame* sf = do_QueryFrame(f);
         if (sf) {
--- a/dom/plugins/test/mochitest/test_painting.html
+++ b/dom/plugins/test/mochitest/test_painting.html
@@ -89,19 +89,18 @@ function invalidate() {
 function done() {
   paintCountIs(clipped, 2, "painted after invalidate");
 
   SimpleTest.finish();  
 }
 
 function waitForPaint(func) {
   paint_waiter.last_paint_count = paint_waiter.getPaintCount();
-  // Ensure the waiter has had a style change, so that this will
+  // Ensure the waiter has been reflowed with zero height, so that this will
   // change its size and cause a paint.
-  paint_waiter.style.backgroundColor = paint_waiter.style.backgroundColor == "blue" ? "yellow" : "blue";
   var flush = paint_waiter.offsetHeight;
   paint_waiter.style.height = "1px";
   waitForPaintHelper(func);
 }
 
 function waitForPaintHelper(func) {
   if (paint_waiter.getPaintCount() != paint_waiter.last_paint_count) {
     // hide the paint waiter
--- a/editor/libeditor/html/crashtests/crashtests.list
+++ b/editor/libeditor/html/crashtests/crashtests.list
@@ -20,11 +20,11 @@ load 535632-1.xhtml
 load 574558-1.xhtml
 load 582138-1.xhtml
 load 612565-1.html
 asserts(0-6) load 615015-1.html # Bug 439258
 load 615450-1.html
 load 639736-1.xhtml
 load 643786-1.html
 load 682650-1.html
-asserts(0-1) load 716456-1.html
+load 716456-1.html
 load 759748.html
 load 761861.html
--- a/editor/reftests/reftest.list
+++ b/editor/reftests/reftest.list
@@ -40,17 +40,17 @@ fails-if(Android) != spellcheck-input-at
 fails-if(Android) != spellcheck-input-property-dynamic-override.html spellcheck-input-ref.html
 == spellcheck-input-property-dynamic-override-inherit.html spellcheck-input-nofocus-ref.html
 fails-if(Android) != spellcheck-input-property-dynamic-override-inherit.html spellcheck-input-ref.html
 == spellcheck-textarea-attr.html spellcheck-textarea-nofocus-ref.html
 #the random-if(Android) tests pass on android native, but fail on android-xul, see bug 728942
 random-if(Android) != spellcheck-textarea-attr.html spellcheck-textarea-ref.html
 needs-focus == spellcheck-textarea-focused.html spellcheck-textarea-ref.html
 needs-focus == spellcheck-textarea-focused-reframe.html spellcheck-textarea-ref.html
-needs-focus == spellcheck-textarea-focused-notreadonly.html spellcheck-textarea-ref2.html
+needs-focus == spellcheck-textarea-focused-notreadonly.html spellcheck-textarea-ref.html
 random-if(Android) != spellcheck-textarea-nofocus.html spellcheck-textarea-ref.html
 random-if(Android) != spellcheck-textarea-disabled.html spellcheck-textarea-ref.html
 random-if(Android) != spellcheck-textarea-attr-inherit.html spellcheck-textarea-ref.html
 random-if(Android) != spellcheck-textarea-attr-dynamic.html spellcheck-textarea-ref.html
 random-if(Android) != spellcheck-textarea-attr-dynamic-inherit.html spellcheck-textarea-ref.html
 random-if(Android) != spellcheck-textarea-property-dynamic.html spellcheck-textarea-ref.html
 random-if(Android) != spellcheck-textarea-property-dynamic-inherit.html spellcheck-textarea-ref.html
 random-if(Android) != spellcheck-textarea-attr-dynamic-override.html spellcheck-textarea-ref.html
--- a/editor/reftests/spellcheck-textarea-focused-notreadonly.html
+++ b/editor/reftests/spellcheck-textarea-focused-notreadonly.html
@@ -1,19 +1,19 @@
-<!DOCTYPE html>
-<html>
-<body>
-
-  <textarea id="testBox" style="padding:2px;" readonly></textarea>
-  <script type="text/javascript">
-    //Adding focus to the textbox should trigger a spellcheck
-    var textbox = document.getElementById("testBox");
-    addEventListener("load", function() {
-      textbox.readOnly = false;
-      textbox.focus();
-      textbox.value = "blahblahblah";
-      textbox.selectionStart = textbox.selectionEnd = 0;
-      textbox.blur();
-    }, false);
-  </script>
-
-</body>
-</html>
+<!DOCTYPE html>
+<html>
+<body>
+
+  <textarea id="testBox" readonly></textarea>
+  <script type="text/javascript">
+    //Adding focus to the textbox should trigger a spellcheck
+    var textbox = document.getElementById("testBox");
+    addEventListener("load", function() {
+      textbox.readOnly = false;
+      textbox.focus();
+      textbox.value = "blahblahblah";
+      textbox.selectionStart = textbox.selectionEnd = 0;
+      textbox.blur();
+    }, false);
+  </script>
+
+</body>
+</html>
deleted file mode 100644
--- a/editor/reftests/spellcheck-textarea-ref2.html
+++ /dev/null
@@ -1,11 +0,0 @@
-<!DOCTYPE html>
-<html>
-<body>
-  <textarea spellcheck="true" style="padding:2px;">blahblahblah</textarea>
-  <script type="text/javascript">
-    var box = document.getElementsByTagName("textarea")[0];
-    box.focus(); //Bring the textbox into focus, triggering a spellcheck
-    box.blur(); //Blur in order to make things similar to other tests otherwise
-  </script>
-</body>
-</html>
--- a/gfx/2d/UserData.h
+++ b/gfx/2d/UserData.h
@@ -21,26 +21,18 @@ class UserData
 {
   typedef void (*destroyFunc)(void *data);
 public:
   UserData() : count(0), entries(NULL) {}
 
   /* Attaches untyped userData associated with key. destroy is called on destruction */
   void Add(UserDataKey *key, void *userData, destroyFunc destroy)
   {
-    for (int i=0; i<count; i++) {
-      if (key == entries[i].key) {
-        if (entries[i].destroy) {
-          entries[i].destroy(entries[i].userData);
-        }
-        entries[i].userData = userData;
-        entries[i].destroy = destroy;
-        return;
-      }
-    }
+    // XXX we should really warn if user data with key has already been added,
+    // since in that case Get() will return the old user data!
 
     // We could keep entries in a std::vector instead of managing it by hand
     // but that would propagate an stl dependency out which we'd rather not
     // do (see bug 666609). Plus, the entries array is expect to stay small
     // so doing a realloc everytime we add a new entry shouldn't be too costly
     entries = static_cast<Entry*>(realloc(entries, sizeof(Entry)*(count+1)));
 
     if (!entries) {
@@ -77,31 +69,22 @@ public:
     for (int i=0; i<count; i++) {
       if (key == entries[i].key) {
         return entries[i].userData;
       }
     }
     return NULL;
   }
 
-  void Destroy()
+  ~UserData()
   {
     for (int i=0; i<count; i++) {
-      if (entries[i].destroy) {
-        entries[i].destroy(entries[i].userData);
-      }
+      entries[i].destroy(entries[i].userData);
     }
     free(entries);
-    entries = NULL;
-    count = 0;
-  }
-
-  ~UserData()
-  {
-    Destroy();
   }
 
 private:
   struct Entry {
     const UserDataKey *key;
     void *userData;
     destroyFunc destroy;
   };
--- a/gfx/layers/ImageLayers.h
+++ b/gfx/layers/ImageLayers.h
@@ -600,20 +600,19 @@ public:
    * Set the size to scale the image to and the mode at which to scale.
    */
   void SetScaleToSize(const gfxIntSize &aSize, ScaleMode aMode)
   {
     mScaleToSize = aSize;
     mScaleMode = aMode;
   }
 
+
   ImageContainer* GetContainer() { return mContainer; }
   gfxPattern::GraphicsFilter GetFilter() { return mFilter; }
-  const gfxIntSize& GetScaleToSize() { return mScaleToSize; }
-  ScaleMode GetScaleMode() { return mScaleMode; }
 
   MOZ_LAYER_DECL_NAME("ImageLayer", TYPE_IMAGE)
 
   virtual void ComputeEffectiveTransforms(const gfx3DMatrix& aTransformToSurface)
   {
     // Snap image edges to pixel boundaries
     gfxRect snap(0, 0, 0, 0);
     if (mContainer) {
deleted file mode 100644
--- a/gfx/layers/LayerTreeInvalidation.cpp
+++ /dev/null
@@ -1,331 +0,0 @@
-/*-*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "LayerTreeInvalidation.h"
-#include "gfxUtils.h"
-
-namespace mozilla {
-namespace layers {
-
-struct LayerPropertiesBase;
-LayerPropertiesBase* CloneLayerTreePropertiesInternal(Layer* aRoot);
-
-static nsIntRect 
-TransformRect(const nsIntRect& aRect, const gfx3DMatrix& aTransform)
-{
-  if (aRect.IsEmpty()) {
-    return nsIntRect();
-  }
-
-  gfxRect rect(aRect.x, aRect.y, aRect.width, aRect.height);
-  rect = aTransform.TransformBounds(rect);
-  rect.RoundOut();
-
-  nsIntRect intRect;
-  if (!gfxUtils::GfxRectToIntRect(rect, &intRect)) {
-    return nsIntRect();
-  }
-
-  return intRect;
-}
-
-/**
- * Walks over this layer, and all descendant layers.
- * If any of these are a ContainerLayer that reports invalidations to a PresShell,
- * then report that the entire bounds have changed.
- */
-static void
-NotifySubdocumentInvalidationRecursive(Layer* aLayer, NotifySubDocInvalidationFunc aCallback)
-{
-  aLayer->ClearInvalidRect();
-  ContainerLayer* container = aLayer->AsContainerLayer();
-
-  if (aLayer->GetMaskLayer()) {
-    NotifySubdocumentInvalidationRecursive(aLayer->GetMaskLayer(), aCallback);
-  }
-
-  if (!container) {
-    return;
-  }
-
-  for (Layer* child = container->GetFirstChild(); child; child = child->GetNextSibling()) {
-    NotifySubdocumentInvalidationRecursive(child, aCallback);
-  }
-
-  aCallback(container, container->GetVisibleRegion());
-}
-
-struct LayerPropertiesBase : public LayerProperties
-{
-  LayerPropertiesBase(Layer* aLayer)
-    : mLayer(aLayer)
-    , mMaskLayer(nsnull)
-    , mVisibleBounds(aLayer->GetVisibleRegion().GetBounds())
-    , mTransform(aLayer->GetTransform())
-    , mOpacity(aLayer->GetOpacity())
-    , mUseClipRect(!!aLayer->GetClipRect())
-  {
-    MOZ_COUNT_CTOR(LayerPropertiesBase);
-    if (aLayer->GetMaskLayer()) {
-      mMaskLayer = CloneLayerTreePropertiesInternal(aLayer->GetMaskLayer());
-    }
-    if (mUseClipRect) {
-      mClipRect = *aLayer->GetClipRect();
-    }
-  }
-  LayerPropertiesBase()
-    : mLayer(nsnull)
-    , mMaskLayer(nsnull)
-  {
-    MOZ_COUNT_CTOR(LayerPropertiesBase);
-  }
-  ~LayerPropertiesBase()
-  {
-    MOZ_COUNT_DTOR(LayerPropertiesBase);
-  }
-  
-  virtual nsIntRect ComputeDifferences(Layer* aRoot, 
-                                       NotifySubDocInvalidationFunc aCallback);
-
-  nsIntRect ComputeChange(NotifySubDocInvalidationFunc aCallback)
-  {
-    bool transformChanged = mTransform != mLayer->GetTransform();
-    Layer* otherMask = mLayer->GetMaskLayer();
-    const nsIntRect* otherClip = mLayer->GetClipRect();
-    nsIntRect result;
-    if ((mMaskLayer ? mMaskLayer->mLayer : nsnull) != otherMask ||
-        (mUseClipRect != !!otherClip) ||
-        mLayer->GetOpacity() != mOpacity ||
-        transformChanged) 
-    {
-      result = OldTransformedBounds();
-      if (transformChanged) {
-        result = result.Union(NewTransformedBounds());
-      }
-
-      // If we don't have to generate invalidations separately for child
-      // layers then we can just stop here since we've already invalidated the entire
-      // old and new bounds.
-      if (!aCallback) {
-        ClearInvalidations(mLayer);
-        return result;
-      }
-    }
-
-    result = result.Union(ComputeChangeInternal(aCallback));
-    result = result.Union(TransformRect(mLayer->GetInvalidRegion().GetBounds(), mTransform));
-
-    if (mMaskLayer && otherMask) {
-      nsIntRect maskDiff = mMaskLayer->ComputeChange(aCallback);
-      result = result.Union(TransformRect(maskDiff, mTransform));
-    }
-
-    if (mUseClipRect && otherClip) {
-      if (!mClipRect.IsEqualInterior(*otherClip)) {
-        nsIntRegion tmp; 
-        tmp.Xor(mClipRect, *otherClip); 
-        result = result.Union(tmp.GetBounds());
-      }
-    }
-
-    mLayer->ClearInvalidRect();
-    return result;
-  }
-
-  nsIntRect NewTransformedBounds()
-  {
-    return TransformRect(mLayer->GetVisibleRegion().GetBounds(), mLayer->GetTransform());
-  }
-
-  nsIntRect OldTransformedBounds()
-  {
-    return TransformRect(mVisibleBounds, mTransform);
-  }
-
-  virtual nsIntRect ComputeChangeInternal(NotifySubDocInvalidationFunc aCallback) { return nsIntRect(); }
-
-  Layer* mLayer;
-  nsAutoPtr<LayerPropertiesBase> mMaskLayer;
-  nsIntRect mVisibleBounds;
-  gfx3DMatrix mTransform;
-  float mOpacity;
-  nsIntRect mClipRect;
-  bool mUseClipRect;
-};
-
-struct ContainerLayerProperties : public LayerPropertiesBase
-{
-  ContainerLayerProperties(ContainerLayer* aLayer)
-    : LayerPropertiesBase(aLayer)
-  {
-    for (Layer* child = aLayer->GetFirstChild(); child; child = child->GetNextSibling()) {
-      mChildren.AppendElement(CloneLayerTreePropertiesInternal(child));
-    }
-  }
-
-  virtual nsIntRect ComputeChangeInternal(NotifySubDocInvalidationFunc aCallback)
-  {
-    ContainerLayer* container = mLayer->AsContainerLayer();
-    nsIntRegion result;
-
-    PRUint32 i = 0;
-    for (Layer* child = container->GetFirstChild(); child; child = child->GetNextSibling()) {
-      if (i >= mChildren.Length() || child != mChildren[i]->mLayer) {
-        // Child change. Invalidate the full areas.
-        // TODO: We could be smarter here if non-overlapping children
-        // swap order.
-        result.Or(result, TransformRect(child->GetVisibleRegion().GetBounds(), child->GetTransform()));
-        if (i < mChildren.Length()) {
-          result.Or(result, mChildren[i]->OldTransformedBounds());
-        }
-        if (aCallback) {
-          NotifySubdocumentInvalidationRecursive(child, aCallback);
-        } else {
-          ClearInvalidations(child);
-        }
-      } else {
-        // Same child, check for differences within the child
-        result.Or(result, mChildren[i]->ComputeChange(aCallback));
-      }
-
-      i++;
-    }
-
-    // Process remaining removed children.
-    while (i < mChildren.Length()) {
-      result.Or(result, mChildren[i]->OldTransformedBounds());
-      i++;
-    }
-
-    if (aCallback) {
-      aCallback(container, result);
-    }
-
-    return TransformRect(result.GetBounds(), mLayer->GetTransform());
-  }
-
-  nsAutoTArray<nsAutoPtr<LayerPropertiesBase>,1> mChildren;
-};
-
-struct ColorLayerProperties : public LayerPropertiesBase
-{
-  ColorLayerProperties(ColorLayer *aLayer)
-    : LayerPropertiesBase(aLayer)
-    , mColor(aLayer->GetColor())
-  { }
-
-  virtual nsIntRect ComputeChangeInternal(NotifySubDocInvalidationFunc aCallback)
-  {
-    ColorLayer* color = static_cast<ColorLayer*>(mLayer);
-
-    if (mColor != color->GetColor()) {
-      return NewTransformedBounds();
-    }
-
-    return nsIntRect();
-  }
-
-  gfxRGBA mColor;
-};
-
-struct ImageLayerProperties : public LayerPropertiesBase
-{
-  ImageLayerProperties(ImageLayer* aImage)
-    : LayerPropertiesBase(aImage)
-    , mVisibleRegion(aImage->GetVisibleRegion())
-    , mContainer(aImage->GetContainer())
-    , mFilter(aImage->GetFilter())
-    , mScaleToSize(aImage->GetScaleToSize())
-    , mScaleMode(aImage->GetScaleMode())
-  { }
-
-  virtual nsIntRect ComputeChangeInternal(NotifySubDocInvalidationFunc aCallback)
-  {
-    ImageLayer* image = static_cast<ImageLayer*>(mLayer);
-    
-    if (!image->GetVisibleRegion().IsEqual(mVisibleRegion)) {
-      nsIntRect result = NewTransformedBounds();
-      result = result.Union(OldTransformedBounds());
-      return result;
-    }
-
-    if (mContainer != image->GetContainer() ||
-        mFilter != image->GetFilter() ||
-        mScaleToSize != image->GetScaleToSize() ||
-        mScaleMode != image->GetScaleMode()) {
-      return NewTransformedBounds();
-    }
-
-    return nsIntRect();
-  }
-
-  nsIntRegion mVisibleRegion;
-  nsRefPtr<ImageContainer> mContainer;
-  gfxPattern::GraphicsFilter mFilter;
-  gfxIntSize mScaleToSize;
-  ImageLayer::ScaleMode mScaleMode;
-};
-
-LayerPropertiesBase*
-CloneLayerTreePropertiesInternal(Layer* aRoot)
-{
-  if (!aRoot) {
-    return new LayerPropertiesBase();
-  }
-
-  switch (aRoot->GetType()) {
-    case Layer::TYPE_CONTAINER:  return new ContainerLayerProperties(aRoot->AsContainerLayer());
-    case Layer::TYPE_COLOR:  return new ColorLayerProperties(static_cast<ColorLayer*>(aRoot));
-    case Layer::TYPE_IMAGE:  return new ImageLayerProperties(static_cast<ImageLayer*>(aRoot));
-    default: return new LayerPropertiesBase(aRoot);
-  }
-
-  return nsnull;
-}
-
-/* static */ LayerProperties*
-LayerProperties::CloneFrom(Layer* aRoot)
-{
-  return CloneLayerTreePropertiesInternal(aRoot);
-}
-
-/* static */ void 
-LayerProperties::ClearInvalidations(Layer *aLayer)
-{
-  aLayer->ClearInvalidRect();
-  if (aLayer->GetMaskLayer()) {
-    ClearInvalidations(aLayer->GetMaskLayer());
-  }
-
-  ContainerLayer* container = aLayer->AsContainerLayer();
-  if (!container) {
-    return;
-  }
-
-  for (Layer* child = container->GetFirstChild(); child; child = child->GetNextSibling()) {
-    ClearInvalidations(child);
-  }
-}
-
-nsIntRect
-LayerPropertiesBase::ComputeDifferences(Layer* aRoot, NotifySubDocInvalidationFunc aCallback)
-{
-  NS_ASSERTION(aRoot, "Must have a layer tree to compare against!");
-  if (mLayer != aRoot) {
-    if (aCallback) {
-      NotifySubdocumentInvalidationRecursive(aRoot, aCallback);
-    } else {
-      ClearInvalidations(aRoot);
-    }
-    nsIntRect result = TransformRect(aRoot->GetVisibleRegion().GetBounds(), aRoot->GetTransform());
-    result = result.Union(OldTransformedBounds());
-    return result;
-  } else {
-    return ComputeChange(aCallback);
-  }
-}
-
-} // namespace layers
-} // namespace mozilla
deleted file mode 100644
--- a/gfx/layers/LayerTreeInvalidation.h
+++ /dev/null
@@ -1,64 +0,0 @@
-/*-*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef GFX_LAYER_TREE_INVALIDATION_H
-#define GFX_LAYER_TREE_INVALIDATION_H
-
-#include "Layers.h"
-
-class nsPresContext;
-
-namespace mozilla {
-namespace layers {
-
-/**
- * Callback for ContainerLayer invalidations.
- *
- * @param aContainer ContainerLayer being invalidated.
- * @param aRegion Invalidated region in the ContainerLayer's coordinate
- * space.
- */
-typedef void (*NotifySubDocInvalidationFunc)(ContainerLayer* aLayer,
-                                             const nsIntRegion& aRegion);
-
-/**
- * A set of cached layer properties (including those of child layers),
- * used for comparing differences in layer trees.
- */
-struct LayerProperties
-{
-  virtual ~LayerProperties() {}
-
-  /**
-   * Copies the current layer tree properties into
-   * a new LayerProperties object.
-   *
-   * @param Layer tree to copy, or nsnull if we have no 
-   * initial layer tree.
-   */
-  static LayerProperties* CloneFrom(Layer* aRoot);
-
-  /**
-   * Clear all invalidation status from this layer tree.
-   */
-  static void ClearInvalidations(Layer* aRoot);
-
-  /**
-   * Compares a set of existing layer tree properties to the current layer
-   * tree and generates the changed rectangle.
-   *
-   * @param aRoot Root layer of the layer tree to compare against.
-   * @param aCallback If specified, callback to call when ContainerLayers
-   * are invalidated.
-   * @return Painted area changed by the layer tree changes.
-   */
-  virtual nsIntRect ComputeDifferences(Layer* aRoot, 
-                                       NotifySubDocInvalidationFunc aCallback) = 0;
-};
-
-} // namespace layers
-} // namespace mozilla
-
-#endif /* GFX_LAYER_TREE_INVALIDATON_H */
--- a/gfx/layers/Layers.h
+++ b/gfx/layers/Layers.h
@@ -162,20 +162,70 @@ public:
  * rendered data between paints (i.e. uses cairo in just the way that
  * Gecko used it before layers were introduced). But we also don't want
  * to have bifurcated "layers"/"non-layers" rendering paths in Gecko.
  * Therefore the layers API is carefully designed to permit maximally
  * efficient implementation in an "immediate mode" style. See the
  * BasicLayerManager for such an implementation.
  */
 
-static void LayerManagerUserDataDestroy(void *data)
-{
-  delete static_cast<LayerUserData*>(data);
-}
+/**
+ * Helper class to manage user data for layers and LayerManagers.
+ */
+class THEBES_API LayerUserDataSet {
+public:
+  LayerUserDataSet() : mKey(nsnull) {}
+
+  void Set(void* aKey, LayerUserData* aValue)
+  {
+    NS_ASSERTION(!mKey || mKey == aKey,
+                 "Multiple LayerUserData objects not supported");
+    mKey = aKey;
+    mValue = aValue;
+  }
+  /**
+   * This can be used anytime. Ownership passes to the caller!
+   */
+  LayerUserData* Remove(void* aKey)
+  {
+    if (mKey == aKey) {
+      mKey = nsnull;
+      LayerUserData* d = mValue.forget();
+      return d;
+    }
+    return nsnull;
+  }
+  /**
+   * This getter can be used anytime.
+   */
+  bool Has(void* aKey)
+  {
+    return mKey == aKey;
+  }
+  /**
+   * This getter can be used anytime. Ownership is retained by this object.
+   */
+  LayerUserData* Get(void* aKey)
+  {
+    return mKey == aKey ? mValue.get() : nsnull;
+  }
+
+  /**
+   * Clear out current user data.
+   */
+  void Clear()
+  {
+    mKey = nsnull;
+    mValue = nsnull;
+  }
+
+private:
+  void* mKey;
+  nsAutoPtr<LayerUserData> mValue;
+};
 
 /**
  * A LayerManager controls a tree of layers. All layers in the tree
  * must use the same LayerManager.
  * 
  * All modifications to a layer tree must happen inside a transaction.
  * Only the state of the layer tree at the end of a transaction is
  * rendered. Transactions cannot be nested
@@ -215,32 +265,26 @@ public:
   virtual ~LayerManager() {}
 
   /**
    * Release layers and resources held by this layer manager, and mark
    * it as destroyed.  Should do any cleanup necessary in preparation
    * for its widget going away.  After this call, only user data calls
    * are valid on the layer manager.
    */
-  virtual void Destroy() { mDestroyed = true; mUserData.Destroy(); }
+  virtual void Destroy() { mDestroyed = true; mUserData.Clear(); }
   bool IsDestroyed() { return mDestroyed; }
 
   virtual ShadowLayerForwarder* AsShadowForwarder()
   { return nsnull; }
 
   virtual ShadowLayerManager* AsShadowManager()
   { return nsnull; }
 
   /**
-   * Returns true if this LayerManager is owned by an nsIWidget,
-   * and is used for drawing into the widget.
-   */
-  virtual bool IsWidgetLayerManager() { return true; }
-
-  /**
    * Start a new transaction. Nested transactions are not allowed so
    * there must be no transaction currently in progress.
    * This transaction will update the state of the window from which
    * this LayerManager was obtained.
    */
   virtual void BeginTransaction() = 0;
   /**
    * Start a new transaction. Nested transactions are not allowed so
@@ -289,43 +333,32 @@ public:
   typedef void (* DrawThebesLayerCallback)(ThebesLayer* aLayer,
                                            gfxContext* aContext,
                                            const nsIntRegion& aRegionToDraw,
                                            const nsIntRegion& aRegionToInvalidate,
                                            void* aCallbackData);
 
   enum EndTransactionFlags {
     END_DEFAULT = 0,
-    END_NO_IMMEDIATE_REDRAW = 1 << 0,  // Do not perform the drawing phase
-    END_NO_COMPOSITE = 1 << 1 // Do not composite after drawing thebes layer contents.
+    END_NO_IMMEDIATE_REDRAW = 1 << 0  // Do not perform the drawing phase
   };
 
   /**
    * Finish the construction phase of the transaction, perform the
    * drawing phase, and end the transaction.
    * During the drawing phase, all ThebesLayers in the tree are
    * drawn in tree order, exactly once each, except for those layers
    * where it is known that the visible region is empty.
    */
   virtual void EndTransaction(DrawThebesLayerCallback aCallback,
                               void* aCallbackData,
                               EndTransactionFlags aFlags = END_DEFAULT) = 0;
 
-  virtual bool HasShadowManagerInternal() const { return false; }
-  bool HasShadowManager() const { return HasShadowManagerInternal(); }
-
   bool IsSnappingEffectiveTransforms() { return mSnapEffectiveTransforms; } 
 
-  /** 
-   * Returns true if this LayerManager can properly support layers with
-   * SURFACE_COMPONENT_ALPHA. This can include disabling component
-   * alpha if required.
-   */
-  virtual bool AreComponentAlphaLayersEnabled() { return true; }
-
   /**
    * CONSTRUCTION PHASE ONLY
    * Set the root layer. The root layer is initially null. If there is
    * no root layer, EndTransaction won't draw anything.
    */
   virtual void SetRoot(Layer* aLayer) = 0;
   /**
    * Can be called anytime
@@ -423,42 +456,33 @@ public:
    */
   virtual void GetBackendName(nsAString& aName) = 0;
 
   /**
    * This setter can be used anytime. The user data for all keys is
    * initially null. Ownership pases to the layer manager.
    */
   void SetUserData(void* aKey, LayerUserData* aData)
-  {
-    mUserData.Add(static_cast<gfx::UserDataKey*>(aKey), aData, LayerManagerUserDataDestroy);
-  }
+  { mUserData.Set(aKey, aData); }
   /**
    * This can be used anytime. Ownership passes to the caller!
    */
   nsAutoPtr<LayerUserData> RemoveUserData(void* aKey)
-  { 
-    nsAutoPtr<LayerUserData> d(static_cast<LayerUserData*>(mUserData.Remove(static_cast<gfx::UserDataKey*>(aKey)))); 
-    return d;
-  }
+  { nsAutoPtr<LayerUserData> d(mUserData.Remove(aKey)); return d; }
   /**
    * This getter can be used anytime.
    */
   bool HasUserData(void* aKey)
-  {
-    return GetUserData(aKey);
-  }
+  { return mUserData.Has(aKey); }
   /**
    * This getter can be used anytime. Ownership is retained by the layer
    * manager.
    */
   LayerUserData* GetUserData(void* aKey)
-  { 
-    return static_cast<LayerUserData*>(mUserData.Get(static_cast<gfx::UserDataKey*>(aKey)));
-  }
+  { return mUserData.Get(aKey); }
 
   /**
    * Flag the next paint as the first for a document.
    */
   virtual void SetIsFirstPaint() {}
 
   // We always declare the following logging symbols, because it's
   // extremely tricky to conditionally declare them.  However, for
@@ -498,17 +522,17 @@ public:
 
   bool IsCompositingCheap(LayerManager::LayersBackend aBackend)
   { return LAYERS_BASIC != aBackend; }
 
   virtual bool IsCompositingCheap() { return true; }
 
 protected:
   nsRefPtr<Layer> mRoot;
-  gfx::UserData mUserData;
+  LayerUserDataSet mUserData;
   bool mDestroyed;
   bool mSnapEffectiveTransforms;
 
   // Print interesting information about this into aTo.  Internally
   // used to implement Dump*() and Log*().
   virtual nsACString& PrintInfo(nsACString& aTo, const char* aPrefix);
 
   static void InitLog();
@@ -748,42 +772,33 @@ public:
     return SURFACE_SINGLE_CHANNEL_ALPHA;
   }
 
   /**
    * This setter can be used anytime. The user data for all keys is
    * initially null. Ownership pases to the layer manager.
    */
   void SetUserData(void* aKey, LayerUserData* aData)
-  { 
-    mUserData.Add(static_cast<gfx::UserDataKey*>(aKey), aData, LayerManagerUserDataDestroy);
-  }
+  { mUserData.Set(aKey, aData); }
   /**
    * This can be used anytime. Ownership passes to the caller!
    */
   nsAutoPtr<LayerUserData> RemoveUserData(void* aKey)
-  { 
-    nsAutoPtr<LayerUserData> d(static_cast<LayerUserData*>(mUserData.Remove(static_cast<gfx::UserDataKey*>(aKey)))); 
-    return d;
-  }
+  { nsAutoPtr<LayerUserData> d(mUserData.Remove(aKey)); return d; }
   /**
    * This getter can be used anytime.
    */
   bool HasUserData(void* aKey)
-  {
-    return GetUserData(aKey);
-  }
+  { return mUserData.Has(aKey); }
   /**
    * This getter can be used anytime. Ownership is retained by the layer
    * manager.
    */
   LayerUserData* GetUserData(void* aKey)
-  { 
-    return static_cast<LayerUserData*>(mUserData.Get(static_cast<gfx::UserDataKey*>(aKey)));
-  }
+  { return mUserData.Get(aKey); }
 
   /**
    * |Disconnect()| is used by layers hooked up over IPC.  It may be
    * called at any time, and may not be called at all.  Using an
    * IPC-enabled layer after Destroy() (drawing etc.) results in a
    * safe no-op; no crashy or uaf etc.
    *
    * XXX: this interface is essentially LayerManager::Destroy, but at
@@ -902,39 +917,16 @@ public:
   /**
    * Log information about just this layer manager itself to the NSPR
    * log (if enabled for "Layers").
    */
   void LogSelf(const char* aPrefix="");
 
   static bool IsLogEnabled() { return LayerManager::IsLogEnabled(); }
 
-  /**
-   * Returns the current area of the layer (in layer-space coordinates)
-   * marked as needed to be recomposited.
-   */
-  const nsIntRegion& GetInvalidRegion() { return mInvalidRegion; }
-
-  /**
-   * Mark the entirety of the layer's visible region as being invalid.
-   */
-  void SetInvalidRectToVisibleRegion() { mInvalidRegion = GetVisibleRegion(); }
-
-  /**
-   * Adds to the current invalid rect.
-   */
-  void AddInvalidRect(const nsIntRect& aRect) { mInvalidRegion.Or(mInvalidRegion, aRect); }
-
-  /**
-   * Clear the invalid rect, marking the layer as being identical to what is currently
-   * composited.
-   */
-  void ClearInvalidRect() { mInvalidRegion.SetEmpty(); }
-
-
 #ifdef DEBUG
   void SetDebugColorIndex(PRUint32 aIndex) { mDebugColorIndex = aIndex; }
   PRUint32 GetDebugColorIndex() { return mDebugColorIndex; }
 #endif
 
 protected:
   Layer(LayerManager* aManager, void* aImplData) :
     mManager(aManager),
@@ -982,29 +974,28 @@ protected:
                             gfxMatrix* aResidualTransform);
 
   LayerManager* mManager;
   ContainerLayer* mParent;
   Layer* mNextSibling;
   Layer* mPrevSibling;
   void* mImplData;
   nsRefPtr<Layer> mMaskLayer;
-  gfx::UserData mUserData;
+  LayerUserDataSet mUserData;
   nsIntRegion mVisibleRegion;
   gfx3DMatrix mTransform;
   gfx3DMatrix mEffectiveTransform;
   float mOpacity;
   nsIntRect mClipRect;
   nsIntRect mTileSourceRect;
   PRUint32 mContentFlags;
   bool mUseClipRect;
   bool mUseTileSourceRect;
   bool mIsFixedPosition;
   DebugOnly<PRUint32> mDebugColorIndex;
-  nsIntRegion mInvalidRegion;
 };
 
 /**
  * A Layer which we can draw into using Thebes. It is a conceptually
  * infinite surface, but each ThebesLayer has an associated "valid region"
  * of contents that it is currently storing, which is finite. ThebesLayer
  * implementations can store content between paints.
  * 
@@ -1311,17 +1302,17 @@ public:
    * This must only be called once.
    */
   virtual void Initialize(const Data& aData) = 0;
 
   /**
    * Notify this CanvasLayer that the canvas surface contents have
    * changed (or will change) before the next transaction.
    */
-  void Updated() { mDirty = true; SetInvalidRectToVisibleRegion(); }
+  void Updated() { mDirty = true; }
 
   /**
    * Register a callback to be called at the end of each transaction.
    */
   typedef void (* DidTransactionCallback)(void* aClosureData);
   void SetDidTransactionCallback(DidTransactionCallback aCallback, void* aClosureData)
   {
     mCallback = aCallback;
--- a/gfx/layers/Makefile.in
+++ b/gfx/layers/Makefile.in
@@ -33,17 +33,16 @@ EXPORTS = \
         BasicImplData.h \
         ImageLayers.h \
         Layers.h \
         LayerManagerOGLShaders.h \
         LayerManagerOGL.h \
         LayerManagerOGLProgram.h \
         ReadbackLayer.h \
         LayerSorter.h \
-        LayerTreeInvalidation.h \
         $(NULL)
 
 CPPSRCS = \
         BasicImages.cpp \
         BasicLayers.cpp \
         BasicTiledThebesLayer.cpp \
         Layers.cpp \
         RenderTrace.cpp \
@@ -54,17 +53,16 @@ CPPSRCS = \
         ContainerLayerOGL.cpp \
         ImageLayerOGL.cpp \
         LayerManagerOGL.cpp \
         ThebesLayerOGL.cpp \
         TiledThebesLayerOGL.cpp \
         ReusableTileStoreOGL.cpp \
         LayerManagerOGLProgram.cpp \
         LayerSorter.cpp \
-        LayerTreeInvalidation.cpp \
         ImageLayers.cpp \
         $(NULL)
 
 ifeq ($(MOZ_WIDGET_TOOLKIT),windows)
 ifdef MOZ_ENABLE_D3D9_LAYER
 EXPORTS += \
         LayerManagerD3D9.h \
         DeviceManagerD3D9.h \
--- a/gfx/layers/basic/BasicImplData.h
+++ b/gfx/layers/basic/BasicImplData.h
@@ -54,22 +54,30 @@ public:
 
   /**
    * Like Paint() but called for ThebesLayers with the additional parameters
    * they need.
    * If mClipToVisibleRegion is set, then the layer must clip to its
    * effective visible region (snapped or unsnapped, it doesn't matter).
    */
   virtual void PaintThebes(gfxContext* aContext,
-                           Layer* aMasklayer,
+                           Layer* aMasklayer,
                            LayerManager::DrawThebesLayerCallback aCallback,
                            void* aCallbackData,
                            ReadbackProcessor* aReadback) {}
 
   /**
+   * Implementations return true here if they *must* retain their
+   * layer contents.  This is true of shadowable layers with shadows,
+   * because there's no target on which to composite directly in the
+   * layer-publishing child process.
+   */
+  virtual bool MustRetainContent() { return false; }
+
+  /**
    * Layers will get this call when their layer manager is destroyed, this
    * indicates they should clear resources they don't really need after their
    * LayerManager ceases to exist.
    */
   virtual void ClearCachedResources() {}
 
   /**
    * This variable is set by MarkLayersHidden() before painting. It indicates
@@ -85,24 +93,24 @@ public:
   void SetOperator(gfxContext::GraphicsOperator aOperator)
   {
     NS_ASSERTION(aOperator == gfxContext::OPERATOR_OVER ||
                  aOperator == gfxContext::OPERATOR_SOURCE,
                  "Bad composition operator");
     mOperator = aOperator;
   }
   gfxContext::GraphicsOperator GetOperator() const { return mOperator; }
-
-  /**
-   * Return a surface for this layer. Will use an existing surface, if
-   * possible, or may create a temporary surface.
-   * Implement this method for any layers that might be used as a mask.
-   * Should only return null if a surface cannor be created.
-   */
-  virtual already_AddRefed<gfxASurface> GetAsSurface() { return nsnull; }
+
+  /**
+   * Return a surface for this layer. Will use an existing surface, if
+   * possible, or may create a temporary surface.
+   * Implement this method for any layers that might be used as a mask.
+   * Should only return null if a surface cannor be created.
+   */
+  virtual already_AddRefed<gfxASurface> GetAsSurface() { return nsnull; }
 
   bool GetClipToVisibleRegion() { return mClipToVisibleRegion; }
   void SetClipToVisibleRegion(bool aClip) { mClipToVisibleRegion = aClip; }
 
   void SetDrawAtomically(bool aDrawAtomically) { mDrawAtomically = aDrawAtomically; }
 
 protected:
   bool mHidden;
--- a/gfx/layers/basic/BasicLayers.cpp
+++ b/gfx/layers/basic/BasicLayers.cpp
@@ -6,17 +6,16 @@
 #include "mozilla/Attributes.h"
 
 #include "gfxSharedImageSurface.h"
 
 #include "mozilla/layers/PLayerChild.h"
 #include "mozilla/layers/PLayersChild.h"
 #include "mozilla/layers/PLayersParent.h"
 #include "mozilla/gfx/2D.h"
-#include "mozilla/Preferences.h"
 
 #include "ipc/ShadowLayerChild.h"
 
 #include "BasicLayers.h"
 #include "BasicImplData.h"
 #include "BasicTiledThebesLayer.h"
 #include "ImageLayers.h"
 #include "RenderTrace.h"
@@ -440,19 +439,17 @@ public:
     NS_ASSERTION(BasicManager()->InConstruction(),
                  "Can only set properties in construction phase");
     ThebesLayer::SetVisibleRegion(aRegion);
   }
   virtual void InvalidateRegion(const nsIntRegion& aRegion)
   {
     NS_ASSERTION(BasicManager()->InConstruction(),
                  "Can only set properties in construction phase");
-    mInvalidRegion.Or(mInvalidRegion, aRegion);
-    mInvalidRegion.SimplifyOutward(10);
-    mValidRegion.Sub(mValidRegion, mInvalidRegion);
+    mValidRegion.Sub(mValidRegion, aRegion);
   }
 
   virtual void PaintThebes(gfxContext* aContext,
                            Layer* aMaskLayer,
                            LayerManager::DrawThebesLayerCallback aCallback,
                            void* aCallbackData,
                            ReadbackProcessor* aReadback);
 
@@ -463,17 +460,19 @@ public:
   {
     nsRefPtr<gfxASurface> referenceSurface = mBuffer.GetBuffer();
     if (!referenceSurface) {
       gfxContext* defaultTarget = BasicManager()->GetDefaultTarget();
       if (defaultTarget) {
         referenceSurface = defaultTarget->CurrentSurface();
       } else {
         nsIWidget* widget = BasicManager()->GetRetainerWidget();
-        if (!widget || !(referenceSurface = widget->GetThebesSurface())) {
+        if (widget) {
+          referenceSurface = widget->GetThebesSurface();
+        } else {
           referenceSurface = BasicManager()->GetTarget()->CurrentSurface();
         }
       }
     }
     return referenceSurface->CreateSimilarSurface(
       aType, gfxIntSize(aSize.width, aSize.height));
   }
 
@@ -642,17 +641,20 @@ BasicThebesLayer::PaintThebes(gfxContext
   SyncFrontBufferToBackBuffer();
 
   bool canUseOpaqueSurface = CanUseOpaqueSurface();
   Buffer::ContentType contentType =
     canUseOpaqueSurface ? gfxASurface::CONTENT_COLOR :
                           gfxASurface::CONTENT_COLOR_ALPHA;
   float opacity = GetEffectiveOpacity();
   
-  if (!BasicManager()->IsRetained()) {
+  if (!BasicManager()->IsRetained() ||
+      (!canUseOpaqueSurface &&
+       (mContentFlags & CONTENT_COMPONENT_ALPHA) &&
+       !MustRetainContent())) {
     NS_ASSERTION(readbackUpdates.IsEmpty(), "Can't do readback for non-retained layer");
 
     mValidRegion.SetEmpty();
     mBuffer.Clear();
 
     nsIntRegion toDraw = IntersectWithClip(GetEffectiveVisibleRegion(), aContext);
 
     RenderTraceInvalidateStart(this, "FFFF00", toDraw.GetBounds());
@@ -1329,28 +1331,32 @@ static nsIntRect
 ToInsideIntRect(const gfxRect& aRect)
 {
   gfxRect r = aRect;
   r.RoundIn();
   return nsIntRect(r.X(), r.Y(), r.Width(), r.Height());
 }
 
 BasicLayerManager::BasicLayerManager(nsIWidget* aWidget) :
+#ifdef DEBUG
   mPhase(PHASE_NONE),
+#endif
   mWidget(aWidget)
   , mDoubleBuffering(BUFFER_NONE), mUsingDefaultTarget(false)
   , mCachedSurfaceInUse(false)
   , mTransactionIncomplete(false)
 {
   MOZ_COUNT_CTOR(BasicLayerManager);
   NS_ASSERTION(aWidget, "Must provide a widget");
 }
 
 BasicLayerManager::BasicLayerManager() :
+#ifdef DEBUG
   mPhase(PHASE_NONE),
+#endif
   mWidget(nsnull)
   , mDoubleBuffering(BUFFER_NONE), mUsingDefaultTarget(false)
   , mCachedSurfaceInUse(false)
   , mTransactionIncomplete(false)
 {
   MOZ_COUNT_CTOR(BasicLayerManager);
 }
 
@@ -1441,17 +1447,19 @@ void
 BasicLayerManager::BeginTransactionWithTarget(gfxContext* aTarget)
 {
 #ifdef MOZ_LAYERS_HAVE_LOG
   MOZ_LAYERS_LOG(("[----- BeginTransaction"));
   Log();
 #endif
 
   NS_ASSERTION(!InTransaction(), "Nested transactions not allowed");
+#ifdef DEBUG
   mPhase = PHASE_CONSTRUCTION;
+#endif
   mTarget = aTarget;
 }
 
 static void
 TransformIntRect(nsIntRect& aRect, const gfxMatrix& aMatrix,
                  nsIntRect (*aRoundMethod)(const gfxRect&))
 {
   gfxRect gr = gfxRect(aRect.x, aRect.y, aRect.width, aRect.height);
@@ -1634,29 +1642,25 @@ BasicLayerManager::EndTransactionInterna
 {
   SAMPLE_LABEL("BasicLayerManager", "EndTranscationInternal");
 #ifdef MOZ_LAYERS_HAVE_LOG
   MOZ_LAYERS_LOG(("  ----- (beginning paint)"));
   Log();
 #endif
 
   NS_ASSERTION(InConstruction(), "Should be in construction phase");
+#ifdef DEBUG
   mPhase = PHASE_DRAWING;
+#endif
 
   Layer* aLayer = GetRoot();
   RenderTraceLayers(aLayer, "FF00");
 
   mTransactionIncomplete = false;
 
-  if (aFlags & END_NO_COMPOSITE) {
-    // TODO: We should really just set mTarget to null and make sure we can handle that further down the call chain
-    nsRefPtr<gfxASurface> surf = gfxPlatform::GetPlatform()->CreateOffscreenSurface(gfxIntSize(1, 1), gfxASurface::CONTENT_COLOR);
-    mTarget = new gfxContext(surf);
-  }
-
   if (mTarget && mRoot && !(aFlags & END_NO_IMMEDIATE_REDRAW)) {
     nsIntRect clipRect;
     if (HasShadowManager()) {
       // If this has a shadow manager, the clip extents of mTarget are meaningless.
       // So instead just use the root layer's visible region bounds.
       const nsIntRect& bounds = mRoot->GetVisibleRegion().GetBounds();
       gfxRect deviceRect =
           mTarget->UserToDevice(gfxRect(bounds.x, bounds.y, bounds.width, bounds.height));
@@ -1676,81 +1680,49 @@ BasicLayerManager::EndTransactionInterna
     if (IsRetained()) {
       nsIntRegion region;
       MarkLayersHidden(mRoot, clipRect, clipRect, region, ALLOW_OPAQUE);
       if (mUsingDefaultTarget && mDoubleBuffering != BUFFER_NONE) {
         ApplyDoubleBuffering(mRoot, clipRect);
       }
     }
 
-    if (aFlags & END_NO_COMPOSITE) {
-      if (IsRetained()) {
-        // Clip the destination out so that we don't draw to it, and
-        // only end up validating ThebesLayers.
-        mTarget->Clip(gfxRect(0, 0, 0, 0));
-        PaintLayer(mTarget, mRoot, aCallback, aCallbackData, nsnull);
-      }
-      // If we're not retained, then don't composite means do nothing at all.
-    } else {
-      PaintLayer(mTarget, mRoot, aCallback, aCallbackData, nsnull);
-      if (mWidget) {
-        FlashWidgetUpdateArea(mTarget);
-      }
-    }
+    PaintLayer(mTarget, mRoot, aCallback, aCallbackData, nsnull);
 
     if (!mTransactionIncomplete) {
       // Clear out target if we have a complete transaction.
       mTarget = nsnull;
     }
   }
 
 #ifdef MOZ_LAYERS_HAVE_LOG
   Log();
   MOZ_LAYERS_LOG(("]----- EndTransaction"));
 #endif
 
+#ifdef DEBUG
   // Go back to the construction phase if the transaction isn't complete.
   // Layout will update the layer tree and call EndTransaction().
   mPhase = mTransactionIncomplete ? PHASE_CONSTRUCTION : PHASE_NONE;
+#endif
 
   if (!mTransactionIncomplete) {
     // This is still valid if the transaction was incomplete.
     mUsingDefaultTarget = false;
   }
 
   NS_ASSERTION(!aCallback || !mTransactionIncomplete,
                "If callback is not null, transaction must be complete");
 
   // XXX - We should probably assert here that for an incomplete transaction
   // out target is the default target.
 
   return !mTransactionIncomplete;
 }
 
-void
-BasicLayerManager::FlashWidgetUpdateArea(gfxContext *aContext)
-{
-  static bool sWidgetFlashingEnabled;
-  static bool sWidgetFlashingPrefCached = false;
-
-  if (!sWidgetFlashingPrefCached) {
-    sWidgetFlashingPrefCached = true;
-    mozilla::Preferences::AddBoolVarCache(&sWidgetFlashingEnabled,
-                                          "nglayout.debug.widget_update_flashing");
-  }
-
-  if (sWidgetFlashingEnabled) {
-    float r = float(rand()) / RAND_MAX;
-    float g = float(rand()) / RAND_MAX;
-    float b = float(rand()) / RAND_MAX;
-    aContext->SetColor(gfxRGBA(r, g, b, 0.2));
-    aContext->Paint();
-  }
-}
-
 bool
 BasicLayerManager::EndEmptyTransaction()
 {
   if (!mRoot) {
     return false;
   }
 
   return EndTransactionInternal(nsnull, nsnull);
@@ -2325,16 +2297,17 @@ public:
 
   virtual void FillSpecificAttributes(SpecificLayerAttributes& aAttrs)
   {
     aAttrs = ThebesLayerAttributes(GetValidRegion());
   }
 
   virtual Layer* AsLayer() { return this; }
   virtual ShadowableLayer* AsShadowableLayer() { return this; }
+  virtual bool MustRetainContent() { return HasShadow(); }
 
   void SetBackBufferAndAttrs(const OptionalThebesBuffer& aBuffer,
                              const nsIntRegion& aValidRegion,
                              const OptionalThebesBuffer& aReadOnlyFrontBuffer,
                              const nsIntRegion& aFrontUpdatedRegion);
 
   virtual void Disconnect()
   {
@@ -3585,17 +3558,19 @@ BasicShadowLayerManager::EndEmptyTransac
   ForwardTransaction();
   return true;
 }
 
 void
 BasicShadowLayerManager::ForwardTransaction()
 {
   RenderTraceScope rendertrace("Foward Transaction", "000090");
+#ifdef DEBUG
   mPhase = PHASE_FORWARD;
+#endif
 
   // forward this transaction's changeset to our ShadowLayerManager
   AutoInfallibleTArray<EditReply, 10> replies;
   if (HasShadowManager() && ShadowLayerForwarder::EndTransaction(&replies)) {
     for (nsTArray<EditReply>::size_type i = 0; i < replies.Length(); ++i) {
       const EditReply& reply = replies[i];
 
       switch (reply.type()) {
@@ -3650,17 +3625,19 @@ BasicShadowLayerManager::ForwardTransact
       default:
         NS_RUNTIMEABORT("not reached");
       }
     }
   } else if (HasShadowManager()) {
     NS_WARNING("failed to forward Layers transaction");
   }
 
+#ifdef DEBUG
   mPhase = PHASE_NONE;
+#endif
 
   // this may result in Layers being deleted, which results in
   // PLayer::Send__delete__() and DeallocShmem()
   mKeepAlive.Clear();
 }
 
 ShadowableLayer*
 BasicShadowLayerManager::Hold(Layer* aLayer)
--- a/gfx/layers/basic/BasicLayers.h
+++ b/gfx/layers/basic/BasicLayers.h
@@ -81,27 +81,23 @@ public:
     BUFFER_BUFFERED
   };
   void SetDefaultTarget(gfxContext* aContext, BufferMode aDoubleBuffering);
   gfxContext* GetDefaultTarget() { return mDefaultTarget; }
 
   nsIWidget* GetRetainerWidget() { return mWidget; }
   void ClearRetainerWidget() { mWidget = nsnull; }
 
-  virtual bool IsWidgetLayerManager() { return mWidget != nsnull; }
-
   virtual void BeginTransaction();
   virtual void BeginTransactionWithTarget(gfxContext* aTarget);
   virtual bool EndEmptyTransaction();
   virtual void EndTransaction(DrawThebesLayerCallback aCallback,
                               void* aCallbackData,
                               EndTransactionFlags aFlags = END_DEFAULT);
 
-  virtual bool AreComponentAlphaLayersEnabled() { return HasShadowManager(); }
-
   virtual void SetRoot(Layer* aLayer);
 
   virtual already_AddRefed<ThebesLayer> CreateThebesLayer();
   virtual already_AddRefed<ContainerLayer> CreateContainerLayer();
   virtual already_AddRefed<ImageLayer> CreateImageLayer();
   virtual already_AddRefed<CanvasLayer> CreateCanvasLayer();
   virtual already_AddRefed<ColorLayer> CreateColorLayer();
   virtual already_AddRefed<ReadbackLayer> CreateReadbackLayer();
@@ -120,21 +116,19 @@ public:
 
   virtual LayersBackend GetBackendType() { return LAYERS_BASIC; }
   virtual void GetBackendName(nsAString& name) { name.AssignLiteral("Basic"); }
 
 #ifdef DEBUG
   bool InConstruction() { return mPhase == PHASE_CONSTRUCTION; }
   bool InDrawing() { return mPhase == PHASE_DRAWING; }
   bool InForward() { return mPhase == PHASE_FORWARD; }
+  bool InTransaction() { return mPhase != PHASE_NONE; }
 #endif
-  bool InTransaction() { return mPhase != PHASE_NONE; }
-
   gfxContext* GetTarget() { return mTarget; }
-  void SetTarget(gfxContext* aTarget) { mUsingDefaultTarget = false; mTarget = aTarget; }
   bool IsRetained() { return mWidget != nsnull; }
 
 #ifdef MOZ_LAYERS_HAVE_LOG
   virtual const char* Name() const { return "Basic"; }
 #endif // MOZ_LAYERS_HAVE_LOG
 
   // Clear the cached contents of this layer.
   void ClearCachedResources();
@@ -145,40 +139,42 @@ public:
   already_AddRefed<gfxContext> PushGroupForLayer(gfxContext* aContext, Layer* aLayer,
                                                  const nsIntRegion& aRegion,
                                                  bool* aNeedsClipToVisibleRegion);
   already_AddRefed<gfxContext> PushGroupWithCachedSurface(gfxContext *aTarget,
                                                           gfxASurface::gfxContentType aContent);
   void PopGroupToSourceWithCachedSurface(gfxContext *aTarget, gfxContext *aPushed);
 
   virtual bool IsCompositingCheap() { return false; }
+  virtual bool HasShadowManagerInternal() const { return false; }
+  bool HasShadowManager() const { return HasShadowManagerInternal(); }
   virtual PRInt32 GetMaxTextureSize() const { return PR_INT32_MAX; }
 
 protected:
+#ifdef DEBUG
   enum TransactionPhase {
     PHASE_NONE, PHASE_CONSTRUCTION, PHASE_DRAWING, PHASE_FORWARD
   };
   TransactionPhase mPhase;
+#endif
 
   // Paints aLayer to mTarget.
   void PaintLayer(gfxContext* aTarget,
                   Layer* aLayer,
                   DrawThebesLayerCallback aCallback,
                   void* aCallbackData,
                   ReadbackProcessor* aReadback);
 
   // Clear the contents of a layer
   void ClearLayer(Layer* aLayer);
 
   bool EndTransactionInternal(DrawThebesLayerCallback aCallback,
                               void* aCallbackData,
                               EndTransactionFlags aFlags = END_DEFAULT);
 
-  void FlashWidgetUpdateArea(gfxContext* aContext);
-
   // Widget whose surface should be used as the basis for ThebesLayer
   // buffers.
   nsIWidget* mWidget;
   // The default context for BeginTransaction.
   nsRefPtr<gfxContext> mDefaultTarget;
   // The context to draw into.
   nsRefPtr<gfxContext> mTarget;
   // A context we want our shadow to draw into.
--- a/gfx/layers/basic/BasicTiledThebesLayer.h
+++ b/gfx/layers/basic/BasicTiledThebesLayer.h
@@ -163,32 +163,33 @@ public:
   {
     MOZ_COUNT_DTOR(BasicTiledThebesLayer);
   }
 
 
   // Thebes Layer
   virtual Layer* AsLayer() { return this; }
   virtual void InvalidateRegion(const nsIntRegion& aRegion) {
-    mInvalidRegion.Or(mInvalidRegion, aRegion);
-    mInvalidRegion.SimplifyOutward(10);
-    mValidRegion.Sub(mValidRegion, mInvalidRegion);
+    mValidRegion.Sub(mValidRegion, aRegion);
   }
 
+  // BasicImplData
+  virtual bool MustRetainContent() { return HasShadow(); }
+
   // Shadow methods
   virtual void FillSpecificAttributes(SpecificLayerAttributes& aAttrs);
   virtual ShadowableLayer* AsShadowableLayer() { return this; }
 
   virtual void Disconnect()
   {
     BasicShadowableLayer::Disconnect();
   }
 
   virtual void PaintThebes(gfxContext* aContext,
-                           Layer* aMaskLayer,
+                           Layer* aMaskLayer,
                            LayerManager::DrawThebesLayerCallback aCallback,
                            void* aCallbackData,
                            ReadbackProcessor* aReadback);
 
 private:
   BasicShadowLayerManager* BasicManager()
   {
     return static_cast<BasicShadowLayerManager*>(mManager);
--- a/gfx/layers/d3d10/LayerManagerD3D10.cpp
+++ b/gfx/layers/d3d10/LayerManagerD3D10.cpp
@@ -194,17 +194,17 @@ LayerManagerD3D10::Initialize(bool force
 
     attachments->mVertexBuffer = mVertexBuffer;
   } else {
     mEffect = attachments->mEffect;
     mVertexBuffer = attachments->mVertexBuffer;
     mInputLayout = attachments->mInputLayout;
   }
 
-  if (LayerManager::HasShadowManager()) {
+  if (HasShadowManager()) {
     reporter.SetSuccessful();
     return true;
   }
 
   nsRefPtr<IDXGIDevice> dxgiDevice;
   nsRefPtr<IDXGIAdapter> dxgiAdapter;
   nsRefPtr<IDXGIFactory> dxgiFactory;
 
@@ -315,17 +315,17 @@ LayerManagerD3D10::EndTransaction(DrawTh
     // so we don't need to pass any global transform here.
     mRoot->ComputeEffectiveTransforms(gfx3DMatrix());
 
 #ifdef MOZ_LAYERS_HAVE_LOG
     MOZ_LAYERS_LOG(("  ----- (beginning paint)"));
     Log();
 #endif
 
-    Render(aFlags);
+    Render();
     mCurrentCallbackInfo.Callback = nsnull;
     mCurrentCallbackInfo.CallbackData = nsnull;
   }
 
 #ifdef MOZ_LAYERS_HAVE_LOG
   Log();
   MOZ_LAYERS_LOG(("]----- EndTransaction"));
 #endif
@@ -644,24 +644,20 @@ LayerManagerD3D10::EnsureReadbackManager
     return;
   }
 
   mReadbackManager = new ReadbackManagerD3D10();
   attachments->mReadbackManager = mReadbackManager;
 }
 
 void
-LayerManagerD3D10::Render(EndTransactionFlags aFlags)
+LayerManagerD3D10::Render()
 {
   static_cast<LayerD3D10*>(mRoot->ImplData())->Validate();
 
-  if (aFlags & END_NO_COMPOSITE) {
-    return;
-  }
-
   SetupPipeline();
 
   float black[] = { 0, 0, 0, 0 };
   device()->ClearRenderTargetView(mRTView, black);
 
   nsIntRect rect;
   mWidget->GetClientBounds(rect);
 
@@ -871,17 +867,17 @@ LayerD3D10::LoadMaskTexture()
       static_cast<LayerD3D10*>(maskLayer->ImplData())->GetAsTexture(&size);
   
     if (!maskSRV) {
       return SHADER_NO_MASK;
     }
 
     gfxMatrix maskTransform;
     bool maskIs2D = maskLayer->GetEffectiveTransform().CanDraw2D(&maskTransform);
-    NS_ASSERTION(maskIs2D, "How did we end up with a 3D transform here?!");
+    NS_ASSERTION(maskIs2D, "How did we end up with a 3D transform here?!");
     gfxRect bounds = gfxRect(gfxPoint(), size);
     bounds = maskTransform.TransformBounds(bounds);
 
     effect()->GetVariableByName("vMaskQuad")->AsVector()->SetFloatVector(
       ShaderConstantRectD3D10(
         (float)bounds.x,
         (float)bounds.y,
         (float)bounds.width,
--- a/gfx/layers/d3d10/LayerManagerD3D10.h
+++ b/gfx/layers/d3d10/LayerManagerD3D10.h
@@ -172,17 +172,17 @@ public:
   static void ReportFailure(const nsACString &aMsg, HRESULT aCode);
 
 private:
   void SetupPipeline();
   void UpdateRenderTarget();
   void VerifyBufferSize();
   void EnsureReadbackManager();
 
-  void Render(EndTransactionFlags aFlags);
+  void Render();
 
   nsRefPtr<ID3D10Device1> mDevice;
 
   nsRefPtr<ID3D10Effect> mEffect;
   nsRefPtr<ID3D10InputLayout> mInputLayout;
   nsRefPtr<ID3D10Buffer> mVertexBuffer;
   nsRefPtr<ReadbackManagerD3D10> mReadbackManager;
 
--- a/gfx/layers/d3d10/ThebesLayerD3D10.cpp
+++ b/gfx/layers/d3d10/ThebesLayerD3D10.cpp
@@ -48,19 +48,17 @@ ThebesLayerD3D10::~ThebesLayerD3D10()
  * figure out the optimal threshold.
  */
 #define RETENTION_THRESHOLD 16384
 
 void
 
 ThebesLayerD3D10::InvalidateRegion(const nsIntRegion &aRegion)
 {
-  mInvalidRegion.Or(mInvalidRegion, aRegion);
-  mInvalidRegion.SimplifyOutward(10);
-  mValidRegion.Sub(mValidRegion, mInvalidRegion);
+  mValidRegion.Sub(mValidRegion, aRegion);
 }
 
 void ThebesLayerD3D10::CopyRegion(ID3D10Texture2D* aSrc, const nsIntPoint &aSrcOffset,
                                   ID3D10Texture2D* aDest, const nsIntPoint &aDestOffset,
                                   const nsIntRegion &aCopyRegion, nsIntRegion* aValidRegion)
 {
   nsIntRegion retainedRegion;
   nsIntRegionRectIterator iter(aCopyRegion);
--- a/gfx/layers/d3d9/CanvasLayerD3D9.cpp
+++ b/gfx/layers/d3d9/CanvasLayerD3D9.cpp
@@ -187,19 +187,16 @@ CanvasLayerD3D9::GetLayer()
 {
   return this;
 }
 
 void
 CanvasLayerD3D9::RenderLayer()
 {
   UpdateSurface();
-  if (mD3DManager->CompositingDisabled()) {
-    return;
-  }
   FireDidTransactionCallback();
 
   if (!mTexture)
     return;
 
   /*
    * We flip the Y axis here, note we can only do this because we are in 
    * CULL_NONE mode!
@@ -359,17 +356,17 @@ Layer*
 ShadowCanvasLayerD3D9::GetLayer()
 {
   return this;
 }
 
 void
 ShadowCanvasLayerD3D9::RenderLayer()
 {
-  if (!mBuffer || mD3DManager->CompositingDisabled()) {
+  if (!mBuffer) {
     return;
   }
 
   mBuffer->RenderTo(mD3DManager, GetEffectiveVisibleRegion());
 }
 
 
 } /* namespace layers */
--- a/gfx/layers/d3d9/ColorLayerD3D9.cpp
+++ b/gfx/layers/d3d9/ColorLayerD3D9.cpp
@@ -14,19 +14,16 @@ ColorLayerD3D9::GetLayer()
   return this;
 }
 
 static void
 RenderColorLayerD3D9(ColorLayer* aLayer, LayerManagerD3D9 *aManager)
 {
   // XXX we might be able to improve performance by using
   // IDirect3DDevice9::Clear
-  if (aManager->CompositingDisabled()) {
-    return;
-  }
 
   nsIntRect visibleRect = aLayer->GetEffectiveVisibleRegion().GetBounds();
 
   aManager->device()->SetVertexShaderConstantF(
     CBvLayerQuad,
     ShaderConstantRect(visibleRect.x,
                        visibleRect.y,
                        visibleRect.width,
--- a/gfx/layers/d3d9/ContainerLayerD3D9.cpp
+++ b/gfx/layers/d3d9/ContainerLayerD3D9.cpp
@@ -142,33 +142,30 @@ ContainerRender(Container* aContainer,
   ReadbackProcessor readback;
   readback.BuildUpdates(aContainer);
 
   nsIntRect visibleRect = aContainer->GetEffectiveVisibleRegion().GetBounds();
   bool useIntermediate = aContainer->UseIntermediateSurface();
 
   aContainer->mSupportsComponentAlphaChildren = false;
   if (useIntermediate) {
+    aManager->device()->GetRenderTarget(0, getter_AddRefs(previousRenderTarget));
+    HRESULT hr = aManager->device()->CreateTexture(visibleRect.width, visibleRect.height, 1,
+                                                   D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8,
+                                                   D3DPOOL_DEFAULT, getter_AddRefs(renderTexture),
+                                                   NULL);
+    if (FAILED(hr)) {
+      aManager->ReportFailure(NS_LITERAL_CSTRING("ContainerLayerD3D9::ContainerRender(): Failed to create texture"),
+                              hr);
+      return;
+    }
+
     nsRefPtr<IDirect3DSurface9> renderSurface;
-    if (!aManager->CompositingDisabled()) {
-      aManager->device()->GetRenderTarget(0, getter_AddRefs(previousRenderTarget));
-      HRESULT hr = aManager->device()->CreateTexture(visibleRect.width, visibleRect.height, 1,
-                                                     D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8,
-                                                     D3DPOOL_DEFAULT, getter_AddRefs(renderTexture),
-                                                     NULL);
-      if (FAILED(hr)) {
-        aManager->ReportFailure(NS_LITERAL_CSTRING("ContainerLayerD3D9::ContainerRender(): Failed to create texture"),
-                                hr);
-        return;
-      }
-
-      nsRefPtr<IDirect3DSurface9> renderSurface;
-      renderTexture->GetSurfaceLevel(0, getter_AddRefs(renderSurface));
-      aManager->device()->SetRenderTarget(0, renderSurface);
-    }
+    renderTexture->GetSurfaceLevel(0, getter_AddRefs(renderSurface));
+    aManager->device()->SetRenderTarget(0, renderSurface);
 
     if (aContainer->mVisibleRegion.GetNumRects() == 1 && 
         (aContainer->GetContentFlags() & aContainer->CONTENT_OPAQUE)) {
       // don't need a background, we're going to paint all opaque stuff
       aContainer->mSupportsComponentAlphaChildren = true;
     } else {
       const gfx3DMatrix& transform3D = aContainer->GetEffectiveTransform();
       gfxMatrix transform;
@@ -180,24 +177,22 @@ ContainerRender(Container* aContainer,
       if (HasOpaqueAncestorLayer(aContainer) &&
           transform3D.Is2D(&transform) && !transform.HasNonIntegerTranslation()) {
         // Copy background up from below
         RECT dest = { 0, 0, visibleRect.width, visibleRect.height };
         RECT src = dest;
         ::OffsetRect(&src,
                      visibleRect.x + PRInt32(transform.x0),
                      visibleRect.y + PRInt32(transform.y0));
-        if (!aManager->CompositingDisabled()) {
-          hr = aManager->device()->
-            StretchRect(previousRenderTarget, &src, renderSurface, &dest, D3DTEXF_NONE);
-        }
+        hr = aManager->device()->
+          StretchRect(previousRenderTarget, &src, renderSurface, &dest, D3DTEXF_NONE);
       }
       if (hr == S_OK) {
         aContainer->mSupportsComponentAlphaChildren = true;
-      } else if (!aManager->CompositingDisabled()) {
+      } else {
         aManager->device()->
           Clear(0, 0, D3DCLEAR_TARGET, D3DCOLOR_RGBA(0, 0, 0, 0), 0, 0);
       }
     }
 
     aManager->device()->
       GetVertexShaderConstantF(CBvRenderTargetOffset, previousRenderTargetOffset, 1);
     renderTargetOffset[0] = (float)visibleRect.x;
@@ -256,17 +251,17 @@ ContainerRender(Container* aContainer,
       static_cast<ThebesLayerD3D9*>(layerToRender)->RenderThebesLayer(&readback);
     } else {
       layerToRender->RenderLayer();
     }
   }
     
   aManager->device()->SetScissorRect(&containerD3D9ClipRect);
 
-  if (useIntermediate && !aManager->CompositingDisabled()) {
+  if (useIntermediate) {
     aManager->device()->SetRenderTarget(0, previousRenderTarget);
     aManager->device()->SetVertexShaderConstantF(CBvRenderTargetOffset, previousRenderTargetOffset, 1);
     aManager->device()->SetVertexShaderConstantF(CBmProjection, &oldViewMatrix[0][0], 4);
 
     aManager->device()->SetVertexShaderConstantF(CBvLayerQuad,
                                        ShaderConstantRect(visibleRect.x,
                                                           visibleRect.y,
                                                           visibleRect.width,
--- a/gfx/layers/d3d9/ImageLayerD3D9.cpp
+++ b/gfx/layers/d3d9/ImageLayerD3D9.cpp
@@ -338,17 +338,17 @@ ImageLayerD3D9::GetTexture(Image *aImage
 
   return data->mTexture;
 }
 
 void
 ImageLayerD3D9::RenderLayer()
 {
   ImageContainer *container = GetContainer();
-  if (!container || mD3DManager->CompositingDisabled()) {
+  if (!container) {
     return;
   }
 
   AutoLockImage autoLock(container);
 
   Image *image = autoLock.GetImage();
   if (!image) {
     return;
@@ -589,20 +589,16 @@ Layer*
 ShadowImageLayerD3D9::GetLayer()
 {
   return this;
 }
 
 void
 ShadowImageLayerD3D9::RenderLayer()
 {
-  if (mD3DManager->CompositingDisabled()) {
-    return;
-  }
-
   if (mBuffer) {
     mBuffer->RenderTo(mD3DManager, GetEffectiveVisibleRegion());
   } else if (mYCbCrImage) {
     if (!mYCbCrImage->mBufferSize) {
       return;
     }
 
     if (!mYCbCrImage->GetBackendData(LayerManager::LAYERS_D3D9)) {
--- a/gfx/layers/d3d9/LayerManagerD3D9.cpp
+++ b/gfx/layers/d3d9/LayerManagerD3D9.cpp
@@ -144,17 +144,16 @@ LayerManagerD3D9::EndTransaction(DrawThe
   if (mRoot && !(aFlags & END_NO_IMMEDIATE_REDRAW)) {
     mCurrentCallbackInfo.Callback = aCallback;
     mCurrentCallbackInfo.CallbackData = aCallbackData;
 
     // The results of our drawing always go directly into a pixel buffer,
     // so we don't need to pass any global transform here.
     mRoot->ComputeEffectiveTransforms(gfx3DMatrix());
 
-    SetCompositingDisabled(aFlags & END_NO_COMPOSITE);
     Render();
     /* Clean this out for sanity */
     mCurrentCallbackInfo.Callback = NULL;
     mCurrentCallbackInfo.CallbackData = NULL;
   }
 
   // Clear mTarget, next transaction could have no target
   mTarget = NULL;
@@ -280,22 +279,16 @@ void
 LayerManagerD3D9::Render()
 {
   if (!mSwapChain->PrepareForRendering()) {
     return;
   }
   deviceManager()->SetupRenderState();
 
   SetupPipeline();
-
-  if (CompositingDisabled()) {
-    static_cast<LayerD3D9*>(mRoot->ImplData())->RenderLayer();
-    return;
-  }
-
   nsIntRect rect;
   mWidget->GetClientBounds(rect);
 
   device()->Clear(0, NULL, D3DCLEAR_TARGET, 0x00000000, 0, 0);
 
   device()->BeginScene();
 
   const nsIntRect *clipRect = mRoot->GetClipRect();
--- a/gfx/layers/d3d9/LayerManagerD3D9.h
+++ b/gfx/layers/d3d9/LayerManagerD3D9.h
@@ -174,19 +174,16 @@ public:
   { return gfxASurface::ImageFormatARGB32; }
 
 #ifdef MOZ_LAYERS_HAVE_LOG
   virtual const char* Name() const { return "D3D9"; }
 #endif // MOZ_LAYERS_HAVE_LOG
 
   void ReportFailure(const nsACString &aMsg, HRESULT aCode);
 
-  bool CompositingDisabled() { return mCompositingDisabled; }
-  void SetCompositingDisabled(bool aCompositingDisabled) { mCompositingDisabled = aCompositingDisabled; }
-
 private:
   /* Default device manager instance */
   static DeviceManagerD3D9 *mDefaultDeviceManager;
 
   /* Device manager instance for this layer manager */
   nsRefPtr<DeviceManagerD3D9> mDeviceManager;
 
   /* Swap chain associated with this layer manager */
@@ -210,22 +207,16 @@ private:
 
   /*
    * Device reset count at last paint. Whenever this changes, we need to
    * do a full layer tree update.
    */
   PRUint32 mDeviceResetCount;
 
   /*
-   * True if we should only be drawing layer contents, not
-   * compositing them to the target.
-   */
-  bool mCompositingDisabled;
-
-  /*
    * Render the current layer tree to the active target.
    */
   void Render();
 
   /*
    * Setup the pipeline.
    */
   void SetupPipeline();
--- a/gfx/layers/d3d9/ThebesLayerD3D9.cpp
+++ b/gfx/layers/d3d9/ThebesLayerD3D9.cpp
@@ -42,19 +42,17 @@ ThebesLayerD3D9::~ThebesLayerD3D9()
  * layer content retention. This is a guesstimate. Profiling could be done to
  * figure out the optimal threshold.
  */
 #define RETENTION_THRESHOLD 16384
 
 void
 ThebesLayerD3D9::InvalidateRegion(const nsIntRegion &aRegion)
 {
-  mInvalidRegion.Or(mInvalidRegion, aRegion);
-  mInvalidRegion.SimplifyOutward(10);
-  mValidRegion.Sub(mValidRegion, mInvalidRegion);
+  mValidRegion.Sub(mValidRegion, aRegion);
 }
 
 void
 ThebesLayerD3D9::CopyRegion(IDirect3DTexture9* aSrc, const nsIntPoint &aSrcOffset,
                             IDirect3DTexture9* aDest, const nsIntPoint &aDestOffset,
                             const nsIntRegion &aCopyRegion, nsIntRegion* aValidRegion)
 {
   nsRefPtr<IDirect3DSurface9> srcSurface, dstSurface;
@@ -233,20 +231,16 @@ ThebesLayerD3D9::RenderThebesLayer(Readb
       return;
     }
 
     DrawRegion(drawRegion, mode, readbackUpdates);
 
     mValidRegion = neededRegion;
   }
 
-  if (mD3DManager->CompositingDisabled()) {
-    return;
-  }
-
   SetShaderTransformAndOpacity();
 
   if (mode == SURFACE_COMPONENT_ALPHA) {
     mD3DManager->SetShaderMode(DeviceManagerD3D9::COMPONENTLAYERPASS1,
                                GetMaskLayer());
     device()->SetTexture(0, mTexture);
     device()->SetTexture(1, mTextureOnWhite);
     device()->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ZERO);
@@ -655,17 +649,17 @@ bool
 ShadowThebesLayerD3D9::IsEmpty()
 {
   return !mBuffer;
 }
 
 void
 ShadowThebesLayerD3D9::RenderThebesLayer()
 {
-  if (!mBuffer || mD3DManager->CompositingDisabled()) {
+  if (!mBuffer) {
     return;
   }
   NS_ABORT_IF_FALSE(mBuffer, "should have a buffer here");
 
   mBuffer->RenderTo(mD3DManager, GetEffectiveVisibleRegion());
 }
 
 void
--- a/gfx/layers/opengl/CanvasLayerOGL.cpp
+++ b/gfx/layers/opengl/CanvasLayerOGL.cpp
@@ -189,19 +189,16 @@ CanvasLayerOGL::UpdateSurface()
   }
 }
 
 void
 CanvasLayerOGL::RenderLayer(int aPreviousDestination,
                             const nsIntPoint& aOffset)
 {
   UpdateSurface();
-  if (mOGLManager->CompositingDisabled()) {
-    return;
-  }
   FireDidTransactionCallback();
 
   mOGLManager->MakeCurrent();
 
   // XXX We're going to need a different program depending on if
   // mGLBufferIsPremultiplied is TRUE or not.  The RGBLayerProgram
   // assumes that it's true.
 
@@ -363,19 +360,16 @@ ShadowCanvasLayerOGL::GetLayer()
 {
   return this;
 }
 
 void
 ShadowCanvasLayerOGL::RenderLayer(int aPreviousFrameBuffer,
                                   const nsIntPoint& aOffset)
 {
-  if (mOGLManager->CompositingDisabled()) {
-    return;
-  }
   mOGLManager->MakeCurrent();
 
   ShaderProgramOGL *program =
     mOGLManager->GetProgram(mTexImage->GetShaderProgramType(),
                             GetMaskLayer());
 
 
   gfx3DMatrix effectiveTransform = GetEffectiveTransform();
--- a/gfx/layers/opengl/ColorLayerOGL.cpp
+++ b/gfx/layers/opengl/ColorLayerOGL.cpp
@@ -7,20 +7,16 @@
 
 namespace mozilla {
 namespace layers {
 
 static void
 RenderColorLayer(ColorLayer* aLayer, LayerManagerOGL *aManager,
                  const nsIntPoint& aOffset)
 {
-  if (aManager->CompositingDisabled()) {
-    return;
-  }
-
   aManager->MakeCurrent();
 
   // XXX we might be able to improve performance by using glClear
 
   nsIntRect visibleRect = aLayer->GetEffectiveVisibleRegion().GetBounds();
 
   /* Multiply color by the layer opacity, as the shader
    * ignores layer opacity and expects a final color to
--- a/gfx/layers/opengl/ContainerLayerOGL.cpp
+++ b/gfx/layers/opengl/ContainerLayerOGL.cpp
@@ -174,24 +174,22 @@ ContainerRender(Container* aContainer,
         mode = LayerManagerOGL::InitModeCopy;
         framebufferRect.x += transform.x0;
         framebufferRect.y += transform.y0;
         aContainer->mSupportsComponentAlphaChildren = true;
       }
     }
 
     aContainer->gl()->PushViewportRect();
-    framebufferRect -= childOffset;
-    if (!aManager->CompositingDisabled()) {
-      aManager->CreateFBOWithTexture(framebufferRect,
-                                     mode,
-                                     aPreviousFrameBuffer,
-                                     &frameBuffer,
-                                     &containerSurface);
-    }
+    framebufferRect -= childOffset; 
+    aManager->CreateFBOWithTexture(framebufferRect,
+                                   mode,
+                                   aPreviousFrameBuffer,
+                                   &frameBuffer,
+                                   &containerSurface);
     childOffset.x = visibleRect.x;
     childOffset.y = visibleRect.y;
   } else {
     frameBuffer = aPreviousFrameBuffer;
     aContainer->mSupportsComponentAlphaChildren = (aContainer->GetContentFlags() & Layer::CONTENT_OPAQUE) ||
       (aContainer->GetParent() && aContainer->GetParent()->SupportsComponentAlphaChildren());
   }
 
@@ -236,57 +234,55 @@ ContainerRender(Container* aContainer,
 #endif
     
     // Restore the viewport
     aContainer->gl()->PopViewportRect();
     nsIntRect viewport = aContainer->gl()->ViewportRect();
     aManager->SetupPipeline(viewport.width, viewport.height,
                             LayerManagerOGL::ApplyWorldTransform);
     aContainer->gl()->PopScissorRect();
+
     aContainer->gl()->fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, aPreviousFrameBuffer);
+    aContainer->gl()->fDeleteFramebuffers(1, &frameBuffer);
 
-    if (!aManager->CompositingDisabled()) {
-      aContainer->gl()->fDeleteFramebuffers(1, &frameBuffer);
+    aContainer->gl()->fActiveTexture(LOCAL_GL_TEXTURE0);
 
-      aContainer->gl()->fActiveTexture(LOCAL_GL_TEXTURE0);
-
-      aContainer->gl()->fBindTexture(aManager->FBOTextureTarget(), containerSurface);
+    aContainer->gl()->fBindTexture(aManager->FBOTextureTarget(), containerSurface);
 
-      MaskType maskType = MaskNone;
-      if (aContainer->GetMaskLayer()) {
-        if (!aContainer->GetTransform().CanDraw2D()) {
-          maskType = Mask3d;
-        } else {
-          maskType = Mask2d;
-        }
+    MaskType maskType = MaskNone;
+    if (aContainer->GetMaskLayer()) {
+      if (!aContainer->GetTransform().CanDraw2D()) {
+        maskType = Mask3d;
+      } else {
+        maskType = Mask2d;
       }
-      ShaderProgramOGL *rgb =
-        aManager->GetFBOLayerProgram(maskType);
+    }
+    ShaderProgramOGL *rgb =
+      aManager->GetFBOLayerProgram(maskType);
 
-      rgb->Activate();
-      rgb->SetLayerQuadRect(visibleRect);
-      rgb->SetLayerTransform(transform);
-      rgb->SetLayerOpacity(opacity);
-      rgb->SetRenderOffset(aOffset);
-      rgb->SetTextureUnit(0);
-      rgb->LoadMask(aContainer->GetMaskLayer());
+    rgb->Activate();
+    rgb->SetLayerQuadRect(visibleRect);
+    rgb->SetLayerTransform(transform);
+    rgb->SetLayerOpacity(opacity);
+    rgb->SetRenderOffset(aOffset);
+    rgb->SetTextureUnit(0);
+    rgb->LoadMask(aContainer->GetMaskLayer());
 
-      if (rgb->GetTexCoordMultiplierUniformLocation() != -1) {
-        // 2DRect case, get the multiplier right for a sampler2DRect
-        rgb->SetTexCoordMultiplier(visibleRect.width, visibleRect.height);
-      }
+    if (rgb->GetTexCoordMultiplierUniformLocation() != -1) {
+      // 2DRect case, get the multiplier right for a sampler2DRect
+      rgb->SetTexCoordMultiplier(visibleRect.width, visibleRect.height);
+    }
 
-      // Drawing is always flipped, but when copying between surfaces we want to avoid
-      // this. Pass true for the flip parameter to introduce a second flip
-      // that cancels the other one out.
-      aManager->BindAndDrawQuad(rgb, true);
+    // Drawing is always flipped, but when copying between surfaces we want to avoid
+    // this. Pass true for the flip parameter to introduce a second flip
+    // that cancels the other one out.
+    aManager->BindAndDrawQuad(rgb, true);
 
-      // Clean up resources.  This also unbinds the texture.
-      aContainer->gl()->fDeleteTextures(1, &containerSurface);
-    }
+    // Clean up resources.  This also unbinds the texture.
+    aContainer->gl()->fDeleteTextures(1, &containerSurface);
   } else {
     aContainer->gl()->PopScissorRect();
   }
 }
 
 ContainerLayerOGL::ContainerLayerOGL(LayerManagerOGL *aManager)
   : ContainerLayer(aManager, NULL)
   , LayerOGL(aManager)
--- a/gfx/layers/opengl/ImageLayerOGL.cpp
+++ b/gfx/layers/opengl/ImageLayerOGL.cpp
@@ -181,17 +181,17 @@ ImageLayerOGL::GetLayer()
 }
 
 void
 ImageLayerOGL::RenderLayer(int,
                            const nsIntPoint& aOffset)
 {
   nsRefPtr<ImageContainer> container = GetContainer();
 
-  if (!container || mOGLManager->CompositingDisabled())
+  if (!container)
     return;
 
   mOGLManager->MakeCurrent();
 
   AutoLockImage autoLock(container);
 
   Image *image = autoLock.GetImage();
   if (!image) {
@@ -767,19 +767,16 @@ ShadowImageLayerOGL::GetLayer()
 {
   return this;
 }
 
 void
 ShadowImageLayerOGL::RenderLayer(int aPreviousFrameBuffer,
                                  const nsIntPoint& aOffset)
 {
-  if (mOGLManager->CompositingDisabled()) {
-    return;
-  }
   mOGLManager->MakeCurrent();
 
   if (mTexImage) {
     ShaderProgramOGL *colorProgram =
       mOGLManager->GetProgram(mTexImage->GetShaderProgramType(), GetMaskLayer());
 
     colorProgram->Activate();
     colorProgram->SetTextureUnit(0);
--- a/gfx/layers/opengl/LayerManagerOGL.cpp
+++ b/gfx/layers/opengl/LayerManagerOGL.cpp
@@ -405,17 +405,16 @@ LayerManagerOGL::EndTransaction(DrawTheb
 
   if (mRoot && !(aFlags & END_NO_IMMEDIATE_REDRAW)) {
     // The results of our drawing always go directly into a pixel buffer,
     // so we don't need to pass any global transform here.
     mRoot->ComputeEffectiveTransforms(gfx3DMatrix());
 
     mThebesLayerCallback = aCallback;
     mThebesLayerCallbackData = aCallbackData;
-    SetCompositingDisabled(aFlags & END_NO_COMPOSITE);
 
     Render();
 
     mThebesLayerCallback = nsnull;
     mThebesLayerCallbackData = nsnull;
   }
 
   mTarget = NULL;
@@ -758,23 +757,16 @@ LayerManagerOGL::Render()
   if (clipRect) {
     nsIntRect r = *clipRect;
     WorldTransformRect(r);
     mGLContext->fScissor(r.x, r.y, r.width, r.height);
   } else {
     mGLContext->fScissor(0, 0, width, height);
   }
 
-  if (CompositingDisabled()) {
-    RootLayer()->RenderLayer(mGLContext->IsDoubleBuffered() ? 0 : mBackBufferFBO,
-                             nsIntPoint(0, 0));
-    mGLContext->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, 0);
-    return;
-  }
-
   mGLContext->fEnable(LOCAL_GL_SCISSOR_TEST);
 
   // If the Java compositor is being used, this clear will be done in
   // DrawWindowUnderlay. Make sure the bits used here match up with those used
   // in mobile/android/base/gfx/LayerRenderer.java
 #ifndef MOZ_JAVA_COMPOSITOR
   mGLContext->fClearColor(0.0, 0.0, 0.0, 0.0);
   mGLContext->fClear(LOCAL_GL_COLOR_BUFFER_BIT | LOCAL_GL_DEPTH_BUFFER_BIT);
--- a/gfx/layers/opengl/LayerManagerOGL.h
+++ b/gfx/layers/opengl/LayerManagerOGL.h
@@ -345,19 +345,16 @@ public:
   gfxMatrix& GetWorldTransform(void);
   void WorldTransformRect(nsIntRect& aRect);
 
   /**
    * Set the size of the surface we're rendering to.
    */
   void SetSurfaceSize(int width, int height);
 
-  bool CompositingDisabled() { return mCompositingDisabled; }
-  void SetCompositingDisabled(bool aCompositingDisabled) { mCompositingDisabled = aCompositingDisabled; }
-
 private:
   /** Widget associated with this layer manager */
   nsIWidget *mWidget;
   nsIntSize mWidgetSize;
 
   /** The size of the surface we are rendering to */
   nsIntSize mSurfaceSize;
 
@@ -389,17 +386,16 @@ private:
    *  flipped and unflipped textures */
   GLuint mQuadVBO;
 
   /** Region we're clipping our current drawing to. */
   nsIntRegion mClippingRegion;
 
   /** Misc */
   bool mHasBGRA;
-  bool mCompositingDisabled;
 
   /**
    * When rendering to an EGL surface (e.g. on Android), we rely on being told
    * about size changes (via SetSurfaceSize) rather than pulling this information
    * from the widget, since the widget's information can lag behind.
    */
   bool mIsRenderingToEGLSurface;
 
--- a/gfx/layers/opengl/ThebesLayerOGL.cpp
+++ b/gfx/layers/opengl/ThebesLayerOGL.cpp
@@ -78,18 +78,16 @@ public:
 
   enum { PAINT_WILL_RESAMPLE = ThebesLayerBuffer::PAINT_WILL_RESAMPLE };
   virtual PaintState BeginPaint(ContentType aContentType,
                                 PRUint32 aFlags) = 0;
 
   void RenderTo(const nsIntPoint& aOffset, LayerManagerOGL* aManager,
                 PRUint32 aFlags);
 
-  void EndUpdate();
-
   nsIntSize GetSize() {
     if (mTexImage)
       return mTexImage->GetSize();
     return nsIntSize(0, 0);
   }
 
   bool Initialised() { return mInitialised; }
 
@@ -100,38 +98,33 @@ protected:
 
   ThebesLayer* mLayer;
   LayerOGL* mOGLLayer;
   nsRefPtr<TextureImage> mTexImage;
   nsRefPtr<TextureImage> mTexImageOnWhite;
   bool mInitialised;
 };
 
-void ThebesLayerBufferOGL::EndUpdate()
-{
-  if (mTexImage && mTexImage->InUpdate()) {
-    mTexImage->EndUpdate();
-  }
-
-  if (mTexImageOnWhite && mTexImageOnWhite->InUpdate()) {
-    mTexImageOnWhite->EndUpdate();
-  }
-}
-
 void
 ThebesLayerBufferOGL::RenderTo(const nsIntPoint& aOffset,
                                LayerManagerOGL* aManager,
                                PRUint32 aFlags)
 {
   NS_ASSERTION(Initialised(), "RenderTo with uninitialised buffer!");
 
   if (!mTexImage || !Initialised())
     return;
 
-  EndUpdate();
+  if (mTexImage->InUpdate()) {
+    mTexImage->EndUpdate();
+  }
+
+  if (mTexImageOnWhite && mTexImageOnWhite->InUpdate()) {
+    mTexImageOnWhite->EndUpdate();
+  }
 
 #ifdef MOZ_DUMP_PAINTING
   if (gfxUtils::sDumpPainting) {
     nsRefPtr<gfxImageSurface> surf = 
       gl()->GetTexImage(mTexImage->GetTextureID(), false, mTexImage->GetShaderProgramType());
     
     WriteSnapshotToDumpFile(mLayer, surf);
   }
@@ -779,19 +772,17 @@ ThebesLayerOGL::SetVisibleRegion(const n
   if (aRegion.IsEqual(mVisibleRegion))
     return;
   ThebesLayer::SetVisibleRegion(aRegion);
 }
 
 void
 ThebesLayerOGL::InvalidateRegion(const nsIntRegion &aRegion)
 {
-  mInvalidRegion.Or(mInvalidRegion, aRegion);
-  mInvalidRegion.SimplifyOutward(10);
-  mValidRegion.Sub(mValidRegion, mInvalidRegion);
+  mValidRegion.Sub(mValidRegion, aRegion);
 }
 
 void
 ThebesLayerOGL::RenderLayer(int aPreviousFrameBuffer,
                             const nsIntPoint& aOffset)
 {
   if (!mBuffer && !CreateSurface()) {
     return;
@@ -837,21 +828,16 @@ ThebesLayerOGL::RenderLayer(int aPreviou
       // here (OR doesn't automatically simplify to the simplest possible
       // representation of a region.)
       nsIntRegion tmp;
       tmp.Or(mVisibleRegion, state.mRegionToDraw);
       mValidRegion.Or(mValidRegion, tmp);
     }
   }
 
-  if (mOGLManager->CompositingDisabled()) {
-    mBuffer->EndUpdate();
-    return;
-  }
-
   // Drawing thebes layers can change the current context, reset it.
   gl()->MakeCurrent();
 
   gl()->fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, aPreviousFrameBuffer);
   mBuffer->RenderTo(aOffset, mOGLManager, flags);
 }
 
 Layer*
@@ -1272,17 +1258,17 @@ ShadowThebesLayerOGL::IsEmpty()
 {
   return !mBuffer;
 }
 
 void
 ShadowThebesLayerOGL::RenderLayer(int aPreviousFrameBuffer,
                                   const nsIntPoint& aOffset)
 {
-  if (!mBuffer || mOGLManager->CompositingDisabled()) {
+  if (!mBuffer) {
     return;
   }
   NS_ABORT_IF_FALSE(mBuffer, "should have a buffer here");
 
   mOGLManager->MakeCurrent();
 
   if (ShouldDoubleBuffer()) {
     // Find out what part of the screen this layer intersects with
--- a/gfx/thebes/gfx3DMatrix.cpp
+++ b/gfx/thebes/gfx3DMatrix.cpp
@@ -107,23 +107,16 @@ gfx3DMatrix::operator==(const gfx3DMatri
 {
   // XXX would be nice to memcmp here, but that breaks IEEE 754 semantics
   return _11 == o._11 && _12 == o._12 && _13 == o._13 && _14 == o._14 &&
          _21 == o._21 && _22 == o._22 && _23 == o._23 && _24 == o._24 &&
          _31 == o._31 && _32 == o._32 && _33 == o._33 && _34 == o._34 &&
          _41 == o._41 && _42 == o._42 && _43 == o._43 && _44 == o._44;
 }
 
-bool
-gfx3DMatrix::operator!=(const gfx3DMatrix& o) const
-{
-  return !((*this) == o);
-}
-
-
 gfx3DMatrix&
 gfx3DMatrix::operator/=(const gfxFloat scalar)
 {
   _11 /= scalar;
   _12 /= scalar;
   _13 /= scalar;
   _14 /= scalar;
   _21 /= scalar;
--- a/gfx/thebes/gfx3DMatrix.h
+++ b/gfx/thebes/gfx3DMatrix.h
@@ -51,17 +51,16 @@ public:
       NS_ABORT_IF_FALSE(aIndex >= 0 && aIndex <= 3, "Invalid matrix array index");
       return *reinterpret_cast<const gfxPointH3D*>((&_11)+4*aIndex);
   }
 
   /**
    * Return true if this matrix and |aMatrix| are the same matrix.
    */
   bool operator==(const gfx3DMatrix& aMatrix) const;
-  bool operator!=(const gfx3DMatrix& aMatrix) const;
   
   /**
    * Divide all values in the matrix by a scalar value
    */
   gfx3DMatrix& operator/=(gfxFloat scalar);
 
   /**
    * Create a 3D matrix from a gfxMatrix 2D affine transformation.
--- a/gfx/thebes/gfxASurface.cpp
+++ b/gfx/thebes/gfxASurface.cpp
@@ -482,23 +482,16 @@ void
 gfxASurface::MovePixels(const nsIntRect& aSourceRect,
                         const nsIntPoint& aDestTopLeft)
 {
     // Assume the backend can't handle self copying well and allocate
     // a temporary surface instead.
     nsRefPtr<gfxASurface> tmp = 
       CreateSimilarSurface(GetContentType(), 
                            gfxIntSize(aSourceRect.width, aSourceRect.height));
-    // CreateSimilarSurface can return nsnull if the current surface is
-    // in an error state. This isn't good, but its better to carry
-    // on with the error surface instead of crashing.
-    NS_ASSERTION(tmp, "Must have temporary surface to move pixels!");
-    if (!tmp) {
-        return;
-    }
     nsRefPtr<gfxContext> ctx = new gfxContext(tmp);
     ctx->SetOperator(gfxContext::OPERATOR_SOURCE);
     ctx->SetSource(this, gfxPoint(-aSourceRect.x, -aSourceRect.y));
     ctx->Paint();
 
     ctx = new gfxContext(this);
     ctx->SetOperator(gfxContext::OPERATOR_SOURCE);
     ctx->SetSource(tmp, gfxPoint(aDestTopLeft.x, aDestTopLeft.y));
--- a/image/test/mochitest/test_animSVGImage.html
+++ b/image/test/mochitest/test_animSVGImage.html
@@ -50,25 +50,23 @@ function takeReferenceSnapshot() {
   referenceDiv.style.display = "none";
   let blankSnapshot2 = snapshotWindow(window, false);
   ok(compareSnapshots(blankSnapshot, blankSnapshot2, true)[0],
      "reference div should disappear when it becomes display:none");
 }
 
 function myOnStopFrame(aRequest, aFrame) {
   gOnStopFrameCounter++;
-  ok(true, "myOnStopFrame called");
   let currentSnapshot = snapshotWindow(window, false);
   if (compareSnapshots(currentSnapshot, gReferenceSnapshot, true)[0]) {
     // SUCCESS!
     ok(true, "Animated image looks correct, " +
              "at call #" + gOnStopFrameCounter + " to onStopFrame");
     cleanUpAndFinish();
   }
-  setTimeout(function() { myOnStopFrame(0, 0); }, 1000);
 }
 
 function failTest() {
   ok(false, "timing out after " + FAILURE_TIMEOUT + "ms.  " +
             "Animated image still doesn't look correct, " +
             "after call #" + gOnStopFrameCounter + " to onStopFrame");
   cleanUpAndFinish();
 }
--- a/layout/base/FrameLayerBuilder.cpp
+++ b/layout/base/FrameLayerBuilder.cpp
@@ -11,119 +11,154 @@
 #include "Layers.h"
 #include "BasicLayers.h"
 #include "nsSubDocumentFrame.h"
 #include "nsCSSRendering.h"
 #include "nsCSSFrameConstructor.h"
 #include "gfxUtils.h"
 #include "nsImageFrame.h"
 #include "nsRenderingContext.h"
-#include "nsPrintfCString.h"
-#include "LayerTreeInvalidation.h"
-#include "nsSVGIntegrationUtils.h"
 
 #include "mozilla/Preferences.h"
 #include "sampler.h"
 
 #ifdef DEBUG
 #include <stdio.h>
-//#define DEBUG_INVALIDATIONS
 #endif
 
 using namespace mozilla::layers;
 
 namespace mozilla {
 
 /**
  * This is the userdata we associate with a layer manager.
  */
 class LayerManagerData : public LayerUserData {
 public:
-  LayerManagerData() :
-    mInvalidateAllLayers(false)
+  LayerManagerData(LayerManager *aManager) :
+    mInvalidateAllLayers(false),
+    mLayerManager(aManager)
   {
     MOZ_COUNT_CTOR(LayerManagerData);
     mFramesWithLayers.Init();
   }
   ~LayerManagerData() {
-    MOZ_COUNT_DTOR(LayerManagerData);
     // Remove display item data properties now, since we won't be able
     // to find these frames again without mFramesWithLayers.
     mFramesWithLayers.EnumerateEntries(
-        FrameLayerBuilder::RemoveDisplayItemDataForFrame, this);
+        FrameLayerBuilder::RemoveDisplayItemDataForFrame, nsnull);
+    MOZ_COUNT_DTOR(LayerManagerData);
   }
 
   /**
    * Tracks which frames have layers associated with them.
    */
   nsTHashtable<FrameLayerBuilder::DisplayItemDataEntry> mFramesWithLayers;
   bool mInvalidateAllLayers;
+  /** Layer manager we belong to, we hold a reference to this object. */
+  nsRefPtr<LayerManager> mLayerManager;
+};
+
+namespace {
+
+class RefCountedRegion : public RefCounted<RefCountedRegion> {
+public:
+  nsRegion mRegion;
 };
 
-/* static */ void
-FrameLayerBuilder::DestroyDisplayItemDataFor(nsIFrame* aFrame)
+static void DestroyRefCountedRegion(void* aPropertyValue)
 {
-  FrameProperties props = aFrame->Properties();
-  props.Delete(LayerManagerDataProperty());
-  props.Delete(LayerManagerSecondaryDataProperty());
+  static_cast<RefCountedRegion*>(aPropertyValue)->Release();
 }
 
-namespace {
+/**
+ * This property represents a region that should be invalidated in every
+ * ThebesLayer child whose parent ContainerLayer is associated with the
+ * frame. This is an nsRegion*; the coordinates of the region are
+ * relative to the top-left of the border-box of the frame the property
+ * is attached to (which is the frame for the ContainerLayer).
+ * 
+ * We add to this region in InvalidateThebesLayerContents. The region
+ * is propagated to ContainerState in BuildContainerLayerFor, and then
+ * the region(s) are actually invalidated in CreateOrRecycleThebesLayer.
+ *
+ * When the property value is null, the region is infinite --- i.e. all
+ * areas of the ThebesLayers should be invalidated.
+ */
+NS_DECLARE_FRAME_PROPERTY(ThebesLayerInvalidRegionProperty, DestroyRefCountedRegion)
+
+static void DestroyPoint(void* aPropertyValue)
+{
+  delete static_cast<nsPoint*>(aPropertyValue);
+}
+
+/**
+ * The valid content in our child ThebesLayers is defined relative to
+ * the offset from this frame to its active scroll root, mapped back
+ * by the ThebesLayer's inverse transform.  Since we accumulate the
+ * region invalidated between last-paint and next-paint, and because
+ * the offset of this frame to its active root may change during that
+ * period, we save the offset at last-paint in this property and use
+ * it to invalidate at next-paint.
+ */
+NS_DECLARE_FRAME_PROPERTY(ThebesLayerLastPaintOffsetProperty, DestroyPoint)
 
 /**
  * This is a helper object used to build up the layer children for
  * a ContainerLayer.
  */
 class ContainerState {
 public:
   ContainerState(nsDisplayListBuilder* aBuilder,
                  LayerManager* aManager,
-                 FrameLayerBuilder* aLayerBuilder,
                  nsIFrame* aContainerFrame,
                  ContainerLayer* aContainerLayer,
                  const FrameLayerBuilder::ContainerParameters& aParameters) :
     mBuilder(aBuilder), mManager(aManager),
-    mLayerBuilder(aLayerBuilder),
     mContainerFrame(aContainerFrame), mContainerLayer(aContainerLayer),
     mParameters(aParameters),
-    mNextFreeRecycledThebesLayer(0)
+    mNextFreeRecycledThebesLayer(0), mNextFreeRecycledColorLayer(0),
+    mNextFreeRecycledImageLayer(0), mInvalidateAllThebesContent(false)
   {
     nsPresContext* presContext = aContainerFrame->PresContext();
     mAppUnitsPerDevPixel = presContext->AppUnitsPerDevPixel();
     // When AllowResidualTranslation is false, display items will be drawn
     // scaled with a translation by integer pixels, so we know how the snapping
     // will work.
     mSnappingEnabled = aManager->IsSnappingEffectiveTransforms() &&
       !mParameters.AllowResidualTranslation();
     mRecycledMaskImageLayers.Init();
     CollectOldLayers();
   }
 
-  enum ProcessDisplayItemsFlags {
-    NO_COMPONENT_ALPHA = 0x01,
-  };
-
+  void AddInvalidThebesContent(const nsIntRegion& aRegion)
+  {
+    mInvalidThebesContent.Or(mInvalidThebesContent, aRegion);
+  }
+  void SetInvalidateAllThebesContent()
+  {
+    mInvalidateAllThebesContent = true;
+  }
   /**
    * This is the method that actually walks a display list and builds
    * the child layers. We invoke it recursively to process clipped sublists.
    * @param aClipRect the clip rect to apply to the list items, or null
    * if no clipping is required
    */
   void ProcessDisplayItems(const nsDisplayList& aList,
-                           FrameLayerBuilder::Clip& aClip,
-                           PRUint32 aFlags);
+                           FrameLayerBuilder::Clip& aClip);
   /**
    * This finalizes all the open ThebesLayers by popping every element off
    * mThebesLayerDataStack, then sets the children of the container layer
    * to be all the layers in mNewChildLayers in that order and removes any
    * layers as children of the container that aren't in mNewChildLayers.
    * @param aTextContentFlags if any child layer has CONTENT_COMPONENT_ALPHA,
    * set *aTextContentFlags to CONTENT_COMPONENT_ALPHA
    */
-  void Finish(PRUint32 *aTextContentFlags, LayerManagerData* aData);
+  void Finish(PRUint32 *aTextContentFlags);
 
   nsRect GetChildrenBounds() { return mBounds; }
 
   nscoord GetAppUnitsPerDevPixel() { return mAppUnitsPerDevPixel; }
 
   nsIntRect ScaleToNearestPixels(const nsRect& aRect)
   {
     return aRect.ScaleToNearestPixels(mParameters.mXScale, mParameters.mYScale,
@@ -141,16 +176,18 @@ public:
   {
     if (aSnap && mSnappingEnabled) {
       return ScaleToNearestPixels(aRect);
     }
     return aRect.ScaleToInsidePixels(mParameters.mXScale, mParameters.mYScale,
                                      mAppUnitsPerDevPixel);
   }
 
+  const FrameLayerBuilder::ContainerParameters& ScaleParameters() { return mParameters; };
+
 protected:
   /**
    * We keep a stack of these to represent the ThebesLayers that are
    * currently available to have display items added to.
    * We use a stack here because as much as possible we want to
    * assign display items to existing ThebesLayers, and to the lowest
    * ThebesLayer in z-order. This reduces the number of layers and
    * makes it more likely a display item will be rendered to an opaque
@@ -293,22 +330,22 @@ protected:
    * a recycled ThebesLayer, and sets up the transform on the ThebesLayer
    * to account for scrolling.
    */
   already_AddRefed<ThebesLayer> CreateOrRecycleThebesLayer(nsIFrame* aActiveScrolledRoot);
   /**
    * Grab the next recyclable ColorLayer, or create one if there are no
    * more recyclable ColorLayers.
    */
-  already_AddRefed<ColorLayer> CreateOrRecycleColorLayer(ThebesLayer* aThebes);
+  already_AddRefed<ColorLayer> CreateOrRecycleColorLayer();
   /**
    * Grab the next recyclable ImageLayer, or create one if there are no
    * more recyclable ImageLayers.
    */
-  already_AddRefed<ImageLayer> CreateOrRecycleImageLayer(ThebesLayer* aThebes);
+  already_AddRefed<ImageLayer> CreateOrRecycleImageLayer();
   /**
    * Grab a recyclable ImageLayer for use as a mask layer for aLayer (that is a
    * mask layer which has been used for aLayer before), or create one if such
    * a layer doesn't exist.
    */
   already_AddRefed<ImageLayer> CreateOrRecycleMaskImageLayerFor(Layer* aLayer);
   /**
    * Grabs all ThebesLayers and ColorLayers from the ContainerLayer and makes them
@@ -371,17 +408,16 @@ protected:
    * SetupMaskLayer will build a mask layer for only the first
    * aRoundedRectClipCount rounded rects in aClip
    */
   void SetupMaskLayer(Layer *aLayer, const FrameLayerBuilder::Clip& aClip,
                       PRUint32 aRoundedRectClipCount = PR_UINT32_MAX);
 
   nsDisplayListBuilder*            mBuilder;
   LayerManager*                    mManager;
-  FrameLayerBuilder*               mLayerBuilder;
   nsIFrame*                        mContainerFrame;
   ContainerLayer*                  mContainerLayer;
   FrameLayerBuilder::ContainerParameters mParameters;
   /**
    * The region of ThebesLayers that should be invalidated every time
    * we recycle one.
    */
   nsIntRegion                      mInvalidThebesContent;
@@ -390,20 +426,25 @@ protected:
   /**
    * We collect the list of children in here. During ProcessDisplayItems,
    * the layers in this array either have mContainerLayer as their parent,
    * or no parent.
    */
   typedef nsAutoTArray<nsRefPtr<Layer>,1> AutoLayersArray;
   AutoLayersArray                  mNewChildLayers;
   nsTArray<nsRefPtr<ThebesLayer> > mRecycledThebesLayers;
+  nsTArray<nsRefPtr<ColorLayer> >  mRecycledColorLayers;
+  nsTArray<nsRefPtr<ImageLayer> >  mRecycledImageLayers;
   nsDataHashtable<nsPtrHashKey<Layer>, nsRefPtr<ImageLayer> >
     mRecycledMaskImageLayers;
   PRUint32                         mNextFreeRecycledThebesLayer;
+  PRUint32                         mNextFreeRecycledColorLayer;
+  PRUint32                         mNextFreeRecycledImageLayer;
   nscoord                          mAppUnitsPerDevPixel;
+  bool                             mInvalidateAllThebesContent;
   bool                             mSnappingEnabled;
 };
 
 class ThebesDisplayItemLayerUserData : public LayerUserData
 {
 public:
   ThebesDisplayItemLayerUserData() :
     mForcedBackgroundColor(NS_RGBA(0,0,0,0)),
@@ -426,21 +467,16 @@ public:
    * frame for the display items that is being actively scrolled). But
    * we force the ThebesLayer transform to be an integer translation, and we may
    * have a resolution scale, so we have to snap the ThebesLayer transform, so
    * 0,0 may not be exactly the top-left of the active scrolled root. Here we
    * store the coordinates in ThebesLayer space of the top-left of the
    * active scrolled root.
    */
   gfxPoint mActiveScrolledRootPosition;
-
-  nsIntRegion mRegionToInvalidate;
-
-  nsRefPtr<ColorLayer> mColorLayer;
-  nsRefPtr<ImageLayer> mImageLayer;
 };
 
 /*
  * User data for layers which will be used as masks.
  */
 struct MaskLayerUserData : public LayerUserData
 {
   // properties of the mask layer; the mask layer may be re-used if these
@@ -497,86 +533,30 @@ MaskLayerUserData* GetMaskLayerUserData(
 ThebesDisplayItemLayerUserData* GetThebesDisplayItemLayerUserData(Layer* aLayer)
 {
   return static_cast<ThebesDisplayItemLayerUserData*>(
     aLayer->GetUserData(&gThebesDisplayItemLayerUserData));
 }
 
 } // anonymous namespace
 
-PRUint8 gLayerManagerLayerBuilder;
-PRUint8 gLayerManagerSecondary;
-
-bool FrameLayerBuilder::sWidgetManagerSecondary = nsnull;
-
-/* static */ const FramePropertyDescriptor* 
-FrameLayerBuilder::GetDescriptorForManager(LayerManager* aManager)
-{
-  bool secondary = sWidgetManagerSecondary;
-  if (aManager) {
-    secondary = !!static_cast<LayerManagerSecondary*>(aManager->GetUserData(&gLayerManagerSecondary));
-  }
-
-  return secondary ? LayerManagerSecondaryDataProperty() : LayerManagerDataProperty();
-}
-
-LayerManagerData*
-FrameLayerBuilder::GetManagerData(nsIFrame* aFrame, LayerManager* aManager)
-{
-  FrameProperties props = aFrame->Properties();
-  return static_cast<LayerManagerData*>(props.Get(GetDescriptorForManager(aManager)));
-}
-
-void
-FrameLayerBuilder::SetManagerData(nsIFrame* aFrame, LayerManagerData* aData)
-{
-  FrameProperties props = aFrame->Properties();
-  const FramePropertyDescriptor* desc = GetDescriptorForManager(nsnull);
-
-  props.Remove(desc);
-  if (aData) {
-    props.Set(desc, aData);
-  }
-}
-
-void
-FrameLayerBuilder::ClearManagerData(nsIFrame* aFrame)
-{
-  SetManagerData(aFrame, nsnull);
-}
-
-void
-FrameLayerBuilder::ClearManagerData(nsIFrame* aFrame, LayerManagerData* aData)
-{
-  NS_ABORT_IF_FALSE(aData, "Must have a widget manager to check for manager data!");
-
-  FrameProperties props = aFrame->Properties();
-  if (aData == static_cast<LayerManagerData*>(props.Get(LayerManagerDataProperty()))) {
-    props.Remove(LayerManagerDataProperty());
-    return;
-  }
-  if (aData == static_cast<LayerManagerData*>(props.Get(LayerManagerSecondaryDataProperty()))) {
-    props.Remove(LayerManagerSecondaryDataProperty());
-    return;
-  }
-}
-
 void
 FrameLayerBuilder::Init(nsDisplayListBuilder* aBuilder)
 {
-  mDisplayListBuilder = aBuilder;
   mRootPresContext = aBuilder->ReferenceFrame()->PresContext()->GetRootPresContext();
   if (mRootPresContext) {
     mInitialDOMGeneration = mRootPresContext->GetDOMGeneration();
   }
 }
 
 bool
 FrameLayerBuilder::DisplayItemDataEntry::HasNonEmptyContainerLayer()
 {
+  if (mIsSharingContainerLayer)
+    return true;
   for (PRUint32 i = 0; i < mData.Length(); ++i) {
     if (mData[i].mLayer->GetType() == Layer::TYPE_CONTAINER &&
         mData[i].mLayerState != LAYER_ACTIVE_EMPTY)
       return true;
   }
   return false;
 }
 
@@ -596,133 +576,52 @@ FrameLayerBuilder::FlashPaint(gfxContext
     float r = float(rand()) / RAND_MAX;
     float g = float(rand()) / RAND_MAX;
     float b = float(rand()) / RAND_MAX;
     aContext->SetColor(gfxRGBA(r, g, b, 0.2));
     aContext->Paint();
   }
 }
 
-nsTArray<FrameLayerBuilder::DisplayItemData>*
+/* static */ nsTArray<FrameLayerBuilder::DisplayItemData>*
 FrameLayerBuilder::GetDisplayItemDataArrayForFrame(nsIFrame* aFrame)
 {
-  LayerManagerData* data = static_cast<LayerManagerData*>
-    (mRetainingManager->GetUserData(&gLayerManagerUserData));
-  if (!data) {
+  FrameProperties props = aFrame->Properties();
+  LayerManagerData *data =
+    reinterpret_cast<LayerManagerData*>(props.Get(LayerManagerDataProperty()));
+  if (!data)
     return nsnull;
-  }
+
   DisplayItemDataEntry *entry = data->mFramesWithLayers.GetEntry(aFrame);
+  NS_ASSERTION(entry, "out of sync?");
   if (!entry)
     return nsnull;
 
   return &entry->mData;
 }
 
-nsACString&
-AppendToString(nsACString& s, const nsIntRect& r,
-               const char* pfx="", const char* sfx="")
-{
-  s += pfx;
-  s += nsPrintfCString(
-    "(x=%d, y=%d, w=%d, h=%d)",
-    r.x, r.y, r.width, r.height);
-  return s += sfx;
-}
-
-nsACString&
-AppendToString(nsACString& s, const nsIntRegion& r,
-               const char* pfx="", const char* sfx="")
-{
-  s += pfx;
-
-  nsIntRegionRectIterator it(r);
-  s += "< ";
-  while (const nsIntRect* sr = it.Next()) {
-    AppendToString(s, *sr) += "; ";
-  }
-  s += ">";
-
-  return s += sfx;
-}
-
-/**
- * Invalidate aRegion in aLayer. aLayer is in the coordinate system
- * *after* aTranslation has been applied, so we need to
- * apply the inverse of that transform before calling InvalidateRegion.
- */
-static void
-InvalidatePostTransformRegion(ThebesLayer* aLayer, const nsIntRegion& aRegion,
-                              const nsIntPoint& aTranslation)
-{
-  // Convert the region from the coordinates of the container layer
-  // (relative to the snapped top-left of the display list reference frame)
-  // to the ThebesLayer's own coordinates
-  nsIntRegion rgn = aRegion;
-  rgn.MoveBy(-aTranslation);
-  aLayer->InvalidateRegion(rgn);
-#ifdef DEBUG_INVALIDATIONS
-  nsCAutoString str;
-  AppendToString(str, rgn);
-  printf("Invalidating layer %p: %s\n", aLayer, str.get());
-#endif
-}
-
-/**
- * Some frames can have multiple, nested, retaining layer managers
- * associated with them (normal manager, inactive managers, SVG effects).
- * In these cases we store the 'outermost' LayerManager data property
- * on the frame since we can walk down the chain from there.
- *
- * If one of these frames has just been destroyed, we will free the inner
- * layer manager when removing the entry from mFramesWithLayers. Destroying
- * the layer manager destroys the LayerManagerData and calls into 
- * RemoveDisplayItemDataForFrame. If the inner layer manager had any
- * items with the same frame, then we attempt to retrieve properties
- * from the deleted frame.
- *
- * Cache the destroyed frame pointer here so we can avoid crashing in this case.
- */
-static nsIFrame* sDestroyedFrame = NULL;
-
 /* static */ void
 FrameLayerBuilder::RemoveFrameFromLayerManager(nsIFrame* aFrame,
                                                void* aPropertyValue)
 {
   LayerManagerData *data = reinterpret_cast<LayerManagerData*>(aPropertyValue);
-
-  DisplayItemDataEntry *entry = data->mFramesWithLayers.GetEntry(aFrame);
-  for (PRUint32 i = 0; i < entry->mData.Length(); ++i) {
-    ThebesLayer* t = entry->mData[i].mLayer->AsThebesLayer();
-    if (t) {
-      ThebesDisplayItemLayerUserData* data =
-          static_cast<ThebesDisplayItemLayerUserData*>(t->GetUserData(&gThebesDisplayItemLayerUserData));
-      if (data) {
-        nsRegion old = entry->mData[i].mGeometry->ComputeInvalidationRegion();
-        nsIntRegion rgn = old.ScaleToOutsidePixels(data->mXScale, data->mYScale, entry->mData[i].mGeometry->mAppUnitsPerDevPixel);
-        rgn.MoveBy(-entry->mData[i].mGeometry->mPaintOffset);
-        data->mRegionToInvalidate.Or(data->mRegionToInvalidate, rgn);
-      }
-    }
+  data->mFramesWithLayers.RemoveEntry(aFrame);
+  if (data->mFramesWithLayers.Count() == 0) {
+    data->mLayerManager->RemoveUserData(&gLayerManagerUserData);
   }
-  sDestroyedFrame = aFrame;
-  data->mFramesWithLayers.RemoveEntry(aFrame);
-  sDestroyedFrame = NULL;
 }
 
 void
 FrameLayerBuilder::DidBeginRetainedLayerTransaction(LayerManager* aManager)
 {
   mRetainingManager = aManager;
   LayerManagerData* data = static_cast<LayerManagerData*>
     (aManager->GetUserData(&gLayerManagerUserData));
   if (data) {
     mInvalidateAllLayers = data->mInvalidateAllLayers;
-  } else {
-    data = new LayerManagerData();
-    aManager->SetUserData(&gLayerManagerUserData, data);
   }
 }
 
 /**
  * A helper function to remove the mThebesLayerItems entries for every
  * layer in aLayer's subtree.
  */
 void
@@ -736,295 +635,256 @@ FrameLayerBuilder::RemoveThebesItemsForL
 
   for (Layer* child = aLayer->GetFirstChild(); child;
        child = child->GetNextSibling()) {
     RemoveThebesItemsForLayerSubtree(child);
   }
 }
 
 void
-FrameLayerBuilder::WillEndTransaction()
+FrameLayerBuilder::DidEndTransaction(LayerManager* aManager)
 {
-  if (!mRetainingManager) {
+  if (aManager != mRetainingManager) {
+    Layer* root = aManager->GetRoot();
+    if (root) {
+      RemoveThebesItemsForLayerSubtree(root);
+    }
+  }
+}
+
+void
+FrameLayerBuilder::WillEndTransaction(LayerManager* aManager)
+{
+  if (aManager != mRetainingManager)
     return;
-  }
 
-  // We need to save the data we'll need to support retaining.
+  // We need to save the data we'll need to support retaining. We do this
+  // before we paint so that invalidation triggered by painting will
+  // be able to update the ThebesLayerInvalidRegionProperty values
+  // correctly and the NS_FRAME_HAS_CONTAINER_LAYER bits will be set
+  // correctly.
   LayerManagerData* data = static_cast<LayerManagerData*>
     (mRetainingManager->GetUserData(&gLayerManagerUserData));
-  NS_ASSERTION(data, "Must have data!");
-  // Update all the frames that used to have layers.
-  data->mFramesWithLayers.EnumerateEntries(UpdateDisplayItemDataForFrame, this);
-
+  if (data) {
+    // Update all the frames that used to have layers.
+    data->mFramesWithLayers.EnumerateEntries(UpdateDisplayItemDataForFrame, this);
+  } else {
+    data = new LayerManagerData(mRetainingManager);
+    mRetainingManager->SetUserData(&gLayerManagerUserData, data);
+  }
   // Now go through all the frames that didn't have any retained
   // display items before, and record those retained display items.
   // This also empties mNewDisplayItemData.
   mNewDisplayItemData.EnumerateEntries(StoreNewDisplayItemData, data);
   data->mInvalidateAllLayers = false;
+
+  NS_ASSERTION(data->mFramesWithLayers.Count() > 0,
+               "Some frame must have a layer!");
 }
 
-/* static */ PLDHashOperator
-FrameLayerBuilder::ProcessRemovedDisplayItems(DisplayItemDataEntry* aEntry,
-                                              void* aUserArg)
+/**
+ * If *aThebesLayerInvalidRegion is non-null, use it as this frame's
+ * region property. Otherwise set it to the frame's region property.
+ */
+static void
+SetHasContainerLayer(nsIFrame* aFrame, nsPoint aOffsetToRoot,
+                     RefCountedRegion** aThebesLayerInvalidRegion)
 {
-  Layer* layer = static_cast<Layer*>(aUserArg);
-  for (PRUint32 i = 0; i < aEntry->mData.Length(); ++i) {
-    DisplayItemData& item = aEntry->mData[i];
-    ThebesLayer* t = item.mLayer->AsThebesLayer();
-    if (!item.mUsed && t && item.mLayer == layer) {
-#ifdef DEBUG_INVALIDATIONS
-      printf("Invalidating unused display item (%i) belonging to frame %p from layer %p\n", item.mDisplayItemKey, aEntry->GetKey(), t);
-#endif
-      ThebesDisplayItemLayerUserData* data =
-          static_cast<ThebesDisplayItemLayerUserData*>(t->GetUserData(&gThebesDisplayItemLayerUserData));
-      InvalidatePostTransformRegion(t,
-          item.mGeometry->ComputeInvalidationRegion().
-            ScaleToOutsidePixels(data->mXScale, data->mYScale, item.mGeometry->mAppUnitsPerDevPixel),
-          item.mGeometry->mPaintOffset);
+  aFrame->AddStateBits(NS_FRAME_HAS_CONTAINER_LAYER);
+  for (nsIFrame* f = aFrame;
+       f && !(f->GetStateBits() & NS_FRAME_HAS_CONTAINER_LAYER_DESCENDANT);
+       f = nsLayoutUtils::GetCrossDocParentFrame(f)) {
+    f->AddStateBits(NS_FRAME_HAS_CONTAINER_LAYER_DESCENDANT);
+  }
+
+  FrameProperties props = aFrame->Properties();
+  nsPoint* lastPaintOffset = static_cast<nsPoint*>
+    (props.Get(ThebesLayerLastPaintOffsetProperty()));
+  if (lastPaintOffset) {
+    *lastPaintOffset = aOffsetToRoot;
+  } else {
+    props.Set(ThebesLayerLastPaintOffsetProperty(), new nsPoint(aOffsetToRoot));
+  }
+
+  // Reset or create the invalid region now so we can start collecting
+  // new dirty areas.
+  if (*aThebesLayerInvalidRegion) {
+    (*aThebesLayerInvalidRegion)->AddRef();
+    props.Set(ThebesLayerInvalidRegionProperty(), *aThebesLayerInvalidRegion);
+  } else {
+    RefCountedRegion* invalidRegion = static_cast<RefCountedRegion*>
+      (props.Get(ThebesLayerInvalidRegionProperty()));
+    if (invalidRegion) {
+      invalidRegion->mRegion.SetEmpty();
+    } else {
+      invalidRegion = new RefCountedRegion();
+      invalidRegion->AddRef();
+      props.Set(ThebesLayerInvalidRegionProperty(), invalidRegion);
     }
+    *aThebesLayerInvalidRegion = invalidRegion;
   }
-  return PL_DHASH_NEXT;
+}
+
+static void
+SetNoContainerLayer(nsIFrame* aFrame)
+{
+  FrameProperties props = aFrame->Properties();
+  props.Delete(ThebesLayerInvalidRegionProperty());
+  props.Delete(ThebesLayerLastPaintOffsetProperty());
+  aFrame->RemoveStateBits(NS_FRAME_HAS_CONTAINER_LAYER);
 }
 
 /* static */ PLDHashOperator
 FrameLayerBuilder::UpdateDisplayItemDataForFrame(DisplayItemDataEntry* aEntry,
                                                  void* aUserArg)
 {
   FrameLayerBuilder* builder = static_cast<FrameLayerBuilder*>(aUserArg);
   nsIFrame* f = aEntry->GetKey();
+  FrameProperties props = f->Properties();
   DisplayItemDataEntry* newDisplayItems =
     builder ? builder->mNewDisplayItemData.GetEntry(f) : nsnull;
-  LayerManagerData* managerData = static_cast<LayerManagerData*>
-    (builder->GetRetainingLayerManager()->GetUserData(&gLayerManagerUserData));
-  LayerManagerData* data = GetManagerData(f);
-  if (!newDisplayItems || newDisplayItems->mData.IsEmpty()) {
+  if (!newDisplayItems) {
     // This frame was visible, but isn't anymore.
-    if (newDisplayItems) {
-      builder->mNewDisplayItemData.RawRemoveEntry(newDisplayItems);
-    }
-    if (data == managerData) {
-      ClearManagerData(f);
-    }
+    bool found;
+    props.Remove(LayerManagerDataProperty(), &found);
+    NS_ASSERTION(found, "How can the frame property be missing?");
+    SetNoContainerLayer(f);
     return PL_DHASH_REMOVE;
   }
 
-  SetManagerData(f, managerData);
+  if (!newDisplayItems->HasNonEmptyContainerLayer()) {
+    SetNoContainerLayer(f);
+  }
 
   // Steal the list of display item layers
   aEntry->mData.SwapElements(newDisplayItems->mData);
   // Don't need to process this frame again
   builder->mNewDisplayItemData.RawRemoveEntry(newDisplayItems);
   return PL_DHASH_NEXT;
 }
-  
-/* static */ PLDHashOperator 
-FrameLayerBuilder::RemoveDisplayItemDataForFrame(DisplayItemDataEntry* aEntry,
-                                                 void* aClosure)
-{
-  LayerManagerData* managerData = static_cast<LayerManagerData*>(aClosure);
-  nsIFrame* f = aEntry->GetKey();
-  // If this was called from a frame destructor then the prop is definitely already gone,
-  // and we could crash trying to check. See the definition of sDestroyedFrame.
-  if (f != sDestroyedFrame) {
-    ClearManagerData(f, managerData);
-  }
-  return PL_DHASH_REMOVE;
-}
 
 /* static */ PLDHashOperator
 FrameLayerBuilder::StoreNewDisplayItemData(DisplayItemDataEntry* aEntry,
                                            void* aUserArg)
 {
   LayerManagerData* data = static_cast<LayerManagerData*>(aUserArg);
   nsIFrame* f = aEntry->GetKey();
+  FrameProperties props = f->Properties();
   // Remember that this frame has display items in retained layers
   NS_ASSERTION(!data->mFramesWithLayers.GetEntry(f),
                "We shouldn't get here if we're already in mFramesWithLayers");
   DisplayItemDataEntry *newEntry = data->mFramesWithLayers.PutEntry(f);
+  NS_ASSERTION(!props.Get(LayerManagerDataProperty()),
+               "mFramesWithLayers out of sync");
 
   newEntry->mData.SwapElements(aEntry->mData);
-  // Remove any old layer manager data for this frame. We don't destroy it
-  // because we don't want it to call the frame destroyed function.
-  // When a frame has multiple layer managers (main, inactive, svg), we
-  // only need to store the outermost one since that will be enough to
-  // invalidate the entire region covered by all the children.
-  SetManagerData(f, data);
+  props.Set(LayerManagerDataProperty(), data);
   return PL_DHASH_REMOVE;
 }
 
-/**
- * Attempts to find the LayerManagerData for the widget manager
- * for the given frame, nsnull otherwise.
- */
-static LayerManagerData*
-GetDefaultLayerManagerDataForFrame(nsIFrame* aFrame)
+bool
+FrameLayerBuilder::HasRetainedLayerFor(nsIFrame* aFrame, PRUint32 aDisplayItemKey)
 {
-  FrameProperties props = aFrame->Properties();
-  return static_cast<LayerManagerData*>(props.Get(FrameLayerBuilder::LayerManagerDataProperty()));
-}
-
-/* static */ FrameLayerBuilder::DisplayItemData*
-FrameLayerBuilder::GetDisplayItemDataForManager(nsIFrame* aFrame, PRUint32 aDisplayItemKey, LayerManager* aManager)
-{
-  LayerManagerData *data;
-  if (!aManager) {
-    data = GetDefaultLayerManagerDataForFrame(aFrame);
-  } else {
-    data = static_cast<LayerManagerData*>(aManager->GetUserData(&gLayerManagerUserData));
-  }
-  
-  if (!data) {
-    return nsnull;
-  }
+  nsTArray<DisplayItemData> *array = GetDisplayItemDataArrayForFrame(aFrame);
+  if (!array)
+    return false;
 
-  DisplayItemDataEntry *entry = data->mFramesWithLayers.GetEntry(aFrame);
-  if (!entry) {
-    return nsnull;
-  }
-
-  for (PRUint32 i = 0; i < entry->mData.Length(); ++i) {
-    if (entry->mData[i].mDisplayItemKey == aDisplayItemKey) {
-      return &entry->mData[i];
-    }
-  }
-  
-  return nsnull;
-}
-
-/* static */ FrameLayerBuilder::DisplayItemData*
-FrameLayerBuilder::GetDisplayItemDataForManager(nsDisplayItem* aItem, LayerManager* aManager)
-{
-  return GetDisplayItemDataForManager(aItem->GetUnderlyingFrame(), aItem->GetPerFrameKey(), aManager);
-}
-
-bool
-FrameLayerBuilder::HasRetainedLayerFor(nsIFrame* aFrame, PRUint32 aDisplayItemKey, LayerManager* aManager)
-{
-  DisplayItemData* data = GetDisplayItemDataForManager(aFrame, aDisplayItemKey, aManager);
-  if (data) {
-    Layer* layer = data->mLayer;
-    if (layer->Manager()->GetUserData(&gLayerManagerUserData)) {
-      // All layer managers with our user data are retained layer managers
-      return true;
+  for (PRUint32 i = 0; i < array->Length(); ++i) {
+    if (array->ElementAt(i).mDisplayItemKey == aDisplayItemKey) {
+      Layer* layer = array->ElementAt(i).mLayer;
+      if (layer->Manager()->GetUserData(&gLayerManagerUserData)) {
+        // All layer managers with our user data are retained layer managers
+        return true;
+      }
     }
   }
   return false;
 }
 
 Layer*
-FrameLayerBuilder::GetOldLayerFor(nsIFrame* aFrame, PRUint32 aDisplayItemKey, nsDisplayItemGeometry** aOldGeometry)
+FrameLayerBuilder::GetOldLayerFor(nsIFrame* aFrame, PRUint32 aDisplayItemKey)
 {
   // If we need to build a new layer tree, then just refuse to recycle
   // anything.
   if (!mRetainingManager || mInvalidateAllLayers)
     return nsnull;
 
   nsTArray<DisplayItemData> *array = GetDisplayItemDataArrayForFrame(aFrame);
   if (!array)
     return nsnull;
 
   for (PRUint32 i = 0; i < array->Length(); ++i) {
     if (array->ElementAt(i).mDisplayItemKey == aDisplayItemKey) {
       Layer* layer = array->ElementAt(i).mLayer;
-      if (layer->Manager() == mRetainingManager) {
-        if (aOldGeometry) {
-          *aOldGeometry = array->ElementAt(i).mGeometry.get();
-        }
+      if (layer->Manager() == mRetainingManager)
         return layer;
-      }
     }
   }
   return nsnull;
 }
 
-/* static */ Layer*
-FrameLayerBuilder::GetDebugOldLayerFor(nsIFrame* aFrame, PRUint32 aDisplayItemKey)
+/**
+ * Invalidate aRegion in aLayer. aLayer is in the coordinate system
+ * *after* aTranslation has been applied, so we need to
+ * apply the inverse of that transform before calling InvalidateRegion.
+ */
+static void
+InvalidatePostTransformRegion(ThebesLayer* aLayer, const nsIntRegion& aRegion,
+                              const nsIntPoint& aTranslation)
 {
-  LayerManagerData* data = GetManagerData(aFrame);
-  if (!data) {
-    return nsnull;
-  }
-  DisplayItemDataEntry *entry = data->mFramesWithLayers.GetEntry(aFrame);
-  if (!entry)
-    return nsnull;
-
-  nsTArray<DisplayItemData> *array = &entry->mData;
-  if (!array)
-    return nsnull;
-
-  for (PRUint32 i = 0; i < array->Length(); ++i) {
-    if (array->ElementAt(i).mDisplayItemKey == aDisplayItemKey) {
-      return array->ElementAt(i).mLayer;
-    }
-  }
-  return nsnull;
-}
-
-LayerManager*
-FrameLayerBuilder::GetInactiveLayerManagerFor(nsDisplayItem* aItem)
-{
-  nsTArray<FrameLayerBuilder::DisplayItemData> *array = GetDisplayItemDataArrayForFrame(aItem->GetUnderlyingFrame());
-  NS_ASSERTION(array, "We need an array here!. Really, we do.");
-
-  nsRefPtr<LayerManager> tempManager;
-  for (PRUint32 i = 0; i < array->Length(); ++i) {
-    if (array->ElementAt(i).mDisplayItemKey == aItem->GetPerFrameKey()) {
-      NS_ASSERTION(array->ElementAt(i).mInactiveManager, "Must already have one of these");
-      return array->ElementAt(i).mInactiveManager;
-      
-    }
-  }
-  NS_ERROR("Failed to find data for display item");
-  return NULL;
+  // Convert the region from the coordinates of the container layer
+  // (relative to the snapped top-left of the display list reference frame)
+  // to the ThebesLayer's own coordinates
+  nsIntRegion rgn = aRegion;
+  rgn.MoveBy(-aTranslation);
+  aLayer->InvalidateRegion(rgn);
 }
 
 already_AddRefed<ColorLayer>
-ContainerState::CreateOrRecycleColorLayer(ThebesLayer *aThebes)
+ContainerState::CreateOrRecycleColorLayer()
 {
-  ThebesDisplayItemLayerUserData* data = 
-      static_cast<ThebesDisplayItemLayerUserData*>(aThebes->GetUserData(&gThebesDisplayItemLayerUserData));
-  nsRefPtr<ColorLayer> layer = data->mColorLayer;
-  if (layer) {
+  nsRefPtr<ColorLayer> layer;
+  if (mNextFreeRecycledColorLayer < mRecycledColorLayers.Length()) {
+    // Recycle a layer
+    layer = mRecycledColorLayers[mNextFreeRecycledColorLayer];
+    ++mNextFreeRecycledColorLayer;
+    // Clear clip rect and mask layer so we don't accidentally stay clipped.
+    // We will reapply any necessary clipping.
     layer->SetClipRect(nsnull);
     layer->SetMaskLayer(nsnull);
   } else {
     // Create a new layer
     layer = mManager->CreateColorLayer();
     if (!layer)
       return nsnull;
     // Mark this layer as being used for Thebes-painting display items
-    data->mColorLayer = layer;
     layer->SetUserData(&gColorLayerUserData, nsnull);
-    
-    // Remove other layer types we might have stored for this ThebesLayer
-    data->mImageLayer = nsnull;
   }
   return layer.forget();
 }
 
 already_AddRefed<ImageLayer>
-ContainerState::CreateOrRecycleImageLayer(ThebesLayer *aThebes)
+ContainerState::CreateOrRecycleImageLayer()
 {
-  ThebesDisplayItemLayerUserData* data = 
-      static_cast<ThebesDisplayItemLayerUserData*>(aThebes->GetUserData(&gThebesDisplayItemLayerUserData));
-  nsRefPtr<ImageLayer> layer = data->mImageLayer;
-  if (layer) {
+  nsRefPtr<ImageLayer> layer;
+  if (mNextFreeRecycledImageLayer < mRecycledImageLayers.Length()) {
+    // Recycle a layer
+    layer = mRecycledImageLayers[mNextFreeRecycledImageLayer];
+    ++mNextFreeRecycledImageLayer;
+    // Clear clip rect and mask layer so we don't accidentally stay clipped.
+    // We will reapply any necessary clipping.
     layer->SetClipRect(nsnull);
     layer->SetMaskLayer(nsnull);
   } else {
     // Create a new layer
     layer = mManager->CreateImageLayer();
     if (!layer)
       return nsnull;
     // Mark this layer as being used for Thebes-painting display items
-    data->mImageLayer = layer;
     layer->SetUserData(&gImageLayerUserData, nsnull);
-
-    // Remove other layer types we might have stored for this ThebesLayer
-    data->mColorLayer = nsnull;
   }
   return layer.forget();
 }
 
 already_AddRefed<ImageLayer>
 ContainerState::CreateOrRecycleMaskImageLayerFor(Layer* aLayer)
 {
   nsRefPtr<ImageLayer> result = mRecycledMaskImageLayers.Get(aLayer);
@@ -1112,54 +972,42 @@ ContainerState::CreateOrRecycleThebesLay
     // This gets called on recycled ThebesLayers that are going to be in the
     // final layer tree, so it's a convenient time to invalidate the
     // content that changed where we don't know what ThebesLayer it belonged
     // to, or if we need to invalidate the entire layer, we can do that.
     // This needs to be done before we update the ThebesLayer to its new
     // transform. See nsGfxScrollFrame::InvalidateInternal, where
     // we ensure that mInvalidThebesContent is updated according to the
     // scroll position as of the most recent paint.
-    if (data->mXScale != mParameters.mXScale ||
+    if (mInvalidateAllThebesContent ||
+        data->mXScale != mParameters.mXScale ||
         data->mYScale != mParameters.mYScale) {
       nsIntRect invalidate = layer->GetValidRegion().GetBounds();
-#ifdef DEBUG_INVALIDATIONS
-      printf("Invalidating entire layer %p\n", layer.get());
-#endif
       layer->InvalidateRegion(invalidate);
+    } else {
+      InvalidatePostTransformRegion(layer, mInvalidThebesContent,
+                                    GetTranslationForThebesLayer(layer));
     }
-    if (!data->mRegionToInvalidate.IsEmpty()) {
-#ifdef DEBUG_INVALIDATIONS
-      printf("Invalidating deleted frame content from layer %p\n", layer.get());
-#endif
-      layer->InvalidateRegion(data->mRegionToInvalidate);
-#ifdef DEBUG_INVALIDATIONS
-      nsCAutoString str;
-      AppendToString(str, data->mRegionToInvalidate);
-      printf("Invalidating layer %p: %s\n", layer.get(), str.get());
-#endif
-      data->mRegionToInvalidate.SetEmpty();
-    }
-
     // We do not need to Invalidate these areas in the widget because we
     // assume the caller of InvalidateThebesLayerContents has ensured
     // the area is invalidated in the widget.
   } else {
     // Create a new thebes layer
     layer = mManager->CreateThebesLayer();
     if (!layer)
       return nsnull;
     // Mark this layer as being used for Thebes-painting display items
     data = new ThebesDisplayItemLayerUserData();
     layer->SetUserData(&gThebesDisplayItemLayerUserData, data);
   }
   data->mXScale = mParameters.mXScale;
   data->mYScale = mParameters.mYScale;
   layer->SetAllowResidualTranslation(mParameters.AllowResidualTranslation());
 
-  mLayerBuilder->SaveLastPaintOffset(layer);
+  mBuilder->LayerBuilder()->SaveLastPaintOffset(layer);
 
   // Set up transform so that 0,0 in the Thebes layer corresponds to the
   // (pixel-snapped) top-left of the aActiveScrolledRoot.
   nsPoint offset = mBuilder->ToReferenceFrame(aActiveScrolledRoot);
   nscoord appUnitsPerDevPixel = aActiveScrolledRoot->PresContext()->AppUnitsPerDevPixel();
   gfxPoint scaledOffset(
       NSAppUnitsToDoublePixels(offset.x, appUnitsPerDevPixel)*mParameters.mXScale,
       NSAppUnitsToDoublePixels(offset.y, appUnitsPerDevPixel)*mParameters.mYScale);
@@ -1232,40 +1080,16 @@ RestrictVisibleRegionForLayer(Layer* aLa
 
   nsIntRegion rgn = aLayer->GetVisibleRegion();
   if (!visibleRect.Contains(rgn.GetBounds())) {
     rgn.And(rgn, visibleRect);
     aLayer->SetVisibleRegion(rgn);
   }
 }
 
-static void
-SetVisibleRegionForLayer(Layer* aLayer, const nsIntRect& aItemVisible, const nsIntRect& aChildBounds)
-{
-  gfx3DMatrix transform = aLayer->GetTransform();
-
-  // if 'transform' is not invertible, then nothing will be displayed
-  // for the layer, so it doesn't really matter what we do here
-  gfxRect itemVisible(aItemVisible.x, aItemVisible.y, aItemVisible.width, aItemVisible.height);
-  gfxRect layerVisible = transform.Inverse().ProjectRectBounds(itemVisible);
-  layerVisible.RoundOut();
-
-  nsIntRect visibleRect;
-  if (!gfxUtils::GfxRectToIntRect(layerVisible, &visibleRect))
-    return;
-
-  nsIntRegion rgn = aChildBounds;
-  if (!visibleRect.Contains(aChildBounds)) {
-    rgn.And(rgn, visibleRect);
-    aLayer->SetVisibleRegion(rgn);
-  } else {
-    aLayer->SetVisibleRegion(aChildBounds);
-  }
-}
-
 nscolor
 ContainerState::FindOpaqueBackgroundColorFor(PRInt32 aThebesLayerIndex)
 {
   ThebesLayerData* target = mThebesLayerDataStack[aThebesLayerIndex];
   for (PRInt32 i = aThebesLayerIndex - 1; i >= 0; --i) {
     ThebesLayerData* candidate = mThebesLayerDataStack[i];
     nsIntRegion visibleAboveIntersection;
     visibleAboveIntersection.And(candidate->mVisibleAboveRegion, target->mVisibleRegion);
@@ -1282,17 +1106,17 @@ ContainerState::FindOpaqueBackgroundColo
       continue;
     }
 
     // The candidate intersects our target. If any layer has a solid-color
     // area behind our target, this must be it. Scan its display items.
     nsRect rect =
       target->mVisibleRegion.GetBounds().ToAppUnits(mAppUnitsPerDevPixel);
     rect.ScaleInverseRoundOut(mParameters.mXScale, mParameters.mYScale);
-    return mLayerBuilder->
+    return mBuilder->LayerBuilder()->
       FindOpaqueColorCovering(mBuilder, candidate->mLayer, rect);
   }
   return NS_RGBA(0,0,0,0);
 }
 
 void
 ContainerState::ThebesLayerData::UpdateCommonClipCount(
     const FrameLayerBuilder::Clip& aCurrentClip)
@@ -1337,30 +1161,30 @@ ContainerState::PopThebesLayerData()
   nsRefPtr<Layer> layer;
   nsRefPtr<ImageContainer> imageContainer = data->CanOptimizeImageLayer(); 
 
   if ((data->mIsSolidColorInVisibleRegion || imageContainer) &&
       data->mLayer->GetValidRegion().IsEmpty()) {
     NS_ASSERTION(!(data->mIsSolidColorInVisibleRegion && imageContainer),
                  "Can't be a solid color as well as an image!");
     if (imageContainer) {
-      nsRefPtr<ImageLayer> imageLayer = CreateOrRecycleImageLayer(data->mLayer);
+      nsRefPtr<ImageLayer> imageLayer = CreateOrRecycleImageLayer();
       imageLayer->SetContainer(imageContainer);
       data->mImage->ConfigureLayer(imageLayer);
       // The layer's current transform is applied first, then the result is scaled.
       gfx3DMatrix transform = imageLayer->GetTransform()*
         gfx3DMatrix::ScalingMatrix(mParameters.mXScale, mParameters.mYScale, 1.0f);
       imageLayer->SetTransform(transform);
       if (data->mItemClip.mHaveClipRect) {
         nsIntRect clip = ScaleToNearestPixels(data->mItemClip.mClipRect);
         imageLayer->IntersectClipRect(clip);
       }
       layer = imageLayer;
     } else {
-      nsRefPtr<ColorLayer> colorLayer = CreateOrRecycleColorLayer(data->mLayer);
+      nsRefPtr<ColorLayer> colorLayer = CreateOrRecycleColorLayer();
       colorLayer->SetIsFixedPosition(data->mLayer->GetIsFixedPosition());
       colorLayer->SetColor(data->mSolidColor);
 
       // Copy transform
       colorLayer->SetTransform(data->mLayer->GetTransform());
       
       // Clip colorLayer to its visible region, since ColorLayers are
       // allowed to paint outside the visible region. Here we rely on the
@@ -1430,17 +1254,17 @@ ContainerState::PopThebesLayerData()
     }
     userData->mForcedBackgroundColor = backgroundColor;
 
     // use a mask layer for rounded rect clipping
     PRInt32 commonClipCount = data->mCommonClipCount;
     NS_ASSERTION(commonClipCount >= 0, "Inconsistent clip count.");
     SetupMaskLayer(layer, data->mItemClip, commonClipCount);
     // copy commonClipCount to the entry
-    FrameLayerBuilder::ThebesLayerItemsEntry* entry = mLayerBuilder->
+    FrameLayerBuilder::ThebesLayerItemsEntry* entry = mBuilder->LayerBuilder()->
       GetThebesLayerItemsEntry(static_cast<ThebesLayer*>(layer.get()));
     entry->mCommonClipCount = commonClipCount;
   } else {
     // mask layer for image and color layers
     SetupMaskLayer(layer, data->mItemClip);
   }
   PRUint32 flags;
   if (isOpaque && !data->mForceTransparentSurface) {
@@ -1698,47 +1522,51 @@ DumpPaintedImage(nsDisplayItem* aItem, g
   fprintf(gfxUtils::sDumpPaintFile, "array[\"%s\"]=\"", string.BeginReading());
   aSurf->DumpAsDataURL(gfxUtils::sDumpPaintFile);
   fprintf(gfxUtils::sDumpPaintFile, "\";");
 }
 #endif
 
 static void
 PaintInactiveLayer(nsDisplayListBuilder* aBuilder,
-                   LayerManager* aManager,
                    nsDisplayItem* aItem,
-                   gfxContext* aContext,
-                   nsRenderingContext* aCtx)
+                   gfxContext* aContext)
 {
   // This item has an inactive layer. Render it to a ThebesLayer
   // using a temporary BasicLayerManager.
-  BasicLayerManager* basic = static_cast<BasicLayerManager*>(aManager);
-  nsRefPtr<gfxContext> context = aContext;
-#ifdef MOZ_DUMP_PAINTING
   PRInt32 appUnitsPerDevPixel = AppUnitsPerDevPixel(aItem);
   nsIntRect itemVisibleRect =
     aItem->GetVisibleRect().ToOutsidePixels(appUnitsPerDevPixel);
 
+  nsRefPtr<gfxContext> context = aContext;
+#ifdef MOZ_DUMP_PAINTING
   nsRefPtr<gfxASurface> surf; 
   if (gfxUtils::sDumpPainting) {
     surf = gfxPlatform::GetPlatform()->CreateOffscreenSurface(itemVisibleRect.Size(), 
                                                               gfxASurface::CONTENT_COLOR_ALPHA);
     surf->SetDeviceOffset(-itemVisibleRect.TopLeft());
     context = new gfxContext(surf);
   }
 #endif
-  basic->SetTarget(context);
 
-  if (aItem->GetType() == nsDisplayItem::TYPE_SVG_EFFECTS) {
-    static_cast<nsDisplaySVGEffects*>(aItem)->PaintAsLayer(aBuilder, aCtx, basic);
-  } else {
-    basic->EndTransaction(FrameLayerBuilder::DrawThebesLayer, aBuilder);
+  nsRefPtr<BasicLayerManager> tempManager = new BasicLayerManager();
+  tempManager->BeginTransactionWithTarget(context);
+  nsRefPtr<Layer> layer =
+    aItem->BuildLayer(aBuilder, tempManager, FrameLayerBuilder::ContainerParameters());
+  if (!layer) {
+    tempManager->EndTransaction(nsnull, nsnull);
+    return;
   }
+  RestrictVisibleRegionForLayer(layer, itemVisibleRect);
+  
+  tempManager->SetRoot(layer);
+  aBuilder->LayerBuilder()->WillEndTransaction(tempManager);
+  tempManager->EndTransaction(FrameLayerBuilder::DrawThebesLayer, aBuilder);
+  aBuilder->LayerBuilder()->DidEndTransaction(tempManager);
  
-  basic->SetUserData(&gLayerManagerLayerBuilder, NULL);
 #ifdef MOZ_DUMP_PAINTING
   if (gfxUtils::sDumpPainting) {
     DumpPaintedImage(aItem, surf);
   
     surf->SetDeviceOffset(gfxPoint(0, 0));
     aContext->SetSource(surf, itemVisibleRect.TopLeft());
     aContext->Rectangle(itemVisibleRect);
     aContext->Fill();
@@ -1758,26 +1586,25 @@ PaintInactiveLayer(nsDisplayListBuilder*
  * (ThebesLayers don't need a clip rect on the layer, we clip the items
  * individually when we draw them.)
  * We set the visible rect for all layers, although the actual setting
  * of visible rects for some ThebesLayers is deferred until the calling
  * of ContainerState::Finish.
  */
 void
 ContainerState::ProcessDisplayItems(const nsDisplayList& aList,
-                                    FrameLayerBuilder::Clip& aClip,
-                                    PRUint32 aFlags)
+                                    FrameLayerBuilder::Clip& aClip)
 {
   SAMPLE_LABEL("ContainerState", "ProcessDisplayItems");
   for (nsDisplayItem* item = aList.GetBottom(); item; item = item->GetAbove()) {
     nsDisplayItem::Type type = item->GetType();
     if (type == nsDisplayItem::TYPE_CLIP ||
         type == nsDisplayItem::TYPE_CLIP_ROUNDED_RECT) {
       FrameLayerBuilder::Clip childClip(aClip, item);
-      ProcessDisplayItems(*item->GetList(), childClip, aFlags);
+      ProcessDisplayItems(*item->GetList(), childClip);
       continue;
     }
 
     NS_ASSERTION(mAppUnitsPerDevPixel == AppUnitsPerDevPixel(item),
       "items in a container layer should all have the same app units per dev pixel");
 
     nsIntRect itemVisibleRect =
       ScaleToOutsidePixels(item->GetVisibleRect(), false);
@@ -1789,32 +1616,23 @@ ContainerState::ProcessDisplayItems(cons
       nsIntRect clipRect = ScaleToNearestPixels(aClip.mClipRect);
       itemDrawRect.IntersectRect(itemDrawRect, clipRect);
     }
     mBounds.UnionRect(mBounds, itemContent);
     itemVisibleRect.IntersectRect(itemVisibleRect, itemDrawRect);
 
     LayerState layerState = item->GetLayerState(mBuilder, mManager, mParameters);
 
-    nsIFrame* activeScrolledRoot;
-    bool forceInactive = false;
-    if (aFlags & NO_COMPONENT_ALPHA) {
-      activeScrolledRoot =
-        nsLayoutUtils::GetActiveScrolledRootFor(mContainerFrame,
-                                                mBuilder->ReferenceFrame());
-      forceInactive = true;
-    } else {
-      activeScrolledRoot = nsLayoutUtils::GetActiveScrolledRootFor(item, mBuilder);
-    }
+    nsIFrame* activeScrolledRoot =
+      nsLayoutUtils::GetActiveScrolledRootFor(item, mBuilder);
 
     // Assign the item to a layer
     if (layerState == LAYER_ACTIVE_FORCE ||
-        (!forceInactive &&
-         (layerState == LAYER_ACTIVE_EMPTY ||
-          layerState == LAYER_ACTIVE))) {
+        layerState == LAYER_ACTIVE_EMPTY ||
+        layerState == LAYER_ACTIVE) {
 
       // LAYER_ACTIVE_EMPTY means the layer is created just for its metadata.
       // We should never see an empty layer with any visible content!
       NS_ASSERTION(layerState != LAYER_ACTIVE_EMPTY ||
                    itemVisibleRect.IsEmpty(),
                    "State is LAYER_ACTIVE_EMPTY but visible rect is not.");
 
       // If the item would have its own layer but is invisible, just hide it.
@@ -1828,20 +1646,16 @@ ContainerState::ProcessDisplayItems(cons
 
       // Just use its layer.
       nsRefPtr<Layer> ownLayer = item->BuildLayer(mBuilder, mManager, mParameters);
       if (!ownLayer) {
         InvalidateForLayerChange(item, ownLayer);
         continue;
       }
 
-      if (item->IsInvalid()) {
-        ownLayer->SetInvalidRectToVisibleRegion();
-      }
-
       // If it's not a ContainerLayer, we need to apply the scale transform
       // ourselves.
       if (!ownLayer->AsContainerLayer()) {
         // The layer's current transform is applied first, then the result is scaled.
         gfx3DMatrix transform = ownLayer->GetTransform()*
             gfx3DMatrix::ScalingMatrix(mParameters.mXScale, mParameters.mYScale, 1.0f);
         ownLayer->SetTransform(transform);
       }
@@ -1886,313 +1700,145 @@ ContainerState::ProcessDisplayItems(cons
         oldContainer->RemoveChild(ownLayer);
       }
       NS_ASSERTION(!mNewChildLayers.Contains(ownLayer),
                    "Layer already in list???");
 
       InvalidateForLayerChange(item, ownLayer);
 
       mNewChildLayers.AppendElement(ownLayer);
-      mLayerBuilder->AddLayerDisplayItem(ownLayer, item, layerState, nsnull);
+      mBuilder->LayerBuilder()->AddLayerDisplayItem(ownLayer, item, layerState);
     } else {
       ThebesLayerData* data =
         FindThebesLayerFor(item, itemVisibleRect, itemDrawRect, aClip,
                            activeScrolledRoot);
 
       data->mLayer->SetIsFixedPosition(
         !nsLayoutUtils::IsScrolledByRootContentDocumentDisplayportScrolling(
                                        activeScrolledRoot, mBuilder));
 
       InvalidateForLayerChange(item, data->mLayer);
 
-      mLayerBuilder->AddThebesDisplayItem(data->mLayer, item, aClip,
-                                          mContainerFrame,
-                                          layerState);
+      mBuilder->LayerBuilder()->AddThebesDisplayItem(data->mLayer, item, aClip,
+                                                     mContainerFrame,
+                                                     layerState);
 
       // check to see if the new item has rounded rect clips in common with
       // other items in the layer
       data->UpdateCommonClipCount(aClip);
     }
   }
 }
 
 void
 ContainerState::InvalidateForLayerChange(nsDisplayItem* aItem, Layer* aNewLayer)
 {
   nsIFrame* f = aItem->GetUnderlyingFrame();
   NS_ASSERTION(f, "Display items that render using Thebes must have a frame");
   PRUint32 key = aItem->GetPerFrameKey();
   NS_ASSERTION(key, "Display items that render using Thebes must have a key");
-  nsDisplayItemGeometry *oldGeometry = NULL;
-  nsAutoPtr<nsDisplayItemGeometry> geometry(aItem->AllocateGeometry(mBuilder));
-  Layer* oldLayer = mLayerBuilder->GetOldLayerFor(f, key, &oldGeometry);
-  if (aNewLayer != oldLayer && oldLayer) {
+  Layer* oldLayer = mBuilder->LayerBuilder()->GetOldLayerFor(f, key);
+  if (!oldLayer) {
+    // Nothing to do here, this item didn't have a layer before
+    return;
+  }
+  if (aNewLayer != oldLayer) {
     // The item has changed layers.
     // Invalidate the bounds in the old layer and new layer.
     // The bounds might have changed, but we assume that any difference
     // in the bounds will have been invalidated for all Thebes layers
     // in the container via regular frame invalidation.
+    bool snap;
+    nsRect bounds = aItem->GetBounds(mBuilder, &snap);
+
     ThebesLayer* t = oldLayer->AsThebesLayer();
     if (t) {
+      ThebesDisplayItemLayerUserData* data =
+          static_cast<ThebesDisplayItemLayerUserData*>(t->GetUserData(&gThebesDisplayItemLayerUserData));
       // Note that whenever the layer's scale changes, we invalidate the whole thing,
       // so it doesn't matter whether we are using the old scale at last paint
       // or a new scale here
-#ifdef DEBUG_INVALIDATIONS
-      printf("Display item type %s(%p) changed layers %p to %p!\n", aItem->Name(), f, t, aNewLayer);
-#endif
-      ThebesDisplayItemLayerUserData* data =
-          static_cast<ThebesDisplayItemLayerUserData*>(t->GetUserData(&gThebesDisplayItemLayerUserData));
       InvalidatePostTransformRegion(t,
-          oldGeometry->ComputeInvalidationRegion().ScaleToOutsidePixels(data->mXScale, data->mYScale, mAppUnitsPerDevPixel),
-          mLayerBuilder->GetLastPaintOffset(t));
+          bounds.ScaleToOutsidePixels(data->mXScale, data->mYScale, mAppUnitsPerDevPixel),
+          mBuilder->LayerBuilder()->GetLastPaintOffset(t));
     }
     if (aNewLayer) {
-      ThebesLayer* newThebesLayer = aNewLayer->AsThebesLayer();
-      if (newThebesLayer) {
+      ThebesLayer* newLayer = aNewLayer->AsThebesLayer();
+      if (newLayer) {
         ThebesDisplayItemLayerUserData* data =
-            static_cast<ThebesDisplayItemLayerUserData*>(newThebesLayer->GetUserData(&gThebesDisplayItemLayerUserData));
-        InvalidatePostTransformRegion(newThebesLayer,
-            geometry->ComputeInvalidationRegion().ScaleToOutsidePixels(data->mXScale, data->mYScale, mAppUnitsPerDevPixel),
-            GetTranslationForThebesLayer(newThebesLayer));
+            static_cast<ThebesDisplayItemLayerUserData*>(newLayer->GetUserData(&gThebesDisplayItemLayerUserData));
+        InvalidatePostTransformRegion(newLayer,
+            bounds.ScaleToOutsidePixels(data->mXScale, data->mYScale, mAppUnitsPerDevPixel),
+            GetTranslationForThebesLayer(newLayer));
       }
     }
-    return;
-  } 
-  if (!aNewLayer) {
-    return;
-  }
 
-  ThebesLayer* newThebesLayer = aNewLayer->AsThebesLayer();
-  if (!newThebesLayer) {
-    return;
-  }
-
-  ThebesDisplayItemLayerUserData* data =
-    static_cast<ThebesDisplayItemLayerUserData*>(newThebesLayer->GetUserData(&gThebesDisplayItemLayerUserData));
-  // If the frame is marked as invalidated then we want to invalidate both the old and new bounds,
-  // otherwise we only want to invalidate the changed areas.
-  nsRegion combined;
-  if (!oldLayer) {
-    //TODO: We call GetGeometry again in AddThebesDisplayItem, we should reuse this.
-    combined = geometry->ComputeInvalidationRegion();
-#ifdef DEBUG_INVALIDATIONS
-    printf("Display item type %s(%p) added to layer %p!\n", aItem->Name(), f, aNewLayer);
-#endif
-  } else if (aItem->IsInvalid()) {
-    combined.Or(geometry->ComputeInvalidationRegion(), oldGeometry->ComputeInvalidationRegion());
-#ifdef DEBUG_INVALIDATIONS
-    printf("Display item type %s(%p) (in layer %p) belongs to an invalidated frame!\n", aItem->Name(), f, aNewLayer);
-#endif
-  } else {
-    ThebesDisplayItemLayerUserData* data =
-        static_cast<ThebesDisplayItemLayerUserData*>(newThebesLayer->GetUserData(&gThebesDisplayItemLayerUserData));
-    nsIntPoint paintOffset = GetTranslationForThebesLayer(newThebesLayer);
-    nsPoint offset((paintOffset.x + data->mActiveScrolledRootPosition.x) * mAppUnitsPerDevPixel / data->mXScale,
-                   (paintOffset.y + data->mActiveScrolledRootPosition.y) * mAppUnitsPerDevPixel / data->mYScale);
-    nsPoint prevOffset((oldGeometry->mPaintOffset.x + oldGeometry->mActiveScrolledRootPosition.x) * oldGeometry->mAppUnitsPerDevPixel / data->mXScale,
-                       (oldGeometry->mPaintOffset.y + oldGeometry->mActiveScrolledRootPosition.y) * oldGeometry->mAppUnitsPerDevPixel / data->mYScale);
-    nsPoint shift = offset - prevOffset;
-    oldGeometry->MoveBy(shift);
-    aItem->ComputeInvalidationRegion(mBuilder, oldGeometry, &combined);
-#ifdef DEBUG_INVALIDATIONS
-    if (!combined.IsEmpty()) {
-      printf("Display item type %s(%p) (in layer %p) changed geometry!\n", aItem->Name(), f, aNewLayer);
-    }
-#endif
-  }
-  if (!combined.IsEmpty()) {
-    InvalidatePostTransformRegion(newThebesLayer,
-        combined.ScaleToOutsidePixels(data->mXScale, data->mYScale, mAppUnitsPerDevPixel),
-        GetTranslationForThebesLayer(newThebesLayer));
+    mContainerFrame->InvalidateWithFlags(
+        bounds - mBuilder->ToReferenceFrame(mContainerFrame),
+        nsIFrame::INVALIDATE_NO_THEBES_LAYERS |
+        nsIFrame::INVALIDATE_EXCLUDE_CURRENT_PAINT);
   }
 }
 
 bool
 FrameLayerBuilder::NeedToInvalidateFixedDisplayItem(nsDisplayListBuilder* aBuilder,
                                                     nsDisplayItem* aItem)
 {
-  if (!aItem->ShouldFixToViewport(aBuilder)) {
-    return true;
-  }
-
-  nsRefPtr<LayerManager> layerManager;
-  nsIFrame* referenceFrame = aBuilder->ReferenceFrame();
-  NS_ASSERTION(referenceFrame == nsLayoutUtils::GetDisplayRootFrame(referenceFrame),
-               "Reference frame must be a display root for us to use the layer manager");
-  nsIWidget* window = referenceFrame->GetNearestWidget();
-  if (window) {
-    layerManager = window->GetLayerManager();
-  }
-
-  if (layerManager) {
-    return !HasRetainedLayerFor(aItem->GetUnderlyingFrame(), aItem->GetPerFrameKey(), layerManager);
-  }
-
-  return true;
+  return !aItem->ShouldFixToViewport(aBuilder) ||
+      !HasRetainedLayerFor(aItem->GetUnderlyingFrame(), aItem->GetPerFrameKey());
 }
 
 void
 FrameLayerBuilder::AddThebesDisplayItem(ThebesLayer* aLayer,
                                         nsDisplayItem* aItem,
                                         const Clip& aClip,
                                         nsIFrame* aContainerLayerFrame,
                                         LayerState aLayerState)
 {
-  nsRefPtr<LayerManager> tempManager;
-  if (aLayerState != LAYER_NONE) {
-    DisplayItemData *data = GetDisplayItemDataForManager(aItem, aLayer->Manager());
-    if (data) {
-      tempManager = data->mInactiveManager;
-    }
-    if (!tempManager) {
-      tempManager = new BasicLayerManager();
-    }
-  }
-
-  AddLayerDisplayItem(aLayer, aItem, aLayerState, tempManager);
+  AddLayerDisplayItem(aLayer, aItem, aLayerState);
 
   ThebesLayerItemsEntry* entry = mThebesLayerItems.PutEntry(aLayer);
   if (entry) {
     entry->mContainerLayerFrame = aContainerLayerFrame;
-    entry->mContainerLayerGeneration = mContainerLayerGeneration;
     NS_ASSERTION(aItem->GetUnderlyingFrame(), "Must have frame");
-    if (tempManager) {
-      FrameLayerBuilder* layerBuilder = new FrameLayerBuilder();
-      layerBuilder->Init(mDisplayListBuilder);
-      layerBuilder->mMaxContainerLayerGeneration = mMaxContainerLayerGeneration;
-      // LayerManager user data took ownership of the FrameLayerBuilder
-      tempManager->SetUserData(&gLayerManagerLayerBuilder, layerBuilder);
-
-      tempManager->BeginTransaction();
-      if (mRetainingManager) {
-        layerBuilder->DidBeginRetainedLayerTransaction(tempManager);
-      }
-  
-      nsAutoPtr<LayerProperties> props(LayerProperties::CloneFrom(tempManager->GetRoot()));
-      nsRefPtr<Layer> layer =
-        aItem->BuildLayer(mDisplayListBuilder, tempManager, FrameLayerBuilder::ContainerParameters());
-      // We have no easy way of detecting if this transaction will ever actually get finished.
-      // For now, I've just silenced the warning with nested transactions in BasicLayers.cpp
-      if (!layer) {
-        tempManager->EndTransaction(nsnull, nsnull);
-        tempManager->SetUserData(&gLayerManagerLayerBuilder, nsnull);
-        return;
-      }
-
-      // If BuildLayer didn't call BuildContainerLayerFor, then our new layer won't have been
-      // stored in layerBuilder. Manually add it now.
-      DisplayItemData data(layer, aItem->GetPerFrameKey(), LAYER_ACTIVE, mContainerLayerGeneration);
-      layerBuilder->StoreDataForFrame(aItem->GetUnderlyingFrame(), data);
-
-      tempManager->SetRoot(layer);
-      layerBuilder->WillEndTransaction();
-      mMaxContainerLayerGeneration = layerBuilder->mMaxContainerLayerGeneration;
-
-      nsIntRect invalid = props->ComputeDifferences(layer, nsnull);
-      if (aLayerState == LAYER_SVG_EFFECTS) {
-        invalid = nsSVGIntegrationUtils::GetInvalidAreaForChangedSource(aItem->GetUnderlyingFrame(), invalid);
-      }
-      invalid.MoveBy(-GetTranslationForThebesLayer(aLayer));
-      aLayer->InvalidateRegion(invalid);
-    }
     ClippedDisplayItem* cdi =
-      entry->mItems.AppendElement(ClippedDisplayItem(aItem, aClip, 
-                                                     mContainerLayerGeneration));
-    cdi->mInactiveLayer = tempManager;
-  }
-}
-
-void
-FrameLayerBuilder::StoreDataForFrame(nsIFrame* aFrame, DisplayItemData& aData)
-{
-  DisplayItemDataEntry *entry = mNewDisplayItemData.GetEntry(aFrame);
-  if (entry) {
-    return;
-  }
-  entry = mNewDisplayItemData.PutEntry(aFrame);
-  if (entry) {
-    entry->mContainerLayerGeneration = mContainerLayerGeneration;
-    DisplayItemData *data = entry->mData.AppendElement();
-    *data = aData;
-  }
-}
-
-FrameLayerBuilder::ClippedDisplayItem::~ClippedDisplayItem()
-{
-  if (mInactiveLayer) {
-    BasicLayerManager* basic = static_cast<BasicLayerManager*>(mInactiveLayer.get());
-    if (basic->InTransaction()) {
-      basic->EndTransaction(nsnull, nsnull);
-    }
-    basic->SetUserData(&gLayerManagerLayerBuilder, nsnull);
+      entry->mItems.AppendElement(ClippedDisplayItem(aItem, aClip));
+    cdi->mInactiveLayer = aLayerState != LAYER_NONE;
   }
 }
 
 void
 FrameLayerBuilder::AddLayerDisplayItem(Layer* aLayer,
                                        nsDisplayItem* aItem,
-                                       LayerState aLayerState,
-                                       LayerManager* aManager)
+                                       LayerState aLayerState)
 {
   if (aLayer->Manager() != mRetainingManager)
     return;
 
   nsIFrame* f = aItem->GetUnderlyingFrame();
   DisplayItemDataEntry* entry = mNewDisplayItemData.PutEntry(f);
   if (entry) {
-#ifdef DEBUG_DUPLICATE_PAIRS
-    for (PRUint32 i = 0; i < entry->mData.Length(); i++) {
-      if (entry->mData[i].mDisplayItemKey == aItem->GetPerFrameKey() &&
-          aItem->GetType() != nsDisplayItem::TYPE_OWN_LAYER) {
-        NS_ERROR("Duplicate frame/key pair");
-        printf("Display item: %s(%i), frame %p\n", aItem->Name(), aItem->GetType(), f);
-      }
-    }
-#endif
-    entry->mContainerLayerGeneration = mContainerLayerGeneration;
-    DisplayItemData* data = entry->mData.AppendElement();
-    DisplayItemData did(aLayer, aItem->GetPerFrameKey(), aLayerState, mContainerLayerGeneration);
-    *data = did;
-
-    ThebesLayer *t = aLayer->AsThebesLayer();
-    if (t) {
-      data->mGeometry = aItem->AllocateGeometry(mDisplayListBuilder);
-      data->mGeometry->mAppUnitsPerDevPixel = AppUnitsPerDevPixel(aItem);
-      ThebesDisplayItemLayerUserData* userData =
-                    static_cast<ThebesDisplayItemLayerUserData*>(t->GetUserData(&gThebesDisplayItemLayerUserData));
-      data->mGeometry->mPaintOffset = GetTranslationForThebesLayer(t);
-      data->mGeometry->mActiveScrolledRootPosition = userData->mActiveScrolledRootPosition;
-    }
-    data->mInactiveManager = aManager;
-
-    DisplayItemData* oldData = GetDisplayItemDataForManager(aItem, mRetainingManager);
-    if (oldData) {
-      oldData->mUsed = true;
-    }
+    entry->mData.AppendElement(DisplayItemData(aLayer, aItem->GetPerFrameKey(), aLayerState));
   }
 }
 
 nsIntPoint
 FrameLayerBuilder::GetLastPaintOffset(ThebesLayer* aLayer)
 {
   ThebesLayerItemsEntry* entry = mThebesLayerItems.PutEntry(aLayer);
-  if (entry) {
-    entry->mContainerLayerGeneration = mContainerLayerGeneration;
-    if (entry->mHasExplicitLastPaintOffset)
-      return entry->mLastPaintOffset;
-  }
+  if (entry && entry->mHasExplicitLastPaintOffset)
+    return entry->mLastPaintOffset;
   return GetTranslationForThebesLayer(aLayer);
 }
 
 void
 FrameLayerBuilder::SaveLastPaintOffset(ThebesLayer* aLayer)
 {
   ThebesLayerItemsEntry* entry = mThebesLayerItems.PutEntry(aLayer);
   if (entry) {
-    entry->mContainerLayerGeneration = mContainerLayerGeneration;
     entry->mLastPaintOffset = GetTranslationForThebesLayer(aLayer);
     entry->mHasExplicitLastPaintOffset = true;
   }
 }
 
 nscolor
 FrameLayerBuilder::FindOpaqueColorCovering(nsDisplayListBuilder* aBuilder,
                                            ThebesLayer* aLayer,
@@ -2217,56 +1863,57 @@ FrameLayerBuilder::FindOpaqueColorCoveri
 
 void
 ContainerState::CollectOldLayers()
 {
   for (Layer* layer = mContainerLayer->GetFirstChild(); layer;
        layer = layer->GetNextSibling()) {
     NS_ASSERTION(!layer->HasUserData(&gMaskLayerUserData),
                  "Mask layer in layer tree; could not be recycled.");
-    if (layer->HasUserData(&gThebesDisplayItemLayerUserData)) {
+    if (layer->HasUserData(&gColorLayerUserData)) {
+      mRecycledColorLayers.AppendElement(static_cast<ColorLayer*>(layer));
+    } else if (layer->HasUserData(&gImageLayerUserData)) {
+      mRecycledImageLayers.AppendElement(static_cast<ImageLayer*>(layer));
+    } else if (layer->HasUserData(&gThebesDisplayItemLayerUserData)) {
       NS_ASSERTION(layer->AsThebesLayer(), "Wrong layer type");
       mRecycledThebesLayers.AppendElement(static_cast<ThebesLayer*>(layer));
     }
 
     if (Layer* maskLayer = layer->GetMaskLayer()) {
       NS_ASSERTION(maskLayer->GetType() == Layer::TYPE_IMAGE,
                    "Could not recycle mask layer, unsupported layer type.");
       mRecycledMaskImageLayers.Put(layer, static_cast<ImageLayer*>(maskLayer));
     }
   }
 }
 
 void
-ContainerState::Finish(PRUint32* aTextContentFlags, LayerManagerData* aData)
+ContainerState::Finish(PRUint32* aTextContentFlags)
 {
   while (!mThebesLayerDataStack.IsEmpty()) {
     PopThebesLayerData();
   }
 
   PRUint32 textContentFlags = 0;
 
   for (PRUint32 i = 0; i <= mNewChildLayers.Length(); ++i) {
     // An invariant of this loop is that the layers in mNewChildLayers
     // with index < i are the first i child layers of mContainerLayer.
     Layer* layer;
     if (i < mNewChildLayers.Length()) {
       layer = mNewChildLayers[i];
-      // Update all the frames that used to have layers.
-      if (aData) {
-        aData->mFramesWithLayers.EnumerateEntries(FrameLayerBuilder::ProcessRemovedDisplayItems, layer);
-      }
       if (!layer->GetVisibleRegion().IsEmpty()) {
         textContentFlags |= layer->GetContentFlags() & Layer::CONTENT_COMPONENT_ALPHA;
       }
       if (!layer->GetParent()) {
         // This is not currently a child of the container, so just add it
         // now.
         Layer* prevChild = i == 0 ? nsnull : mNewChildLayers[i - 1].get();
         mContainerLayer->InsertAfter(layer, prevChild);
+        continue;
       }
       NS_ASSERTION(layer->GetParent() == mContainerLayer,
                    "Layer shouldn't be the child of some other container");
     } else {
       layer = nsnull;
     }
 
     // If layer is non-null, then it's already a child of the container,
@@ -2360,86 +2007,79 @@ ChooseScaleAndSetTransform(FrameLayerBui
     }
   }
   if (isRetained && (!canDraw2D || transform2d.HasNonIntegerTranslation())) {
     result.mDisableSubpixelAntialiasingInDescendants = true;
   }
   return result;
 }
 
-/* static */ PLDHashOperator
-FrameLayerBuilder::RestoreDisplayItemData(DisplayItemDataEntry* aEntry, void* aUserArg)
+static void
+ApplyThebesLayerInvalidation(nsDisplayListBuilder* aBuilder,
+                             nsIFrame* aContainerFrame,
+                             nsDisplayItem* aContainerItem,
+                             ContainerState& aState,
+                             nsPoint* aCurrentOffset)
 {
-  PRUint32 *generation = static_cast<PRUint32*>(aUserArg);
-
-  if (aEntry->mContainerLayerGeneration >= *generation) {
-    return PL_DHASH_REMOVE;
-  }
-
-  for (PRUint32 i = 0; i < aEntry->mData.Length(); i++) {
-    if (aEntry->mData[i].mContainerLayerGeneration >= *generation) {
-      aEntry->mData.TruncateLength(i);
-      return PL_DHASH_NEXT;
-    }
-  }
+  *aCurrentOffset = aContainerItem ? aContainerItem->ToReferenceFrame()
+    : aBuilder->ToReferenceFrame(aContainerFrame);
 
-  return PL_DHASH_NEXT;
-}
-
-/* static */ PLDHashOperator
-FrameLayerBuilder::RestoreThebesLayerItemEntries(ThebesLayerItemsEntry* aEntry, void* aUserArg)
-{
-  PRUint32 *generation = static_cast<PRUint32*>(aUserArg);
-
-  if (aEntry->mContainerLayerGeneration >= *generation) {
-    return PL_DHASH_REMOVE;
+  FrameProperties props = aContainerFrame->Properties();
+  RefCountedRegion* invalidThebesContent = static_cast<RefCountedRegion*>
+    (props.Get(ThebesLayerInvalidRegionProperty()));
+  if (invalidThebesContent) {
+    const FrameLayerBuilder::ContainerParameters& scaleParameters = aState.ScaleParameters();
+    aState.AddInvalidThebesContent(invalidThebesContent->mRegion.
+      ScaleToOutsidePixels(scaleParameters.mXScale, scaleParameters.mYScale,
+                           aState.GetAppUnitsPerDevPixel()));
+    // We have to preserve the current contents of invalidThebesContent
+    // because there might be multiple container layers for the same
+    // frame and we need to invalidate the ThebesLayer children of all
+    // of them. Also, multiple calls to ApplyThebesLayerInvalidation for the
+    // same layer can share the same region.
+  } else {
+    // The region was deleted to indicate that everything should be
+    // invalidated.
+    aState.SetInvalidateAllThebesContent();
   }
-
-  for (PRUint32 i = 0; i < aEntry->mItems.Length(); i++) {
-    if (aEntry->mItems[i].mContainerLayerGeneration >= *generation) {
-      aEntry->mItems.TruncateLength(i);
-      return PL_DHASH_NEXT;
-    }
-  }
-
-  return PL_DHASH_NEXT;
 }
 
 already_AddRefed<ContainerLayer>
 FrameLayerBuilder::BuildContainerLayerFor(nsDisplayListBuilder* aBuilder,
                                           LayerManager* aManager,
                                           nsIFrame* aContainerFrame,
                                           nsDisplayItem* aContainerItem,
                                           const nsDisplayList& aChildren,
                                           const ContainerParameters& aParameters,
                                           const gfx3DMatrix* aTransform)
 {
-  FrameProperties props = aContainerFrame->Properties();
   PRUint32 containerDisplayItemKey =
     aContainerItem ? aContainerItem->GetPerFrameKey() : 0;
   NS_ASSERTION(aContainerFrame, "Container display items here should have a frame");
   NS_ASSERTION(!aContainerItem ||
                aContainerItem->GetUnderlyingFrame() == aContainerFrame,
                "Container display item must match given frame");
 
   nsRefPtr<ContainerLayer> containerLayer;
-  Layer* oldLayer = GetOldLayerFor(aContainerFrame, containerDisplayItemKey);
-  if (oldLayer) {
-    NS_ASSERTION(oldLayer->Manager() == mRetainingManager, "Wrong manager");
-    if (oldLayer->HasUserData(&gThebesDisplayItemLayerUserData)) {
-      // The old layer for this item is actually our ThebesLayer
-      // because we rendered its layer into that ThebesLayer. So we
-      // don't actually have a retained container layer.
-    } else {
-      NS_ASSERTION(oldLayer->GetType() == Layer::TYPE_CONTAINER,
-                   "Wrong layer type");
-      containerLayer = static_cast<ContainerLayer*>(oldLayer);
-      // Clear clip rect; the caller will set it if necessary.
-      containerLayer->SetClipRect(nsnull);
-      containerLayer->SetMaskLayer(nsnull);
+  if (aManager == mRetainingManager) {
+    Layer* oldLayer = GetOldLayerFor(aContainerFrame, containerDisplayItemKey);
+    if (oldLayer) {
+      NS_ASSERTION(oldLayer->Manager() == aManager, "Wrong manager");
+      if (oldLayer->HasUserData(&gThebesDisplayItemLayerUserData)) {
+        // The old layer for this item is actually our ThebesLayer
+        // because we rendered its layer into that ThebesLayer. So we
+        // don't actually have a retained container layer.
+      } else {
+        NS_ASSERTION(oldLayer->GetType() == Layer::TYPE_CONTAINER,
+                     "Wrong layer type");
+        containerLayer = static_cast<ContainerLayer*>(oldLayer);
+        // Clear clip rect; the caller will set it if necessary.
+        containerLayer->SetClipRect(nsnull);
+        containerLayer->SetMaskLayer(nsnull);
+      }
     }
   }
   if (!containerLayer) {
     // No suitable existing layer was found.
     containerLayer = aManager->CreateContainerLayer();
     if (!containerLayer)
       return nsnull;
   }
@@ -2452,104 +2092,84 @@ FrameLayerBuilder::BuildContainerLayerFo
     // should never have anything to paint, it should never be invalidated.
     NS_ASSERTION(aChildren.IsEmpty(), "Should have no children");
     return containerLayer.forget();
   }
 
   ContainerParameters scaleParameters =
     ChooseScaleAndSetTransform(this, aContainerFrame, aTransform, aParameters,
                                containerLayer);
-
-  PRUint32 oldGeneration = mContainerLayerGeneration;
-  mContainerLayerGeneration = ++mMaxContainerLayerGeneration;
+  ContainerState state(aBuilder, aManager, aContainerFrame, containerLayer,
+                       scaleParameters);
 
-  LayerManagerData* data = static_cast<LayerManagerData*>
-    (aManager->GetUserData(&gLayerManagerUserData));
-
-  if (mRetainingManager) {
+  if (aManager == mRetainingManager) {
     DisplayItemDataEntry* entry = mNewDisplayItemData.PutEntry(aContainerFrame);
     if (entry) {
-      DisplayItemData *data = entry->mData.AppendElement();
-      DisplayItemData did(containerLayer, containerDisplayItemKey,
-                          LAYER_ACTIVE, mContainerLayerGeneration);
-      *data = did;
-      entry->mContainerLayerGeneration = mContainerLayerGeneration;
+      entry->mData.AppendElement(
+          DisplayItemData(containerLayer, containerDisplayItemKey, LAYER_ACTIVE));
+    }
+    nsPoint currentOffset;
+    ApplyThebesLayerInvalidation(aBuilder, aContainerFrame, aContainerItem, state,
+                                 &currentOffset);
+    RefCountedRegion* thebesLayerInvalidRegion = nsnull;
+    SetHasContainerLayer(aContainerFrame, currentOffset, &thebesLayerInvalidRegion);
+
+    nsAutoTArray<nsIFrame*,4> mergedFrames;
+    if (aContainerItem) {
+      aContainerItem->GetMergedFrames(&mergedFrames);
+    }
+    for (PRUint32 i = 0; i < mergedFrames.Length(); ++i) {
+      nsIFrame* mergedFrame = mergedFrames[i];
+      DisplayItemDataEntry* entry = mNewDisplayItemData.PutEntry(mergedFrame);
+      if (entry) {
+        // Ensure that UpdateDisplayItemDataForFrame recognizes that we
+        // still have a container layer associated with this frame.
+        entry->mIsSharingContainerLayer = true;
+      }
+      ApplyThebesLayerInvalidation(aBuilder, mergedFrame, nsnull, state,
+                                   &currentOffset);
+      SetHasContainerLayer(mergedFrame, currentOffset, &thebesLayerInvalidRegion);
     }
   }
 
-  nsRect bounds;
-  nsIntRect pixBounds;
-  PRInt32 appUnitsPerDevPixel;
-
-  PRUint32 stateFlags =
-    (aContainerFrame->GetStateBits() & NS_FRAME_NO_COMPONENT_ALPHA) ?
-      ContainerState::NO_COMPONENT_ALPHA : 0;
-  PRUint32 flags;
-  while (true) {
-    ContainerState state(aBuilder, aManager, GetLayerBuilderForManager(aManager),
-                         aContainerFrame, containerLayer, scaleParameters);
-    Clip clip;
-    state.ProcessDisplayItems(aChildren, clip, stateFlags);
- 
-    // Set CONTENT_COMPONENT_ALPHA if any of our children have it.
-    // This is suboptimal ... a child could have text that's over transparent
-    // pixels in its own layer, but over opaque parts of previous siblings.
-    state.Finish(&flags, data);
-    bounds = state.GetChildrenBounds();
-    pixBounds = state.ScaleToOutsidePixels(bounds, false);
-    appUnitsPerDevPixel = state.GetAppUnitsPerDevPixel();
+  Clip clip;
+  state.ProcessDisplayItems(aChildren, clip);
 
-    if ((flags & Layer::CONTENT_COMPONENT_ALPHA) &&
-        mRetainingManager &&
-        !mRetainingManager->AreComponentAlphaLayersEnabled() &&
-        !stateFlags) {
-      // Since we don't want any component alpha layers on BasicLayers, we repeat
-      // the layer building process with this explicitely forced off.
-      // We restore the previous FrameLayerBuilder state since the first set
-      // of layer building will have changed it.
-      stateFlags = ContainerState::NO_COMPONENT_ALPHA;
-      mNewDisplayItemData.EnumerateEntries(RestoreDisplayItemData,
-                                           &mContainerLayerGeneration);
-      mThebesLayerItems.EnumerateEntries(RestoreThebesLayerItemEntries,
-                                         &mContainerLayerGeneration);
-      aContainerFrame->AddStateBits(NS_FRAME_NO_COMPONENT_ALPHA);
-      continue;
-    }
-    break;
-  }
+  // Set CONTENT_COMPONENT_ALPHA if any of our children have it.
+  // This is suboptimal ... a child could have text that's over transparent
+  // pixels in its own layer, but over opaque parts of previous siblings.
+  PRUint32 flags;
+  state.Finish(&flags);
 
+  nsRect bounds = state.GetChildrenBounds();
   NS_ASSERTION(bounds.IsEqualInterior(aChildren.GetBounds(aBuilder)), "Wrong bounds");
-  if (aContainerItem) {
-    nsIntRect itemVisibleRect =
-      aContainerItem->GetVisibleRect().ToOutsidePixels(AppUnitsPerDevPixel(aContainerItem));
-    SetVisibleRegionForLayer(containerLayer, itemVisibleRect, pixBounds);
-  } else {
-    containerLayer->SetVisibleRegion(pixBounds);
-  }
+  nsIntRect pixBounds = state.ScaleToOutsidePixels(bounds, false);
+  containerLayer->SetVisibleRegion(pixBounds);
   // Make sure that rounding the visible region out didn't add any area
   // we won't paint
   if (aChildren.IsOpaque() && !aChildren.NeedsTransparentSurface()) {
     bounds.ScaleRoundIn(scaleParameters.mXScale, scaleParameters.mYScale);
-    if (bounds.Contains(pixBounds.ToAppUnits(appUnitsPerDevPixel))) {
+    if (bounds.Contains(pixBounds.ToAppUnits(state.GetAppUnitsPerDevPixel()))) {
       // Clear CONTENT_COMPONENT_ALPHA
       flags = Layer::CONTENT_OPAQUE;
     }
   }
   containerLayer->SetContentFlags(flags);
 
-  containerLayer->SetUserData(&gNotifySubDocInvalidationData, nsnull);
-
-  mContainerLayerGeneration = oldGeneration;
   return containerLayer.forget();
 }
 
 Layer*
 FrameLayerBuilder::GetLeafLayerFor(nsDisplayListBuilder* aBuilder,
+                                   LayerManager* aManager,
                                    nsDisplayItem* aItem)
 {
+  if (aManager != mRetainingManager)
+    return nsnull;
+
   nsIFrame* f = aItem->GetUnderlyingFrame();
   NS_ASSERTION(f, "Can only call GetLeafLayerFor on items that have a frame");
   Layer* layer = GetOldLayerFor(f, aItem->GetPerFrameKey());
   if (!layer)
     return nsnull;
   if (layer->HasUserData(&gThebesDisplayItemLayerUserData)) {
     // This layer was created to render Thebes-rendered content for this
     // display item. The display item should not use it for its own
@@ -2558,62 +2178,124 @@ FrameLayerBuilder::GetLeafLayerFor(nsDis
   }
   // Clear clip rect; the caller is responsible for setting it.
   layer->SetClipRect(nsnull);
   layer->SetMaskLayer(nsnull);
   return layer;
 }
 
 /* static */ void
+FrameLayerBuilder::InvalidateThebesLayerContents(nsIFrame* aFrame,
+                                                 const nsRect& aRect)
+{
+  FrameProperties props = aFrame->Properties();
+  RefCountedRegion* invalidThebesContent = static_cast<RefCountedRegion*>
+    (props.Get(ThebesLayerInvalidRegionProperty()));
+  if (!invalidThebesContent)
+    return;
+
+  nsPoint* offsetAtLastPaint = static_cast<nsPoint*>
+    (props.Get(ThebesLayerLastPaintOffsetProperty()));
+  NS_ASSERTION(offsetAtLastPaint,
+               "This must have been set up along with ThebesLayerInvalidRegionProperty");
+  invalidThebesContent->mRegion.Or(invalidThebesContent->mRegion,
+          aRect + *offsetAtLastPaint);
+  invalidThebesContent->mRegion.SimplifyOutward(20);
+}
+
+/**
+ * Returns true if we find a descendant with a container layer
+ */
+static bool
+InternalInvalidateThebesLayersInSubtree(nsIFrame* aFrame)
+{
+  if (!(aFrame->GetStateBits() & NS_FRAME_HAS_CONTAINER_LAYER_DESCENDANT))
+    return false;
+
+  bool foundContainerLayer = false;
+  if (aFrame->GetStateBits() & NS_FRAME_HAS_CONTAINER_LAYER) {
+    // Delete the invalid region to indicate that all Thebes contents
+    // need to be invalidated
+    aFrame->Properties().Delete(ThebesLayerInvalidRegionProperty());
+    foundContainerLayer = true;
+  }
+
+  nsAutoTArray<nsIFrame::ChildList,4> childListArray;
+  if (!aFrame->GetFirstPrincipalChild()) {
+    nsSubDocumentFrame* subdocumentFrame = do_QueryFrame(aFrame);
+    if (subdocumentFrame) {
+      // Descend into the subdocument
+      nsIFrame* root = subdocumentFrame->GetSubdocumentRootFrame();
+      if (root) {
+        childListArray.AppendElement(nsIFrame::ChildList(
+          nsFrameList(root, nsLayoutUtils::GetLastSibling(root)),
+          nsIFrame::kPrincipalList));
+      }
+    }
+  }
+
+  aFrame->GetChildLists(&childListArray);
+  nsIFrame::ChildListArrayIterator lists(childListArray);
+  for (; !lists.IsDone(); lists.Next()) {
+    nsFrameList::Enumerator childFrames(lists.CurrentList());
+    for (; !childFrames.AtEnd(); childFrames.Next()) {
+      if (InternalInvalidateThebesLayersInSubtree(childFrames.get())) {
+        foundContainerLayer = true;
+      }
+    }
+  }
+
+  if (!foundContainerLayer) {
+    aFrame->RemoveStateBits(NS_FRAME_HAS_CONTAINER_LAYER_DESCENDANT);
+  }
+  return foundContainerLayer;
+}
+
+/* static */ void
+FrameLayerBuilder::InvalidateThebesLayersInSubtree(nsIFrame* aFrame)
+{
+  InternalInvalidateThebesLayersInSubtree(aFrame);
+}
+
+/* static */ void
 FrameLayerBuilder::InvalidateAllLayers(LayerManager* aManager)
 {
   LayerManagerData* data = static_cast<LayerManagerData*>
     (aManager->GetUserData(&gLayerManagerUserData));
   if (data) {
     data->mInvalidateAllLayers = true;
   }
 }
 
 /* static */
 Layer*
 FrameLayerBuilder::GetDedicatedLayer(nsIFrame* aFrame, PRUint32 aDisplayItemKey)
 {
-  //TODO: This isn't completely correct, since a frame could exist as a layer
-  // in the normal widget manager, and as a different layer (or no layer)
-  // in the secondary manager
-
-  DisplayItemData *data = GetDisplayItemDataForManager(aFrame, aDisplayItemKey, nsnull);
-  if (!data) {
+  nsTArray<DisplayItemData>* array = GetDisplayItemDataArrayForFrame(aFrame);
+  if (!array)
     return nsnull;
-  }
- 
-  Layer* layer = data->mLayer;
-  if (!layer->HasUserData(&gColorLayerUserData) &&
-      !layer->HasUserData(&gImageLayerUserData) &&
-      !layer->HasUserData(&gThebesDisplayItemLayerUserData)) {
-    return layer;
+
+  for (PRUint32 i = 0; i < array->Length(); ++i) {
+    if (array->ElementAt(i).mDisplayItemKey == aDisplayItemKey) {
+      Layer* layer = array->ElementAt(i).mLayer;
+      if (!layer->HasUserData(&gColorLayerUserData) &&
+          !layer->HasUserData(&gImageLayerUserData) &&
+          !layer->HasUserData(&gThebesDisplayItemLayerUserData))
+        return layer;
+    }
   }
   return nsnull;
 }
 
 bool
 FrameLayerBuilder::GetThebesLayerResolutionForFrame(nsIFrame* aFrame,
                                                     double* aXres, double* aYres,
                                                     gfxPoint* aPoint)
 {
-  LayerManagerData *data = GetDefaultLayerManagerDataForFrame(aFrame);
-  if (!data) {
-    return false;
-  }
-
-  DisplayItemDataEntry *entry = data->mFramesWithLayers.GetEntry(aFrame);
-  if (!entry)
-    return false;
-
-  nsTArray<DisplayItemData>* array = &entry->mData;
+  nsTArray<DisplayItemData> *array = GetDisplayItemDataArrayForFrame(aFrame);
   if (array) {
     for (PRUint32 i = 0; i < array->Length(); ++i) {
       Layer* layer = array->ElementAt(i).mLayer;
       if (layer->HasUserData(&gThebesDisplayItemLayerUserData)) {
         ThebesDisplayItemLayerUserData* data =
           static_cast<ThebesDisplayItemLayerUserData*>
             (layer->GetUserData(&gThebesDisplayItemLayerUserData));
         *aXres = data->mXScale;
@@ -2705,26 +2387,25 @@ FrameLayerBuilder::DrawThebesLayer(Thebe
                                    const nsIntRegion& aRegionToInvalidate,
                                    void* aCallbackData)
 {
   SAMPLE_LABEL("gfx", "DrawThebesLayer");
 
   nsDisplayListBuilder* builder = static_cast<nsDisplayListBuilder*>
     (aCallbackData);
 
-  FrameLayerBuilder *layerBuilder = GetLayerBuilderForManager(aLayer->Manager());
-
-  if (layerBuilder->CheckDOMModified())
+  if (builder->LayerBuilder()->CheckDOMModified())
     return;
 
   nsTArray<ClippedDisplayItem> items;
   PRUint32 commonClipCount;
   nsIFrame* containerLayerFrame;
   {
-    ThebesLayerItemsEntry* entry = layerBuilder->mThebesLayerItems.GetEntry(aLayer);
+    ThebesLayerItemsEntry* entry =
+      builder->LayerBuilder()->mThebesLayerItems.GetEntry(aLayer);
     NS_ASSERTION(entry, "We shouldn't be drawing into a layer with no items!");
     items.SwapElements(entry->mItems);
     commonClipCount = entry->mCommonClipCount;
     containerLayerFrame = entry->mContainerLayerFrame;
     // Later after this point, due to calls to DidEndTransaction
     // for temporary layer managers, mThebesLayerItems can change,
     // so 'entry' could become invalid.
   }
@@ -2748,16 +2429,24 @@ FrameLayerBuilder::DrawThebesLayer(Thebe
   // Apply the residual transform if it has been enabled, to ensure that
   // snapping when we draw into aContext exactly matches the ideal transform.
   // See above for why this is OK.
   aContext->Translate(aLayer->GetResidualTranslation() - gfxPoint(offset.x, offset.y));
   aContext->Scale(userData->mXScale, userData->mYScale);
 
   nsPresContext* presContext = containerLayerFrame->PresContext();
   PRInt32 appUnitsPerDevPixel = presContext->AppUnitsPerDevPixel();
+  if (!aRegionToInvalidate.IsEmpty()) {
+    nsRect r = (aRegionToInvalidate.GetBounds() + offset).
+      ToAppUnits(appUnitsPerDevPixel);
+    r.ScaleInverseRoundOut(userData->mXScale, userData->mYScale);
+    containerLayerFrame->InvalidateWithFlags(r,
+        nsIFrame::INVALIDATE_NO_THEBES_LAYERS |
+        nsIFrame::INVALIDATE_EXCLUDE_CURRENT_PAINT);
+  }
 
   PRUint32 i;
   // Update visible regions. We need perform visibility analysis again
   // because we may be asked to draw into part of a ThebesLayer that
   // isn't actually visible in the window (e.g., because a ThebesLayer
   // expanded its visible region to a rectangle internally), in which
   // case the mVisibleRect stored in the display item may be wrong.
   nsRegion visible = aRegionToDraw.ToAppUnits(appUnitsPerDevPixel);
@@ -2830,17 +2519,17 @@ FrameLayerBuilder::DrawThebesLayer(Thebe
         aContext->Save();
         NS_ASSERTION(commonClipCount < 100,
           "Maybe you really do have more than a hundred clipping rounded rects, or maybe something has gone wrong.");
         currentClip.ApplyTo(aContext, presContext, commonClipCount);
       }
     }
 
     if (cdi->mInactiveLayer) {
-      PaintInactiveLayer(builder, cdi->mInactiveLayer, cdi->mItem, aContext, rc);
+      PaintInactiveLayer(builder, cdi->mItem, aContext);
     } else {
       nsIFrame* frame = cdi->mItem->GetUnderlyingFrame();
       if (frame) {
         frame->AddStateBits(NS_FRAME_PAINTED_THEBES);
       }
 #ifdef MOZ_DUMP_PAINTING
 
       if (gfxUtils::sDumpPainting) {
@@ -2848,28 +2537,25 @@ FrameLayerBuilder::DrawThebesLayer(Thebe
       } else {
 #else
       {
 #endif
         cdi->mItem->Paint(builder, rc);
       }
     }
 
-    if (layerBuilder->CheckDOMModified())
+    if (builder->LayerBuilder()->CheckDOMModified())
       break;
   }
 
   if (setClipRect) {
     aContext->Restore();
   }
 
   FlashPaint(aContext);
-  if (!aRegionToInvalidate.IsEmpty()) {
-    aLayer->AddInvalidRect(aRegionToInvalidate.GetBounds());
-  }
 }
 
 bool
 FrameLayerBuilder::CheckDOMModified()
 {
   if (!mRootPresContext ||
       mInitialDOMGeneration == mRootPresContext->GetDOMGeneration())
     return false;
@@ -2881,20 +2567,22 @@ FrameLayerBuilder::CheckDOMModified()
   // Painting is not going to complete properly. There's not much
   // we can do here though. Invalidating the window to get another repaint
   // is likely to lead to an infinite repaint loop.
   NS_WARNING("Detected DOM modification during paint, bailing out!");
   return true;
 }
 
 #ifdef MOZ_DUMP_PAINTING
-/* static */ void
-FrameLayerBuilder::DumpRetainedLayerTree(LayerManager* aManager, FILE* aFile)
+void
+FrameLayerBuilder::DumpRetainedLayerTree(FILE* aFile)
 {
-  aManager->Dump(aFile);
+  if (mRetainingManager) {
+    mRetainingManager->Dump(aFile);
+  }
 }
 #endif
 
 FrameLayerBuilder::Clip::Clip(const Clip& aOther, nsDisplayItem* aClipItem)
   : mRoundedClipRects(aOther.mRoundedClipRects),
     mHaveClipRect(true)
 {
   nsDisplayItem::Type type = aClipItem->GetType();
--- a/layout/base/FrameLayerBuilder.h
+++ b/layout/base/FrameLayerBuilder.h
@@ -7,47 +7,34 @@
 #define FRAMELAYERBUILDER_H_
 
 #include "nsTHashtable.h"
 #include "nsHashKeys.h"
 #include "nsTArray.h"
 #include "nsRegion.h"
 #include "nsIFrame.h"
 #include "Layers.h"
-#include "nsDisplayListInvalidation.h"
-#include "LayerTreeInvalidation.h"
 
 class nsDisplayListBuilder;
 class nsDisplayList;
 class nsDisplayItem;
 class gfxContext;
 class nsRootPresContext;
 
 namespace mozilla {
 
-class FrameLayerBuilder;
-class LayerManagerData;
-
 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,
   // Special layer that is metadata only.
-  LAYER_ACTIVE_EMPTY,
-  // Inactive style layer for rendering SVG effects.
-  LAYER_SVG_EFFECTS
-};
-
-extern PRUint8 gLayerManagerLayerBuilder;
-extern PRUint8 gLayerManagerSecondary;
-
-class LayerManagerSecondary : public layers::LayerUserData {
+  LAYER_ACTIVE_EMPTY
 };
 
 /**
  * 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
@@ -79,53 +66,53 @@ class LayerManagerSecondary : public lay
  * applied to the layer. If the transform scales the content, we can get
  * better results when intermediate buffers are used by pushing some scale
  * from the container's transform down to the children. For ThebesLayer
  * children, the scaling can be achieved by changing the size of the layer
  * and drawing into it with increased or decreased resolution. By convention,
  * integer types (nsIntPoint/nsIntSize/nsIntRect/nsIntRegion) are all in layer
  * coordinates, post-scaling, whereas appunit types are all pre-scaling.
  */
-class FrameLayerBuilder : public layers::LayerUserData {
+class FrameLayerBuilder {
 public:
   typedef layers::ContainerLayer ContainerLayer; 
   typedef layers::Layer Layer; 
   typedef layers::ThebesLayer ThebesLayer;
   typedef layers::LayerManager LayerManager;
 
   FrameLayerBuilder() :
     mRetainingManager(nsnull),
     mDetectedDOMModification(false),
-    mInvalidateAllLayers(false),
-    mContainerLayerGeneration(0),
-    mMaxContainerLayerGeneration(0)
+    mInvalidateAllLayers(false)
   {
-    MOZ_COUNT_CTOR(FrameLayerBuilder);
     mNewDisplayItemData.Init();
     mThebesLayerItems.Init();
   }
-  ~FrameLayerBuilder()
-  {
-    MOZ_COUNT_DTOR(FrameLayerBuilder);
-  }
 
   void Init(nsDisplayListBuilder* aBuilder);
 
   /**
    * Call this to notify that we have just started a transaction on the
    * retained layer manager aManager.
    */
   void DidBeginRetainedLayerTransaction(LayerManager* aManager);
 
   /**
    * Call this just before we end a transaction on aManager. If aManager
    * is not the retained layer manager then it must be a temporary layer
    * manager that will not be used again.
    */
-  void WillEndTransaction();
+  void WillEndTransaction(LayerManager* aManager);
+
+  /**
+   * Call this after we end a transaction on aManager. If aManager
+   * is not the retained layer manager then it must be a temporary layer
+   * manager that will not be used again.
+   */
+  void DidEndTransaction(LayerManager* aManager);
 
   struct ContainerParameters {
     ContainerParameters() :
       mXScale(1), mYScale(1),
       mInTransformedSubtree(false), mInActiveTransformedSubtree(false),
       mDisableSubpixelAntialiasingInDescendants(false)
     {}
     ContainerParameters(float aXScale, float aYScale) :
@@ -188,153 +175,117 @@ public:
    * null if no retained layer is available, which usually means that this
    * display item didn't have a layer before so the caller will
    * need to create one.
    * Returns a layer with clip rect cleared; it is the
    * caller's responsibility to add any clip rect and set the visible
    * region.
    */
   Layer* GetLeafLayerFor(nsDisplayListBuilder* aBuilder,
+                         LayerManager* aManager,
                          nsDisplayItem* aItem);
 
   /**
+   * Call this during invalidation if aFrame has
+   * the NS_FRAME_HAS_CONTAINER_LAYER state bit. Only the nearest
+   * ancestor frame of the damaged frame that has
+   * NS_FRAME_HAS_CONTAINER_LAYER needs to be invalidated this way.
+   */
+  static void InvalidateThebesLayerContents(nsIFrame* aFrame,
+                                            const nsRect& aRect);
+
+  /**
+   * For any descendant frame of aFrame (including across documents) that
+   * has an associated container layer, invalidate all the contents of
+   * all ThebesLayer children of the container. Useful when aFrame is
+   * being moved and we need to invalidate everything in aFrame's subtree.
+   */
+  static void InvalidateThebesLayersInSubtree(nsIFrame* aFrame);
+
+  /**
    * Call this to force all retained layers to be discarded and recreated at
    * the next paint.
    */
   static void InvalidateAllLayers(LayerManager* aManager);
 
   /**
    * Call this to determine if a frame has a dedicated (non-Thebes) layer
    * for the given display item key. If there isn't one, we return null,
    * otherwise we return the layer.
    */
   static Layer* GetDedicatedLayer(nsIFrame* aFrame, PRUint32 aDisplayItemKey);
-  
+
   /**
    * This callback must be provided to EndTransaction. The callback data
    * must be the nsDisplayListBuilder containing this FrameLayerBuilder.
    */
   static void DrawThebesLayer(ThebesLayer* aLayer,
                               gfxContext* aContext,
                               const nsIntRegion& aRegionToDraw,
                               const nsIntRegion& aRegionToInvalidate,
                               void* aCallbackData);
 
 #ifdef MOZ_DUMP_PAINTING
   /**
    * Dumps this FrameLayerBuilder's retained layer manager's retained
    * layer tree to stderr.
    */
-  static void DumpRetainedLayerTree(LayerManager* aManager, FILE* aFile = stdout);
+  void DumpRetainedLayerTree(FILE* aFile = stdout);
 #endif
 
   /******* PRIVATE METHODS to FrameLayerBuilder.cpp ********/
   /* These are only in the public section because they need
    * to be called by file-scope helper functions in FrameLayerBuilder.cpp.
    */
   
   /**
    * Record aItem as a display item that is rendered by aLayer.
-   *
-   * @param aLayer Layer that the display item will be rendered into
-   * @param aItem Display item to be drawn.
-   * @param aLayerState What LayerState the item is using.
-   * @param aManager If the layer is in the LAYER_INACTIVE state,
-   * then this is the temporary layer manager to draw with.
    */
   void AddLayerDisplayItem(Layer* aLayer,
                            nsDisplayItem* aItem,
-                           LayerState aLayerState,
-                           LayerManager* aManager = nsnull);
+                           LayerState aLayerState);
 
   /**
    * Record aItem as a display item that is rendered by the ThebesLayer
    * aLayer, with aClipRect, where aContainerLayerFrame is the frame
    * for the container layer this ThebesItem belongs to.
    * aItem must have an underlying frame.
    */
   struct Clip;
   void AddThebesDisplayItem(ThebesLayer* aLayer,
                             nsDisplayItem* aItem,
                             const Clip& aClip,
                             nsIFrame* aContainerLayerFrame,
                             LayerState aLayerState);
 
   /**
-   * Set the current top-level LayerManager for the widget being
-   * painted.
-   */
-  static void SetWidgetLayerManager(LayerManager* aManager)
-  {
-    LayerManagerSecondary* secondary = 
-      static_cast<LayerManagerSecondary*>(aManager->GetUserData(&gLayerManagerSecondary));
-    sWidgetManagerSecondary = !!secondary;
-  }
-
-  /**
-   * Gets the frame property descriptor for the given manager, or for the current
-   * widget layer manager if nsnull is passed.
-   */
-  static const FramePropertyDescriptor* GetDescriptorForManager(LayerManager* aManager);
-
-  /**
-   * Get the LayerManagerData for a given frame and layer manager. If no layer manager
-   * is passed, then the current widget layer manager is used.
-   */
-  static LayerManagerData* GetManagerData(nsIFrame* aFrame, LayerManager* aManager = nsnull);
-
-  /**
-   * Set the LayerManagerData for a given frame and current widget layer manager.
-   * This replaces any existing data for the same frame/layer manager pair.
-   */
-  static void SetManagerData(nsIFrame* aFrame, LayerManagerData* aData);
-
-  /**
-   * Clears the current LayerManagerData for the given frame and current widget
-   * layer manager.
-   */
-  static void ClearManagerData(nsIFrame* aFrame);
-
-  /**
-   * Clears any references to the given LayerManagerData for the given frame
-   * and belonging to any layer manager.
-   */
-  static void ClearManagerData(nsIFrame* aFrame, LayerManagerData* aData);
-
-  /**
    * Given a frame and a display item key that uniquely identifies a
    * display item for the frame, find the layer that was last used to
    * render that display item. Returns null if there is no such layer.
    * This could be a dedicated layer for the display item, or a ThebesLayer
    * that renders many display items.
    */
-  Layer* GetOldLayerFor(nsIFrame* aFrame, PRUint32 aDisplayItemKey, nsDisplayItemGeometry** aOldGeometry = nsnull);
-
-  static Layer* GetDebugOldLayerFor(nsIFrame* aFrame, PRUint32 aDisplayItemKey);
-
-  /**
-   * If the display item was previously drawn as an inactive layer,
-   * then return the layer manager used for the inactive transaction.
-   * Returns nsnull if no manager could be found.
-   */
-  LayerManager* GetInactiveLayerManagerFor(nsDisplayItem* aItem);
+  Layer* GetOldLayerFor(nsIFrame* aFrame, PRUint32 aDisplayItemKey);
 
   /**
    * Try to determine whether the ThebesLayer aLayer paints an opaque
    * single color everywhere it's visible in aRect.
    * If successful, return that color, otherwise return NS_RGBA(0,0,0,0).
    */
   nscolor FindOpaqueColorCovering(nsDisplayListBuilder* aBuilder,
                                   ThebesLayer* aLayer, const nsRect& aRect);
 
   /**
    * Destroy any stored LayerManagerDataProperty and the associated data for
    * aFrame.
    */
-  static void DestroyDisplayItemDataFor(nsIFrame* aFrame);
+  static void DestroyDisplayItemDataFor(nsIFrame* aFrame)
+  {
+    aFrame->Properties().Delete(LayerManagerDataProperty());
+  }
 
   LayerManager* GetRetainingLayerManager() { return mRetainingManager; }
 
   /**
    * Returns true if the given item (which we assume here is
    * background-attachment:fixed) needs to be repainted as we scroll in its
    * document.
    * Returns false if it doesn't need to be repainted because the layer system
@@ -343,21 +294,18 @@ public:
   static bool NeedToInvalidateFixedDisplayItem(nsDisplayListBuilder* aBuilder,
                                                  nsDisplayItem* aItem);
 
   /**
    * Returns true if the given display item was rendered directly
    * into a retained layer.
    * Returns false if it was rendered into a temporary layer manager and then
    * into a retained layer.
-   *
-   * Since display items can belong to multiple retained LayerManagers, we need to
-   * specify which LayerManager to check.
    */
-  static bool HasRetainedLayerFor(nsIFrame* aFrame, PRUint32 aDisplayItemKey, LayerManager* aManager);
+  static bool HasRetainedLayerFor(nsIFrame* aFrame, PRUint32 aDisplayItemKey);
 
   /**
    * Save transform that was in aLayer when we last painted. It must be an integer
    * translation.
    */
   void SaveLastPaintOffset(ThebesLayer* aLayer);
   /**
    * Get the translation transform that was in aLayer when we last painted. It's either
@@ -453,167 +401,108 @@ public:
       return mHaveClipRect == aOther.mHaveClipRect &&
              (!mHaveClipRect || mClipRect.IsEqualInterior(aOther.mClipRect)) &&
              mRoundedClipRects == aOther.mRoundedClipRects;
     }
     bool operator!=(const Clip& aOther) const {
       return !(*this == aOther);
     }
   };
-  
-  NS_DECLARE_FRAME_PROPERTY_WITH_FRAME_IN_DTOR(LayerManagerDataProperty,
-                                               RemoveFrameFromLayerManager)
-
-  NS_DECLARE_FRAME_PROPERTY_WITH_FRAME_IN_DTOR(LayerManagerSecondaryDataProperty,
-                                               RemoveFrameFromLayerManager)
 
 protected:
   /**
    * We store an array of these for each frame that is associated with
    * one or more retained layers. Each DisplayItemData records the layer
    * used to render one of the frame's display items.
    */
   class DisplayItemData {
   public:
-    DisplayItemData(Layer* aLayer, PRUint32 aKey, LayerState aLayerState, PRUint32 aGeneration)
-      : mLayer(aLayer)
-      , mDisplayItemKey(aKey)
-      , mContainerLayerGeneration(aGeneration)
-      , mLayerState(aLayerState)
-      , mUsed(false)
-    {}
-    
-    DisplayItemData()
-      : mUsed(false)
-    {}
-    DisplayItemData(DisplayItemData &toCopy)
-    {
-      // This isn't actually a copy-constructor; notice that it steals toCopy's
-      // mGeometry pointer.  Be careful.
-      mLayer = toCopy.mLayer;
-      mInactiveManager = toCopy.mInactiveManager;
-      mGeometry = toCopy.mGeometry;
-      mDisplayItemKey = toCopy.mDisplayItemKey;
-      mContainerLayerGeneration = toCopy.mContainerLayerGeneration;
-      mLayerState = toCopy.mLayerState;
-      mUsed = toCopy.mUsed;
-    }
+    DisplayItemData(Layer* aLayer, PRUint32 aKey, LayerState aLayerState)
+      : mLayer(aLayer), mDisplayItemKey(aKey), mLayerState(aLayerState) {}
 
     nsRefPtr<Layer> mLayer;
-    nsRefPtr<LayerManager> mInactiveManager;
-    nsAutoPtr<nsDisplayItemGeometry> mGeometry;
     PRUint32        mDisplayItemKey;
-    PRUint32        mContainerLayerGeneration;
     LayerState      mLayerState;
-
-    /**
-     * Used to track if data currently stored in mFramesWithLayers (from an existing
-     * paint) is also used in the current paint and has an equivalent data object
-     * in mNewDisplayItemData.
-     */
-    bool            mUsed;
   };
-  
-  // LayerManagerData needs to see DisplayItemDataEntry.
-  friend class LayerManagerData;
 
   static void RemoveFrameFromLayerManager(nsIFrame* aFrame, void* aPropertyValue);
 
+  NS_DECLARE_FRAME_PROPERTY_WITH_FRAME_IN_DTOR(LayerManagerDataProperty,
+                                               RemoveFrameFromLayerManager)
+
   /**
    * We accumulate DisplayItemData elements in a hashtable during
    * the paint process, and store them in the frame property only when
    * paint is complete. This is the hashentry for that hashtable.
    */
   class DisplayItemDataEntry : public nsPtrHashKey<nsIFrame> {
   public:
-    DisplayItemDataEntry(const nsIFrame *key) : nsPtrHashKey<nsIFrame>(key) { MOZ_COUNT_CTOR(DisplayItemDataEntry); }
+    DisplayItemDataEntry(const nsIFrame *key) : nsPtrHashKey<nsIFrame>(key), mIsSharingContainerLayer(false) {}
     DisplayItemDataEntry(DisplayItemDataEntry &toCopy) :
-      nsPtrHashKey<nsIFrame>(toCopy.mKey)
+      nsPtrHashKey<nsIFrame>(toCopy.mKey), mIsSharingContainerLayer(toCopy.mIsSharingContainerLayer)
     {
-      MOZ_COUNT_CTOR(DisplayItemDataEntry);
       // This isn't actually a copy-constructor; notice that it steals toCopy's
       // array.  Be careful.
       mData.SwapElements(toCopy.mData);
-      mContainerLayerGeneration = toCopy.mContainerLayerGeneration;
     }
-    ~DisplayItemDataEntry() { MOZ_COUNT_DTOR(DisplayItemDataEntry); }
 
     bool HasNonEmptyContainerLayer();
 
     nsAutoTArray<DisplayItemData, 1> mData;
-    PRUint32 mContainerLayerGeneration;
+    bool mIsSharingContainerLayer;
 
     enum { ALLOW_MEMMOVE = false };
   };
 
-  /**
-   * Stores DisplayItemData associated with aFrame, stores the data in
-   * mNewDisplayItemData.
-   */
-  void StoreDataForFrame(nsIFrame* aFrame, DisplayItemData& data);
+  // LayerManagerData needs to see DisplayItemDataEntry.
+  friend class LayerManagerData;
 
   // Flash the area within the context clip if paint flashing is enabled.
   static void FlashPaint(gfxContext *aContext);
 
   /*
    * Get the DisplayItemData array associated with this frame, or null if one
    * doesn't exist.
    *
    * Note that the pointer returned here is only valid so long as you don't
    * poke the LayerManagerData's mFramesWithLayers hashtable.
    */
-  nsTArray<DisplayItemData>* GetDisplayItemDataArrayForFrame(nsIFrame *aFrame);
-
-  /*
-   * Get the DisplayItemData associated with this frame / display item pair,
-   * using the LayerManager instead of FrameLayerBuilder.
-   */
-  static DisplayItemData* GetDisplayItemDataForManager(nsIFrame* aFrame, 
-                                                       PRUint32 aDisplayItemKey, 
-                                                       LayerManager* aManager);
-  static DisplayItemData* GetDisplayItemDataForManager(nsDisplayItem* aItem, LayerManager* aManager);
+  static nsTArray<DisplayItemData>* GetDisplayItemDataArrayForFrame(nsIFrame *aFrame);
 
   /**
    * A useful hashtable iteration function that removes the
    * DisplayItemData property for the frame, clears its
    * NS_FRAME_HAS_CONTAINER_LAYER bit and returns PL_DHASH_REMOVE.
    * aClosure is ignored.
    */
   static PLDHashOperator RemoveDisplayItemDataForFrame(DisplayItemDataEntry* aEntry,
-                                                       void* aClosure);
+                                                       void* aClosure)
+  {
+    return UpdateDisplayItemDataForFrame(aEntry, nsnull);
+  }
 
   /**
    * We store one of these for each display item associated with a
    * ThebesLayer, in a hashtable that maps each ThebesLayer to an array
    * of ClippedDisplayItems. (ThebesLayerItemsEntry is the hash entry
    * for that hashtable.)
    * These are only stored during the paint process, so that the
    * DrawThebesLayer callback can figure out which items to draw for the
    * ThebesLayer.
    * mItem always has an underlying frame.
    */
   struct ClippedDisplayItem {
-    ClippedDisplayItem(nsDisplayItem* aItem, const Clip& aClip, PRUint32 aGeneration)
-      : mItem(aItem), mClip(aClip), mContainerLayerGeneration(aGeneration)
+    ClippedDisplayItem(nsDisplayItem* aItem, const Clip& aClip)
+      : mItem(aItem), mClip(aClip)
     {
     }
 
-    ~ClippedDisplayItem();
-
     nsDisplayItem* mItem;
-
-    /**
-     * If the display item is being rendered as an inactive
-     * layer, then this stores the layer manager being
-     * used for the inactive transaction.
-     */
-    nsRefPtr<LayerManager> mInactiveLayer;
-
     Clip mClip;
-    PRUint32 mContainerLayerGeneration;
+    bool mInactiveLayer;
   };
 
   /**
    * We accumulate ClippedDisplayItem elements in a hashtable during
    * the paint process. This is the hashentry for that hashtable.
    */
 public:
   class ThebesLayerItemsEntry : public nsPtrHashKey<ThebesLayer> {
@@ -627,17 +516,16 @@ public:
       NS_ERROR("Should never be called, since we ALLOW_MEMMOVE");
     }
 
     nsTArray<ClippedDisplayItem> mItems;
     nsIFrame* mContainerLayerFrame;
     // The translation set on this ThebesLayer before we started updating the
     // layer tree.
     nsIntPoint mLastPaintOffset;
-    PRUint32 mContainerLayerGeneration;
     bool mHasExplicitLastPaintOffset;
     /**
       * The first mCommonClipCount rounded rectangle clips are identical for
       * all items in the layer. Computed in ThebesLayerData.
       */
     PRUint32 mCommonClipCount;
 
     enum { ALLOW_MEMMOVE = true };
@@ -647,54 +535,40 @@ public:
    * Get the ThebesLayerItemsEntry object associated with aLayer in this
    * FrameLayerBuilder
    */
   ThebesLayerItemsEntry* GetThebesLayerItemsEntry(ThebesLayer* aLayer)
   {
     return mThebesLayerItems.GetEntry(aLayer);
   }
 
-  static PLDHashOperator ProcessRemovedDisplayItems(DisplayItemDataEntry* aEntry,
-                                                    void* aUserArg);
 protected:
   void RemoveThebesItemsForLayerSubtree(Layer* aLayer);
 
   static PLDHashOperator UpdateDisplayItemDataForFrame(DisplayItemDataEntry* aEntry,
                                                        void* aUserArg);
-  
   static PLDHashOperator StoreNewDisplayItemData(DisplayItemDataEntry* aEntry,
                                                  void* aUserArg);
 
-  static PLDHashOperator RestoreDisplayItemData(DisplayItemDataEntry* aEntry,
-                                                void *aUserArg);
-
-  static PLDHashOperator RestoreThebesLayerItemEntries(ThebesLayerItemsEntry* aEntry,
-                                                       void *aUserArg);
-
   /**
    * Returns true if the DOM has been modified since we started painting,
    * in which case we should bail out and not paint anymore. This should
    * never happen, but plugins can trigger it in some cases.
    */
   bool CheckDOMModified();
 
   /**
    * The layer manager belonging to the widget that is being retained
    * across paints.
    */
   LayerManager*                       mRetainingManager;
   /**
    * The root prescontext for the display list builder reference frame
    */
   nsRootPresContext*                  mRootPresContext;
-
-  /**
-   * The display list builder being used.
-   */
-  nsDisplayListBuilder*               mDisplayListBuilder;
   /**
    * A map from frames to a list of (display item key, layer) pairs that
    * describes what layers various parts of the frame are assigned to.
    */
   nsTHashtable<DisplayItemDataEntry>  mNewDisplayItemData;
   /**
    * A map from ThebesLayers to the list of display items (plus
    * clipping data) to be rendered in the layer.
@@ -709,27 +583,13 @@ protected:
    * the current paint.
    */
   bool                                mDetectedDOMModification;
   /**
    * Indicates that the entire layer tree should be rerendered
    * during this paint.
    */
   bool                                mInvalidateAllLayers;
-
-  PRUint32                            mContainerLayerGeneration;
-  PRUint32                            mMaxContainerLayerGeneration;
-
-  /**
-   * True if the current top-level LayerManager for the widget being
-   * painted is marked as being a 'secondary' LayerManager.
-   */
-  static bool                         sWidgetManagerSecondary;
 };
 
-static inline FrameLayerBuilder *GetLayerBuilderForManager(layers::LayerManager* aManager)
-{
-  return static_cast<FrameLayerBuilder*>(aManager->GetUserData(&gLayerManagerLayerBuilder));
-}
-
 }
 
 #endif /* FRAMELAYERBUILDER_H_ */
--- a/layout/base/Makefile.in
+++ b/layout/base/Makefile.in
@@ -32,17 +32,16 @@ EXPORTS		= \
 		nsBidi.h \
 		nsBidiPresUtils.h \
 		nsCaret.h \
 		nsCSSFrameConstructor.h \
 		nsChangeHint.h \
 		nsCompatibility.h \
 		nsDisplayItemTypes.h \
 		nsDisplayList.h \
-		nsDisplayListInvalidation.h \
 		nsFrameManager.h \
 		nsFrameManagerBase.h \
 		nsFrameTraversal.h \
 		nsIFrameTraversal.h \
 		nsILayoutDebugger.h \
 		nsILayoutHistoryState.h \
 		nsIPercentHeightObserver.h  \
 		nsIPresShell.h \
--- a/layout/base/nsCSSFrameConstructor.cpp
+++ b/layout/base/nsCSSFrameConstructor.cpp
@@ -7554,16 +7554,21 @@ UpdateViewsForTree(nsIFrame* aFrame,
           do {
             DoApplyRenderingChangeToTree(outOfFlowFrame, aFrameManager,
                                          aChange);
           } while ((outOfFlowFrame = outOfFlowFrame->GetNextContinuation()));
         } else if (lists.CurrentID() == nsIFrame::kPopupList) {
           DoApplyRenderingChangeToTree(child, aFrameManager,
                                        aChange);
         } else {  // regular frame
+          if ((child->GetStateBits() & NS_FRAME_HAS_CONTAINER_LAYER) &&
+              (aChange & nsChangeHint_RepaintFrame)) {
+            FrameLayerBuilder::InvalidateThebesLayerContents(child,
+              child->GetVisualOverflowRectRelativeToSelf());
+          }
           UpdateViewsForTree(child, aFrameManager, aChange);
         }
       }
     }
   }
 }
 
 static void
@@ -7594,27 +7599,31 @@ DoApplyRenderingChangeToTree(nsIFrame* a
         if (aChange & nsChangeHint_UpdateEffects) {
           // Invalidate and update our area:
           nsSVGUtils::InvalidateAndScheduleBoundsUpdate(aFrame);
         } else {
           // Just invalidate our area:
           nsSVGUtils::InvalidateBounds(aFrame);
         }
       } else {
-        aFrame->InvalidateFrameSubtree();
+        aFrame->InvalidateOverflowRect();
       }
     }
     if (aChange & nsChangeHint_UpdateOpacityLayer) {
       aFrame->MarkLayersActive(nsChangeHint_UpdateOpacityLayer);
+      aFrame->InvalidateLayer(aFrame->GetVisualOverflowRectRelativeToSelf(),
+                              nsDisplayItem::TYPE_OPACITY);
     }
     
     if (aChange & nsChangeHint_UpdateTransformLayer) {
       aFrame->MarkLayersActive(nsChangeHint_UpdateTransformLayer);
-    }
-    aFrame->SchedulePaint();
+      // Invalidate the old transformed area. The new transformed area
+      // will be invalidated by nsFrame::FinishAndStoreOverflowArea.
+      aFrame->InvalidateTransformLayer();
+    }
   }
 }
 
 static void
 ApplyRenderingChangeToTree(nsPresContext* aPresContext,
                            nsIFrame* aFrame,
                            nsChangeHint aChange)
 {
@@ -11922,35 +11931,39 @@ bool
 nsCSSFrameConstructor::RecomputePosition(nsIFrame* aFrame)
 {
   const nsStyleDisplay* display = aFrame->GetStyleDisplay();
   // Changes to the offsets of a non-positioned element can safely be ignored.
   if (display->mPosition == NS_STYLE_POSITION_STATIC) {
     return true;
   }
 
-  aFrame->SchedulePaint();
-
   // For relative positioning, we can simply update the frame rect
   if (display->mPosition == NS_STYLE_POSITION_RELATIVE) {
     nsIFrame* cb = aFrame->GetContainingBlock();
     const nsSize size = cb->GetSize();
     const nsPoint oldOffsets = aFrame->GetRelativeOffset();
     nsMargin newOffsets;
 
+    // Invalidate the old rect
+    aFrame->InvalidateOverflowRect();
+
     // Move the frame
     nsHTMLReflowState::ComputeRelativeOffsets(
         cb->GetStyleVisibility()->mDirection,
         aFrame, size.width, size.height, newOffsets);
     NS_ASSERTION(newOffsets.left == -newOffsets.right &&
                  newOffsets.top == -newOffsets.bottom,
                  "ComputeRelativeOffsets should return valid results");
     aFrame->SetPosition(aFrame->GetPosition() - oldOffsets +
                         nsPoint(newOffsets.left, newOffsets.top));
 
+    // Invalidate the new rect
+    aFrame->InvalidateOverflowRect();
+
     return true;
   }
 
   // For absolute positioning, the width can potentially change if width is
   // auto and either of left or right are not.  The height can also potentially
   // change if height is auto and either of top or bottom are not.  In these
   // cases we fall back to a reflow, and in all other cases, we attempt to
   // move the frame here.
@@ -12012,22 +12025,28 @@ nsCSSFrameConstructor::RecomputePosition
     if (NS_AUTOOFFSET == reflowState.mComputedOffsets.top) {
       reflowState.mComputedOffsets.top = cbSize.height -
                                          reflowState.mComputedOffsets.bottom -
                                          reflowState.mComputedMargin.bottom -
                                          size.height -
                                          reflowState.mComputedMargin.top;
     }
 
+    // Invalidate the old rect
+    aFrame->InvalidateOverflowRect();
+
     // Move the frame
     nsPoint pos(parentBorder.left + reflowState.mComputedOffsets.left +
                 reflowState.mComputedMargin.left,
                 parentBorder.top + reflowState.mComputedOffsets.top +
                 reflowState.mComputedMargin.top);
     aFrame->SetPosition(pos);
 
+    // Invalidate the new rect
+    aFrame->InvalidateOverflowRect();
+
     return true;
   }
 
   // Fall back to a reflow
   StyleChangeReflow(aFrame, nsChangeHint_NeedReflow);
   return false;
 }
--- a/layout/base/nsCaret.cpp
+++ b/layout/base/nsCaret.cpp
@@ -478,19 +478,18 @@ nsIFrame * nsCaret::GetCaretFrame(PRInt3
   return frame;
 }
 
 void nsCaret::InvalidateOutsideCaret()
 {
   nsIFrame *frame = GetCaretFrame();
 
   // Only invalidate if we are not fully contained by our frame's rect.
-  if (frame && !frame->GetVisualOverflowRect().Contains(GetCaretRect())) {
-    frame->SchedulePaint();
-  }
+  if (frame && !frame->GetVisualOverflowRect().Contains(GetCaretRect()))
+    InvalidateRects(mCaretRect, GetHookRect(), frame);
 }
 
 void nsCaret::UpdateCaretPosition()
 {
   // We'll recalculate anyway if we're not drawn right now.
   if (!mDrawn)
     return;
 
@@ -609,19 +608,41 @@ nsresult nsCaret::PrimeTimer()
 
     mBlinkTimer->InitWithFuncCallback(CaretBlinkCallback, this, mBlinkRate,
                                       nsITimer::TYPE_REPEATING_SLACK);
   }
 
   return NS_OK;
 }
 
+void nsCaret::InvalidateTextOverflowBlock()
+{
+  // If the nearest block has a potential 'text-overflow' marker then
+  // invalidate it.
+  if (mLastContent) {
+    nsIFrame* caretFrame = mLastContent->GetPrimaryFrame();
+    if (caretFrame) {
+      nsIFrame* block = nsLayoutUtils::GetAsBlock(caretFrame) ? caretFrame :
+        nsLayoutUtils::FindNearestBlockAncestor(caretFrame);
+      if (block) {
+        const nsStyleTextReset* style = block->GetStyleTextReset();
+        if (style->mTextOverflow.mLeft.mType != NS_STYLE_TEXT_OVERFLOW_CLIP ||
+            style->mTextOverflow.mRight.mType != NS_STYLE_TEXT_OVERFLOW_CLIP) {
+          block->InvalidateOverflowRect();
+        }
+      }
+    }
+  }
+}
+
 //-----------------------------------------------------------------------------
 void nsCaret::StartBlinking()
 {
+  InvalidateTextOverflowBlock();
+
   if (mReadOnly) {
     // Make sure the one draw command we use for a readonly caret isn't
     // done until the selection is set
     DrawCaretAfterBriefDelay();
     return;
   }
   PrimeTimer();
 
@@ -635,16 +656,18 @@ void nsCaret::StartBlinking()
 
   DrawCaret(true);    // draw it right away
 }
 
 
 //-----------------------------------------------------------------------------
 void nsCaret::StopBlinking()
 {
+  InvalidateTextOverflowBlock();
+
   if (mDrawn)     // erase the caret if necessary
     DrawCaret(true);
 
   NS_ASSERTION(!mDrawn, "Caret still drawn after StopBlinking().");
   KillTimer();
 }
 
 bool
@@ -693,17 +716,17 @@ nsCaret::DrawAtPositionWithHint(nsIDOMNo
     }
 
     // Only update the caret's rect when we're not currently drawn.
     if (!UpdateCaretRects(theFrame, theFrameOffset))
       return false;
   }
 
   if (aInvalidate)
-    theFrame->SchedulePaint();
+    InvalidateRects(mCaretRect, mHookRect, theFrame);
 
   return true;
 }
 
 nsresult 
 nsCaret::GetCaretFrameForNodeOffset(nsIContent*             aContentNode,
                                     PRInt32                 aOffset,
                                     nsFrameSelection::HINT aFrameHint,
@@ -1109,16 +1132,26 @@ nsCaret::UpdateCaretRects(nsIFrame* aFra
                       mCaretRect.y + bidiIndicatorSize,
                       bidiIndicatorSize,
                       mCaretRect.width);
   }
 #endif //IBMBIDI
   return true;
 }
 
+// static
+void nsCaret::InvalidateRects(const nsRect &aRect, const nsRect &aHook,
+                              nsIFrame *aFrame)
+{
+  NS_ASSERTION(aFrame, "Must have a frame to invalidate");
+  nsRect rect;
+  rect.UnionRect(aRect, aHook);
+  aFrame->Invalidate(rect);
+}
+
 //-----------------------------------------------------------------------------
 /* static */
 void nsCaret::CaretBlinkCallback(nsITimer *aTimer, void *aClosure)
 {
   nsCaret   *theCaret = reinterpret_cast<nsCaret*>(aClosure);
   if (!theCaret) return;
   
   theCaret->DrawCaret(true);
--- a/layout/base/nsCaret.h
+++ b/layout/base/nsCaret.h
@@ -168,16 +168,20 @@ class nsCaret : public nsISelectionListe
 protected:
 
     void          KillTimer();
     nsresult      PrimeTimer();
 
     void          StartBlinking();
     void          StopBlinking();
 
+    // If the nearest block has a potential 'text-overflow' marker then
+    // invalidate it.
+    void          InvalidateTextOverflowBlock();
+    
     bool          DrawAtPositionWithHint(nsIDOMNode* aNode,
                                          PRInt32 aOffset,
                                          nsFrameSelection::HINT aFrameHint,
                                          PRUint8 aBidiLevel,
                                          bool aInvalidate);
 
     struct Metrics {
       nscoord mBidiIndicatorSize; // width and height of bidi indicator
@@ -194,16 +198,18 @@ protected:
     // is true, we don't take into account whether the caret is currently
     // drawn or not. This can be used to determine if the caret is drawn when
     // it shouldn't be.
     bool          MustDrawCaret(bool aIgnoreDrawnState);
 
     void          DrawCaret(bool aInvalidate);
     void          DrawCaretAfterBriefDelay();
     bool          UpdateCaretRects(nsIFrame* aFrame, PRInt32 aFrameOffset);
+    static void   InvalidateRects(const nsRect &aRect, const nsRect &aHook,
+                                  nsIFrame *aFrame);
     nsRect        GetHookRect()
     {
 #ifdef IBMBIDI
       return mHookRect;
 #else
       return nsRect();
 #endif
     }
--- a/layout/base/nsDisplayList.cpp
+++ b/layout/base/nsDisplayList.cpp
@@ -21,27 +21,25 @@
 #include "gfxContext.h"
 #include "nsStyleStructInlines.h"
 #include "nsStyleTransformMatrix.h"
 #include "gfxMatrix.h"
 #include "nsSVGIntegrationUtils.h"
 #include "nsLayoutUtils.h"
 #include "nsIScrollableFrame.h"
 #include "nsThemeConstants.h"
-#include "LayerTreeInvalidation.h"
 
 #include "imgIContainer.h"
 #include "nsIInterfaceRequestorUtils.h"
 #include "BasicLayers.h"
 #include "nsBoxFrame.h"
 #include "nsViewportFrame.h"
 #include "nsSVGEffects.h"
 #include "nsSVGClipPathFrame.h"
 #include "sampler.h"
-#include "nsIViewManager.h"
 
 #include "mozilla/StandardInteger.h"
 
 using namespace mozilla;
 using namespace mozilla::layers;
 typedef FrameMetrics::ViewID ViewID;
 
 nsDisplayListBuilder::nsDisplayListBuilder(nsIFrame* aReferenceFrame,
@@ -83,16 +81,18 @@ nsDisplayListBuilder::nsDisplayListBuild
 
   if(mReferenceFrame->GetType() == nsGkAtoms::viewportFrame) {
     ViewportFrame* viewportFrame = static_cast<ViewportFrame*>(mReferenceFrame);
     if (!viewportFrame->GetChildList(nsIFrame::kFixedList).IsEmpty()) {
       mHasFixedItems = true;
     }
   }
 
+  LayerBuilder()->Init(this);
+
   PR_STATIC_ASSERT(nsDisplayItem::TYPE_MAX < (1 << nsDisplayItem::TYPE_BITS));
 }
 
 static void MarkFrameForDisplay(nsIFrame* aFrame, nsIFrame* aStopAtFrame) {
   for (nsIFrame* f = aFrame; f;
        f = nsLayoutUtils::GetParentOrPlaceholderFor(f)) {
     if (f->GetStateBits() & NS_FRAME_FORCE_DISPLAY_LIST_DESCEND_INTO)
       return;
@@ -559,89 +559,63 @@ void nsDisplayList::PaintRoot(nsDisplayL
 void nsDisplayList::PaintForFrame(nsDisplayListBuilder* aBuilder,
                                   nsRenderingContext* aCtx,
                                   nsIFrame* aForFrame,
                                   PRUint32 aFlags) const {
   NS_ASSERTION(mDidComputeVisibility,
                "Must call ComputeVisibility before calling Paint");
 
   nsRefPtr<LayerManager> layerManager;
-  bool widgetTransaction = false;
   bool allowRetaining = false;
   bool doBeginTransaction = true;
-  nsIView *view = nsnull;
   if (aFlags & PAINT_USE_WIDGET_LAYERS) {
     nsIFrame* referenceFrame = aBuilder->ReferenceFrame();
-    view = referenceFrame->GetView();
     NS_ASSERTION(referenceFrame == nsLayoutUtils::GetDisplayRootFrame(referenceFrame),
                  "Reference frame must be a display root for us to use the layer manager");
     nsIWidget* window = referenceFrame->GetNearestWidget();
     if (window) {
       layerManager = window->GetLayerManager(&allowRetaining);
       if (layerManager) {
         doBeginTransaction = !(aFlags & PAINT_EXISTING_TRANSACTION);
-        FrameLayerBuilder::SetWidgetLayerManager(layerManager);
-        widgetTransaction = true;
       }
     }
   }
   if (!layerManager) {
     if (!aCtx) {
       NS_WARNING("Nowhere to paint into");
       return;
     }
     layerManager = new BasicLayerManager();
   }
 
-  FrameLayerBuilder *layerBuilder = new FrameLayerBuilder();
-  layerBuilder->Init(aBuilder);
-  layerManager->SetUserData(&gLayerManagerLayerBuilder, layerBuilder);
-
   if (aFlags & PAINT_FLUSH_LAYERS) {
     FrameLayerBuilder::InvalidateAllLayers(layerManager);
   }
 
   if (doBeginTransaction) {
     if (aCtx) {
       layerManager->BeginTransactionWithTarget(aCtx->ThebesContext());
     } else {
       layerManager->BeginTransaction();
     }
   }
   if (allowRetaining) {
-    layerBuilder->DidBeginRetainedLayerTransaction(layerManager);
+    aBuilder->LayerBuilder()->DidBeginRetainedLayerTransaction(layerManager);
   }
 
   nsPresContext* presContext = aForFrame->PresContext();
   nsIPresShell* presShell = presContext->GetPresShell();
 
-  NotifySubDocInvalidationFunc computeInvalidFunc =
-    presContext->MayHavePaintEventListenerInSubDocument() ? nsPresContext::NotifySubDocInvalidation : 0;
-  bool computeInvalidRect = (computeInvalidFunc ||
-                             (layerManager->GetBackendType() == LayerManager::LAYERS_BASIC)) && 
-                            widgetTransaction;
-
-  nsAutoPtr<LayerProperties> props(computeInvalidRect ? 
-                                     LayerProperties::CloneFrom(layerManager->GetRoot()) : 
-                                     nsnull);
-
   nsDisplayItem::ContainerParameters containerParameters
     (presShell->GetXResolution(), presShell->GetYResolution());
-  nsRefPtr<ContainerLayer> root = layerBuilder->
+  nsRefPtr<ContainerLayer> root = aBuilder->LayerBuilder()->
     BuildContainerLayerFor(aBuilder, layerManager, aForFrame, nsnull, *this,
                            containerParameters, nsnull);
- 
-  if (widgetTransaction) {
-    aForFrame->ClearInvalidationStateBits();
-  }
-
-  if (!root) {
-    layerManager->RemoveUserData(&gLayerManagerLayerBuilder);
+  if (!root)
     return;
-  }
   // Root is being scaled up by the X/Y resolution. Scale it back down.
   gfx3DMatrix rootTransform = root->GetTransform()*
     gfx3DMatrix::ScalingMatrix(1.0f/containerParameters.mXScale,
                                1.0f/containerParameters.mYScale, 1.0f);
   root->SetTransform(rootTransform);
 
   ViewID id = presContext->IsRootContentDocument() ? FrameMetrics::ROOT_SCROLL_ID
                                                    : FrameMetrics::NULL_SCROLL_ID;
@@ -662,48 +636,26 @@ void nsDisplayList::PaintForFrame(nsDisp
   if (usingDisplayport &&
       !(root->GetContentFlags() & Layer::CONTENT_OPAQUE)) {
     // See bug 693938, attachment 567017
     NS_WARNING("We don't support transparent content with displayports, force it to be opqaue");
     root->SetContentFlags(Layer::CONTENT_OPAQUE);
   }
 
   layerManager->SetRoot(root);
-  layerBuilder->WillEndTransaction();
+  aBuilder->LayerBuilder()->WillEndTransaction(layerManager);
   layerManager->EndTransaction(FrameLayerBuilder::DrawThebesLayer,
-                               aBuilder, (aFlags & PAINT_NO_COMPOSITE) ? LayerManager::END_NO_COMPOSITE : LayerManager::END_DEFAULT);
-
-  nsIntRect invalid;
-  if (props) {
-    invalid = props->ComputeDifferences(root, computeInvalidFunc);
-  } else if (widgetTransaction) {
-    LayerProperties::ClearInvalidations(root);
-  }
-
-  if (view) {
-    if (props) {
-      if (!invalid.IsEmpty()) {
-        nsRect rect(presContext->DevPixelsToAppUnits(invalid.x),
-                    presContext->DevPixelsToAppUnits(invalid.y),
-                    presContext->DevPixelsToAppUnits(invalid.width),
-                    presContext->DevPixelsToAppUnits(invalid.height));
-        view->GetViewManager()->InvalidateViewNoSuppression(view, rect);
-        presContext->NotifyInvalidation(invalid, 0);
-      }
-    } else {
-      view->GetViewManager()->InvalidateView(view);
-    }
-  }
+                               aBuilder);
+  aBuilder->LayerBuilder()->DidEndTransaction(layerManager);
 
   if (aFlags & PAINT_FLUSH_LAYERS) {
     FrameLayerBuilder::InvalidateAllLayers(layerManager);
   }
 
   nsCSSRendering::DidPaint();
-  layerManager->RemoveUserData(&gLayerManagerLayerBuilder);
 }
 
 PRUint32 nsDisplayList::Count() const {
   PRUint32 count = 0;
   for (nsDisplayItem* i = GetBottom(); i; i = i->GetAbove()) {
     ++count;
   }
   return count;
@@ -1347,17 +1299,17 @@ nsDisplayBackground::GetInsideClipRegion
 nsRegion
 nsDisplayBackground::GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
                                      bool* aSnap) {
   nsRegion result;
   *aSnap = false;
   // theme background overrides any other background
   if (mIsThemed) {
     if (mThemeTransparency == nsITheme::eOpaque) {
-      result = nsRect(ToReferenceFrame(), mFrame->GetSize());
+      result = GetBounds(aBuilder, aSnap);
     }
     return result;
   }
 
   nsStyleContext* bgSC;
   nsPresContext* presContext = mFrame->PresContext();
   if (!nsCSSRendering::FindBackground(presContext, mFrame, &bgSC))
     return result;
@@ -1449,46 +1401,16 @@ nsDisplayBackground::IsVaryingRelativeTo
   // not the viewport frame, then moving aFrame will move mFrame
   // relative to the viewport, so our fixed-pos background will change.
   return aFrame->GetParent() &&
     (aFrame == mFrame ||
      nsLayoutUtils::IsProperAncestorFrame(aFrame, mFrame));
 }
 
 bool
-nsDisplayBackground::RenderingMightDependOnFrameSize()
-{
-  // theme background overrides any other background and we don't know what to do here
-  if (mIsThemed)
-    return true;
-  
-  // We could be smarter with rounded corners and only invalidate the new area + the piece that was previously
-  // clipped out.
-  nscoord radii[8];
-  if (mFrame->GetBorderRadii(radii))
-    return true;
-
-  nsPresContext* presContext = mFrame->PresContext();
-  nsStyleContext *bgSC;
-  bool hasBG =
-    nsCSSRendering::FindBackground(presContext, mFrame, &bgSC);
-  if (!hasBG)
-    return false;
-  const nsStyleBackground* bg = bgSC->GetStyleBackground();
-
-  NS_FOR_VISIBLE_BACKGROUND_LAYERS_BACK_TO_FRONT(i, bg) {
-    const nsStyleBackground::Layer &layer = bg->mLayers[i];
-    if (layer.RenderingMightDependOnFrameSize()) {
-      return true;
-    }
-  }
-  return false;
-}
-
-bool
 nsDisplayBackground::ShouldFixToViewport(nsDisplayListBuilder* aBuilder)
 {
   if (mIsThemed)
     return false;
 
   nsPresContext* presContext = mFrame->PresContext();
   nsStyleContext* bgSC;
   bool hasBG =
@@ -1535,51 +1457,25 @@ nsDisplayBackground::Paint(nsDisplayList
     flags |= nsCSSRendering::PAINTBG_WILL_PAINT_BORDER;
   }
   nsCSSRendering::PaintBackground(mFrame->PresContext(), *aCtx, mFrame,
                                   mVisibleRect,
                                   nsRect(offset, mFrame->GetSize()),
                                   flags);
 }
 
-void nsDisplayBackground::ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
-                                                    const nsDisplayItemGeometry* aGeometry,
-                                                    nsRegion* aInvalidRegion)
-{
-  const nsDisplayBackgroundGeometry* geometry = static_cast<const nsDisplayBackgroundGeometry*>(aGeometry);
-  if (ShouldFixToViewport(aBuilder)) {
-    // This is incorrect, We definitely need to check more things here. 
-    return;
-  }
-
-  bool snap;
-  if (!geometry->mBounds.IsEqualInterior(GetBounds(aBuilder, &snap)) ||
-      !geometry->mPaddingRect.IsEqualInterior(GetPaddingRect()) ||
-      !geometry->mContentRect.IsEqualInterior(GetContentRect())) {
-    if (!RenderingMightDependOnFrameSize() && geometry->mBounds.TopLeft() == GetBounds(aBuilder, &snap).TopLeft()) {
-      aInvalidRegion->Xor(GetBounds(aBuilder, &snap), geometry->mBounds);
-    } else {
-      aInvalidRegion->Or(GetBounds(aBuilder, &snap), geometry->mBounds);
-    }
-  }
-}
-
 nsRect
 nsDisplayBackground::GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) {
   nsRect r(nsPoint(0,0), mFrame->GetSize());
   nsPresContext* presContext = mFrame->PresContext();
 
   if (mIsThemed) {
     presContext->GetTheme()->
         GetWidgetOverflow(presContext->DeviceContext(), mFrame,
                           mFrame->GetStyleDisplay()->mAppearance, &r);
-#ifdef XP_MACOSX
-    // Bug 748219
-    r.Inflate(mFrame->PresContext()->AppUnitsPerDevPixel());
-#endif
   }
 
   *aSnap = true;
   return r + ToReferenceFrame();
 }
 
 nsRect
 nsDisplayOutline::GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) {
@@ -1664,43 +1560,17 @@ nsDisplayBorder::ComputeVisibility(nsDis
     // Skip this if there's a border-image (which draws a background
     // too) or if there is a border-radius (which makes the border draw
     // further in).
     return false;
   }
 
   return true;
 }
-  
-nsDisplayItemGeometry* 
-nsDisplayBorder::AllocateGeometry(nsDisplayListBuilder* aBuilder)
-{
-  bool snap;
-  nsDisplayBorderGeometry* geometry = new nsDisplayBorderGeometry;
-  geometry->mBounds = GetBounds(aBuilder, &snap);
-  geometry->mPaddingRect = GetContentRect();
-  return geometry;
-}
-
-void
-nsDisplayBorder::ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
-                                           const nsDisplayItemGeometry* aGeometry,
-                                           nsRegion* aInvalidRegion)
-{
-  const nsDisplayBorderGeometry* geometry = static_cast<const nsDisplayBorderGeometry*>(aGeometry);
-  bool snap;
-  if (!geometry->mBounds.IsEqualInterior(GetBounds(aBuilder, &snap)) ||
-      !geometry->mPaddingRect.IsEqualInterior(GetContentRect())) {
-    // We can probably get away with only invalidating the difference
-    // between the border and padding rects, but the XUL ui at least
-    // is apparently painting a background with this?
-    aInvalidRegion->Or(GetBounds(aBuilder, &snap), geometry->mBounds);
-  }
-}
-  
+
 void
 nsDisplayBorder::Paint(nsDisplayListBuilder* aBuilder,
                        nsRenderingContext* aCtx) {
   nsPoint offset = ToReferenceFrame();
   nsCSSRendering::PaintBorder(mFrame->PresContext(), *aCtx, mFrame,
                               mVisibleRect,
                               nsRect(offset, mFrame->GetSize()),
                               mFrame->GetStyleContext(),
@@ -2035,17 +1905,17 @@ nsRegion nsDisplayOpacity::GetOpaqueRegi
   return nsRegion();
 }
 
 // nsDisplayOpacity uses layers for rendering
 already_AddRefed<Layer>
 nsDisplayOpacity::BuildLayer(nsDisplayListBuilder* aBuilder,
                              LayerManager* aManager,
                              const ContainerParameters& aContainerParameters) {
-  nsRefPtr<Layer> layer = GetLayerBuilderForManager(aManager)->
+  nsRefPtr<Layer> layer = aBuilder->LayerBuilder()->
     BuildContainerLayerFor(aBuilder, aManager, mFrame, this, mList,
                            aContainerParameters, nsnull);
   if (!layer)
     return nsnull;
 
   layer->SetOpacity(mFrame->GetStyleDisplay()->mOpacity);
   return layer.forget();
 }
@@ -2105,43 +1975,35 @@ bool nsDisplayOpacity::TryMerge(nsDispla
   // aItem->GetUnderlyingFrame() returns non-null because it's nsDisplayOpacity
   if (aItem->GetUnderlyingFrame()->GetContent() != mFrame->GetContent())
     return false;
   MergeFromTrackingMergedFrames(static_cast<nsDisplayOpacity*>(aItem));
   return true;
 }
 
 nsDisplayOwnLayer::nsDisplayOwnLayer(nsDisplayListBuilder* aBuilder,
-                                     nsIFrame* aFrame, nsDisplayList* aList,
-                                     PRUint32 aFlags)
-    : nsDisplayWrapList(aBuilder, aFrame, aList)
-    , mFlags(aFlags) {
+                                     nsIFrame* aFrame, nsDisplayList* aList)
+    : nsDisplayWrapList(aBuilder, aFrame, aList) {
   MOZ_COUNT_CTOR(nsDisplayOwnLayer);
 }
 
 #ifdef NS_BUILD_REFCNT_LOGGING
 nsDisplayOwnLayer::~nsDisplayOwnLayer() {
   MOZ_COUNT_DTOR(nsDisplayOwnLayer);
 }
 #endif
 
 // nsDisplayOpacity uses layers for rendering
 already_AddRefed<Layer>
 nsDisplayOwnLayer::BuildLayer(nsDisplayListBuilder* aBuilder,
                               LayerManager* aManager,
                               const ContainerParameters& aContainerParameters) {
-  nsRefPtr<Layer> layer = GetLayerBuilderForManager(aManager)->
+  nsRefPtr<Layer> layer = aBuilder->LayerBuilder()->
     BuildContainerLayerFor(aBuilder, aManager, mFrame, this, mList,
                            aContainerParameters, nsnull);
-
-  if (mFlags & GENERATE_SUBDOC_INVALIDATIONS) {
-    ContainerLayerPresContext* pres = new ContainerLayerPresContext;
-    pres->mPresContext = mFrame->PresContext();
-    layer->SetUserData(&gNotifySubDocInvalidationData, pres);
-  }
   return layer.forget();
 }
 
 nsDisplayScrollLayer::nsDisplayScrollLayer(nsDisplayListBuilder* aBuilder,
                                            nsDisplayList* aList,
                                            nsIFrame* aForFrame,
                                            nsIFrame* aScrolledFrame,
                                            nsIFrame* aScrollFrame)
@@ -2196,17 +2058,17 @@ nsDisplayScrollLayer::~nsDisplayScrollLa
   MOZ_COUNT_DTOR(nsDisplayScrollLayer);
 }
 #endif
 
 already_AddRefed<Layer>
 nsDisplayScrollLayer::BuildLayer(nsDisplayListBuilder* aBuilder,
                                  LayerManager* aManager,
                                  const ContainerParameters& aContainerParameters) {
-  nsRefPtr<ContainerLayer> layer = GetLayerBuilderForManager(aManager)->
+  nsRefPtr<ContainerLayer> layer = aBuilder->LayerBuilder()->
     BuildContainerLayerFor(aBuilder, aManager, mFrame, this, mList,
                            aContainerParameters, nsnull);
 
   // Get the already set unique ID for scrolling this content remotely.
   // Or, if not set, generate a new ID.
   nsIContent* content = mScrolledFrame->GetContent();
   ViewID scrollId = nsLayoutUtils::FindIDFor(content);
 
@@ -2379,17 +2241,17 @@ nsDisplaySimpleScrollLayer::~nsDisplaySi
   MOZ_COUNT_DTOR(nsDisplaySimpleScrollLayer);
 }
 #endif
 
 already_AddRefed<Layer>
 nsDisplaySimpleScrollLayer::BuildLayer(nsDisplayListBuilder* aBuilder,
                                        LayerManager* aManager,
                                        const ContainerParameters& aContainerParameters) {
-  nsRefPtr<ContainerLayer> layer = GetLayerBuilderForManager(aManager)->
+  nsRefPtr<ContainerLayer> layer = aBuilder->LayerBuilder()->
     BuildContainerLayerFor(aBuilder, aManager, mFrame, this, mList,
                            aContainerParameters, nsnull);
 
   // Get the already set unique ID for scrolling this content remotely.
   // Or, if not set, generate a new ID.
   nsIContent* content = mFrame->PresContext()->Document()->GetRootElement();
   ViewID scrollId = nsLayoutUtils::FindIDFor(content);
 
@@ -2588,20 +2450,19 @@ bool nsDisplayClipRoundedRect::TryMerge(
     return false;
   // No need to track merged frames for clipping
   MergeFrom(other);
   return true;
 }
 
 nsDisplayZoom::nsDisplayZoom(nsDisplayListBuilder* aBuilder,
                              nsIFrame* aFrame, nsDisplayList* aList,
-                             PRInt32 aAPD, PRInt32 aParentAPD,
-                             PRUint32 aFlags)
-    : nsDisplayOwnLayer(aBuilder, aFrame, aList, aFlags)
-    , mAPD(aAPD), mParentAPD(aParentAPD) {
+                             PRInt32 aAPD, PRInt32 aParentAPD)
+    : nsDisplayOwnLayer(aBuilder, aFrame, aList), mAPD(aAPD),
+      mParentAPD(aParentAPD) {
   MOZ_COUNT_CTOR(nsDisplayZoom);
 }
 
 #ifdef NS_BUILD_REFCNT_LOGGING
 nsDisplayZoom::~nsDisplayZoom() {
   MOZ_COUNT_DTOR(nsDisplayZoom);
 }
 #endif
@@ -3015,17 +2876,17 @@ already_AddRefed<Layer> nsDisplayTransfo
 {
   const gfx3DMatrix& newTransformMatrix = 
     GetTransform(mFrame->PresContext()->AppUnitsPerDevPixel());
 
   if (!IsFrameVisible(mFrame, newTransformMatrix)) {
     return nsnull;
   }
 
-  nsRefPtr<ContainerLayer> container = GetLayerBuilderForManager(aManager)->
+  nsRefPtr<ContainerLayer> container = aBuilder->LayerBuilder()->
     BuildContainerLayerFor(aBuilder, aManager, mFrame, this, *mStoredList.GetList(),
                            aContainerParameters, &newTransformMatrix);
 
   // Add the preserve-3d flag for this layer, BuildContainerLayerFor clears all flags,
   // so we never need to explicitely unset this flag.
   if (mFrame->Preserves3D() || mFrame->Preserves3DChildren()) {
     container->SetContentFlags(container->GetContentFlags() | Layer::CONTENT_PRESERVE_3D);
   }
@@ -3390,62 +3251,21 @@ nsDisplaySVGEffects::HitTest(nsDisplayLi
 {
   nsPoint rectCenter(aRect.x + aRect.width / 2, aRect.y + aRect.height / 2);
   if (nsSVGIntegrationUtils::HitTestFrameForEffects(mFrame,
       rectCenter - ToReferenceFrame())) {
     mList.HitTest(aBuilder, aRect, aState, aOutFrames);
   }
 }
 
-void
-nsDisplaySVGEffects::PaintAsLayer(nsDisplayListBuilder* aBuilder,
-                                  nsRenderingContext* aCtx,
-                                  LayerManager* aManager)
-{
-  nsSVGIntegrationUtils::PaintFramesWithEffects(aCtx, mFrame,
-                                                mVisibleRect,
-                                                aBuilder, aManager);
-}
-
-LayerState
-nsDisplaySVGEffects::GetLayerState(nsDisplayListBuilder* aBuilder,
-                                   LayerManager* aManager,
-                                   const ContainerParameters& aParameters)
-{
-  return LAYER_SVG_EFFECTS;
-}
-
-already_AddRefed<Layer>
-nsDisplaySVGEffects::BuildLayer(nsDisplayListBuilder* aBuilder,
-                                LayerManager* aManager,
-                                const ContainerParameters& aContainerParameters)
+void nsDisplaySVGEffects::Paint(nsDisplayListBuilder* aBuilder,
+                                nsRenderingContext* aCtx)
 {
-  float opacity = mFrame->GetStyleDisplay()->mOpacity;
-  if (opacity == 0.0f)
-    return nsnull;
-
-  nsIFrame* firstFrame =
-    nsLayoutUtils::GetFirstContinuationOrSpecialSibling(mFrame);
-  nsSVGEffects::EffectProperties effectProperties =
-    nsSVGEffects::GetEffectProperties(firstFrame);
-
-  bool isOK = true;
-  nsSVGClipPathFrame *clipPathFrame = effectProperties.GetClipPathFrame(&isOK);
-  nsSVGMaskFrame *maskFrame = effectProperties.GetMaskFrame(&isOK);
-  nsSVGFilterFrame *filterFrame = effectProperties.GetFilterFrame(&isOK);
-
-  if (!isOK) {
-    return nsnull;
-  }
-
-  nsRefPtr<ContainerLayer> container = GetLayerBuilderForManager(aManager)->
-    BuildContainerLayerFor(aBuilder, aManager, mFrame, this, mList,
-                           aContainerParameters, nsnull);
-
-  return container.forget();
+  nsSVGIntegrationUtils::PaintFramesWithEffects(aCtx,
+          mFrame, mVisibleRect, aBuilder, &mList);
 }
 
 bool nsDisplaySVGEffects::ComputeVisibility(nsDisplayListBuilder* aBuilder,
                                               nsRegion* aVisibleRegion,
                                               const nsRect& aAllowVisibleRegionExpansion) {
   nsPoint offset = ToReferenceFrame();
   nsRect dirtyRect =
     nsSVGIntegrationUtils::GetRequiredSourceForInvalidArea(mFrame,
--- a/layout/base/nsDisplayList.h
+++ b/layout/base/nsDisplayList.h
@@ -20,18 +20,16 @@
 #include "nsISelection.h"
 #include "nsCaret.h"
 #include "plarena.h"
 #include "Layers.h"
 #include "nsRegion.h"
 #include "FrameLayerBuilder.h"
 #include "nsThemeConstants.h"
 #include "ImageLayers.h"
-#include "nsLayoutUtils.h"
-#include "nsDisplayListInvalidation.h"
 
 #include "mozilla/StandardInteger.h"
 
 #include <stdlib.h>
 
 class nsIPresShell;
 class nsIContent;
 class nsRenderingContext;
@@ -327,16 +325,21 @@ public:
   /**
    * Mark all child frames that Preserve3D() as needing display.
    * Because these frames include transforms set on their parent, dirty rects
    * for intermediate frames may be empty, yet child frames could still be visible.
    */
   void MarkPreserve3DFramesForDisplayList(nsIFrame* aDirtyFrame, const nsRect& aDirtyRect);
 
   /**
+   * Return the FrameLayerBuilder.
+   */
+  FrameLayerBuilder* LayerBuilder() { return &mLayerBuilder; }
+
+  /**
    * Get the area of the final transparent region.
    */
   const nsRegion* GetFinalTransparentRegion() { return mFinalTransparentRegion; }
   /**
    * Record the area of the final transparent region after all visibility
    * calculations were performed.
    */
   void SetFinalTransparentRegion(const nsRegion& aFinalTransparentRegion)
@@ -495,16 +498,17 @@ private:
     bool          mIsBackgroundOnly;
   };
   PresShellState* CurrentPresShellState() {
     NS_ASSERTION(mPresShellStates.Length() > 0,
                  "Someone forgot to enter a presshell");
     return &mPresShellStates[mPresShellStates.Length() - 1];
   }
 
+  FrameLayerBuilder              mLayerBuilder;
   nsIFrame*                      mReferenceFrame;
   nsIFrame*                      mIgnoreScrollFrame;
   PLArenaPool                    mPool;
   nsCOMPtr<nsISelection>         mBoundingSelection;
   nsAutoTArray<PresShellState,8> mPresShellStates;
   nsAutoTArray<nsIFrame*,100>    mFramesMarkedForDisplay;
   nsAutoTArray<ThemeGeometry,2>  mThemeGeometries;
   nsDisplayTableItem*            mCurrentTableItem;
@@ -673,82 +677,16 @@ public:
    * @return a rectangle relative to aBuilder->ReferenceFrame() that
    * contains the area drawn by this display item
    */
   virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap)
   {
     *aSnap = false;
     return nsRect(ToReferenceFrame(), GetUnderlyingFrame()->GetSize());
   }
-  nsRect GetBorderRect() {
-    return nsRect(ToReferenceFrame(), GetUnderlyingFrame()->GetSize());
-  }
-  nsRect GetPaddingRect() {
-    return GetUnderlyingFrame()->GetPaddingRectRelativeToSelf() + ToReferenceFrame();
-  }
-  nsRect GetContentRect() {
-    return GetUnderlyingFrame()->GetContentRectRelativeToSelf() + ToReferenceFrame();
-  }
-
-  /**
-   * Checks if the frame(s) owning this display item have been marked as invalid,
-   * and needing repainting.
-   */
-  virtual bool IsInvalid() { return mFrame ? mFrame->IsInvalid() : false; }
-
-  /**
-   * Creates and initializes an nsDisplayItemGeometry object that retains the current
-   * areas covered by this display item. These need to retain enough information
-   * such that they can be compared against a future nsDisplayItem of the same type, 
-   * and determine if repainting needs to happen.
-   *
-   * Subclasses wishing to store more information need to override both this
-   * and ComputeInvalidationRegion, as well as implementing an nsDisplayItemGeometry
-   * subclass.
-   *
-   * The default implementation tracks both the display item bounds, and the frame's
-   * border rect.
-   */
-  virtual nsDisplayItemGeometry* AllocateGeometry(nsDisplayListBuilder* aBuilder)
-  {
-    nsDisplayItemGenericGeometry* geometry = new nsDisplayItemGenericGeometry();
-    bool snap;
-    geometry->mBounds = GetBounds(aBuilder, &snap);
-    geometry->mBorderRect = GetBorderRect();
-    return geometry;
-  }
-
-  /**
-   * Compares an nsDisplayItemGeometry object from a previous paint against the 
-   * current item. Computes if the geometry of the item has changed, and the 
-   * invalidation area required for correct repainting.
-   *
-   * The existing geometry will have been created from a display item with a 
-   * matching GetPerFrameKey()/mFrame pair to the current item.
-   *
-   * The default implementation compares the display item bounds, and the frame's
-   * border rect, and invalidates the entire bounds if either rect changes.
-   *
-   * @param aGeometry The geometry of the matching display item from the 
-   * previous paint.
-   * @param aInvalidRegion Output param, the region to invalidate, or
-   * unchanged if none.
-   */
-  virtual void ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
-                                         const nsDisplayItemGeometry* aGeometry,
-                                         nsRegion* aInvalidRegion)
-  {
-    const nsDisplayItemGenericGeometry* geometry = static_cast<const nsDisplayItemGenericGeometry*>(aGeometry);
-    bool snap;
-    if (!geometry->mBounds.IsEqualInterior(GetBounds(aBuilder, &snap)) ||
-        !geometry->mBorderRect.IsEqualInterior(GetBorderRect())) {
-      aInvalidRegion->Or(GetBounds(aBuilder, &snap), geometry->mBounds);
-    }
-  }
-  
   /**
    * @param aSnap set to true if the edges of the rectangles of the opaque
    * region would be snapped to device pixels when drawing
    * @return a region of the item that is opaque --- that is, every pixel
    * that is visible (according to ComputeVisibility) is painted with an opaque
    * color. This is useful for determining when one piece
    * of content completely obscures another so that we can do occlusion
    * culling.
@@ -1218,18 +1156,17 @@ public:
    * 
    * This must only be called on the root display list of the display list
    * tree.
    */
   enum {
     PAINT_DEFAULT = 0,
     PAINT_USE_WIDGET_LAYERS = 0x01,
     PAINT_FLUSH_LAYERS = 0x02,
-    PAINT_EXISTING_TRANSACTION = 0x04,
-    PAINT_NO_COMPOSITE = 0x08
+    PAINT_EXISTING_TRANSACTION = 0x04
   };
   void PaintRoot(nsDisplayListBuilder* aBuilder, nsRenderingContext* aCtx,
                  PRUint32 aFlags) const;
   /**
    * Like PaintRoot, but used for internal display sublists.
    * aForFrame is the frame that the list is associated with.
    */
   void PaintForFrame(nsDisplayListBuilder* aBuilder, nsRenderingContext* aCtx,
@@ -1571,22 +1508,16 @@ public:
 #endif
 
   virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap);
   virtual void Paint(nsDisplayListBuilder* aBuilder, nsRenderingContext* aCtx);
   virtual bool ComputeVisibility(nsDisplayListBuilder* aBuilder,
                                    nsRegion* aVisibleRegion,
                                    const nsRect& aAllowVisibleRegionExpansion);
   NS_DISPLAY_DECL_NAME("Border", TYPE_BORDER)
-  
-  virtual nsDisplayItemGeometry* AllocateGeometry(nsDisplayListBuilder* aBuilder);
-
-  virtual void ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
-                                         const nsDisplayItemGeometry* aGeometry,
-                                         nsRegion* aInvalidRegion);
 };
 
 /**
  * A simple display item that just renders a solid color across the
  * specified bounds. For canvas frames (in the CSS sense) we split off the
  * drawing of the background color into this class (from nsDisplayBackground
  * via nsDisplayCanvasBackground). This is done so that we can always draw a
  * background color to avoid ugly flashes of white when we can't draw a full
@@ -1669,37 +1600,16 @@ public:
   virtual bool IsUniform(nsDisplayListBuilder* aBuilder, nscolor* aColor);
   virtual bool ShouldFixToViewport(nsDisplayListBuilder* aBuilder);
   virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap);
   virtual void Paint(nsDisplayListBuilder* aBuilder, nsRenderingContext* aCtx);
   NS_DISPLAY_DECL_NAME("Background", TYPE_BACKGROUND)
   // Returns the value of GetUnderlyingFrame()->IsThemed(), but cached
   bool IsThemed() { return mIsThemed; }
 
-  /**
-   * Returns true if existing rendered pixels of this display item may need
-   * to be redrawn if the frame size changes.
-   * If false, only the changed area needs to be redrawn.
-   */
-  bool RenderingMightDependOnFrameSize();
-  
-  virtual nsDisplayItemGeometry* AllocateGeometry(nsDisplayListBuilder* aBuilder)
-  {
-    bool snap;
-    nsDisplayBackgroundGeometry* geometry = new nsDisplayBackgroundGeometry;
-    geometry->mBounds = GetBounds(aBuilder, &snap);
-    geometry->mPaddingRect = GetPaddingRect();
-    geometry->mContentRect = GetContentRect();
-    return geometry;
-  }
-
-  virtual void ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
-                                         const nsDisplayItemGeometry* aGeometry,
-                                         nsRegion* aInvalidRegion);
-
 protected:
   typedef class mozilla::layers::ImageContainer ImageContainer;
   typedef class mozilla::layers::ImageLayer ImageLayer;
 
   nsRegion GetInsideClipRegion(nsPresContext* aPresContext, PRUint8 aClip,
                                const nsRect& aRect, bool* aSnap);
 
   bool TryOptimizeToImageLayer(nsDisplayListBuilder* aBuilder);
@@ -1730,31 +1640,16 @@ public:
 #endif
 
   virtual void Paint(nsDisplayListBuilder* aBuilder, nsRenderingContext* aCtx);
   virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap);
   virtual bool ComputeVisibility(nsDisplayListBuilder* aBuilder,
                                    nsRegion* aVisibleRegion,
                                    const nsRect& aAllowVisibleRegionExpansion);
   NS_DISPLAY_DECL_NAME("BoxShadowOuter", TYPE_BOX_SHADOW_OUTER)
-  
-  virtual void ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
-                                         const nsDisplayItemGeometry* aGeometry,
-                                         nsRegion* aInvalidRegion)
-  {
-    const nsDisplayItemGenericGeometry* geometry = static_cast<const nsDisplayItemGenericGeometry*>(aGeometry);
-    bool snap;
-    if (!geometry->mBounds.IsEqualInterior(GetBounds(aBuilder, &snap)) ||
-        !geometry->mBorderRect.IsEqualInterior(GetBorderRect())) {
-      nsRegion oldShadow, newShadow;
-      oldShadow = oldShadow.Sub(geometry->mBounds, geometry->mBorderRect);
-      newShadow = newShadow.Sub(GetBounds(aBuilder, &snap), GetBorderRect());
-      aInvalidRegion->Or(oldShadow, newShadow);
-    }
-  }
 
 private:
   nsRegion mVisibleRegion;
 };
 
 /**
  * The standard display item to paint the inner CSS box-shadows of a frame.
  */
@@ -1770,38 +1665,16 @@ public:
   }
 #endif
 
   virtual void Paint(nsDisplayListBuilder* aBuilder, nsRenderingContext* aCtx);
   virtual bool ComputeVisibility(nsDisplayListBuilder* aBuilder,
                                    nsRegion* aVisibleRegion,
                                    const nsRect& aAllowVisibleRegionExpansion);
   NS_DISPLAY_DECL_NAME("BoxShadowInner", TYPE_BOX_SHADOW_INNER)
-  
-  virtual nsDisplayItemGeometry* AllocateGeometry(nsDisplayListBuilder* aBuilder)
-  {
-    nsDisplayBoxShadowInnerGeometry* geometry = new nsDisplayBoxShadowInnerGeometry;
-    bool snap;
-    geometry->mBounds = GetBounds(aBuilder, &snap);
-    geometry->mPaddingRect = GetPaddingRect();
-    return geometry;
-  }
-
-  virtual void ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
-                                         const nsDisplayItemGeometry* aGeometry,
-                                         nsRegion* aInvalidRegion)
-  {
-    const nsDisplayBoxShadowInnerGeometry* geometry = static_cast<const nsDisplayBoxShadowInnerGeometry*>(aGeometry);
-    if (!geometry->mPaddingRect.IsEqualInterior(GetPaddingRect())) {
-      // nsDisplayBoxShadowInner is based around the padding rect, but it can
-      // touch pixels outside of this. We should invalidate the entire bounds.
-      bool snap;
-      aInvalidRegion->Or(geometry->mBounds, GetBounds(aBuilder, &snap));
-    }
-  }
 
 private:
   nsRegion mVisibleRegion;
 };
 
 /**
  * The standard display item to paint the CSS outline of a frame.
  */
@@ -1898,28 +1771,16 @@ public:
   virtual bool TryMerge(nsDisplayListBuilder* aBuilder, nsDisplayItem* aItem) {
     NS_WARNING("This list should already have been flattened!!!");
     return false;
   }
   virtual void GetMergedFrames(nsTArray<nsIFrame*>* aFrames)
   {
     aFrames->AppendElements(mMergedFrames);
   }
-  virtual bool IsInvalid()
-  {
-    if (mFrame->IsInvalid()) {
-      return true;
-    }
-    for (PRUint32 i = 0; i < mMergedFrames.Length(); i++) {
-      if (mMergedFrames[i]->IsInvalid()) {
-        return true;
-      }
-    }
-    return false;
-  }
   NS_DISPLAY_DECL_NAME("WrapList", TYPE_WRAP_LIST)
 
   virtual nsRect GetComponentAlphaBounds(nsDisplayListBuilder* aBuilder);
                                     
   virtual nsDisplayList* GetList() { return &mList; }
   
   /**
    * This creates a copy of this item, but wrapping aItem instead of
@@ -2020,52 +1881,37 @@ public:
 };
 
 /**
  * A display item that has no purpose but to ensure its contents get
  * their own layer.
  */
 class nsDisplayOwnLayer : public nsDisplayWrapList {
 public:
-
-  /**
-   * nsDisplayOwnLayer constructor flags
-   */
-  enum {
-    GENERATE_SUBDOC_INVALIDATIONS = 0x01
-  };
-
-  /**
-   * @param aFlags GENERATE_SUBDOC_INVALIDATIONS :
-   * Add UserData to the created ContainerLayer, so that invalidations
-   * for this layer are send to our nsPresContext.
-   */
   nsDisplayOwnLayer(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
-                    nsDisplayList* aList, PRUint32 aFlags = 0);
+                    nsDisplayList* aList);
 #ifdef NS_BUILD_REFCNT_LOGGING
   virtual ~nsDisplayOwnLayer();
 #endif
   
   virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
                                              LayerManager* aManager,
                                              const ContainerParameters& aContainerParameters);
   virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
                                    LayerManager* aManager,
                                    const ContainerParameters& aParameters)
   {
-    return mozilla::LAYER_ACTIVE_FORCE;
+    return mozilla::LAYER_ACTIVE;
   }
   virtual bool TryMerge(nsDisplayListBuilder* aBuilder, nsDisplayItem* aItem)
   {
     // Don't allow merging, each sublist must have its own layer
     return false;
   }
   NS_DISPLAY_DECL_NAME("OwnLayer", TYPE_OWN_LAYER)
-private:
-  PRUint32 mFlags;
 };
 
 /**
  * This potentially creates a layer for the given list of items, whose
  * visibility is determined by the displayport for the given frame instead of
  * what is passed in to ComputeVisibility.
  *
  * Here in content, we can use this to render more content than is actually
@@ -2290,24 +2136,20 @@ private:
 class nsDisplayZoom : public nsDisplayOwnLayer {
 public:
   /**
    * @param aFrame is the root frame of the subdocument.
    * @param aList contains the display items for the subdocument.
    * @param aAPD is the app units per dev pixel ratio of the subdocument.
    * @param aParentAPD is the app units per dev pixel ratio of the parent
    * document.
-   * @param aFlags GENERATE_SUBDOC_INVALIDATIONS :
-   * Add UserData to the created ContainerLayer, so that invalidations
-   * for this layer are send to our nsPresContext.
    */
   nsDisplayZoom(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
                 nsDisplayList* aList,
-                PRInt32 aAPD, PRInt32 aParentAPD,
-                PRUint32 aFlags = 0);
+                PRInt32 aAPD, PRInt32 aParentAPD);
 #ifdef NS_BUILD_REFCNT_LOGGING
   virtual ~nsDisplayZoom();
 #endif
   
   virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap);
   virtual void Paint(nsDisplayListBuilder* aBuilder, nsRenderingContext* aCtx);
   virtual void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
                        HitTestState* aState, nsTArray<nsIFrame*> *aOutFrames);
@@ -2340,34 +2182,23 @@ public:
   virtual nsRegion GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
                                    bool* aSnap);
   virtual void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
                        HitTestState* aState, nsTArray<nsIFrame*> *aOutFrames);
   virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) {
     *aSnap = false;
     return mEffectsBounds + ToReferenceFrame();
   }
+  virtual void Paint(nsDisplayListBuilder* aBuilder, nsRenderingContext* aCtx);
   virtual bool ComputeVisibility(nsDisplayListBuilder* aBuilder,
                                    nsRegion* aVisibleRegion,
                                    const nsRect& aAllowVisibleRegionExpansion);  
   virtual bool TryMerge(nsDisplayListBuilder* aBuilder, nsDisplayItem* aItem);
   NS_DISPLAY_DECL_NAME("SVGEffects", TYPE_SVG_EFFECTS)
 
-  virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
-                                   LayerManager* aManager,
-                                   const ContainerParameters& aParameters);
- 
-  virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
-                                             LayerManager* aManager,
-                                             const ContainerParameters& aContainerParameters);
-
-  void PaintAsLayer(nsDisplayListBuilder* aBuilder,
-                    nsRenderingContext* aCtx,
-                    LayerManager* aManager);
-
 #ifdef MOZ_DUMP_PAINTING
   void PrintEffects(FILE* aOutput);
 #endif
 
 private:
   // relative to mFrame
   nsRect mEffectsBounds;
 };
deleted file mode 100644
--- a/layout/base/nsDisplayListInvalidation.h
+++ /dev/null
@@ -1,118 +0,0 @@
-/*-*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef NSDISPLAYLISTINVALIDATION_H_
-#define NSDISPLAYLISTINVALIDATION_H_
-
-/**
- * This stores the geometry of an nsDisplayItem, and the area
- * that will be affected when painting the item.
- *
- * It is used to retain information about display items so they
- * can be compared against new display items in the next paint.
- */
-class nsDisplayItemGeometry
-{
-public:
-  nsDisplayItemGeometry()
-  {
-    MOZ_COUNT_CTOR(nsDisplayItemGeometry);
-  }
-  virtual ~nsDisplayItemGeometry()
-  {
-    MOZ_COUNT_DTOR(nsDisplayItemGeometry);
-  }
-  /**
-   * Compute the area required to be invalidated if this
-   * display item is removed.
-   */
-  nsRegion ComputeInvalidationRegion() { return mBounds; }
-  
-  /**
-   * Shifts all retained areas of the nsDisplayItemGeometry by the given offset.
-   * 
-   * This is used to compensate for scrolling, since the destination buffer
-   * can scroll without requiring a full repaint.
-   *
-   * @param aOffset Offset to shift by.
-   */
-  virtual void MoveBy(const nsPoint& aOffset) = 0;
-
-  /**
-   * The appunits per dev pixel for the item's frame.
-   */
-  nscoord mAppUnitsPerDevPixel;
-
-  /**
-   * The offset (in pixels) of the TopLeft() of the ThebesLayer
-   * this display item was drawn into.
-   */
-  nsIntPoint mPaintOffset;
-
-  gfxPoint mActiveScrolledRootPosition;
-  
-  /**
-   * Bounds of the display item
-   */
-  nsRect mBounds;
-};
-
-/**
- * A default geometry implementation, used by nsDisplayItem. Retains
- * and compares the bounds, and border rect.
- *
- * This should be sufficient for the majority of display items.
- */
-class nsDisplayItemGenericGeometry : public nsDisplayItemGeometry
-{
-public:
-  virtual void MoveBy(const nsPoint& aOffset)
-  {
-    mBounds.MoveBy(aOffset);
-    mBorderRect.MoveBy(aOffset);
-  }
-
-  nsRect mBorderRect;
-};
-
-class nsDisplayBorderGeometry : public nsDisplayItemGeometry
-{
-public:
-  virtual void MoveBy(const nsPoint& aOffset)
-  {
-    mBounds.MoveBy(aOffset);
-    mPaddingRect.MoveBy(aOffset);
-  }
-
-  nsRect mPaddingRect;
-};
-
-class nsDisplayBackgroundGeometry : public nsDisplayItemGeometry
-{
-public:
-  virtual void MoveBy(const nsPoint& aOffset)
-  {
-    mBounds.MoveBy(aOffset);
-    mPaddingRect.MoveBy(aOffset);
-    mContentRect.MoveBy(aOffset);
-  }
-
-  nsRect mPaddingRect;
-  nsRect mContentRect;
-};
-
-class nsDisplayBoxShadowInnerGeometry : public nsDisplayItemGeometry
-{
-public:
-  virtual void MoveBy(const nsPoint& aOffset)
-  {
-    mBounds.MoveBy(aOffset);
-    mPaddingRect.MoveBy(aOffset);
-  }
-
-  nsRect mPaddingRect;
-};
-
-#endif /*NSDISPLAYLISTINVALIDATION_H_*/
--- a/layout/base/nsDocumentViewer.cpp
+++ b/layout/base/nsDocumentViewer.cpp
@@ -2878,17 +2878,18 @@ DocumentViewerImpl::SetFullZoom(float aF
     nsIPageSequenceFrame* pf = shell->GetPageSequenceFrame();
     if (pf) {
       nsIFrame* f = do_QueryFrame(pf);
       shell->FrameNeedsReflow(f, nsIPresShell::eResize, NS_FRAME_IS_DIRTY);
     }
 
     nsIFrame* rootFrame = shell->GetRootFrame();
     if (rootFrame) {
-      rootFrame->InvalidateFrame();
+      nsRect rect(nsPoint(0, 0), rootFrame->GetSize());
+      rootFrame->Invalidate(rect);
     }
     return NS_OK;
   }
 #endif
 
   mPageZoom = aFullZoom;
 
   struct ZoomInfo ZoomInfo = { aFullZoom };
--- a/layout/base/nsFrameManager.cpp
+++ b/layout/base/nsFrameManager.cpp
@@ -463,21 +463,32 @@ nsFrameManager::InsertFrames(nsIFrame*  
            InsertFrames(aParentFrame, aListID, aPrevFrame, aFrameList);
   } else {
     return aParentFrame->InsertFrames(aListID, aPrevFrame, aFrameList);
   }
 }
 
 nsresult
 nsFrameManager::RemoveFrame(ChildListID     aListID,
-                            nsIFrame*       aOldFrame)
+                            nsIFrame*       aOldFrame,
+                            bool            aInvalidate /* = true */)
 {
   bool wasDestroyingFrames = mIsDestroyingFrames;
   mIsDestroyingFrames = true;
 
+  // In case the reflow doesn't invalidate anything since it just leaves
+  // a gap where the old frame was, we invalidate it here.  (This is
+  // reasonably likely to happen when removing a last child in a way
+  // that doesn't change the size of the parent.)
+  // This has to sure to invalidate the entire overflow rect; this
+  // is important in the presence of absolute positioning
+  if (aInvalidate) {
+    aOldFrame->InvalidateFrameSubtree();
+  }
+
   NS_ASSERTION(!aOldFrame->GetPrevContinuation() ||
                // exception for nsCSSFrameConstructor::RemoveFloatingFirstLetterFrames
                aOldFrame->GetType() == nsGkAtoms::textFrame,
                "Must remove first continuation.");
   NS_ASSERTION(!(aOldFrame->GetStateBits() & NS_FRAME_OUT_OF_FLOW &&
                  GetPlaceholderFrameFor(aOldFrame)),
                "Must call RemoveFrame on placeholder for out-of-flows.");
   nsresult rv = NS_OK;
--- a/layout/base/nsFrameManager.h
+++ b/layout/base/nsFrameManager.h
@@ -90,17 +90,18 @@ public:
                                     nsFrameList&    aFrameList);
 
   NS_HIDDEN_(nsresult) InsertFrames(nsIFrame*       aParentFrame,
                                     ChildListID     aListID,
                                     nsIFrame*       aPrevFrame,
                                     nsFrameList&    aFrameList);
 
   NS_HIDDEN_(nsresult) RemoveFrame(ChildListID     aListID,
-                                   nsIFrame*       aOldFrame);
+                                   nsIFrame*       aOldFrame,
+                                   bool            aInvalidate = true);
 
   /*
    * Notification that a frame is about to be destroyed. This allows any
    * outstanding references to the frame to be cleaned up.
    */
   NS_HIDDEN_(void)     NotifyDestroyingFrame(nsIFrame* aFrame);
 
   /*
--- a/layout/base/nsIPresShell.h
+++ b/layout/base/nsIPresShell.h
@@ -1202,47 +1202,35 @@ public:
 
   /**
    * Dispatch a mouse move event based on the most recent mouse position if
    * this PresShell is visible. This is used when the contents of the page
    * moved (aFromScroll is false) or scrolled (aFromScroll is true).
    */
   virtual void SynthesizeMouseMove(bool aFromScroll) = 0;
 
-  enum PaintType {
-    PaintType_Composite,
-    PaintType_NoComposite
-  };
-  virtual void Paint(nsIView* aViewToPaint, const nsRegion& aDirtyRegion,
-                     PaintType aType, bool aWillSendDidPaint) = 0;
+  virtual void Paint(nsIView* aViewToPaint, nsIWidget* aWidget,
+                     const nsRegion& aDirtyRegion, const nsIntRegion& aIntDirtyRegion,
+                     bool aWillSendDidPaint) = 0;
   virtual nsresult HandleEvent(nsIFrame*       aFrame,
                                nsGUIEvent*     aEvent,
                                bool            aDontRetargetEvents,
                                nsEventStatus*  aEventStatus) = 0;
   virtual bool ShouldIgnoreInvalidation() = 0;
   /**
    * Notify that the NS_WILL_PAINT event was received. Fires on every
    * visible presshell in the document tree.
    */
   virtual void WillPaint(bool aWillSendDidPaint) = 0;
   /**
    * Notify that the NS_DID_PAINT event was received. Only fires on the
    * root pres shell.
    */
   virtual void DidPaint() = 0;
-
-  /**
-   * Ensures that the refresh driver is running, and schedules a view 
-   * manager flush on the next tick.
-   *
-   * @param aFlags nsIFrame::PAINT_COMPOSITE_ONLY : No changes have 
-   * been made that require a layer tree update, so only schedule a 
-   * layer tree composite.
-   */
-  virtual void ScheduleViewManagerFlush(PRUint32 aFlags = 0) = 0;
+  virtual void ScheduleViewManagerFlush() = 0;
   virtual void ClearMouseCaptureOnView(nsIView* aView) = 0;
   virtual bool IsVisible() = 0;
   virtual void DispatchSynthMouseMove(nsGUIEvent *aEvent, bool aFlushOnHoverChange) = 0;
 
   virtual void SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf,
                                    size_t *aArenasSize,
                                    size_t *aStyleSetsSize,
                                    size_t *aTextRunsSize,
--- a/layout/base/nsImageLoader.cpp
+++ b/layout/base/nsImageLoader.cpp
@@ -208,12 +208,44 @@ nsImageLoader::DoRedraw(const nsRect* aD
   // NOTE: It is not sufficient to invalidate only the size of the image:
   //       the image may be tiled! 
   //       The best option is to call into the frame, however lacking this
   //       we have to at least invalidate the frame's bounds, hence
   //       as long as we have a frame we'll use its size.
   //
 
   // Invalidate the entire frame
+  // XXX We really only need to invalidate the client area of the frame...    
+
+  nsRect bounds(nsPoint(0, 0), mFrame->GetSize());
+
+  if (mFrame->GetType() == nsGkAtoms::canvasFrame) {
+    // The canvas's background covers the whole viewport.
+    bounds = mFrame->GetVisualOverflowRect();
+  }
+
+  // XXX this should be ok, but there is some crappy ass bug causing it not to work
+  // XXX seems related to the "body fixup rule" dealing with the canvas and body frames...
+#if 0
+  // Invalidate the entire frame only if the frame has a tiled background
+  // image, otherwise just invalidate the intersection of the frame's bounds
+  // with the damaged rect.
+  nsStyleContext* styleContext;
+  mFrame->GetStyleContext(&styleContext);
+  const nsStyleBackground* bg = styleContext->GetStyleBackground();
+
+  if ((bg->mBackgroundFlags & NS_STYLE_BG_IMAGE_NONE) ||
+      (bg->mBackgroundRepeat == NS_STYLE_BG_REPEAT_OFF)) {
+    // The frame does not have a background image so we are free
+    // to invalidate only the intersection of the damage rect and
+    // the frame's bounds.
+
+    if (aDamageRect) {
+      bounds.IntersectRect(*aDamageRect, bounds);
+    }
+  }
+
+#endif
+
   if (mFrame->GetStyleVisibility()->IsVisible()) {
-    mFrame->InvalidateFrame();
+    mFrame->Invalidate(bounds);
   }
 }
--- a/layout/base/nsLayoutDebugger.cpp
+++ b/layout/base/nsLayoutDebugger.cpp
@@ -175,17 +175,17 @@ PrintDisplayListTo(nsDisplayListBuilder*
             vis.x, vis.y, vis.width, vis.height,
             opaque.IsEmpty() ? "" : " opaque",
             i->IsUniform(aBuilder, &color) ? " uniform" : "");
     if (i->Painted()) {
       fprintf(aOutput, "</a>");
     }
     if (f) {
       PRUint32 key = i->GetPerFrameKey();
-      Layer* layer = mozilla::FrameLayerBuilder::GetDebugOldLayerFor(f, key);
+      Layer* layer = aBuilder->LayerBuilder()->GetOldLayerFor(f, key);
       if (layer) {
         fprintf(aOutput, " <a href=\"#%p\">layer=%p</a>", layer, layer);
       }
     }
     if (i->GetType() == nsDisplayItem::TYPE_SVG_EFFECTS) {
       (static_cast<nsDisplaySVGEffects*>(i))->PrintEffects(aOutput);
     }
     fputc('\n', aOutput);
--- a/layout/base/nsLayoutUtils.cpp
+++ b/layout/base/nsLayoutUtils.cpp
@@ -1778,19 +1778,16 @@ nsLayoutUtils::PaintFrame(nsRenderingCon
         // pres shell, notify the widget about any toolbars we've encountered.
         widget->UpdateThemeGeometries(builder.GetThemeGeometries());
       }
     }
   }
   if (aFlags & PAINT_EXISTING_TRANSACTION) {
     flags |= nsDisplayList::PAINT_EXISTING_TRANSACTION;
   }
-  if (aFlags & PAINT_NO_COMPOSITE) {
-    flags |= nsDisplayList::PAINT_NO_COMPOSITE;
-  }
 
   list.PaintRoot(&builder, aRenderingContext, flags);
 
   // Update the widget's opaque region information. This sets
   // glass boundaries on Windows.
   if ((aFlags & PAINT_WIDGET_LAYERS) &&
       !willFlushRetainedLayers &&
       !(aFlags & PAINT_DOCUMENT_RELATIVE)) {
@@ -1804,23 +1801,17 @@ nsLayoutUtils::PaintFrame(nsRenderingCon
   }
 
 #ifdef MOZ_DUMP_PAINTING
   if (gfxUtils::sDumpPaintList || gfxUtils::sDumpPainting) {
     fprintf(gfxUtils::sDumpPaintFile, "</script>Painting --- after optimization:\n");
     nsFrame::PrintDisplayList(&builder, list, gfxUtils::sDumpPaintFile);
 
     fprintf(gfxUtils::sDumpPaintFile, "Painting --- retained layer tree:\n");
-    nsIWidget* widget = aFrame->GetNearestWidget();
-    if (widget) {
-      nsRefPtr<LayerManager> layerManager = widget->GetLayerManager();
-      if (layerManager) {
-        FrameLayerBuilder::DumpRetainedLayerTree(layerManager, gfxUtils::sDumpPaintFile);
-      }
-    }
+    builder.LayerBuilder()->DumpRetainedLayerTree(gfxUtils::sDumpPaintFile);
     fprintf(gfxUtils::sDumpPaintFile, "</body></html>");
     
     if (gfxUtils::sDumpPaintingToFile) {
       fclose(gfxUtils::sDumpPaintFile);
     }
     gfxUtils::sDumpPaintFile = NULL;
     gPaintCount++;
   }
@@ -3948,18 +3939,16 @@ nsLayoutUtils::IsPopup(nsIFrame* aFrame)
     return false;
   }
   return IsPopupFrame(aFrame);
 }
 
 /* static */ nsIFrame*
 nsLayoutUtils::GetDisplayRootFrame(nsIFrame* aFrame)
 {
-  // We could use GetRootPresContext() here if the
-  // NS_FRAME_IN_POPUP frame bit is set.
   nsIFrame* f = aFrame;
   for (;;) {
     if (IsPopup(f))
       return f;
     nsIFrame* parent = GetCrossDocParentFrame(f);
     if (!parent)
       return f;
     f = parent;
--- a/layout/base/nsLayoutUtils.h
+++ b/layout/base/nsLayoutUtils.h
@@ -591,18 +591,17 @@ public:
     PAINT_IN_TRANSFORM = 0x01,
     PAINT_SYNC_DECODE_IMAGES = 0x02,
     PAINT_WIDGET_LAYERS = 0x04,
     PAINT_IGNORE_SUPPRESSION = 0x08,
     PAINT_DOCUMENT_RELATIVE = 0x10,
     PAINT_HIDE_CARET = 0x20,
     PAINT_ALL_CONTINUATIONS = 0x40,
     PAINT_TO_WINDOW = 0x80,
-    PAINT_EXISTING_TRANSACTION = 0x100,
-    PAINT_NO_COMPOSITE = 0x200
+    PAINT_EXISTING_TRANSACTION = 0x100
   };
 
   /**
    * Given aFrame, the root frame of a stacking context, paint it and its
    * descendants to aRenderingContext.
    * @param aRenderingContext a rendering context translated so that (0,0)
    * is the origin of aFrame; for best results, (0,0) should transform
    * to pixel-aligned coordinates. This can be null, in which case
--- a/layout/base/nsPresContext.cpp
+++ b/layout/base/nsPresContext.cpp
@@ -78,18 +78,16 @@
 //needed for resetting of image service color
 #include "nsLayoutCID.h"
 
 #include "nsCSSParser.h"
 
 using namespace mozilla;
 using namespace mozilla::dom;
 
-PRUint8 gNotifySubDocInvalidationData;
-
 namespace {
 
 class CharSetChangingRunnable : public nsRunnable
 {
 public:
   CharSetChangingRunnable(nsPresContext* aPresContext,
                           const nsCString& aCharSet)
     : mPresContext(aPresContext),
@@ -133,31 +131,16 @@ nsPresContext::PrefChangedCallback(const
 
   NS_ASSERTION(nsnull != presContext, "bad instance data");
   if (nsnull != presContext) {
     presContext->PreferenceChanged(aPrefName);
   }
   return 0;  // PREF_OK
 }
 
-bool
-nsPresContext::IsDOMPaintEventPending() 
-{
-  if (!mInvalidateRequests.mRequests.IsEmpty()) {
-    return true;    
-  }
-  if (GetRootPresContext()->mRefreshDriver->ViewManagerFlushIsPending()) {
-    // Since we're promising that there will be a MozAfterPaint event
-    // fired, we record an empty invalidation in case display list
-    // invalidation doesn't invalidate anything further.
-    NotifyInvalidation(nsRect(0, 0, 0, 0), 0);
-    return true;
-  }
-  return false;
-}
 
 void
 nsPresContext::PrefChangedUpdateTimerCallback(nsITimer *aTimer, void *aClosure)
 {
   nsPresContext*  presContext = (nsPresContext*)aClosure;
   NS_ASSERTION(presContext != nsnull, "bad instance data");
   if (presContext)
     presContext->UpdateAfterPreferencesChanged();
@@ -813,17 +796,17 @@ nsPresContext::InvalidateThebesLayers()
 {
   if (!mShell)
     return;
   nsIFrame* rootFrame = mShell->FrameManager()->GetRootFrame();
   if (rootFrame) {
     // FrameLayerBuilder caches invalidation-related values that depend on the
     // appunits-per-dev-pixel ratio, so ensure that all ThebesLayer drawing
     // is completely flushed.
-    rootFrame->InvalidateFrameSubtree();
+    FrameLayerBuilder::InvalidateThebesLayersInSubtree(rootFrame);
   }
 }
 
 void
 nsPresContext::AppUnitsPerDevPixelChanged()
 {
   InvalidateThebesLayers();
 
@@ -1192,28 +1175,16 @@ nsPresContext::GetParentPresContext()
   if (shell) {
     nsIFrame* rootFrame = shell->FrameManager()->GetRootFrame();
     if (rootFrame) {
       nsIFrame* f = nsLayoutUtils::GetCrossDocParentFrame(rootFrame);
       if (f)
         return f->PresContext();
     }
   }
-  // Not sure if this is always strictly the parent, but it works for GetRootPresContext
-  // where the current pres context has no frames.
-  nsIDocument *doc = Document();
-  if (doc) {
-    doc = doc->GetParentDocument();
-    if (doc) {
-      shell = doc->GetShell();
-      if (shell) {
-        return shell->GetPresContext();
-      }
-    }
-  }
   return nsnull;
 }
 
 nsPresContext*
 nsPresContext::GetToplevelContentDocumentPresContext()
 {
   if (IsChrome())
     return nsnull;
@@ -1228,17 +1199,17 @@ nsPresContext::GetToplevelContentDocumen
 
 // We may want to replace this with something faster, maybe caching the root prescontext
 nsRootPresContext*
 nsPresContext::GetRootPresContext()
 {
   nsPresContext* pc = this;
   for (;;) {
     nsPresContext* parent = pc->GetParentPresContext();
-    if (!parent || parent == pc)
+    if (!parent)
       break;
     pc = parent;
   }
   return pc->IsRoot() ? static_cast<nsRootPresContext*>(pc) : nsnull;
 }
 
 void
 nsPresContext::CompatibilityModeChanged()
@@ -2071,24 +2042,39 @@ void
 nsPresContext::FireDOMPaintEvent()
 {
   nsPIDOMWindow* ourWindow = mDocument->GetWindow();
   if (!ourWindow)
     return;
 
   nsCOMPtr<nsIDOMEventTarget> dispatchTarget = do_QueryInterface(ourWindow);
   nsCOMPtr<nsIDOMEventTarget> eventTarget = dispatchTarget;
-  if (!IsChrome() && !mSendAfterPaintToContent) {
-    // Don't tell the window about this event, it should not know that
-    // something happened in a subdocument. Tell only the chrome event handler.
-    // (Events sent to the window get propagated to the chrome event handler
-    // automatically.)
-    dispatchTarget = do_QueryInterface(ourWindow->GetParentTarget());
-    if (!dispatchTarget) {
-      return;
+  if (!IsChrome()) {
+    bool notifyContent = mSendAfterPaintToContent;
+
+    if (notifyContent) {
+      // If the pref is set, we still don't post events when they're
+      // entirely cross-doc.
+      notifyContent = false;
+      for (PRUint32 i = 0; i < mInvalidateRequests.mRequests.Length(); ++i) {
+        if (!(mInvalidateRequests.mRequests[i].mFlags &
+              nsIFrame::INVALIDATE_CROSS_DOC)) {
+          notifyContent = true;
+        }
+      }
+    }
+    if (!notifyContent) {
+      // Don't tell the window about this event, it should not know that
+      // something happened in a subdocument. Tell only the chrome event handler.
+      // (Events sent to the window get propagated to the chrome event handler
+      // automatically.)
+      dispatchTarget = do_QueryInterface(ourWindow->GetParentTarget());
+      if (!dispatchTarget) {
+        return;
+      }
     }
   }
   // Events sent to the window get propagated to the chrome event handler
   // automatically.
   nsCOMPtr<nsIDOMEvent> event;
   // This will empty our list in case dispatching the event causes more damage
   // (hopefully it won't, or we're likely to get an infinite loop! At least
   // it won't be blocking app execution though).
@@ -2103,34 +2089,16 @@ nsPresContext::FireDOMPaintEvent()
   // the chrome event handler, not the window), the window is still
   // logically the event target.
   event->SetTarget(eventTarget);
   event->SetTrusted(true);
   nsEventDispatcher::DispatchDOMEvent(dispatchTarget, nsnull, event, this, nsnull);
 }
 
 static bool
-MayHavePaintEventListenerSubdocumentCallback(nsIDocument* aDocument, void* aData)
-{
-  bool *result = static_cast<bool*>(aData);
-  nsIPresShell* shell = aDocument->GetShell();
-  if (shell) {
-    nsPresContext* pc = shell->GetPresContext();
-    if (pc) {
-      *result = pc->MayHavePaintEventListenerInSubDocument();
-
-      // If we found a paint event listener, then we can stop enumerating
-      // sub documents.
-      return !*result;
-    }
-  }
-  return true;
-}
-
-static bool
 MayHavePaintEventListener(nsPIDOMWindow* aInnerWindow)
 {
   if (!aInnerWindow)
     return false;
   if (aInnerWindow->HasPaintEventListeners())
     return true;
 
   nsIDOMEventTarget* parentTarget = aInnerWindow->GetParentTarget();
@@ -2171,46 +2139,26 @@ MayHavePaintEventListener(nsPIDOMWindow*
 }
 
 bool
 nsPresContext::MayHavePaintEventListener()
 {
   return ::MayHavePaintEventListener(mDocument->GetInnerWindow());
 }
 
-bool
-nsPresContext::MayHavePaintEventListenerInSubDocument()
-{
-  if (MayHavePaintEventListener()) {
-    return true;
-  }
-
-  bool result = false;
-  mDocument->EnumerateSubDocuments(MayHavePaintEventListenerSubdocumentCallback, &result);
-  return result;
-}
-
-void
-nsPresContext::NotifyInvalidation(const nsIntRect& aRect, PRUint32 aFlags)
-{
-  nsRect rect(DevPixelsToAppUnits(aRect.x),
-              DevPixelsToAppUnits(aRect.y),
-              DevPixelsToAppUnits(aRect.width),
-              DevPixelsToAppUnits(aRect.height));
-  NotifyInvalidation(rect, aFlags);
-}
-
 void
 nsPresContext::NotifyInvalidation(const nsRect& aRect, PRUint32 aFlags)
 {
   // If there is no paint event listener, then we don't need to fire
   // the asynchronous event. We don't even need to record invalidation.
   // MayHavePaintEventListener is pretty cheap and we could make it
   // even cheaper by providing a more efficient
   // nsPIDOMWindow::GetListenerManager.
+  if (aRect.IsEmpty() || !MayHavePaintEventListener())
+    return;
 
   nsPresContext* pc;
   for (pc = this; pc; pc = pc->GetParentPresContext()) {
     if (pc->mFireAfterPaintEvents)
       break;
     pc->mFireAfterPaintEvents = true;
   }
   if (!pc) {
@@ -2224,68 +2172,45 @@ nsPresContext::NotifyInvalidation(const 
     mInvalidateRequests.mRequests.AppendElement();
   if (!request)
     return;
 
   request->mRect = aRect;
   request->mFlags = aFlags;
 }
 
-/* static */ void 
-nsPresContext::NotifySubDocInvalidation(ContainerLayer* aContainer,
-                                        const nsIntRegion& aRegion)
-{
-  ContainerLayerPresContext *data = 
-    static_cast<ContainerLayerPresContext*>(
-      aContainer->GetUserData(&gNotifySubDocInvalidationData));
-  if (!data) {
-    return;
-  }
-
-  nsIntPoint topLeft = aContainer->GetVisibleRegion().GetBounds().TopLeft();
-
-  nsIntRegionRectIterator iter(aRegion);
-  while (const nsIntRect* r = iter.Next()) {
-    nsIntRect rect = *r;
-    //PresContext coordinate space is relative to the start of our visible
-    // region. Is this really true? This feels like the wrong way to get the right
-    // answer.
-    rect.MoveBy(-topLeft);
-    data->mPresContext->NotifyInvalidation(rect, 0);
-  }
-}
-
 static bool
 NotifyDidPaintSubdocumentCallback(nsIDocument* aDocument, void* aData)
 {
   nsIPresShell* shell = aDocument->GetShell();
   if (shell) {
     nsPresContext* pc = shell->GetPresContext();
     if (pc) {
       pc->NotifyDidPaintForSubtree();
     }
   }
   return true;
 }
 
 void
 nsPresContext::NotifyDidPaintForSubtree()
 {
+  if (!mFireAfterPaintEvents)
+    return;
+  mFireAfterPaintEvents = false;
+
   if (IsRoot()) {
-    if (!mFireAfterPaintEvents)
-      return;
-
     static_cast<nsRootPresContext*>(this)->CancelDidPaintTimer();
   }
 
-  mFireAfterPaintEvents = false;
-
-  nsCOMPtr<nsIRunnable> ev =
-    NS_NewRunnableMethod(this, &nsPresContext::FireDOMPaintEvent);
-  nsContentUtils::AddScriptRunner(ev);
+  if (!mInvalidateRequests.mRequests.IsEmpty()) {
+    nsCOMPtr<nsIRunnable> ev =
+      NS_NewRunnableMethod(this, &nsPresContext::FireDOMPaintEvent);
+    nsContentUtils::AddScriptRunner(ev);
+  }
 
   mDocument->EnumerateSubDocuments(NotifyDidPaintSubdocumentCallback, nsnull);
 }
 
 bool
 nsPresContext::HasCachedStyleData()
 {
   return mShell && mShell->StyleSet()->HasCachedStyleData();
--- a/layout/base/nsPresContext.h
+++ b/layout/base/nsPresContext.h
@@ -111,27 +111,16 @@ public:
   struct Request {
     nsRect   mRect;
     PRUint32 mFlags;
   };
 
   nsTArray<Request> mRequests;
 };
 
-/**
- * Layer UserData for ContainerLayers that want to be notified
- * of local invalidations of them and their descendant layers.
- * Pass a callback to ComputeDifferences to have these called.
- */
-class ContainerLayerPresContext : public mozilla::layers::LayerUserData {
-public:
-  nsPresContext* mPresContext;
-};
-extern PRUint8 gNotifySubDocInvalidationData;
-
 /* Used by nsPresContext::HasAuthorSpecifiedRules */
 #define NS_AUTHOR_SPECIFIED_BACKGROUND      (1 << 0)
 #define NS_AUTHOR_SPECIFIED_BORDER          (1 << 1)
 #define NS_AUTHOR_SPECIFIED_PADDING         (1 << 2)
 
 class nsRootPresContext;
 
 // An interface for presentation contexts. Presentation contexts are
@@ -846,26 +835,22 @@ public:
 
   // Ensure that it is safe to hand out CSS rules outside the layout
   // engine by ensuring that all CSS style sheets have unique inners
   // and, if necessary, synchronously rebuilding all style data.
   // Returns true on success and false on failure (not safe).
   bool EnsureSafeToHandOutCSSRules();
 
   void NotifyInvalidation(const nsRect& aRect, PRUint32 aFlags);
-  // aRect is in device pixels
-  void NotifyInvalidation(const nsIntRect& aRect, PRUint32 aFlags);
   void NotifyDidPaintForSubtree();
   void FireDOMPaintEvent();
 
-  // Callback for catching invalidations in ContainerLayers
-  // Passed to LayerProperties::ComputeDifference
-  static void NotifySubDocInvalidation(mozilla::layers::ContainerLayer* aContainer,
-                                       const nsIntRegion& aRegion);
-  bool IsDOMPaintEventPending();
+  bool IsDOMPaintEventPending() {
+    return !mInvalidateRequests.mRequests.IsEmpty();
+  }
   void ClearMozAfterPaintEvents() {
     mInvalidateRequests.mRequests.Clear();
   }
 
   bool IsProcessingRestyles() const {
     return mProcessingRestyles;
   }
 
@@ -1070,32 +1055,22 @@ protected:
     mLangGroupFontPrefs.mLangGroup = nsnull;
   }
 
   NS_HIDDEN_(void) UpdateCharSet(const nsCString& aCharSet);
 
 public:
   void DoChangeCharSet(const nsCString& aCharSet);
 
-  /**
-   * Checks for MozAfterPaint listeners on the document
-   */
-  bool MayHavePaintEventListener();
-
-  /**
-   * Checks for MozAfterPaint listeners on the document and 
-   * any subdocuments, except for subdocuments that are non-top-level
-   * content documents.
-   */
-  bool MayHavePaintEventListenerInSubDocument();
-
 protected:
   void InvalidateThebesLayers();
   void AppUnitsPerDevPixelChanged();
 
+  bool MayHavePaintEventListener();
+
   void HandleRebuildUserFontSet() {
     mPostedFlushUserFontSet = false;
     FlushUserFontSet();
   }
 
   bool HavePendingInputEvent();
 
   // Can't be inline because we can't include nsStyleSet.h.
--- a/layout/base/nsPresShell.cpp
+++ b/layout/base/nsPresShell.cpp
@@ -165,17 +165,16 @@
 #include "gfxPlatform.h"
 
 #include "mozilla/FunctionTimer.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/Telemetry.h"
 #include "sampler.h"
 
 #include "Layers.h"
-#include "LayerTreeInvalidation.h"
 #include "nsAsyncDOMEvent.h"
 
 #ifdef NS_FUNCTION_TIMER
 #define NS_TIME_FUNCTION_DECLARE_DOCURL                \
   nsCAutoString docURL__("N/A");                       \
   nsIURI *uri__ = mDocument->GetDocumentURI();         \
   if (uri__) uri__->GetSpec(docURL__);
 #define NS_TIME_FUNCTION_WITH_DOCURL                   \
@@ -1630,20 +1629,16 @@ PresShell::InitialReflow(nscoord aWidth,
   }
 
   NS_ENSURE_STATE(!mHaveShutDown);
 
   if (!rootFrame) {
     return NS_ERROR_OUT_OF_MEMORY;
   }
 
-  for (nsIFrame* f = rootFrame; f; f = nsLayoutUtils::GetCrossDocParentFrame(f)) {
-    f->RemoveStateBits(NS_FRAME_NO_COMPONENT_ALPHA);
-  }
-
   Element *root = mDocument->GetRootElement();
 
   if (root) {
     {
       nsAutoCauseReflowNotifier reflowNotifier(this);
       mFrameConstructor->BeginUpdate();
 
       // Have the style sheet processor construct frame for the root
@@ -3374,24 +3369,21 @@ PresShell::GetRectVisibility(nsIFrame* a
     return nsRectVisibility_kLeftOfViewport;
   if (r.x >= insetRect.XMost())
     return nsRectVisibility_kRightOfViewport;
 
   return nsRectVisibility_kVisible;
 }
 
 void
-PresShell::ScheduleViewManagerFlush(PRUint32 aFlags)
+PresShell::ScheduleViewManagerFlush()
 {
   nsPresContext* presContext = GetPresContext();
   if (presContext) {
     presContext->RefreshDriver()->ScheduleViewManagerFlush();
-    if (!(aFlags & nsIFrame::PAINT_COMPOSITE_ONLY)) {
-      mPaintRequired = true;
-    }
   }
   if (mDocument) {
     mDocument->SetNeedLayoutFlush();
   }
 }
 
 void
 PresShell::DispatchSynthMouseMove(nsGUIEvent *aEvent,
@@ -3553,17 +3545,18 @@ PresShell::UnsuppressAndInvalidate()
     // go back to the event loop and actually draw the page.
     nsContentUtils::AddScriptRunner(new nsBeforeFirstPaintDispatcher(mDocument));
   }
 
   mPaintingSuppressed = false;
   nsIFrame* rootFrame = mFrameConstructor->GetRootFrame();
   if (rootFrame) {
     // let's assume that outline on a root frame is not supported
-    rootFrame->InvalidateFrame();
+    nsRect rect(nsPoint(0, 0), rootFrame->GetSize());
+    rootFrame->Invalidate(rect);
 
     if (mCaretEnabled && mCaret) {
       mCaret->CheckCaretDrawingState();
     }
 
     nsRootPresContext* rootPC = mPresContext->GetRootPresContext();
     if (rootPC) {
       rootPC->RequestUpdatePluginGeometry(rootFrame);
@@ -3951,17 +3944,22 @@ PresShell::DocumentStatesChanged(nsIDocu
       mStyleSet->HasDocumentStateDependentStyle(mPresContext,
                                                 mDocument->GetRootElement(),
                                                 aStateMask)) {
     mFrameConstructor->PostRestyleEvent(mDocument->GetRootElement(),
                                         eRestyle_Subtree, NS_STYLE_HINT_NONE);
     VERIFY_STYLE_TREE;
   }
 
-  ScheduleViewManagerFlush();
+  if (aStateMask.HasState(NS_DOCUMENT_STATE_WINDOW_INACTIVE)) {
+    nsIFrame* root = mFrameConstructor->GetRootFrame();
+    if (root) {
+      root->InvalidateFrameSubtree();
+    }
+  }
 }
 
 void
 PresShell::AttributeWillChange(nsIDocument* aDocument,
                                Element*     aElement,
                                PRInt32      aNameSpaceID,
                                nsIAtom*     aAttribute,
                                PRInt32      aModType)
@@ -5199,155 +5197,108 @@ public:
   }
 
 private:
   bool mWillSendDidPaint;
 };
 
 void
 PresShell::Paint(nsIView*           aViewToPaint,
+                 nsIWidget*         aWidgetToPaint,
                  const nsRegion&    aDirtyRegion,
-                 PaintType          aType,
+                 const nsIntRegion& aIntDirtyRegion,
                  bool               aWillSendDidPaint)
 {
 #ifdef NS_FUNCTION_TIMER
   NS_TIME_FUNCTION_DECLARE_DOCURL;
   const nsRect& bounds__ = aDirtyRegion.GetBounds();
   NS_TIME_FUNCTION_MIN_FMT(1.0, "%s (line %d) (document: %s, dirty rect: (<%f, %f>, <%f, %f>)",
                            MOZ_FUNCTION_NAME, __LINE__, docURL__.get(),
                            NSCoordToFloat(bounds__.x),
                            NSCoordToFloat(bounds__.y),
                            NSCoordToFloat(bounds__.XMost()),
                            NSCoordToFloat(bounds__.YMost()));
 #endif
 
   SAMPLE_LABEL("Paint", "PresShell::Paint");
   NS_ASSERTION(!mIsDestroying, "painting a destroyed PresShell");
   NS_ASSERTION(aViewToPaint, "null view");
+  NS_ASSERTION(aWidgetToPaint, "Can't paint without a widget");
 
   nsAutoNotifyDidPaint notifyDidPaint(aWillSendDidPaint);
 
   nsPresContext* presContext = GetPresContext();
   AUTO_LAYOUT_PHASE_ENTRY_POINT(presContext, Paint);
 
   nsIFrame* frame = aViewToPaint->GetFrame();
 
   bool isRetainingManager;
   LayerManager* layerManager =
-    aViewToPaint->GetWidget()->GetLayerManager(&isRetainingManager);
+    aWidgetToPaint->GetLayerManager(&isRetainingManager);
   NS_ASSERTION(layerManager, "Must be in paint event");
 
   if (mIsFirstPaint) {
     layerManager->SetIsFirstPaint();
     mIsFirstPaint = false;
   }
+  layerManager->BeginTransaction();
 
   if (frame && isRetainingManager) {
     // Try to do an empty transaction, if the frame tree does not
     // need to be updated. Do not try to do an empty transaction on
     // a non-retained layer manager (like the BasicLayerManager that
     // draws the window title bar on Mac), because a) it won't work
-    // and b) below we don't want to clear mPaintRequired,
+    // and b) below we don't want to clear NS_FRAME_UPDATE_LAYER_TREE,
     // that will cause us to forget to update the real layer manager!
-    if (aType == PaintType_Composite) {
-      if (layerManager->HasShadowManager()) {
-        return;
-      }
-      layerManager->BeginTransaction();
+    if (!(frame->GetStateBits() & NS_FRAME_UPDATE_LAYER_TREE)) {
       if (layerManager->EndEmptyTransaction()) {
-        return;
-      }
-      NS_WARNING("Must complete empty transaction when compositing!");
-    } else {
-      layerManager->BeginTransaction();
-    }
-
-    if (!mPaintRequired) {
-      NotifySubDocInvalidationFunc computeInvalidFunc =
-        presContext->MayHavePaintEventListenerInSubDocument() ? nsPresContext::NotifySubDocInvalidation : 0;
-      bool computeInvalidRect = computeInvalidFunc ||
-                                (layerManager->GetBackendType() == LayerManager::LAYERS_BASIC);
-
-      nsAutoPtr<LayerProperties> props(computeInvalidRect ? 
-                                         LayerProperties::CloneFrom(layerManager->GetRoot()) : 
-                                         nsnull);
-
-      if (layerManager->EndEmptyTransaction()) {
-        nsIntRect invalid;
-        if (props) {
-          invalid = props->ComputeDifferences(layerManager->GetRoot(), computeInvalidFunc);
-        } else {
-          LayerProperties::ClearInvalidations(layerManager->GetRoot());
-        }
-        if (!invalid.IsEmpty()) {
-          if (props) {
-            nsRect rect(presContext->DevPixelsToAppUnits(invalid.x),
-                        presContext->DevPixelsToAppUnits(invalid.y),
-                        presContext->DevPixelsToAppUnits(invalid.width),
-                        presContext->DevPixelsToAppUnits(invalid.height));
-            aViewToPaint->GetViewManager()->InvalidateViewNoSuppression(aViewToPaint, rect);
-            presContext->NotifyInvalidation(invalid, 0);
-          } else {
-            aViewToPaint->GetViewManager()->InvalidateView(aViewToPaint);
-          }
-        }
-    
         frame->UpdatePaintCountForPaintedPresShells();
         presContext->NotifyDidPaintForSubtree();
         return;
       }
     }
-    mPaintRequired = false;
-  } else {
-    layerManager->BeginTransaction();
+
+    frame->RemoveStateBits(NS_FRAME_UPDATE_LAYER_TREE);
   }
   if (frame) {
     frame->ClearPresShellsFromLastPaint();
   }
 
   nscolor bgcolor = ComputeBackstopColor(aViewToPaint);
-  PRUint32 flags = nsLayoutUtils::PAINT_WIDGET_LAYERS | nsLayoutUtils::PAINT_EXISTING_TRANSACTION;
-  if (aType == Pa