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 96383 f08886a8cf22a6ceb6d96b68f8c9aad020a1fd92
parent 96382 a430a3d30163393ed5bdc18ec1a274be1abfc2f5
child 96384 8060c5ce574daf35c2bb77b348d6851e658c9548
push id10502
push useremorley@mozilla.com
push dateMon, 11 Jun 2012 09:10:00 +0000
treeherdermozilla-inbound@f08886a8cf22 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs539356, 761884, 741682, 739671
milestone16.0a1
backs out61fd66629c4f21f56d797d4c934a9347129beabc
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
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();</