Merge from mc
authorDoug Turner <dougt@dougt.org>
Tue, 10 Aug 2010 20:59:42 -0700
changeset 49376 adbf1571c30d04349e22a7a0cbb8151da0c872a0
parent 49375 18cd465199df7cc9fe5d64666162f3a569aeb268 (current diff)
parent 49368 b1be7d4acee211e547389d0d0151c0ebfd774027 (diff)
child 49377 f734ee9382eff78dd4fa1633a5d808c0d69f9de3
push id1
push userroot
push dateTue, 26 Apr 2011 22:38:44 +0000
treeherdermozilla-beta@bfdb6e623a36 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone2.0b4pre
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
Merge from mc
--- a/browser/base/content/browser.css
+++ b/browser/base/content/browser.css
@@ -78,23 +78,19 @@ toolbar[printpreview="true"] {
   -moz-box-ordinal-group: 100;
 }
 
 #TabsToolbar[tabsontop="true"] {
   -moz-box-ordinal-group: 10;
 }
 
 %ifdef MENUBAR_CAN_AUTOHIDE
-#main-window[inFullscreen] > #titlebar {
+#main-window[inFullscreen] > #appmenu-button-container {
   display: none;
 }
-
-#titlebar {
-  -moz-binding: url("chrome://global/content/bindings/general.xml#windowdragbox");
-}
 %endif
 
 toolbarpaletteitem[place="palette"] > toolbaritem > hbox[type="places"] {
   display: none;
 }
 
 toolbar[mode="icons"] > #reload-button:not([displaystop]) + #stop-button,
 toolbar[mode="icons"] > #reload-button[displaystop] {
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -1315,25 +1315,16 @@ function prepareForStartup() {
   gBrowser.addEventListener("DOMLinkAdded", DOMLinkHandler, false);
 
   // setup our MozApplicationManifest listener
   gBrowser.addEventListener("MozApplicationManifest",
                             OfflineApps, false);
 
   // setup simple gestures support
   gGestureSupport.init(true);
-
-#ifdef MENUBAR_CAN_AUTOHIDE
-  // update the visibility of the titlebar buttons after the window is
-  // displayed. (required by theme code.)
-  window.addEventListener("MozAfterPaint", function () {
-    window.removeEventListener("MozAfterPaint", arguments.callee, false);
-    document.getElementById("titlebar-buttonbox").collapsed = false;
-  }, false);
-#endif
 }
 
 function delayedStartup(isLoadingBlank, mustLoadSidebar) {
   Services.obs.addObserver(gSessionHistoryObserver, "browser:purge-session-history", false);
   Services.obs.addObserver(gXPInstallObserver, "addon-install-blocked", false);
   Services.obs.addObserver(gXPInstallObserver, "addon-install-failed", false);
   Services.obs.addObserver(gXPInstallObserver, "addon-install-complete", false);
 
@@ -4764,30 +4755,23 @@ var TabsOnTop = {
 
 #ifdef MENUBAR_CAN_AUTOHIDE
 function updateAppButtonDisplay() {
   var displayAppButton =
     !gInPrintPreviewMode &&
     window.menubar.visible &&
     document.getElementById("toolbar-menubar").getAttribute("autohide") == "true";
 
-  document.getElementById("titlebar").hidden = !displayAppButton;
+  document.getElementById("appmenu-button-container").hidden = !displayAppButton;
 
   if (displayAppButton)
     document.documentElement.setAttribute("chromemargin", "0,-1,-1,-1");
   else
     document.documentElement.removeAttribute("chromemargin");
 }
-
-function onTitlebarMaxClick() {
-  if (window.windowState == window.STATE_MAXIMIZED)
-    window.restore();
-  else
-    window.maximize();
-}
 #endif
 
 function displaySecurityInfo()
 {
   BrowserPageInfo(null, "securityTab");
 }
 
 /**
--- a/browser/base/content/browser.xul
+++ b/browser/base/content/browser.xul
@@ -432,19 +432,17 @@
               style="&dialog.style;"
               hidden="true"/>
     </panel>
 
     <tooltip id="tabbrowser-tab-tooltip" onpopupshowing="gBrowser.createTooltip(event);"/>
   </popupset>
 
 #ifdef MENUBAR_CAN_AUTOHIDE
-  <vbox id="titlebar">
-    <hbox id="titlebar-content">
-    <hbox id="appmenu-button-container" align="start">
+  <hbox id="appmenu-button-container">
     <button id="appmenu-button"
             type="menu"
             label="&brandShortName;"
             style="-moz-user-focus: ignore;">
       <menupopup id="appmenu-popup">
         <hbox flex="1" class="split-menuitem">
           <menuitem id="appmenu_newTab"
                     class="split-menuitem-item"
@@ -574,25 +572,17 @@
 #ifdef XP_WIN
                   label="&quitApplicationCmdWin.label;"
 #else
                   label="&quitApplicationCmd.label;"
 #endif
                   command="cmd_quitApplication"/>
       </menupopup>
     </button>
-    </hbox>
-    <spacer id="titlebar-spacer" flex="1"/>
-    <hbox id="titlebar-buttonbox" collapsed="true">
-      <toolbarbutton id="titlebar-min" onclick="window.minimize();"/>
-      <toolbarbutton id="titlebar-max" onclick="onTitlebarMaxClick();"/>
-      <toolbarbutton id="titlebar-close" onclick="window.close();"/>
-    </hbox>
-    </hbox>
-  </vbox>
+  </hbox>
 #endif
 
   <toolbox id="navigator-toolbox"
            defaultmode="icons" mode="icons"
 #ifdef WINCE
            defaulticonsize="small" iconsize="small"
 #endif
 #ifdef XP_WIN
--- a/browser/base/content/test/test_contextmenu.html
+++ b/browser/base/content/test/test_contextmenu.html
@@ -31,16 +31,30 @@ function openContextMenuFor(element) {
     var eventDetails = { type : "contextmenu", button : 2 };
     synthesizeMouse(element, 2, 2, eventDetails, element.ownerDocument.defaultView);
 }
 
 function closeContextMenu() {
     contextMenu.hidePopup();
 }
 
+function executeCopyCommand(command, expectedValue)
+{
+  // Just execute the command directly rather than simulating a context menu
+  // press to avoid having to deal with its asynchronous nature
+  subwindow.controllers.getControllerForCommand(command).doCommand(command);
+
+  // The easiest way to check the clipboard is to paste the contents into a
+  // textbox
+  input.focus();
+  input.value = "";
+  input.controllers.getControllerForCommand("cmd_paste").doCommand("cmd_paste");
+  is(input.value, expectedValue, "paste for command " + command);
+}
+
 function getVisibleMenuItems(aMenu) {
     var items = [];
     var accessKeys = {};
     for (var i = 0; i < aMenu.childNodes.length; i++) {
         var item = aMenu.childNodes[i];
         if (item.hidden)
             continue;
 
@@ -386,16 +400,23 @@ function runTest(testNum) {
                           "---",                 null,
                           "spell-check-enabled", true,
                           "spell-dictionaries",  true,
                               ["spell-check-dictionary-en-US", true,
                                "---",                          null,
                                "spell-add-dictionaries",       true], null]);
 
         closeContextMenu();
+        openContextMenuFor(link); // Invoke context menu for next test.
+        break;
+
+  case 15:
+        executeCopyCommand("cmd_copyLink", "http://mozilla.com/");
+        closeContextMenu();
+
         subwindow.close();
         SimpleTest.finish();
         return;
 
     /*
      * Other things that would be nice to test:
      *  - selected text
      *  - spelling / misspelled word (in text input?)
--- a/browser/themes/winstripe/browser/browser-aero.css
+++ b/browser/themes/winstripe/browser/browser-aero.css
@@ -16,16 +16,25 @@
 }
 
 @media all and (-moz-windows-compositor) {
   #main-window:not(:-moz-lwtheme) {
     -moz-appearance: -moz-win-glass;
     background: transparent;
   }
 
+  /* the new titlebar requires this, or content will be clipped at the top of the screen. */
+  #main-window[sizemode="maximized"][chromemargin^="0,"] {
+    margin-top: 8px;
+  }
+
+  #main-window[sizemode="normal"][chromemargin^="0,"] {
+    margin-top: 2px;
+  }
+
   #main-window:not(:-moz-lwtheme)[inFullscreen="true"] {
     -moz-appearance: none;
     background-color: #556;
   }
 
   #toolbar-menubar:not(:-moz-lwtheme),
   #TabsToolbar[tabsontop="true"]:not(:-moz-lwtheme),
   #navigator-toolbox[tabsontop="false"] > #nav-bar:not(:-moz-lwtheme),
--- a/browser/themes/winstripe/browser/browser.css
+++ b/browser/themes/winstripe/browser/browser.css
@@ -21,17 +21,16 @@
  * Contributor(s):
  *   Joe Hewitt (hewitt@netscape.com)
  *   Jason Kersey (kerz@netscape.com)
  *   Pierre Chanial (chanial@noos.fr)
  *   Dean Tessman (dean_tessman@hotmail.com)
  *   Blake Ross (blake@cs.stanford.edu)
  *   Pamela Greene (pamg.bugs@gmail.com)
  *   Dão Gottwald (dao@mozilla.com)
- *   Jim Mathies (jmathies@mozilla.com)
  *
  * Alternatively, the contents of this file may be used under the terms of
  * either the GNU General Public License Version 2 or later (the "GPL"), or
  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  * in which case the provisions of the GPL or the LGPL are applicable instead
  * of those above. If you wish to allow use of your version of this file only
  * under the terms of either the GPL or the LGPL, and not to allow others to
  * use your version of this file under the terms of the MPL, indicate your
@@ -97,17 +96,31 @@
 #print-preview-toolbar:not(:-moz-lwtheme) {
   -moz-appearance: toolbox;
 }
 
 statusbarpanel#statusbar-display {
   -moz-padding-start: 0;
 }
 
-/* ::::: app menu button ::::: */
+/* App menu button */
+
+%ifndef WINSTRIPE_AERO
+#appmenu-button-container {
+  background: ActiveCaption;
+}
+
+#appmenu-button-container:-moz-window-inactive {
+  background: InactiveCaption;
+}
+%endif
+
+#appmenu-button-container {
+  -moz-binding: url("chrome://global/content/bindings/general.xml#windowdragbox");
+}
 
 #appmenu-button {
   -moz-appearance: none;
   background-color: rgb(228,120,14);
   background-image: -moz-linear-gradient(rgba(255,255,255,.7),
                                          rgba(255,255,255,.4) 10%,
                                          rgba(255,255,255,0) 50%);
   background-clip: padding-box;
@@ -152,94 +165,34 @@ statusbarpanel#statusbar-display {
 }
 
 .split-menuitem-item[_moz-menuactive="true"],
 .split-menuitem-menu[_moz-menuactive="true"] {
   background-color: -moz-menuhover;
   color: -moz-menuhovertext;
 }
 
-/* ::::: titlebar ::::: */
-
-#titlebar {
-  -moz-appearance: -moz-window-titlebar;
-  /* we only need to the middle section, hide the edges of the
-  theme background beyond the window frame. */
-  margin-left: -15px;
-  margin-right: -15px;
-}
-
-#main-window[sizemode="maximized"] > #titlebar {
-  -moz-appearance: -moz-window-titlebar-maximized;
-}
-
-#titlebar-content {
-  margin-left: 15px;
-  margin-right: 15px;
-}
-
-/* aesthetic - push the fx button off the top window border */
-@media not all and (-moz-windows-classic) {
-  #main-window[sizemode="normal"] > #titlebar > #titlebar-content > #appmenu-button-container {
-%ifndef WINSTRIPE_AERO
-    margin-top: 1px;
-%else
-    margin-top: 2px;
+/* XXX: stop-gap until the button can be drawn in the title bar */
+%ifdef WINSTRIPE_AERO
+@media not all and (-moz-windows-compositor) {
 %endif
+  #main-window[tabsontop="true"] > #appmenu-button-container > #appmenu-button {
+    position: relative !important;
+    margin-bottom: -1.6em !important;
   }
-}
-
-#titlebar-buttonbox {
-  -moz-appearance: -moz-window-button-box;
-  -moz-box-align: start;
-}
-
-#main-window[sizemode="maximized"] > #titlebar > #titlebar-content > #titlebar-buttonbox {
-  -moz-appearance: -moz-window-button-box-maximized;
+  #navigator-toolbox[tabsontop="true"] > #toolbar-menubar[autohide="true"] {
+    position: relative !important;
+    background-color: -moz-dialog !important;
+  }
+  #navigator-toolbox[tabsontop="true"] > #toolbar-menubar[autohide="true"] ~ #TabsToolbar:not([inFullscreen]) {
+    -moz-padding-start: 10em !important;
+  }
+%ifdef WINSTRIPE_AERO
 }
-
-/* titlebar command buttons */
-
-#titlebar-min {
-  -moz-appearance: -moz-window-button-minimize;
-}
-
-#titlebar-max {
-  -moz-appearance: -moz-window-button-maximize;
-}
-
-#main-window[sizemode="maximized"] > #titlebar > #titlebar-content > #titlebar-buttonbox > #titlebar-max {
-  -moz-appearance: -moz-window-button-restore;
-}
-
-#titlebar-close {
-  -moz-appearance: -moz-window-button-close;
-}
-
-@media not all and (-moz-windows-classic) {
-  #titlebar-min {
-    -moz-margin-end: 1px;
-  }
-
-  #titlebar-max {
-    -moz-margin-start: 1px;
-    -moz-margin-end: 1px;
-  }
-
-  #titlebar-close {
-    -moz-margin-start: 1px;
-    -moz-margin-end: 0;
-  }
-}
-
-@media all and (-moz-windows-classic) {
-  #titlebar-close {
-    -moz-margin-start: 2px !important;
-  }
-}
+%endif
 
 /* ::::: bookmark buttons ::::: */
 
 toolbarbutton.bookmark-item {
   margin: 0;
   padding: 2px 3px;
 }
 
--- a/content/html/document/src/nsHTMLFragmentContentSink.cpp
+++ b/content/html/document/src/nsHTMLFragmentContentSink.cpp
@@ -1095,16 +1095,20 @@ nsHTMLParanoidFragmentSink::OpenContaine
   return nsHTMLFragmentContentSink::OpenContainer(aNode);
 }
 
 NS_IMETHODIMP
 nsHTMLParanoidFragmentSink::CloseContainer(const nsHTMLTag aTag)
 {
   nsresult rv = NS_OK;
 
+  if (mIgnoreNextCloseHead && aTag == eHTMLTag_head) {
+    mIgnoreNextCloseHead = PR_FALSE;
+    return NS_OK;
+  }
   if (mSkip) {
     mSkip = PR_FALSE;
     return rv;
   }
 
   nsCOMPtr<nsIAtom> name;
   rv = NameFromType(aTag, getter_AddRefs(name));
   NS_ENSURE_SUCCESS(rv, rv);
@@ -1224,17 +1228,20 @@ nsHTMLParanoidFragmentSink::SanitizeStyl
 
 NS_IMETHODIMP
 nsHTMLParanoidFragmentSink::AddLeaf(const nsIParserNode& aNode)
 {
   NS_ENSURE_TRUE(mNodeInfoManager, NS_ERROR_NOT_INITIALIZED);
   
   nsresult rv = NS_OK;
 
-  if (mSkip) {
+  // We need to explicitly skip adding leaf nodes in the paranoid sink,
+  // otherwise things like the textnode under <title> get appended to
+  // the fragment itself, and won't be popped off in CloseContainer.
+  if (mSkip || mIgnoreNextCloseHead) {
     return rv;
   }
   
   if (aNode.GetTokenType() == eToken_start) {
     nsCOMPtr<nsIAtom> name;
     rv = NameFromNode(aNode, getter_AddRefs(name));
     NS_ENSURE_SUCCESS(rv, rv);
 
--- a/dom/plugins/PluginModuleParent.cpp
+++ b/dom/plugins/PluginModuleParent.cpp
@@ -49,55 +49,63 @@
 #include "base/process_util.h"
 
 #include "mozilla/unused.h"
 #include "mozilla/ipc/SyncChannel.h"
 #include "mozilla/plugins/PluginModuleParent.h"
 #include "mozilla/plugins/BrowserStreamParent.h"
 #include "PluginIdentifierParent.h"
 
+#include "nsAutoPtr.h"
 #include "nsContentUtils.h"
 #include "nsCRT.h"
 #ifdef MOZ_CRASHREPORTER
 #include "nsExceptionHandler.h"
 #endif
 #include "nsNPAPIPlugin.h"
 
 using base::KillProcess;
 
 using mozilla::PluginLibrary;
 using mozilla::ipc::SyncChannel;
 
 using namespace mozilla::plugins;
 
 static const char kTimeoutPref[] = "dom.ipc.plugins.timeoutSecs";
+static const char kLaunchTimeoutPref[] = "dom.ipc.plugins.processLaunchTimeoutSecs";
 
 template<>
 struct RunnableMethodTraits<mozilla::plugins::PluginModuleParent>
 {
     typedef mozilla::plugins::PluginModuleParent Class;
     static void RetainCallee(Class* obj) { }
     static void ReleaseCallee(Class* obj) { }
 };
 
 // static
 PluginLibrary*
 PluginModuleParent::LoadModule(const char* aFilePath)
 {
     PLUGIN_LOG_DEBUG_FUNCTION;
 
+    PRInt32 prefSecs = nsContentUtils::GetIntPref(kLaunchTimeoutPref, 0);
+
     // Block on the child process being launched and initialized.
-    PluginModuleParent* parent = new PluginModuleParent(aFilePath);
-    parent->mSubprocess->Launch();
+    nsAutoPtr<PluginModuleParent> parent(new PluginModuleParent(aFilePath));
+    bool launched = parent->mSubprocess->Launch(prefSecs * 1000);
+    if (!launched) {
+        // Need to set this so the destructor doesn't complain.
+        parent->mShutdown = true;
+        return nsnull;
+    }
     parent->Open(parent->mSubprocess->GetChannel(),
                  parent->mSubprocess->GetChildProcessHandle());
 
     TimeoutChanged(kTimeoutPref, parent);
-
-    return parent;
+    return parent.forget();
 }
 
 
 PluginModuleParent::PluginModuleParent(const char* aFilePath)
     : mSubprocess(new PluginProcessParent(aFilePath))
     , mPluginThread(0)
     , mShutdown(false)
     , mNPNIface(NULL)
--- a/dom/plugins/PluginProcessParent.cpp
+++ b/dom/plugins/PluginProcessParent.cpp
@@ -63,21 +63,21 @@ PluginProcessParent::PluginProcessParent
 {
 }
 
 PluginProcessParent::~PluginProcessParent()
 {
 }
 
 bool
-PluginProcessParent::Launch()
+PluginProcessParent::Launch(PRInt32 timeoutMs)
 {
     vector<string> args;
     args.push_back(MungePluginDsoPath(mPluginFilePath));
-    return SyncLaunch(args);
+    return SyncLaunch(args, timeoutMs);
 }
 
 void
 PluginProcessParent::Delete()
 {
   MessageLoop* currentLoop = MessageLoop::current();
   MessageLoop* ioLoop = XRE_GetIOMessageLoop();
 
--- a/dom/plugins/PluginProcessParent.h
+++ b/dom/plugins/PluginProcessParent.h
@@ -56,19 +56,20 @@ namespace plugins {
 
 class PluginProcessParent : mozilla::ipc::GeckoChildProcessHost
 {
 public:
     PluginProcessParent(const std::string& aPluginFilePath);
     ~PluginProcessParent();
 
     /**
-     * Synchronously launch the plugin process.
+     * Synchronously launch the plugin process. If the process fails to launch
+     * after timeoutMs, this method will return false.
      */
-    bool Launch();
+    bool Launch(PRInt32 timeoutMs);
 
     void Delete();
 
     virtual bool CanShutdown()
     {
         return true;
     }
 
--- a/editor/libeditor/html/tests/test_bug520189.html
+++ b/editor/libeditor/html/tests/test_bug520189.html
@@ -47,16 +47,18 @@ https://bugzilla.mozilla.org/show_bug.cg
   <iframe id="ee" src="about:blank"></iframe>
   <div id="ff" contenteditable="true"></div>
   <iframe id="gg" src="about:blank"></iframe>
   <div id="hh" contenteditable="true"></div>
   <iframe id="ii" src="about:blank"></iframe>
   <div id="jj" contenteditable="true"></div>
   <iframe id="kk" src="about:blank"></iframe>
   <div id="ll" contenteditable="true"></div>
+  <iframe id="mm" src="about:blank"></iframe>
+  <div id="nn" contenteditable="true"></div>
 </div>
 <pre id="test">
 <script type="application/javascript">
 
 /** Test for Bug 520182 **/
 
 const dataPayload = "foo<iframe src=\"data:text/html,bar\"></iframe>baz";
 const jsPayload = "foo<iframe src=\"javascript:void('bar');\"></iframe>baz";
@@ -68,16 +70,17 @@ const validStyle2Payload = "foo<span sty
 const validStyle3Payload = "foo<style>@font-face{font-family:xxx;src:'xxx.ttf';}</style>baz";
 const validStyle4Payload = "foo<style>@namespace xxx url(http://example.com/);</style>baz";
 const invalidStyle1Payload = "foo<style>#bar{-moz-binding:url('data:text/xml,<?xml version=\"1.0\"><binding xmlns=\"http://www.mozilla.org/xbl\"/>');}</style>baz";
 const invalidStyle2Payload = "foo<span style=\"-moz-binding:url('data:text/xml,<?xml version=&quot;1.0&quot;><binding xmlns=&quot;http://www.mozilla.org/xbl&quot;/>');\">bar</span>baz";
 const invalidStyle3Payload = "foo<style>@import 'xxx.css';</style>baz";
 const invalidStyle4Payload = "foo<span style=\"@import 'xxx.css';\">bar</span>baz";
 const invalidStyle5Payload = "foo<span style=\"@font-face{font-family:xxx;src:'xxx.ttf';}\">bar</span>baz";
 const invalidStyle6Payload = "foo<span style=\"@namespace xxx url(http://example.com/);\">bar</span>baz";
+const invalidStyle7Payload = "<html><head><title>xxx</title></head><body>foo</body></html>";
 const nestedStylePayload = "foo<style>#bar1{-moz-binding:url('data:text/xml,<?xml version=&quot;1.0&quot;><binding xmlns=&quot;http://www.mozilla.org/xbl&quot; id=&quot;binding-1&quot;/>');<style></style>#bar2{-moz-binding:url('data:text/xml,<?xml version=&quot;1.0&quot;><binding xmlns=&quot;http://www.mozilla.org/xbl&quot; id=&quot;binding-2&quot;/>');</style>baz";
 const validImgSrc1Payload = "foo<img src=\"data:image/png,bar\">baz";
 const validImgSrc2Payload = "foo<img src=\"javascript:void('bar');\">baz";
 const validImgSrc3Payload = "foo<img src=\"file:///bar.png\">baz";
 
 var tests = [
   {
     id: "a",
@@ -194,36 +197,36 @@ var tests = [
     id: "r",
     payload: invalidStyle2Payload,
     rootElement: function() document.getElementById("r"),
     checkResult: function(html) is(html.indexOf("binding"), -1, "Should not have retained the binding style")
   },
   {
     id: "s",
     isIFrame: true,
-    payload: invalidStyle1Payload,
+    payload: invalidStyle3Payload,
     rootElement: function() document.getElementById("s").contentDocument.documentElement,
     checkResult: function(html) is(html.indexOf("xxx"), -1, "Should not have retained the import style")
   },
   {
     id: "t",
-    payload: invalidStyle1Payload,
+    payload: invalidStyle3Payload,
     rootElement: function() document.getElementById("t"),
     checkResult: function(html) is(html.indexOf("xxx"), -1, "Should not have retained the import style")
   },
   {
     id: "u",
     isIFrame: true,
-    payload: invalidStyle2Payload,
+    payload: invalidStyle4Payload,
     rootElement: function() document.getElementById("u").contentDocument.documentElement,
     checkResult: function(html) is(html.indexOf("xxx"), -1, "Should not have retained the import style")
   },
   {
     id: "v",
-    payload: invalidStyle2Payload,
+    payload: invalidStyle4Payload,
     rootElement: function() document.getElementById("v"),
     checkResult: function(html) is(html.indexOf("xxx"), -1, "Should not have retained the import style")
   },
   {
     id: "w",
     isIFrame: true,
     payload: validStyle3Payload,
     rootElement: function() document.getElementById("w").contentDocument.documentElement,
@@ -293,51 +296,72 @@ var tests = [
     id: "ff",
     payload: invalidStyle6Payload,
     rootElement: function() document.getElementById("ff"),
     checkResult: function(html) is(html.indexOf("xxx"), -1, "Should not have retained the namespace style")
   },
   {
     id: "gg",
     isIFrame: true,
-    payload: invalidStyle6Payload,
+    payload: validImgSrc1Payload,
     rootElement: function() document.getElementById("gg").contentDocument.documentElement,
     checkResult: function(html) isnot(html.indexOf("bar"), -1, "Should have retained the src attribute for the image")
   },
   {
     id: "hh",
-    payload: invalidStyle6Payload,
+    payload: validImgSrc1Payload,
     rootElement: function() document.getElementById("hh"),
     checkResult: function(html) isnot(html.indexOf("bar"), -1, "Should have retained the src attribute for the image")
   },
   {
     id: "ii",
     isIFrame: true,
-    payload: invalidStyle6Payload,
+    payload: validImgSrc2Payload,
     rootElement: function() document.getElementById("ii").contentDocument.documentElement,
     checkResult: function(html) isnot(html.indexOf("bar"), -1, "Should have retained the src attribute for the image")
   },
   {
     id: "jj",
-    payload: invalidStyle6Payload,
+    payload: validImgSrc2Payload,
     rootElement: function() document.getElementById("jj"),
     checkResult: function(html) isnot(html.indexOf("bar"), -1, "Should have retained the src attribute for the image")
   },
   {
     id: "kk",
     isIFrame: true,
-    payload: invalidStyle6Payload,
+    payload: validImgSrc3Payload,
     rootElement: function() document.getElementById("kk").contentDocument.documentElement,
     checkResult: function(html) isnot(html.indexOf("bar"), -1, "Should have retained the src attribute for the image")
   },
   {
     id: "ll",
-    payload: invalidStyle6Payload,
+    payload: validImgSrc3Payload,
     rootElement: function() document.getElementById("ll"),
     checkResult: function(html) isnot(html.indexOf("bar"), -1, "Should have retained the src attribute for the image")
+  },
+  {
+    id: "mm",
+    isIFrame: true,
+    insertHTML: true,
+    payload: invalidStyle7Payload,
+    rootElement: function() document.getElementById("mm").contentDocument.documentElement,
+    checkResult: function(html) {
+      is(html.indexOf("xxx"), -1, "Should not have retained the title text");
+      isnot(html.indexOf("foo"), -1, "Should have retained the body text");
+    }
+  },
+  {
+    id: "nn",
+    insertHTML: true,
+    payload: invalidStyle7Payload,
+    rootElement: function() document.getElementById("nn"),
+    checkResult: function(html) {
+      is(html.indexOf("xxx"), -1, "Should not have retained the title text");
+      isnot(html.indexOf("foo"), -1, "Should have retained the body text");
+    }
   }
 ];
 
 function doNextTest() {
   if (typeof testCounter == "undefined")
     testCounter = 0;
   else if (++testCounter == tests.length) {
     SimpleTest.finish();
@@ -352,38 +376,47 @@ function doNextTest() {
 function runTest(test) {
   var elem = document.getElementById(test.id);
   if ("isIFrame" in test) {
     elem.contentDocument.designMode = "on";
     elem.contentWindow.focus();
   } else
     elem.focus();
 
-  netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
+  if ("insertHTML" in test) {
+    if ("isIFrame" in test) {
+      elem.contentDocument.execCommand("inserthtml", false, test.payload);
+    } else {
+      getSelection().collapse(elem, 0);
+      document.execCommand("inserthtml", false, test.payload);
+    }
+  } else {
+    netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
 
-  var clipboard = Components.classes["@mozilla.org/widget/clipboard;1"]
-                            .getService(Components.interfaces.nsIClipboard);
+    var clipboard = Components.classes["@mozilla.org/widget/clipboard;1"]
+                              .getService(Components.interfaces.nsIClipboard);
 
-  var trans = Components.classes["@mozilla.org/widget/transferable;1"]
-                        .createInstance(Components.interfaces.nsITransferable);
-  var data = Components.classes["@mozilla.org/supports-string;1"]
-                       .createInstance(Components.interfaces.nsISupportsString);
-  data.data = test.payload;
-  trans.addDataFlavor("text/html");
-  trans.setTransferData("text/html", data, data.data.length * 2);
-  clipboard.setData(trans, null, Components.interfaces.nsIClipboard.kGlobalClipboard);
+    var trans = Components.classes["@mozilla.org/widget/transferable;1"]
+                          .createInstance(Components.interfaces.nsITransferable);
+    var data = Components.classes["@mozilla.org/supports-string;1"]
+                         .createInstance(Components.interfaces.nsISupportsString);
+    data.data = test.payload;
+    trans.addDataFlavor("text/html");
+    trans.setTransferData("text/html", data, data.data.length * 2);
+    clipboard.setData(trans, null, Components.interfaces.nsIClipboard.kGlobalClipboard);
 
-  var mainWindow = window.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
-                         .getInterface(Components.interfaces.nsIWebNavigation)
-                         .QueryInterface(Components.interfaces.nsIDocShellTreeItem)
-                         .rootTreeItem
-                         .QueryInterface(Components.interfaces.nsIInterfaceRequestor)
-                         .getInterface(Components.interfaces.nsIDOMWindow);
+    var mainWindow = window.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
+                           .getInterface(Components.interfaces.nsIWebNavigation)
+                           .QueryInterface(Components.interfaces.nsIDocShellTreeItem)
+                           .rootTreeItem
+                           .QueryInterface(Components.interfaces.nsIInterfaceRequestor)
+                           .getInterface(Components.interfaces.nsIDOMWindow);
 
-  mainWindow.goDoCommand("cmd_paste");
+    mainWindow.goDoCommand("cmd_paste");
+  }
 
   if ("checkResult" in test) {
     if ("isIFrame" in test) {
       test.checkResult(elem.contentDocument.documentElement.innerHTML,
         elem.contentDocument.documentElement.textContent);
     } else {
       test.checkResult(elem.innerHTML, elem.textContent);
     }
--- a/extensions/pref/autoconfig/src/nsJSConfigTriggers.cpp
+++ b/extensions/pref/autoconfig/src/nsJSConfigTriggers.cpp
@@ -102,17 +102,17 @@ AutoConfigSecMan::CanAccess(PRUint32 aAc
 }
 
 //*****************************************************************************
 
 static  JSContext *autoconfig_cx = nsnull;
 static  JSObject *autoconfig_glob;
 
 static JSClass global_class = {
-    "autoconfig_global", 0,
+    "autoconfig_global", JSCLASS_GLOBAL_FLAGS,
     JS_PropertyStub,  JS_PropertyStub,  JS_PropertyStub,  JS_PropertyStub,
     JS_EnumerateStub, JS_ResolveStub,   JS_ConvertStub,   nsnull
 };
 
 static void
 autoConfigErrorReporter(JSContext *cx, const char *message, 
                         JSErrorReport *report)
 {
new file mode 100644
--- /dev/null
+++ b/gfx/cairo/cairo/src/cairo-d2d-private-fx.h
@@ -0,0 +1,546 @@
+#if 0
+//
+// FX Version: fx_4_0
+// Child effect (requires effect pool): false
+//
+// 1 local buffer(s)
+//
+cbuffer cb0
+{
+    float4  QuadDesc;                   // Offset:    0, size:   16
+    float4  TexCoords;                  // Offset:   16, size:   16
+}
+
+//
+// 2 local object(s)
+//
+Texture2D tex;
+SamplerState sSampler
+{
+    Texture  = tex;
+    AddressU = uint(CLAMP /* 3 */);
+    AddressV = uint(CLAMP /* 3 */);
+};
+
+//
+// 1 technique(s)
+//
+technique10 SampleTexture
+{
+    pass P0
+    {
+        VertexShader = asm {
+            //
+            // Generated by Microsoft (R) HLSL Shader Compiler 9.27.952.3022
+            //
+            //
+            // Buffer Definitions: 
+            //
+            // cbuffer cb0
+            // {
+            //
+            //   float4 QuadDesc;                   // Offset:    0 Size:    16
+            //   float4 TexCoords;                  // Offset:   16 Size:    16
+            //
+            // }
+            //
+            //
+            // Resource Bindings:
+            //
+            // Name                                 Type  Format         Dim Slot Elements
+            // ------------------------------ ---------- ------- ----------- ---- --------
+            // cb0                               cbuffer      NA          NA    0        1
+            //
+            //
+            //
+            // Input signature:
+            //
+            // Name                 Index   Mask Register SysValue Format   Used
+            // -------------------- ----- ------ -------- -------- ------ ------
+            // POSITION                 0   xyz         0     NONE  float   xy  
+            //
+            //
+            // Output signature:
+            //
+            // Name                 Index   Mask Register SysValue Format   Used
+            // -------------------- ----- ------ -------- -------- ------ ------
+            // SV_Position              0   xyzw        0      POS  float   xyzw
+            // TEXCOORD                 0   xy          1     NONE  float   xy  
+            //
+            //
+            // Constant buffer to DX9 shader constant mappings:
+            //
+            // Target Reg Buffer  Start Reg # of Regs        Data Conversion
+            // ---------- ------- --------- --------- ----------------------
+            // c1         cb0             0         2  ( FLT, FLT, FLT, FLT)
+            //
+            //
+            // Runtime generated constant mappings:
+            //
+            // Target Reg                               Constant Description
+            // ---------- --------------------------------------------------
+            // c0                              Vertex Shader position offset
+            //
+            //
+            // Level9 shader bytecode:
+            //
+                vs_2_x
+                def c3, 0, 1, 0, 0
+                dcl_texcoord v0
+                mad oT0.xy, v0, c2.zwzw, c2
+                mad r0.x, v0.x, c1.z, c1.x
+                mad r0.y, v0.y, c1.w, c1.y
+                add oPos.xy, r0, c0
+                mov oPos.zw, c3.xyxy
+            
+            // approximately 5 instruction slots used
+            vs_4_0
+            dcl_constantbuffer cb0[2], immediateIndexed
+            dcl_input v0.xy
+            dcl_output_siv o0.xyzw, position
+            dcl_output o1.xy
+            mad o0.xy, v0.xyxx, cb0[0].zwzz, cb0[0].xyxx
+            mov o0.zw, l(0,0,0,1.000000)
+            mad o1.xy, v0.xyxx, cb0[1].zwzz, cb0[1].xyxx
+            ret 
+            // Approximately 4 instruction slots used
+                    
+        };
+        GeometryShader = NULL;
+        PixelShader = asm {
+            //
+            // Generated by Microsoft (R) HLSL Shader Compiler 9.27.952.3022
+            //
+            //
+            // Resource Bindings:
+            //
+            // Name                                 Type  Format         Dim Slot Elements
+            // ------------------------------ ---------- ------- ----------- ---- --------
+            // sSampler                          sampler      NA          NA    0        1
+            // tex                               texture  float4          2d    0        1
+            //
+            //
+            //
+            // Input signature:
+            //
+            // Name                 Index   Mask Register SysValue Format   Used
+            // -------------------- ----- ------ -------- -------- ------ ------
+            // SV_Position              0   xyzw        0      POS  float       
+            // TEXCOORD                 0   xy          1     NONE  float   xy  
+            //
+            //
+            // Output signature:
+            //
+            // Name                 Index   Mask Register SysValue Format   Used
+            // -------------------- ----- ------ -------- -------- ------ ------
+            // SV_Target                0   xyzw        0   TARGET  float   xyzw
+            //
+            //
+            // Sampler/Resource to DX9 shader sampler mappings:
+            //
+            // Target Sampler Source Sampler  Source Resource
+            // -------------- --------------- ----------------
+            // s0             s0              t0               
+            //
+            //
+            // Level9 shader bytecode:
+            //
+                ps_2_x
+                dcl t0.xy
+                dcl_2d s0
+                texld r0, t0, s0
+                mov oC0, r0
+            
+            // approximately 2 instruction slots used (1 texture, 1 arithmetic)
+            ps_4_0
+            dcl_sampler s0, mode_default
+            dcl_resource_texture2d (float,float,float,float) t0
+            dcl_input_ps linear v1.xy
+            dcl_output o0.xyzw
+            sample o0.xyzw, v1.xyxx, t0.xyzw, s0
+            ret 
+            // Approximately 2 instruction slots used
+                    
+        };
+    }
+
+}
+
+#endif
+
+const BYTE g_main[] =
+{
+     68,  88,  66,  67, 235,  24, 
+    238,   6,  37, 230, 191, 228, 
+     58,  61,  41, 219,  70, 130, 
+     61,  51,   1,   0,   0,   0, 
+    187,   8,   0,   0,   1,   0, 
+      0,   0,  36,   0,   0,   0, 
+     70,  88,  49,  48, 143,   8, 
+      0,   0,   1,  16, 255, 254, 
+      1,   0,   0,   0,   2,   0, 
+      0,   0,   2,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      1,   0,   0,   0,  79,   7, 
+      0,   0,   0,   0,   0,   0, 
+      1,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   1,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   2,   0, 
+      0,   0,   2,   0,   0,   0, 
+      0,   0,   0,   0,  99,  98, 
+     48,   0, 102, 108, 111,  97, 
+    116,  52,   0,   8,   0,   0, 
+      0,   1,   0,   0,   0,   0, 
+      0,   0,   0,  16,   0,   0, 
+      0,  16,   0,   0,   0,  16, 
+      0,   0,   0,  10,  33,   0, 
+      0,  81, 117,  97, 100,  68, 
+    101, 115,  99,   0,  84, 101, 
+    120,  67, 111, 111, 114, 100, 
+    115,   0,  84, 101, 120, 116, 
+    117, 114, 101,  50,  68,   0, 
+     62,   0,   0,   0,   2,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+     12,   0,   0,   0, 116, 101, 
+    120,   0,  83,  97, 109, 112, 
+    108, 101, 114,  83, 116,  97, 
+    116, 101,   0, 104,   0,   0, 
+      0,   2,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,  21,   0,   0, 
+      0, 115,  83,  97, 109, 112, 
+    108, 101, 114,   0,   1,   0, 
+      0,   0,   2,   0,   0,   0, 
+      3,   0,   0,   0,   1,   0, 
+      0,   0,   2,   0,   0,   0, 
+      3,   0,   0,   0,  83,  97, 
+    109, 112, 108, 101,  84, 101, 
+    120, 116, 117, 114, 101,   0, 
+     80,  48,   0, 172,   3,   0, 
+      0,  68,  88,  66,  67, 247, 
+    105,  31, 113, 120,  95,  58, 
+     12, 207, 141,  45,  76, 175, 
+     59, 223,  25,   1,   0,   0, 
+      0, 172,   3,   0,   0,   6, 
+      0,   0,   0,  56,   0,   0, 
+      0, 248,   0,   0,   0, 188, 
+      1,   0,   0,  56,   2,   0, 
+      0,  32,   3,   0,   0,  84, 
+      3,   0,   0,  65, 111, 110, 
+     57, 184,   0,   0,   0, 184, 
+      0,   0,   0,   0,   2, 254, 
+    255, 132,   0,   0,   0,  52, 
+      0,   0,   0,   1,   0,  36, 
+      0,   0,   0,  48,   0,   0, 
+      0,  48,   0,   0,   0,  36, 
+      0,   1,   0,  48,   0,   0, 
+      0,   0,   0,   2,   0,   1, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   1,   2, 254, 
+    255,  81,   0,   0,   5,   3, 
+      0,  15, 160,   0,   0,   0, 
+      0,   0,   0, 128,  63,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,  31,   0,   0,   2,   5, 
+      0,   0, 128,   0,   0,  15, 
+    144,   4,   0,   0,   4,   0, 
+      0,   3, 224,   0,   0, 228, 
+    144,   2,   0, 238, 160,   2, 
+      0, 228, 160,   4,   0,   0, 
+      4,   0,   0,   1, 128,   0, 
+      0,   0, 144,   1,   0, 170, 
+    160,   1,   0,   0, 160,   4, 
+      0,   0,   4,   0,   0,   2, 
+    128,   0,   0,  85, 144,   1, 
+      0, 255, 160,   1,   0,  85, 
+    160,   2,   0,   0,   3,   0, 
+      0,   3, 192,   0,   0, 228, 
+    128,   0,   0, 228, 160,   1, 
+      0,   0,   2,   0,   0,  12, 
+    192,   3,   0,  68, 160, 255, 
+    255,   0,   0,  83,  72,  68, 
+     82, 188,   0,   0,   0,  64, 
+      0,   1,   0,  47,   0,   0, 
+      0,  89,   0,   0,   4,  70, 
+    142,  32,   0,   0,   0,   0, 
+      0,   2,   0,   0,   0,  95, 
+      0,   0,   3,  50,  16,  16, 
+      0,   0,   0,   0,   0, 103, 
+      0,   0,   4, 242,  32,  16, 
+      0,   0,   0,   0,   0,   1, 
+      0,   0,   0, 101,   0,   0, 
+      3,  50,  32,  16,   0,   1, 
+      0,   0,   0,  50,   0,   0, 
+     11,  50,  32,  16,   0,   0, 
+      0,   0,   0,  70,  16,  16, 
+      0,   0,   0,   0,   0, 230, 
+    138,  32,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,  70, 
+    128,  32,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,  54, 
+      0,   0,   8, 194,  32,  16, 
+      0,   0,   0,   0,   0,   2, 
+     64,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0, 128, 
+     63,  50,   0,   0,  11,  50, 
+     32,  16,   0,   1,   0,   0, 
+      0,  70,  16,  16,   0,   0, 
+      0,   0,   0, 230, 138,  32, 
+      0,   0,   0,   0,   0,   1, 
+      0,   0,   0,  70, 128,  32, 
+      0,   0,   0,   0,   0,   1, 
+      0,   0,   0,  62,   0,   0, 
+      1,  83,  84,  65,  84, 116, 
+      0,   0,   0,   4,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   3,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   1,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   1,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,  82, 
+     68,  69,  70, 224,   0,   0, 
+      0,   1,   0,   0,   0,  64, 
+      0,   0,   0,   1,   0,   0, 
+      0,  28,   0,   0,   0,   0, 
+      4, 254, 255,   0, 129,   0, 
+      0, 174,   0,   0,   0,  60, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   1, 
+      0,   0,   0,   0,   0,   0, 
+      0,  99,  98,  48,   0,  60, 
+      0,   0,   0,   2,   0,   0, 
+      0,  88,   0,   0,   0,  32, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0, 136, 
+      0,   0,   0,   0,   0,   0, 
+      0,  16,   0,   0,   0,   2, 
+      0,   0,   0, 148,   0,   0, 
+      0,   0,   0,   0,   0, 164, 
+      0,   0,   0,  16,   0,   0, 
+      0,  16,   0,   0,   0,   2, 
+      0,   0,   0, 148,   0,   0, 
+      0,   0,   0,   0,   0,  81, 
+    117,  97, 100,  68, 101, 115, 
+     99,   0, 171, 171, 171,   1, 
+      0,   3,   0,   1,   0,   4, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,  84, 101, 120, 
+     67, 111, 111, 114, 100, 115, 
+      0,  77, 105,  99, 114, 111, 
+    115, 111, 102, 116,  32,  40, 
+     82,  41,  32,  72,  76,  83, 
+     76,  32,  83, 104,  97, 100, 
+    101, 114,  32,  67, 111, 109, 
+    112, 105, 108, 101, 114,  32, 
+     57,  46,  50,  55,  46,  57, 
+     53,  50,  46,  51,  48,  50, 
+     50,   0, 171,  73,  83,  71, 
+     78,  44,   0,   0,   0,   1, 
+      0,   0,   0,   8,   0,   0, 
+      0,  32,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   3,   0,   0,   0,   0, 
+      0,   0,   0,   7,   3,   0, 
+      0,  80,  79,  83,  73,  84, 
+     73,  79,  78,   0, 171, 171, 
+    171,  79,  83,  71,  78,  80, 
+      0,   0,   0,   2,   0,   0, 
+      0,   8,   0,   0,   0,  56, 
+      0,   0,   0,   0,   0,   0, 
+      0,   1,   0,   0,   0,   3, 
+      0,   0,   0,   0,   0,   0, 
+      0,  15,   0,   0,   0,  68, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   3, 
+      0,   0,   0,   1,   0,   0, 
+      0,   3,  12,   0,   0,  83, 
+     86,  95,  80, 111, 115, 105, 
+    116, 105, 111, 110,   0,  84, 
+     69,  88,  67,  79,  79,  82, 
+     68,   0, 171, 171, 171, 195, 
+      0,   0,   0,   0,   0,   0, 
+      0,   1,   0,   0,   0,   2, 
+      0,   0,   0,   0,   0,   0, 
+      0, 188,   2,   0,   0,  68, 
+     88,  66,  67,  90,  17, 243, 
+     62, 104,  14,   0,  40,  49, 
+     70, 150,  92,  77,   1, 115, 
+    141,   1,   0,   0,   0, 188, 
+      2,   0,   0,   6,   0,   0, 
+      0,  56,   0,   0,   0, 164, 
+      0,   0,   0,  16,   1,   0, 
+      0, 140,   1,   0,   0,  48, 
+      2,   0,   0, 136,   2,   0, 
+      0,  65, 111, 110,  57, 100, 
+      0,   0,   0, 100,   0,   0, 
+      0,   0,   2, 255, 255,  60, 
+      0,   0,   0,  40,   0,   0, 
+      0,   0,   0,  40,   0,   0, 
+      0,  40,   0,   0,   0,  40, 
+      0,   1,   0,  36,   0,   0, 
+      0,  40,   0,   0,   0,   0, 
+      0,   1,   2, 255, 255,  31, 
+      0,   0,   2,   0,   0,   0, 
+    128,   0,   0,   3, 176,  31, 
+      0,   0,   2,   0,   0,   0, 
+    144,   0,   8,  15, 160,  66, 
+      0,   0,   3,   0,   0,  15, 
+    128,   0,   0, 228, 176,   0, 
+      8, 228, 160,   1,   0,   0, 
+      2,   0,   8,  15, 128,   0, 
+      0, 228, 128, 255, 255,   0, 
+      0,  83,  72,  68,  82, 100, 
+      0,   0,   0,  64,   0,   0, 
+      0,  25,   0,   0,   0,  90, 
+      0,   0,   3,   0,  96,  16, 
+      0,   0,   0,   0,   0,  88, 
+     24,   0,   4,   0, 112,  16, 
+      0,   0,   0,   0,   0,  85, 
+     85,   0,   0,  98,  16,   0, 
+      3,  50,  16,  16,   0,   1, 
+      0,   0,   0, 101,   0,   0, 
+      3, 242,  32,  16,   0,   0, 
+      0,   0,   0,  69,   0,   0, 
+      9, 242,  32,  16,   0,   0, 
+      0,   0,   0,  70,  16,  16, 
+      0,   1,   0,   0,   0,  70, 
+    126,  16,   0,   0,   0,   0, 
+      0,   0,  96,  16,   0,   0, 
+      0,   0,   0,  62,   0,   0, 
+      1,  83,  84,  65,  84, 116, 
+      0,   0,   0,   2,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   2,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   1,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   1, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,  82, 
+     68,  69,  70, 156,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   2,   0,   0, 
+      0,  28,   0,   0,   0,   0, 
+      4, 255, 255,   0, 129,   0, 
+      0, 105,   0,   0,   0,  92, 
+      0,   0,   0,   3,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   1, 
+      0,   0,   0,   0,   0,   0, 
+      0, 101,   0,   0,   0,   2, 
+      0,   0,   0,   5,   0,   0, 
+      0,   4,   0,   0,   0, 255, 
+    255, 255, 255,   0,   0,   0, 
+      0,   1,   0,   0,   0,  12, 
+      0,   0,   0, 115,  83,  97, 
+    109, 112, 108, 101, 114,   0, 
+    116, 101, 120,   0,  77, 105, 
+     99, 114, 111, 115, 111, 102, 
+    116,  32,  40,  82,  41,  32, 
+     72,  76,  83,  76,  32,  83, 
+    104,  97, 100, 101, 114,  32, 
+     67, 111, 109, 112, 105, 108, 
+    101, 114,  32,  57,  46,  50, 
+     55,  46,  57,  53,  50,  46, 
+     51,  48,  50,  50,   0, 171, 
+    171,  73,  83,  71,  78,  80, 
+      0,   0,   0,   2,   0,   0, 
+      0,   8,   0,   0,   0,  56, 
+      0,   0,   0,   0,   0,   0, 
+      0,   1,   0,   0,   0,   3, 
+      0,   0,   0,   0,   0,   0, 
+      0,  15,   0,   0,   0,  68, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   3, 
+      0,   0,   0,   1,   0,   0, 
+      0,   3,   3,   0,   0,  83, 
+     86,  95,  80, 111, 115, 105, 
+    116, 105, 111, 110,   0,  84, 
+     69,  88,  67,  79,  79,  82, 
+     68,   0, 171, 171, 171,  79, 
+     83,  71,  78,  44,   0,   0, 
+      0,   1,   0,   0,   0,   8, 
+      0,   0,   0,  32,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   3,   0,   0, 
+      0,   0,   0,   0,   0,  15, 
+      0,   0,   0,  83,  86,  95, 
+     84,  97, 114, 103, 101, 116, 
+      0, 171, 171, 135,   4,   0, 
+      0,   0,   0,   0,   0,   4, 
+      0,   0,   0,  32,   0,   0, 
+      0,   0,   0,   0,   0,   2, 
+      0,   0,   0, 255, 255, 255, 
+    255,   0,   0,   0,   0,  43, 
+      0,   0,   0,  15,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,  52,   0,   0, 
+      0,  15,   0,   0,   0,   0, 
+      0,   0,   0,  16,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0, 100,   0,   0,   0,  72, 
+      0,   0,   0,   0,   0,   0, 
+      0, 255, 255, 255, 255,   0, 
+      0,   0,   0, 145,   0,   0, 
+      0, 117,   0,   0,   0,   0, 
+      0,   0,   0, 255, 255, 255, 
+    255,   3,   0,   0,   0,  55, 
+      0,   0,   0,   0,   0,   0, 
+      0,   2,   0,   0,   0, 100, 
+      0,   0,   0,  46,   0,   0, 
+      0,   0,   0,   0,   0,   1, 
+      0,   0,   0, 154,   0,   0, 
+      0,  47,   0,   0,   0,   0, 
+      0,   0,   0,   1,   0,   0, 
+      0, 166,   0,   0,   0,   0, 
+      0,   0,   0, 178,   0,   0, 
+      0,   1,   0,   0,   0,   0, 
+      0,   0,   0, 192,   0,   0, 
+      0,   3,   0,   0,   0,   0, 
+      0,   0,   0,   6,   0,   0, 
+      0,   0,   0,   0,   0,   7, 
+      0,   0,   0, 115,   4,   0, 
+      0,   8,   0,   0,   0,   0, 
+      0,   0,   0,   1,   0,   0, 
+      0, 123,   4,   0,   0,   7, 
+      0,   0,   0,   0,   0,   0, 
+      0,   7,   0,   0,   0,  71, 
+      7,   0,   0
+};
new file mode 100644
--- /dev/null
+++ b/gfx/cairo/cairo/src/cairo-d2d-private.fx
@@ -0,0 +1,57 @@
+// We store vertex coordinates and the quad shape in a constant buffer, this is
+// easy to update and allows us to use a single call to set the x, y, w, h of
+// the quad.
+// The QuadDesc and TexCoords both work as follows:
+// The x component is the quad left point, the y component is the top point
+// the z component is the width, and the w component is the height. The quad
+// are specified in viewport coordinates, i.e. { -1.0f, 1.0f, 2.0f, -2.0f }
+// would cover the entire viewport (which runs from <-1.0f, 1.0f> left to right
+// and <-1.0f, 1.0f> -bottom- to top. The TexCoords desc is specified in texture
+// space <0, 1.0f> left to right and top to bottom. The input vertices of the
+// shader stage always form a rectangle from {0, 0} - {1, 1}
+cbuffer cb0
+{
+    float4 QuadDesc;
+    float4 TexCoords;
+}
+
+struct VS_OUTPUT
+{
+    float4 Position : SV_Position;
+    float2 TexCoord : TEXCOORD0;
+};
+
+Texture2D tex;
+
+sampler sSampler = sampler_state {
+    Texture = tex;
+    AddressU = Clamp;
+    AddressV = Clamp;
+};
+
+VS_OUTPUT SampleTextureVS(float3 pos : POSITION)
+{
+    VS_OUTPUT Output;
+    Output.Position.w = 1.0f;
+    Output.Position.x = pos.x * QuadDesc.z + QuadDesc.x;
+    Output.Position.y = pos.y * QuadDesc.w + QuadDesc.y;
+    Output.Position.z = 0;
+    Output.TexCoord.x = pos.x * TexCoords.z + TexCoords.x;
+    Output.TexCoord.y = pos.y * TexCoords.w + TexCoords.y;
+    return Output;
+}
+
+float4 SampleTexturePS( VS_OUTPUT In) : SV_Target
+{
+    return tex.Sample(sSampler, In.TexCoord);
+};
+
+technique10 SampleTexture
+{
+    pass P0
+    {
+        SetVertexShader(CompileShader(vs_4_0_level_9_3, SampleTextureVS()));
+        SetGeometryShader(NULL);
+        SetPixelShader(CompileShader(ps_4_0_level_9_3, SampleTexturePS()));
+    }
+}
--- a/gfx/cairo/cairo/src/cairo-d2d-private.h
+++ b/gfx/cairo/cairo/src/cairo-d2d-private.h
@@ -44,28 +44,50 @@
 #include <dxgi.h>
 
 extern "C" {
 #include "cairoint.h"
 #include "cairo-surface-clipper-private.h"
 }
 
 #include "cairo-win32-refptr.h"
+#include "cairo-d2d-private-fx.h"
+#include "cairo-win32.h"
 
 /* describes the type of the currently applied clip so that we can pop it */
 struct d2d_clip;
 
+#define MAX_OPERATORS CAIRO_OPERATOR_HSL_LUMINOSITY + 1
+
+struct _cairo_d2d_device
+{
+    cairo_device_t base;
+
+    HMODULE mD3D10_1;
+    RefPtr<ID3D10Device1> mD3D10Device;
+    RefPtr<ID3D10Effect> mSampleEffect;
+    RefPtr<ID3D10InputLayout> mInputLayout;
+    RefPtr<ID3D10Buffer> mQuadBuffer;
+    RefPtr<ID3D10RasterizerState> mRasterizerState;
+    RefPtr<ID3D10BlendState> mBlendStates[MAX_OPERATORS];
+};
+typedef struct _cairo_d2d_device cairo_d2d_device_t;
+
 struct _cairo_d2d_surface {
     _cairo_d2d_surface() : d2d_clip(NULL), clipping(false), isDrawing(false),
 	textRenderingInit(true)
     {
 	_cairo_clip_init (&this->clip);
     }
 
     cairo_surface_t base;
+    /* Device used by this surface 
+     * NOTE: In upstream cairo this is in the surface base class */
+    cairo_d2d_device_t *device;
+
     /** Render target of the texture we render to */
     RefPtr<ID2D1RenderTarget> rt;
     /** Surface containing our backstore */
     RefPtr<ID3D10Resource> surface;
     /** 
      * Surface used to temporarily store our surface if a bitmap isn't available
      * straight from our render target surface.
      */
@@ -98,16 +120,20 @@ struct _cairo_d2d_surface {
     RefPtr<ID2D1BitmapBrush> bitmapBrush;
     /** Brush used for solid colors */
     RefPtr<ID2D1SolidColorBrush> solidColorBrush;
     /** Indicates if our render target is currently in drawing mode */
     bool isDrawing;
     /** Indicates if text rendering is initialized */
     bool textRenderingInit;
 
+    RefPtr<ID3D10RenderTargetView> buffer_rt_view;
+    RefPtr<ID3D10ShaderResourceView> buffer_sr_view;
+
+
     //cairo_surface_clipper_t clipper;
 };
 typedef struct _cairo_d2d_surface cairo_d2d_surface_t;
 
 typedef HRESULT (WINAPI*D2D1CreateFactoryFunc)(
     __in D2D1_FACTORY_TYPE factoryType,
     __in REFIID iid,
     __in_opt CONST D2D1_FACTORY_OPTIONS *pFactoryOptions,
@@ -119,118 +145,35 @@ typedef HRESULT (WINAPI*D3D10CreateDevic
   D3D10_DRIVER_TYPE DriverType,
   HMODULE Software,
   UINT Flags,
   D3D10_FEATURE_LEVEL1 HardwareLevel,
   UINT SDKVersion,
   ID3D10Device1 **ppDevice
 );
 
-class D2DSurfFactory
-{
-public:
-    static ID2D1Factory *Instance()
-    {
-	if (!mFactoryInstance) {
-	    D2D1CreateFactoryFunc createD2DFactory = (D2D1CreateFactoryFunc)
-		GetProcAddress(LoadLibraryW(L"d2d1.dll"), "D2D1CreateFactory");
-	    if (createD2DFactory) {
-		D2D1_FACTORY_OPTIONS options;
-#ifdef DEBUG
-		options.debugLevel = D2D1_DEBUG_LEVEL_INFORMATION;
-#else
-		options.debugLevel = D2D1_DEBUG_LEVEL_NONE;
-#endif
-		createD2DFactory(
-		    D2D1_FACTORY_TYPE_SINGLE_THREADED,
-		    __uuidof(ID2D1Factory),
-		    &options,
-		    (void**)&mFactoryInstance);
-	    }
-	}
-	return mFactoryInstance;
-    }
-private:
-    static ID2D1Factory *mFactoryInstance;
-};
-
-/**
- * On usage of D3D10_CREATE_DEVICE_PREVENT_INTERNAL_THREADING_OPTIMIZATIONS:
- * documentation on D3D10_CREATE_DEVICE_PREVENT_INTERNAL_THREADING_OPTIMIZATIONS
- * can be misleading. In fact, that flag gives no such indication. I pointed this
- * out to Bas in my email. However, Microsoft is in fact using this flag to
- * indicate "light weight" DX applications. By light weight they are essentially
- * referring to applications that are not games. The idea is that when you create
- * a DX game, the driver assumes that you will pretty much have a single instance
- * and therefore it doesn't try to hold back when it comes to GPU resource
- * allocation as long as it can crank out performance. In other words, the
- * priority in regular DX applications is to make that one application run as fast
- * as you can. For "light weight" applications, including D2D applications, the
- * priorities are a bit different. Now you are no longer going to have a single
- * (or very few) instances. You can have a lot of them (say, for example, a
- * separate DX context/device per browser tab). In such cases, the GPU resource
- * allocation scheme changes.
- */
-class D3D10Factory
-{
-public:
-    static ID3D10Device1 *Device()
-    {
-	if (!mDeviceInstance) {
-	    D3D10CreateDevice1Func createD3DDevice = (D3D10CreateDevice1Func)
-		GetProcAddress(LoadLibraryA("d3d10_1.dll"), "D3D10CreateDevice1");
-	    if (createD3DDevice) {
-		HRESULT hr = createD3DDevice(
-		    NULL, 
-		    D3D10_DRIVER_TYPE_HARDWARE,
-		    NULL,
-		    D3D10_CREATE_DEVICE_BGRA_SUPPORT |
-		    D3D10_CREATE_DEVICE_PREVENT_INTERNAL_THREADING_OPTIMIZATIONS,
-		    D3D10_FEATURE_LEVEL_10_1,
-		    D3D10_1_SDK_VERSION,
-		    &mDeviceInstance);
-		if (FAILED(hr)) {
-		    HRESULT hr = createD3DDevice(
-			NULL, 
-			D3D10_DRIVER_TYPE_HARDWARE,
-			NULL,
-			D3D10_CREATE_DEVICE_BGRA_SUPPORT |
-			D3D10_CREATE_DEVICE_PREVENT_INTERNAL_THREADING_OPTIMIZATIONS,
-			D3D10_FEATURE_LEVEL_10_0,
-			D3D10_1_SDK_VERSION,
-			&mDeviceInstance);
-		    if (FAILED(hr)) {
-			/* TODO: D3D10Level9 might be slower than GDI */
-			HRESULT hr = createD3DDevice(
-			    NULL, 
-			    D3D10_DRIVER_TYPE_HARDWARE,
-			    NULL,
-			    D3D10_CREATE_DEVICE_BGRA_SUPPORT |
-			    D3D10_CREATE_DEVICE_PREVENT_INTERNAL_THREADING_OPTIMIZATIONS,
-			    D3D10_FEATURE_LEVEL_9_3,
-			    D3D10_1_SDK_VERSION,
-			    &mDeviceInstance);
-
-		    }
-		}
-		if (SUCCEEDED(hr)) {
-		    mDeviceInstance->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_LINESTRIP);
-		}
-	    }
-	}
-	return mDeviceInstance;
-    }
-private:
-    static ID3D10Device1 *mDeviceInstance;
-};
-
+typedef HRESULT (WINAPI*D3D10CreateEffectFromMemoryFunc)(
+    void *pData,
+    SIZE_T DataLength,
+    UINT FXFlags,
+    ID3D10Device *pDevice, 
+    ID3D10EffectPool *pEffectPool,
+    ID3D10Effect **ppEffect
+);
 
 RefPtr<ID2D1Brush>
 _cairo_d2d_create_brush_for_pattern(cairo_d2d_surface_t *d2dsurf, 
 			            const cairo_pattern_t *pattern,
 				    bool unique = false);
 void
 _cairo_d2d_begin_draw_state(cairo_d2d_surface_t *d2dsurf);
+
 cairo_status_t
 _cairo_d2d_set_clip(cairo_d2d_surface_t *d2dsurf, cairo_clip_t *clip);
 
+cairo_int_status_t _cairo_d2d_blend_temp_surface(cairo_d2d_surface_t *surf, cairo_operator_t op, ID2D1RenderTarget *rt, cairo_clip_t *clip, const cairo_rectangle_int_t *bounds = NULL);
+
+RefPtr<ID2D1RenderTarget> _cairo_d2d_get_temp_rt(cairo_d2d_surface_t *surf, cairo_clip_t *clip);
+
+cairo_operator_t _cairo_d2d_simplify_operator(cairo_operator_t op, const cairo_pattern_t *source);
+
 #endif /* CAIRO_HAS_D2D_SURFACE */
 #endif /* CAIRO_D2D_PRIVATE_H */
--- a/gfx/cairo/cairo/src/cairo-d2d-surface.cpp
+++ b/gfx/cairo/cairo/src/cairo-d2d-surface.cpp
@@ -42,21 +42,338 @@
 extern "C" {
 #include "cairo-win32.h"
 #include "cairo-analysis-surface-private.h"
 }
 
 // Required for using placement new.
 #include <new>
 
-ID2D1Factory *D2DSurfFactory::mFactoryInstance = NULL;
-ID3D10Device1 *D3D10Factory::mDeviceInstance = NULL;
-
 #define CAIRO_INT_STATUS_SUCCESS (cairo_int_status_t)CAIRO_STATUS_SUCCESS
 
+struct Vertex
+{
+    float position[2];
+};
+
+// This factory is not device dependent, we can store it. But will clear it
+// if there are no devices left needing it.
+static ID2D1Factory *sD2DFactory = NULL;
+static HMODULE sD2DModule;
+
+static void
+_cairo_d2d_release_factory()
+{
+    int refcnt = sD2DFactory->Release();
+    if (!refcnt) {
+	// Once the last reference goes, free the library.
+	sD2DFactory = NULL;
+	FreeLibrary(sD2DModule);
+    }
+}
+
+/**
+ * Set a blending mode for an operator. This will also return a boolean that
+ * reports if for this blend mode the entire surface needs to be blended. This
+ * is true whenever the DEST blend is not ONE when src alpha is 0.
+ */
+static cairo_int_status_t
+_cairo_d2d_set_operator(cairo_d2d_device_t *device,
+			cairo_operator_t op)
+{
+    assert(op < MAX_OPERATORS);
+    if (op >= MAX_OPERATORS) {
+	// Eep! Someone forgot to update MAX_OPERATORS probably.
+	return CAIRO_INT_STATUS_UNSUPPORTED;
+    }
+
+    if (device->mBlendStates[op]) {
+	device->mD3D10Device->OMSetBlendState(device->mBlendStates[op], NULL, 0xffffffff);
+	return CAIRO_INT_STATUS_SUCCESS;
+    }
+
+    D3D10_BLEND_DESC desc;
+    memset(&desc, 0, sizeof(desc));
+    desc.BlendEnable[0] = TRUE;
+    desc.AlphaToCoverageEnable = FALSE;
+    desc.RenderTargetWriteMask[0] = D3D10_COLOR_WRITE_ENABLE_ALL;
+
+    switch (op) {
+	case CAIRO_OPERATOR_OVER:
+	    desc.BlendOp = desc.BlendOpAlpha = D3D10_BLEND_OP_ADD;
+	    desc.DestBlend = desc.DestBlendAlpha = D3D10_BLEND_INV_SRC_ALPHA;
+	    desc.SrcBlend = desc.SrcBlendAlpha = D3D10_BLEND_ONE;
+	    break;
+	case CAIRO_OPERATOR_ADD:
+	    desc.BlendOp = desc.BlendOpAlpha = D3D10_BLEND_OP_ADD;
+	    desc.DestBlend = desc.DestBlendAlpha = D3D10_BLEND_ONE;
+	    desc.SrcBlend = desc.SrcBlendAlpha = D3D10_BLEND_ONE;
+	    break;
+	case CAIRO_OPERATOR_IN:
+	    desc.BlendOp = desc.BlendOpAlpha = D3D10_BLEND_OP_ADD;
+	    desc.DestBlend = desc.DestBlendAlpha = D3D10_BLEND_ZERO;
+	    desc.SrcBlend = desc.SrcBlendAlpha = D3D10_BLEND_DEST_ALPHA;
+	    break;
+	case CAIRO_OPERATOR_OUT:
+	    desc.BlendOp = desc.BlendOpAlpha = D3D10_BLEND_OP_ADD;
+	    desc.DestBlend = desc.DestBlendAlpha = D3D10_BLEND_ZERO;
+	    desc.SrcBlend = desc.SrcBlendAlpha = D3D10_BLEND_INV_DEST_ALPHA;
+	    break;
+	case CAIRO_OPERATOR_ATOP:
+	    desc.BlendOp = desc.BlendOpAlpha = D3D10_BLEND_OP_ADD;
+	    desc.DestBlend = desc.DestBlendAlpha = D3D10_BLEND_INV_SRC_ALPHA;
+	    desc.SrcBlend = desc.SrcBlendAlpha = D3D10_BLEND_DEST_ALPHA;
+	    break;
+	case CAIRO_OPERATOR_DEST:
+	    desc.BlendOp = desc.BlendOpAlpha = D3D10_BLEND_OP_ADD;
+	    desc.DestBlend = desc.DestBlendAlpha = D3D10_BLEND_ONE;
+	    desc.SrcBlend = desc.SrcBlendAlpha = D3D10_BLEND_ZERO;
+	    break;
+	case CAIRO_OPERATOR_DEST_OVER:
+	    desc.BlendOp = desc.BlendOpAlpha = D3D10_BLEND_OP_ADD;
+	    desc.DestBlend = desc.DestBlendAlpha = D3D10_BLEND_ONE;
+	    desc.SrcBlend = desc.SrcBlendAlpha = D3D10_BLEND_INV_DEST_ALPHA;
+	    break;
+	case CAIRO_OPERATOR_DEST_IN:
+	    desc.BlendOp = desc.BlendOpAlpha = D3D10_BLEND_OP_ADD;
+	    desc.DestBlend = desc.DestBlendAlpha = D3D10_BLEND_SRC_ALPHA;
+	    desc.SrcBlend = desc.SrcBlendAlpha = D3D10_BLEND_ZERO;
+	    break;
+	case CAIRO_OPERATOR_DEST_OUT:
+	    desc.BlendOp = desc.BlendOpAlpha = D3D10_BLEND_OP_ADD;
+	    desc.DestBlend = desc.DestBlendAlpha = D3D10_BLEND_INV_SRC_ALPHA;
+	    desc.SrcBlend = desc.SrcBlendAlpha = D3D10_BLEND_ZERO;
+	    break;
+	case CAIRO_OPERATOR_DEST_ATOP:
+	    desc.BlendOp = desc.BlendOpAlpha = D3D10_BLEND_OP_ADD;
+	    desc.DestBlend = desc.DestBlendAlpha = D3D10_BLEND_SRC_ALPHA;
+	    desc.SrcBlend = desc.SrcBlendAlpha = D3D10_BLEND_INV_DEST_ALPHA;
+	    break;
+	case CAIRO_OPERATOR_XOR:
+	    desc.BlendOp = desc.BlendOpAlpha = D3D10_BLEND_OP_ADD;
+	    desc.DestBlend = desc.DestBlendAlpha = D3D10_BLEND_INV_SRC_ALPHA;
+	    desc.SrcBlend = desc.SrcBlendAlpha = D3D10_BLEND_INV_DEST_ALPHA;
+	    break;
+	default:
+	    return CAIRO_INT_STATUS_UNSUPPORTED;
+    };
+    device->mD3D10Device->CreateBlendState(&desc, &device->mBlendStates[op]);
+
+    device->mD3D10Device->OMSetBlendState(device->mBlendStates[op], NULL, 0xffffffff);
+    return CAIRO_INT_STATUS_SUCCESS;
+}
+
+cairo_device_t *
+cairo_d2d_create_device()
+{
+    D3D10_RASTERIZER_DESC rastDesc;
+    D3D10_INPUT_ELEMENT_DESC layout[] =
+    {
+	{ "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D10_INPUT_PER_VERTEX_DATA, 0 },
+    };
+    D3D10_PASS_DESC passDesc;
+    ID3D10EffectTechnique *technique;
+    Vertex vertices[] = { {0.0, 0.0}, {1.0, 0.0}, {0.0, 1.0}, {1.0, 1.0} };
+    CD3D10_BUFFER_DESC bufferDesc(sizeof(vertices), D3D10_BIND_VERTEX_BUFFER);
+    D3D10_SUBRESOURCE_DATA data;
+
+    cairo_d2d_device_t *device = new cairo_d2d_device_t;
+    device->mD3D10_1 = LoadLibraryA("d3d10_1.dll");
+    D3D10CreateDevice1Func createD3DDevice = (D3D10CreateDevice1Func)
+	GetProcAddress(device->mD3D10_1, "D3D10CreateDevice1");
+    D3D10CreateEffectFromMemoryFunc createEffect = (D3D10CreateEffectFromMemoryFunc)
+	GetProcAddress(device->mD3D10_1, "D3D10CreateEffectFromMemory");
+    D2D1CreateFactoryFunc createD2DFactory;
+
+    if (!createD3DDevice || !createEffect) {
+	goto FAILED;
+    }
+
+    /**
+     * On usage of D3D10_CREATE_DEVICE_PREVENT_INTERNAL_THREADING_OPTIMIZATIONS:
+     * documentation on D3D10_CREATE_DEVICE_PREVENT_INTERNAL_THREADING_OPTIMIZATIONS
+     * can be misleading. In fact, that flag gives no such indication. I pointed this
+     * out to Bas in my email. However, Microsoft is in fact using this flag to
+     * indicate "light weight" DX applications. By light weight they are essentially
+     * referring to applications that are not games. The idea is that when you create
+     * a DX game, the driver assumes that you will pretty much have a single instance
+     * and therefore it doesn't try to hold back when it comes to GPU resource
+     * allocation as long as it can crank out performance. In other words, the
+     * priority in regular DX applications is to make that one application run as fast
+     * as you can. For "light weight" applications, including D2D applications, the
+     * priorities are a bit different. Now you are no longer going to have a single
+     * (or very few) instances. You can have a lot of them (say, for example, a
+     * separate DX context/device per browser tab). In such cases, the GPU resource
+     * allocation scheme changes.
+     */
+    HRESULT hr = createD3DDevice(
+	NULL, 
+	D3D10_DRIVER_TYPE_HARDWARE,
+	NULL,
+	D3D10_CREATE_DEVICE_BGRA_SUPPORT |
+	D3D10_CREATE_DEVICE_PREVENT_INTERNAL_THREADING_OPTIMIZATIONS,
+	D3D10_FEATURE_LEVEL_10_1,
+	D3D10_1_SDK_VERSION,
+	&device->mD3D10Device);
+    if (FAILED(hr)) {
+	HRESULT hr = createD3DDevice(
+	    NULL, 
+	    D3D10_DRIVER_TYPE_HARDWARE,
+	    NULL,
+	    D3D10_CREATE_DEVICE_BGRA_SUPPORT |
+	    D3D10_CREATE_DEVICE_PREVENT_INTERNAL_THREADING_OPTIMIZATIONS,
+	    D3D10_FEATURE_LEVEL_10_0,
+	    D3D10_1_SDK_VERSION,
+	    &device->mD3D10Device);
+	if (FAILED(hr)) {
+	    /* This is not guaranteed to be too fast! */
+	    HRESULT hr = createD3DDevice(
+		NULL, 
+		D3D10_DRIVER_TYPE_HARDWARE,
+		NULL,
+		D3D10_CREATE_DEVICE_BGRA_SUPPORT |
+		D3D10_CREATE_DEVICE_PREVENT_INTERNAL_THREADING_OPTIMIZATIONS,
+		D3D10_FEATURE_LEVEL_9_3,
+		D3D10_1_SDK_VERSION,
+		&device->mD3D10Device);
+
+	}
+    }
+    if (FAILED(hr)) {
+	goto FAILED;
+    }
+
+    if (!sD2DFactory) {
+	sD2DModule = LoadLibraryW(L"d2d1.dll");
+	createD2DFactory = (D2D1CreateFactoryFunc)
+	    GetProcAddress(sD2DModule, "D2D1CreateFactory");
+	if (!createD2DFactory) {
+	    goto FAILED;
+	}
+	D2D1_FACTORY_OPTIONS options;
+#ifdef DEBUG
+	options.debugLevel = D2D1_DEBUG_LEVEL_INFORMATION;
+#else
+	options.debugLevel = D2D1_DEBUG_LEVEL_NONE;
+#endif
+	hr = createD2DFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED,
+			      __uuidof(ID2D1Factory),
+			      &options,
+			      (void**)&sD2DFactory);
+	if (FAILED(hr)) {
+	    goto FAILED;
+	}
+    } else {
+	sD2DFactory->AddRef();
+    }
+
+    device->mD3D10Device->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_LINESTRIP);
+    createEffect((void*)g_main, sizeof(g_main), 0, device->mD3D10Device, NULL, &device->mSampleEffect);
+
+    technique = device->mSampleEffect->GetTechniqueByName("SampleTexture");
+    technique->GetPassByIndex(0)->GetDesc(&passDesc);
+
+
+    hr = device->mD3D10Device->CreateInputLayout(layout,
+						 sizeof(layout) / sizeof(D3D10_INPUT_ELEMENT_DESC),
+						 passDesc.pIAInputSignature,
+						 passDesc.IAInputSignatureSize,
+						 &device->mInputLayout);
+    if (FAILED(hr)) {
+	goto FAILED;
+    }
+
+    data.pSysMem = (void*)vertices;
+    hr = device->mD3D10Device->CreateBuffer(&bufferDesc, &data, &device->mQuadBuffer);
+    if (FAILED(hr)) {
+	goto FAILED;
+    }
+
+    memset(&rastDesc, 0, sizeof(rastDesc));
+    rastDesc.CullMode = D3D10_CULL_NONE;
+    rastDesc.FillMode = D3D10_FILL_SOLID;
+    hr = device->mD3D10Device->CreateRasterizerState(&rastDesc, &device->mRasterizerState);
+    if (FAILED(hr)) {
+	goto FAILED;
+    }
+    device->base.refcount = 1;
+
+    return &device->base;
+FAILED:
+    delete &device->base;
+    return NULL;
+}
+
+int
+cairo_release_device(cairo_device_t *device)
+{
+    int newrefcnt = --device->refcount;
+    if (!newrefcnt) {
+	// Call the correct destructor
+	cairo_d2d_device_t *d2d_device = reinterpret_cast<cairo_d2d_device_t*>(device);
+	FreeLibrary(d2d_device->mD3D10_1);
+	delete d2d_device;
+	_cairo_d2d_release_factory();
+    }
+    return newrefcnt;
+}
+
+int
+cairo_addref_device(cairo_device_t *device)
+{
+    return ++device->refcount;
+}
+
+void
+cairo_d2d_finish_device(cairo_device_t *device)
+{
+    cairo_d2d_device_t *d2d_device = reinterpret_cast<cairo_d2d_device_t*>(device);
+    // Here it becomes interesting, this flush method is generally called when
+    // interop is going on between our device and another device. The
+    // synchronisation between these devices is not always that great. The
+    // device flush method may flush the device's command queue, but it gives
+    // no guarantee that the device will actually be done with those commands,
+    // and so the surface may still not be complete when the external device
+    // chooses to use it. The EVENT query will actually tell us when the GPU
+    // is completely done with our commands.
+    D3D10_QUERY_DESC queryDesc;
+    queryDesc.MiscFlags = 0;
+    queryDesc.Query = D3D10_QUERY_EVENT;
+    RefPtr<ID3D10Query> query;
+
+    d2d_device->mD3D10Device->CreateQuery(&queryDesc, &query);
+
+    // QUERY_EVENT does not use Begin(). It's disabled.
+    query->End();
+
+    BOOL done = FALSE;
+    while (!done) {
+	// This will return S_OK and done = FALSE when the GPU is not done, and
+	// S_OK and done = TRUE when the GPU is done. Any other return value
+	// means we need to break out or risk an infinite loop.
+	if (FAILED(query->GetData(&done, sizeof(BOOL), 0))) {
+	    break;
+	}
+    }
+}
+
+static void
+_cairo_d2d_setup_for_blend(cairo_d2d_device_t *device)
+{
+    device->mD3D10Device->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
+    device->mD3D10Device->IASetInputLayout(device->mInputLayout);
+
+    UINT stride = sizeof(Vertex);
+    UINT offset = 0;
+    ID3D10Buffer *buff = device->mQuadBuffer;
+    device->mD3D10Device->IASetVertexBuffers(0, 1, &buff, &stride, &offset);
+
+    device->mD3D10Device->RSSetState(device->mRasterizerState);
+}
+
 // Contains our cache usage - perhaps this should be made threadsafe.
 static int cache_usage = 0;
 
 /**
  * Create a similar surface which will blend effectively to
  * another surface. For D2D, this will create another texture.
  * Within the types we use blending is always easy.
  *
@@ -342,16 +659,25 @@ static D2D1_COLOR_F
 _cairo_d2d_color_from_cairo_color(const cairo_color_t &color)
 {
     return D2D1::ColorF((FLOAT)color.red, 
 			(FLOAT)color.green, 
 			(FLOAT)color.blue,
 			(FLOAT)color.alpha);
 }
 
+static void
+_cairo_d2d_round_out_to_int_rect(cairo_rectangle_int_t *rect, double x1, double y1, double x2, double y2)
+{
+    rect->x = (int)floor(x1);
+    rect->y = (int)floor(y1);
+    rect->width = (int)ceil(x2) - rect->x;
+    rect->height = (int)ceil(y2) - rect->y;    
+}
+
 /**
  * Gets the surface buffer texture for window surfaces whose backbuffer
  * is not directly usable as a bitmap.
  *
  * \param surface D2D surface.
  * \return Buffer texture
  */
 static ID3D10Texture2D*
@@ -361,17 +687,17 @@ static ID3D10Texture2D*
 	IDXGISurface *surf;
 	DXGI_SURFACE_DESC surfDesc;
 	surface->surface->QueryInterface(&surf);
 	surf->GetDesc(&surfDesc);
 	CD3D10_TEXTURE2D_DESC softDesc(surfDesc.Format, surfDesc.Width, surfDesc.Height);
         softDesc.MipLevels = 1;
 	softDesc.Usage = D3D10_USAGE_DEFAULT;
 	softDesc.BindFlags = D3D10_BIND_RENDER_TARGET | D3D10_BIND_SHADER_RESOURCE;
-	D3D10Factory::Device()->CreateTexture2D(&softDesc, NULL, &surface->bufferTexture);
+	surface->device->mD3D10Device->CreateTexture2D(&softDesc, NULL, &surface->bufferTexture);
     }
     return surface->bufferTexture;
 }
 
 /**
  * Ensure that the surface has an up-to-date surface bitmap. Used for
  * window surfaces which cannot have a surface bitmap directly related
  * to their backbuffer for some reason.
@@ -409,17 +735,17 @@ void cairo_d2d_present_backbuffer(cairo_
 {
     if (surface->type != CAIRO_SURFACE_TYPE_D2D) {
 	return;
     }
     cairo_d2d_surface_t *d2dsurf = reinterpret_cast<cairo_d2d_surface_t*>(surface);
     _cairo_d2d_flush(d2dsurf);
     if (d2dsurf->dxgiChain) {
 	d2dsurf->dxgiChain->Present(0, 0);
-	D3D10Factory::Device()->Flush();
+	d2dsurf->device->mD3D10Device->Flush();
     }
 }
 
 struct d2d_clip
 {
     enum clip_type {LAYER, AXIS_ALIGNED_CLIP};
     d2d_clip * const prev;
     const enum clip_type type;
@@ -738,42 +1064,54 @@ static RefPtr<ID2D1StrokeStyle>
     }
 
     D2D1_DASH_STYLE dashStyle = D2D1_DASH_STYLE_SOLID;
     if (dashes) {
 	dashStyle = D2D1_DASH_STYLE_CUSTOM;
     }
 
     RefPtr<ID2D1StrokeStyle> strokeStyle;
-    D2DSurfFactory::Instance()->CreateStrokeStyle(D2D1::StrokeStyleProperties(line_cap, 
-									      line_cap,
-									      line_cap, 
-									      line_join, 
-									      (FLOAT)style->miter_limit,
-									      dashStyle,
-									      (FLOAT)style->dash_offset),
-						  dashes,
-						  style->num_dashes,
-						  &strokeStyle);
+    sD2DFactory->CreateStrokeStyle(D2D1::StrokeStyleProperties(line_cap, 
+							       line_cap,
+							       line_cap, 
+							       line_join, 
+							       (FLOAT)style->miter_limit,
+							       dashStyle,
+							       (FLOAT)style->dash_offset),
+							        dashes,
+							        style->num_dashes,
+							        &strokeStyle);
     delete [] dashes;
     return strokeStyle;
 }
 
 static int _d2d_compute_bitmap_mem_size(ID2D1Bitmap *bitmap)
 {
     D2D1_SIZE_U size = bitmap->GetPixelSize();
     int bytes_per_pixel = bitmap->GetPixelFormat().format == DXGI_FORMAT_A8_UNORM ? 1 : 4;
     return size.width * size.height * bytes_per_pixel;
 }
 
 cairo_user_data_key_t bitmap_key_nonextend;
 cairo_user_data_key_t bitmap_key_extend;
 cairo_user_data_key_t bitmap_key_snapshot;
 
 struct cached_bitmap {
+    cached_bitmap()
+    {
+	sD2DFactory->AddRef();
+    }
+
+    ~cached_bitmap()
+    {
+	// Clear bitmap out first because it depends on the factory.
+	bitmap = NULL;
+	_cairo_d2d_release_factory();
+    }
+
     /** The cached bitmap */
     RefPtr<ID2D1Bitmap> bitmap;
     /** The cached bitmap is dirty and needs its data refreshed */
     bool dirty;
     /** Order of snapshot detach/release bitmap called not guaranteed, single threaded refcount for now */
     int refs;
 };
 
@@ -1719,17 +2057,17 @@ static cairo_status_t
  * \return A D2D geometry
  */
 static RefPtr<ID2D1PathGeometry>
 _cairo_d2d_create_path_geometry_for_path(cairo_path_fixed_t *path, 
 					 cairo_fill_rule_t fill_rule,
 					 D2D1_FIGURE_BEGIN type)
 {
     RefPtr<ID2D1PathGeometry> d2dpath;
-    D2DSurfFactory::Instance()->CreatePathGeometry(&d2dpath);
+    sD2DFactory->CreatePathGeometry(&d2dpath);
     RefPtr<ID2D1GeometrySink> sink;
     d2dpath->Open(&sink);
     D2D1_FILL_MODE fillMode = D2D1_FILL_MODE_WINDING;
     if (fill_rule == CAIRO_FILL_RULE_WINDING) {
 	fillMode = D2D1_FILL_MODE_WINDING;
     } else if (fill_rule == CAIRO_FILL_RULE_EVEN_ODD) {
 	fillMode = D2D1_FILL_MODE_ALTERNATE;
     }
@@ -1839,18 +2177,18 @@ static cairo_int_status_t
 	    d2dsurf->rt->PopAxisAlignedClip();
 	}
 
     }
 
     return CAIRO_INT_STATUS_SUCCESS;
 }
 
-static cairo_operator_t _cairo_d2d_simplify_operator(cairo_operator_t op,
-						     const cairo_pattern_t *source)
+cairo_operator_t _cairo_d2d_simplify_operator(cairo_operator_t op,
+					      const cairo_pattern_t *source)
 {
     if (op == CAIRO_OPERATOR_SOURCE) {
 	/** Operator over is easier for D2D! If the source if opaque, change */
 	if (source->type == CAIRO_PATTERN_TYPE_SURFACE) {
 	    const cairo_surface_pattern_t *surfpattern =
 		reinterpret_cast<const cairo_surface_pattern_t*>(source);
 	    if (surfpattern->surface->content == CAIRO_CONTENT_COLOR) {
 		return CAIRO_OPERATOR_OVER;
@@ -1930,41 +2268,41 @@ static cairo_surface_t*
     
     /* CreateTexture2D does not support D3D10_RESOURCE_MISC_GDI_COMPATIBLE with DXGI_FORMAT_A8_UNORM */
     if (desc.Format != DXGI_FORMAT_A8_UNORM)
 	desc.MiscFlags = D3D10_RESOURCE_MISC_GDI_COMPATIBLE;
 
     RefPtr<ID3D10Texture2D> texture;
     RefPtr<IDXGISurface> dxgiSurface;
 
-    hr = D3D10Factory::Device()->CreateTexture2D(&desc, NULL, &texture);
+    hr = d2dsurf->device->mD3D10Device->CreateTexture2D(&desc, NULL, &texture);
     if (FAILED(hr)) {
 	goto FAIL_CREATESIMILAR;
     }
 
     newSurf->surface = texture;
 
     // Create the DXGI surface.
     hr = newSurf->surface->QueryInterface(IID_IDXGISurface, (void**)&dxgiSurface);
     if (FAILED(hr)) {
 	goto FAIL_CREATESIMILAR;
     }
 
     D2D1_RENDER_TARGET_USAGE usage = (desc.MiscFlags & D3D10_RESOURCE_MISC_GDI_COMPATIBLE) ?
 					  D2D1_RENDER_TARGET_USAGE_GDI_COMPATIBLE
 					: D2D1_RENDER_TARGET_USAGE_NONE;
 
-    hr = D2DSurfFactory::Instance()->CreateDxgiSurfaceRenderTarget(dxgiSurface,
-								   D2D1::RenderTargetProperties(D2D1_RENDER_TARGET_TYPE_DEFAULT,
-								       D2D1::PixelFormat(DXGI_FORMAT_UNKNOWN,
-											 alpha),
-								       dpiX,
-								       dpiY,
-								       usage),
-								   &newSurf->rt);
+    hr = sD2DFactory->CreateDxgiSurfaceRenderTarget(dxgiSurface,
+						    D2D1::RenderTargetProperties(D2D1_RENDER_TARGET_TYPE_DEFAULT,
+										 D2D1::PixelFormat(DXGI_FORMAT_UNKNOWN,
+												   alpha),
+										 dpiX,
+										 dpiY,
+										 usage),
+						    &newSurf->rt);
 
     if (FAILED(hr)) {
 	goto FAIL_CREATESIMILAR;
     }
 
     if (desc.Format != DXGI_FORMAT_A8_UNORM) {
 	/* For some reason creation of shared bitmaps for A8 UNORM surfaces
 	 * doesn't work even though the documentation suggests it does. The
@@ -1977,32 +2315,36 @@ static cairo_surface_t*
 	    goto FAIL_CREATESIMILAR;
 	}
     }
 
     newSurf->rt->CreateSolidColorBrush(D2D1::ColorF(0, 1.0), &newSurf->solidColorBrush);
 
     _d2d_clear_surface(newSurf);
 
+    newSurf->device = d2dsurf->device;
+    cairo_addref_device(&newSurf->device->base);
+
     return reinterpret_cast<cairo_surface_t*>(newSurf);
 
 FAIL_CREATESIMILAR:
     /** Ensure we call our surfaces desctructor */
     newSurf->~cairo_d2d_surface_t();
     free(newSurf);
     return _cairo_surface_create_in_error(_cairo_error(CAIRO_STATUS_NO_MEMORY));
 }
 
 static cairo_status_t
 _cairo_d2d_finish(void	    *surface)
 {
     cairo_d2d_surface_t *d2dsurf = static_cast<cairo_d2d_surface_t*>(surface);
 
     reset_clip(d2dsurf);
 
+    cairo_release_device(&d2dsurf->device->base);
     d2dsurf->~cairo_d2d_surface_t();
     return CAIRO_STATUS_SUCCESS;
 }
 
 static cairo_status_t
 _cairo_d2d_acquire_source_image(void                    *abstract_surface,
 				cairo_image_surface_t  **image_out,
 				void                   **image_extra)
@@ -2027,22 +2369,22 @@ static cairo_status_t
      * We can't actually map our backing store texture, so we create one in CPU memory, and then
      * tell D3D to copy the data from our surface there, readback is expensive, we -never-
      * -ever- want this to happen.
      */
     softDesc.MipLevels = 1;
     softDesc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE | D3D10_CPU_ACCESS_READ;
     softDesc.Usage = D3D10_USAGE_STAGING;
     softDesc.BindFlags = 0;
-    hr = D3D10Factory::Device()->CreateTexture2D(&softDesc, NULL, &softTexture);
+    hr = d2dsurf->device->mD3D10Device->CreateTexture2D(&softDesc, NULL, &softTexture);
     if (FAILED(hr)) {
 	return CAIRO_STATUS_NO_MEMORY;
     }
 
-    D3D10Factory::Device()->CopyResource(softTexture, d2dsurf->surface);
+    d2dsurf->device->mD3D10Device->CopyResource(softTexture, d2dsurf->surface);
 
     D3D10_MAPPED_TEXTURE2D data;
     hr = softTexture->Map(0, D3D10_MAP_READ_WRITE, 0, &data);
     if (FAILED(hr)) {
 	return (cairo_status_t)CAIRO_INT_STATUS_UNSUPPORTED;
     }
     *image_out = 
 	(cairo_image_surface_t*)_cairo_image_surface_create_for_data_with_content((unsigned char*)data.pData,
@@ -2100,21 +2442,21 @@ static cairo_status_t
     image_rect->width = desc.Width;
     image_rect->height = desc.Height;
     image_rect->x = image_rect->y = 0;
 
     softDesc.MipLevels = 1;
     softDesc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE | D3D10_CPU_ACCESS_READ;
     softDesc.Usage = D3D10_USAGE_STAGING;
     softDesc.BindFlags = 0;
-    hr = D3D10Factory::Device()->CreateTexture2D(&softDesc, NULL, &softTexture);
+    hr = d2dsurf->device->mD3D10Device->CreateTexture2D(&softDesc, NULL, &softTexture);
     if (FAILED(hr)) {
 	return CAIRO_STATUS_NO_MEMORY;
     }
-    D3D10Factory::Device()->CopyResource(softTexture, d2dsurf->surface);
+    d2dsurf->device->mD3D10Device->CopyResource(softTexture, d2dsurf->surface);
 
     D3D10_MAPPED_TEXTURE2D data;
     hr = softTexture->Map(0, D3D10_MAP_READ_WRITE, 0, &data);
     if (FAILED(hr)) {
 	return (cairo_status_t)CAIRO_INT_STATUS_UNSUPPORTED;
     }
     *image_out = 
 	(cairo_image_surface_t*)_cairo_image_surface_create_for_data_with_content((unsigned char*)data.pData,
@@ -2144,17 +2486,17 @@ static void
     D2D1_SIZE_U size = d2dsurf->rt->GetPixelSize();
     rect.left = rect.top = 0;
     rect.right = size.width;
     rect.bottom = size.height;
 
     cairo_surface_destroy(&image->base);
 
     softTexture->Unmap(0);
-    D3D10Factory::Device()->CopyResource(d2dsurf->surface, softTexture);
+    d2dsurf->device->mD3D10Device->CopyResource(d2dsurf->surface, softTexture);
     softTexture->Release();
 }
 
 
 static cairo_status_t
 _cairo_d2d_flush(void                  *surface)
 {
     cairo_d2d_surface_t *d2dsurf = static_cast<cairo_d2d_surface_t*>(surface);
@@ -2163,65 +2505,419 @@ static cairo_status_t
 	reset_clip(d2dsurf);
 	HRESULT hr = d2dsurf->rt->EndDraw();
 	d2dsurf->isDrawing = false;
     }
 
     return CAIRO_STATUS_SUCCESS;
 }
 
-
+static cairo_int_status_t
+_cairo_d2d_copy_surface(cairo_d2d_surface_t *dst,
+			cairo_d2d_surface_t *src,
+			cairo_point_int_t *translation,
+			cairo_region_t *region)
+{
+    RefPtr<IDXGISurface> dstSurface;
+    dst->surface->QueryInterface(&dstSurface);
+    RefPtr<IDXGISurface> srcSurface;
+    src->surface->QueryInterface(&srcSurface);
+    DXGI_SURFACE_DESC srcDesc, dstDesc;
+
+    srcSurface->GetDesc(&srcDesc);
+    dstSurface->GetDesc(&dstDesc);
+
+    cairo_rectangle_int_t clip_rect;
+    clip_rect.x = 0;
+    clip_rect.y = 0;
+    clip_rect.width = dstDesc.Width;
+    clip_rect.height = dstDesc.Height;
+    
+    cairo_int_status_t rv = CAIRO_INT_STATUS_SUCCESS;
+
+    _cairo_d2d_flush(dst);
+    ID3D10Resource *srcResource = src->surface;
+    if (src->surface.get() == dst->surface.get()) {
+	// Self-copy
+	srcResource = _cairo_d2d_get_buffer_texture(dst);
+	src->device->mD3D10Device->CopyResource(srcResource, src->surface);
+    } else {
+	// Need to flush the source too if it's a different surface.
+        _cairo_d2d_flush(src);
+    }
+
+    // One copy for each rectangle in the final clipping region.
+    for (int i = 0; i < cairo_region_num_rectangles(region); i++) {
+	D3D10_BOX rect;
+	cairo_rectangle_int_t area_to_copy;
+
+	cairo_region_get_rectangle(region, i, &area_to_copy);
+
+	cairo_rectangle_int_t transformed_rect = { area_to_copy.x + translation->x,
+						   area_to_copy.y + translation->y,
+						   area_to_copy.width, area_to_copy.height };
+	cairo_rectangle_int_t surface_rect = { 0, 0, srcDesc.Width, srcDesc.Height };
+
+
+	if (!_cairo_rectangle_contains(&surface_rect, &transformed_rect)) {
+	    /* We cannot do any sort of extend, in the future a little bit of extra code could
+	     * allow us to support EXTEND_NONE.
+	     */
+	    rv = CAIRO_INT_STATUS_UNSUPPORTED;
+	    break;
+	}
+
+	rect.front = 0;
+	rect.back = 1;
+	rect.left = transformed_rect.x;
+	rect.top = transformed_rect.y;
+	rect.right = transformed_rect.x + transformed_rect.width;
+	rect.bottom = transformed_rect.y + transformed_rect.height;
+
+	src->device->mD3D10Device->CopySubresourceRegion(dst->surface,
+							 0,
+							 area_to_copy.x,
+							 area_to_copy.y,
+							 0,
+							 srcResource,
+							 0,
+							 &rect);
+    }
+
+    return rv;
+}
+
+/**
+ * This function will text if we can use GPU mem cpy to execute an operation with
+ * a surface pattern. If box is NULL it will operate on the entire dst surface.
+ */
+static cairo_int_status_t
+_cairo_d2d_try_copy(cairo_d2d_surface_t *dst,
+		    cairo_surface_t *src,
+		    cairo_box_t *box,
+		    const cairo_matrix_t *matrix,
+		    cairo_clip_t *clip,
+		    cairo_operator_t op)
+{
+    if (op != CAIRO_OPERATOR_SOURCE &&
+	!(op == CAIRO_OPERATOR_OVER && src->content == CAIRO_CONTENT_COLOR)) {
+	return CAIRO_INT_STATUS_UNSUPPORTED;
+    }
+
+    cairo_point_int_t translation;
+    if ((box && !box_is_integer(box)) ||
+	!_cairo_matrix_is_integer_translation(matrix, &translation.x, &translation.y)) {
+	return CAIRO_INT_STATUS_UNSUPPORTED;
+    }
+
+    /* For now we do only D2D sources */
+    if (src->type != CAIRO_SURFACE_TYPE_D2D) {
+	return CAIRO_INT_STATUS_UNSUPPORTED;
+    }
+    
+    cairo_rectangle_int_t rect;
+    if (box) {
+	_cairo_box_round_to_rectangle(box, &rect);
+    } else {
+	rect.x = rect.y = 0;
+	rect.width = dst->rt->GetPixelSize().width;
+	rect.height = dst->rt->GetPixelSize().height;
+    }
+    
+    cairo_d2d_surface_t *d2dsrc = reinterpret_cast<cairo_d2d_surface_t*>(src);
+
+    if (d2dsrc->device != dst->device) {
+	// This doesn't work between different devices.
+	return CAIRO_INT_STATUS_UNSUPPORTED;
+    }
+
+    /* Region we need to clip this operation to */
+    cairo_region_t *clipping_region = NULL;
+    cairo_region_t *region;
+    if (clip) {
+	_cairo_clip_get_region(clip, &clipping_region);
+
+	if (!clipping_region) {
+	    return CAIRO_INT_STATUS_UNSUPPORTED;
+	}
+	region = cairo_region_copy(clipping_region);
+
+	cairo_region_intersect_rectangle(region, &rect);
+
+	if (cairo_region_is_empty(region)) {
+	    // Nothing to do.
+	    return CAIRO_INT_STATUS_SUCCESS;
+	}
+    } else {
+	region = cairo_region_create_rectangle(&rect);
+	// Areas outside of the surface do not matter.
+	cairo_rectangle_int_t surface_rect = { 0, 0,
+					       dst->rt->GetPixelSize().width,
+					       dst->rt->GetPixelSize().height };
+	cairo_region_intersect_rectangle(region, &surface_rect);
+    }
+
+    cairo_int_status_t rv = _cairo_d2d_copy_surface(dst, d2dsrc, &translation, region);
+    
+    cairo_region_destroy(region);
+    
+    return rv;
+}
+
+RefPtr<ID2D1RenderTarget> _cairo_d2d_get_temp_rt(cairo_d2d_surface_t *surf, cairo_clip_t *clip)
+{
+    RefPtr<ID3D10Texture2D> texture = _cairo_d2d_get_buffer_texture(surf);
+    RefPtr<ID2D1RenderTarget> new_rt;
+    RefPtr<IDXGISurface> dxgiSurface;
+    texture->QueryInterface(&dxgiSurface);
+    HRESULT hr;
+
+    _cairo_d2d_flush(surf);
+
+    if (!surf) {
+	return NULL;
+    }
+
+    D2D1_RENDER_TARGET_PROPERTIES props = 
+	D2D1::RenderTargetProperties(D2D1_RENDER_TARGET_TYPE_DEFAULT,
+				     D2D1::PixelFormat(DXGI_FORMAT_UNKNOWN, D2D1_ALPHA_MODE_PREMULTIPLIED));
+    hr = sD2DFactory->CreateDxgiSurfaceRenderTarget(dxgiSurface,
+						    props,
+						    &new_rt);
+
+    if (FAILED(hr)) {
+	return NULL;
+    }
+
+    new_rt->BeginDraw();
+    new_rt->Clear(D2D1::ColorF(0, 0));
+
+    // Since this is a fresh surface there's no point in doing clever things to
+    // keep the clip path around until a certain depth. So we just do a straight-
+    // forward push of all clip paths in the tree, similar to what the normal
+    // clip code does, but a little less clever.
+    if (clip) {
+	cairo_clip_path_t *path = clip->path;
+	while (path) {
+	    cairo_box_t clip_box;
+	    if (_cairo_path_fixed_is_box(&path->path, &clip_box)) {
+		// If this does not have a region it could be none-pixel aligned.
+		D2D1_ANTIALIAS_MODE aaMode = D2D1_ANTIALIAS_MODE_PER_PRIMITIVE;
+		if (box_is_integer(&clip_box)) {
+		    aaMode = D2D1_ANTIALIAS_MODE_ALIASED;
+		}
+		new_rt->PushAxisAlignedClip(D2D1::RectF(_cairo_fixed_to_float(clip_box.p1.x),
+							_cairo_fixed_to_float(clip_box.p1.y),
+							_cairo_fixed_to_float(clip_box.p2.x),
+							_cairo_fixed_to_float(clip_box.p2.y)),
+					    aaMode);
+	    } else {
+		HRESULT hr;
+		RefPtr<ID2D1PathGeometry> geom = _cairo_d2d_create_path_geometry_for_path (&path->path,
+											   path->fill_rule,
+											   D2D1_FIGURE_BEGIN_FILLED);
+		RefPtr<ID2D1Layer> layer;
+
+		hr = new_rt->CreateLayer (&layer);
+
+		D2D1_LAYER_OPTIONS options = D2D1_LAYER_OPTIONS_NONE;
+
+		new_rt->PushLayer(D2D1::LayerParameters(
+					D2D1::InfiniteRect(),
+					geom,
+					D2D1_ANTIALIAS_MODE_PER_PRIMITIVE,
+					D2D1::IdentityMatrix(),
+					1.0,
+					0,
+					options),
+				  layer);
+	    }
+	    path = path->prev;
+	}
+    }
+    return new_rt;
+}
+
+cairo_int_status_t _cairo_d2d_blend_temp_surface(cairo_d2d_surface_t *surf, cairo_operator_t op, ID2D1RenderTarget *rt, cairo_clip_t *clip, const cairo_rectangle_int_t *bounds)
+{
+    int numPaths = 0;
+    if (clip) {
+	cairo_clip_path_t *path = clip->path;
+	while (path) {
+	    numPaths++;
+	    path = path->prev;
+	}
+	
+	cairo_clip_path_t **paths = new cairo_clip_path_t*[numPaths];
+
+	numPaths = 0;
+	path = clip->path;
+	while (path) {
+	    paths[numPaths++] = path;
+	    path = path->prev;
+	}	
+
+	for (int i = numPaths - 1; i >= 0; i--) {
+	    if (paths[i]->flags & CAIRO_CLIP_PATH_IS_BOX) {
+		rt->PopAxisAlignedClip();
+	    } else {
+		rt->PopLayer();
+	    }
+	}
+	delete [] paths;
+    }
+    rt->EndDraw();
+    HRESULT hr;
+
+    RefPtr<ID3D10Texture2D> srcTexture = _cairo_d2d_get_buffer_texture(surf);
+    RefPtr<ID3D10Texture2D> dstTexture;
+
+    surf->surface->QueryInterface(&dstTexture);
+    ID3D10Device *device = surf->device->mD3D10Device;
+
+    if (!surf->buffer_rt_view) {
+	hr = device->CreateRenderTargetView(dstTexture, NULL, &surf->buffer_rt_view);
+	if (FAILED(hr)) {
+	    return CAIRO_INT_STATUS_UNSUPPORTED;
+	}
+    }
+
+    if (!surf->buffer_sr_view) {
+	hr = device->CreateShaderResourceView(srcTexture, NULL, &surf->buffer_sr_view);
+	if (FAILED(hr)) {
+	    return CAIRO_INT_STATUS_UNSUPPORTED;
+	}
+    }
+
+    cairo_int_status_t status;
+
+    status = _cairo_d2d_set_operator(surf->device, op);
+
+    if (unlikely(status)) {
+	return status;
+    }
+
+    D3D10_TEXTURE2D_DESC tDesc;
+    dstTexture->GetDesc(&tDesc);
+    D3D10_VIEWPORT vp;
+    vp.Height = tDesc.Height;
+    vp.MinDepth = 0;
+    vp.MaxDepth = 1.0;
+    vp.TopLeftX = 0;
+    vp.TopLeftY = 0;
+    vp.Width = tDesc.Width;
+    device->RSSetViewports(1, &vp);
+
+    ID3D10Effect *effect = surf->device->mSampleEffect;
+
+    ID3D10RenderTargetView *rtViewPtr = surf->buffer_rt_view;
+    device->OMSetRenderTargets(1, &rtViewPtr, 0);
+    ID3D10EffectVectorVariable *quadDesc = effect->GetVariableByName("QuadDesc")->AsVector();
+    ID3D10EffectVectorVariable *texCoords = effect->GetVariableByName("TexCoords")->AsVector();
+
+    float quadDescVal[] = { -1.0f, 1.0f, 2.0f, -2.0f };
+    float texCoordsVal[] = { 0.0, 0.0, 1.0f, 1.0f };
+    if (bounds && _cairo_operator_bounded_by_mask(op)) {
+	quadDescVal[0] = -1.0f + ((float)bounds->x / (float)tDesc.Width) * 2.0f;
+	quadDescVal[1] = 1.0f - ((float)bounds->y / (float)tDesc.Height) * 2.0f;
+	quadDescVal[2] = ((float)bounds->width / (float)tDesc.Width) * 2.0f;
+	quadDescVal[3] = -((float)bounds->height / (float)tDesc.Height) * 2.0f;
+	texCoordsVal[0] = (float)bounds->x / (float)tDesc.Width;
+	texCoordsVal[1] = (float)bounds->y / (float)tDesc.Height;
+	texCoordsVal[2] = (float)bounds->width / (float)tDesc.Width;
+	texCoordsVal[3] = (float)bounds->height / (float)tDesc.Height;
+    }
+    quadDesc->SetFloatVector(quadDescVal);
+    texCoords->SetFloatVector(texCoordsVal);
+
+    _cairo_d2d_setup_for_blend(surf->device);
+    ID3D10EffectTechnique *technique = effect->GetTechniqueByName("SampleTexture");
+    technique->GetPassByIndex(0)->Apply(0);
+
+    ID3D10ShaderResourceView *srViewPtr = surf->buffer_sr_view;
+    device->PSSetShaderResources(0, 1, &srViewPtr);
+
+    device->Draw(4, 0);
+
+#ifdef DEBUG
+    // Quiet down some info messages from D3D10 debug layer
+    srViewPtr = NULL;
+    device->PSSetShaderResources(0, 1, &srViewPtr);
+    rtViewPtr = NULL;
+    device->OMSetRenderTargets(1, &rtViewPtr, 0); 
+#endif
+    return CAIRO_INT_STATUS_SUCCESS;
+}
 
 static cairo_int_status_t
 _cairo_d2d_paint(void			*surface,
 		 cairo_operator_t	 op,
 		 const cairo_pattern_t	*source,
 		 cairo_clip_t		*clip)
 {
     cairo_d2d_surface_t *d2dsurf = static_cast<cairo_d2d_surface_t*>(surface);
     cairo_int_status_t status;
 
     op = _cairo_d2d_simplify_operator(op, source);
 
+    if (op == CAIRO_OPERATOR_SOURCE) {
+	return CAIRO_INT_STATUS_UNSUPPORTED;
+    }
+
     if (op == CAIRO_OPERATOR_CLEAR) {
 	return _cairo_d2d_clear(d2dsurf, clip);
     }
 
-
-    _begin_draw_state(d2dsurf);
-    status = (cairo_int_status_t)_cairo_d2d_set_clip (d2dsurf, clip);
-
-    if (unlikely(status))
-	return status;
-
-    d2dsurf->rt->SetAntialiasMode(D2D1_ANTIALIAS_MODE_ALIASED);
+    if (source->type == CAIRO_PATTERN_TYPE_SURFACE) {
+	const cairo_surface_pattern_t *surf_pattern = 
+	    reinterpret_cast<const cairo_surface_pattern_t*>(source);
+
+	status = _cairo_d2d_try_copy(d2dsurf, surf_pattern->surface,
+				     NULL, &source->matrix, clip, op);
+
+	if (status != CAIRO_INT_STATUS_UNSUPPORTED) {
+	    return status;
+	}
+    }
+    RefPtr<ID2D1RenderTarget> target_rt = d2dsurf->rt;
+#ifndef ALWAYS_MANUAL_COMPOSITE
+    if (op != CAIRO_OPERATOR_OVER) {
+#endif
+	target_rt = _cairo_d2d_get_temp_rt(d2dsurf, clip);
+	if (!target_rt) {
+	    return CAIRO_INT_STATUS_UNSUPPORTED;
+	}
+#ifndef ALWAYS_MANUAL_COMPOSITE
+    } else {
+	_begin_draw_state(d2dsurf);
+	status = (cairo_int_status_t)_cairo_d2d_set_clip (d2dsurf, clip);
+
+	if (unlikely(status))
+	    return status;
+    }
+#endif
+
+    target_rt->SetAntialiasMode(D2D1_ANTIALIAS_MODE_ALIASED);
 
     RefPtr<ID2D1Brush> brush = _cairo_d2d_create_brush_for_pattern(d2dsurf,
 								   source);
     
     if (!brush) {
 	return CAIRO_INT_STATUS_UNSUPPORTED;
     }
-    if (op == CAIRO_OPERATOR_OVER) {
-	D2D1_SIZE_F size = d2dsurf->rt->GetSize();
-	d2dsurf->rt->FillRectangle(D2D1::RectF((FLOAT)0,
-					       (FLOAT)0,
-					       (FLOAT)size.width,
-					       (FLOAT)size.height),
-				   brush);
-    } else if (op == CAIRO_OPERATOR_SOURCE) {
-	D2D1_SIZE_F size = d2dsurf->rt->GetSize();
-	d2dsurf->rt->Clear(D2D1::ColorF(0, 0));
-	d2dsurf->rt->FillRectangle(D2D1::RectF((FLOAT)0,
-					       (FLOAT)0,
-					       (FLOAT)size.width,
-					       (FLOAT)size.height),
-				   brush);
-    } else {
-	return CAIRO_INT_STATUS_UNSUPPORTED;
+
+    D2D1_SIZE_F size = target_rt->GetSize();
+    target_rt->FillRectangle(D2D1::RectF((FLOAT)0,
+					 (FLOAT)0,
+					 (FLOAT)size.width,
+					 (FLOAT)size.height),
+			     brush);
+
+    if (target_rt.get() != d2dsurf->rt.get()) {
+	return _cairo_d2d_blend_temp_surface(d2dsurf, op, target_rt, clip);
     }
 
     return CAIRO_INT_STATUS_SUCCESS;
 }
 
 static cairo_int_status_t
 _cairo_d2d_mask(void			*surface,
 		cairo_operator_t	 op,
@@ -2312,141 +3008,187 @@ static cairo_int_status_t
 		  cairo_clip_t		*clip)
 {
     cairo_int_status_t status;
 
     cairo_d2d_surface_t *d2dsurf = static_cast<cairo_d2d_surface_t*>(surface);
 
     op = _cairo_d2d_simplify_operator(op, source);
 
-    if (op != CAIRO_OPERATOR_OVER && op != CAIRO_OPERATOR_ADD) {
-	/** 
-	 * We don't really support ADD yet. True ADD support requires getting
-	 * the tesselated mesh from D2D, and blending that using D3D which has
-	 * an add operator available.
-	 */
+    if (op == CAIRO_OPERATOR_SOURCE) {
 	return CAIRO_INT_STATUS_UNSUPPORTED;
     }
 
-    _begin_draw_state(d2dsurf);
-
-    status = (cairo_int_status_t)_cairo_d2d_set_clip (d2dsurf, clip);
-
-    if (unlikely (status))
-	return status;
-
+    RefPtr<ID2D1RenderTarget> target_rt = d2dsurf->rt;
+#ifndef ALWAYS_MANUAL_COMPOSITE
+    if (op != CAIRO_OPERATOR_OVER) {
+#endif
+	target_rt = _cairo_d2d_get_temp_rt(d2dsurf, clip);
+	if (!target_rt) {
+	    return CAIRO_INT_STATUS_UNSUPPORTED;
+	}
+#ifndef ALWAYS_MANUAL_COMPOSITE
+    } else {
+	_begin_draw_state(d2dsurf);
+	status = (cairo_int_status_t)_cairo_d2d_set_clip (d2dsurf, clip);
+
+	if (unlikely(status))
+	    return status;
+    }
+#endif
 
     if (antialias == CAIRO_ANTIALIAS_NONE) {
-	d2dsurf->rt->SetAntialiasMode(D2D1_ANTIALIAS_MODE_ALIASED);
+	target_rt->SetAntialiasMode(D2D1_ANTIALIAS_MODE_ALIASED);
     } else {
-	d2dsurf->rt->SetAntialiasMode(D2D1_ANTIALIAS_MODE_PER_PRIMITIVE);
+	target_rt->SetAntialiasMode(D2D1_ANTIALIAS_MODE_PER_PRIMITIVE);
     }
     RefPtr<ID2D1StrokeStyle> strokeStyle = _cairo_d2d_create_strokestyle_for_stroke_style(style);
 
     if (!strokeStyle) {
 	return CAIRO_INT_STATUS_UNSUPPORTED;
     }
     D2D1::Matrix3x2F mat = _cairo_d2d_matrix_from_matrix(ctm);
     RefPtr<ID2D1Geometry> d2dpath = _cairo_d2d_create_path_geometry_for_path(path, 
 		    							     CAIRO_FILL_RULE_WINDING, 
 									     D2D1_FIGURE_BEGIN_FILLED);
     D2D1::Matrix3x2F inverse_mat = _cairo_d2d_invert_matrix(mat);
     
     RefPtr<ID2D1TransformedGeometry> trans_geom;
-    D2DSurfFactory::Instance()->CreateTransformedGeometry(d2dpath, &inverse_mat, &trans_geom);
-
-    d2dsurf->rt->SetTransform(mat);
+    sD2DFactory->CreateTransformedGeometry(d2dpath, &inverse_mat, &trans_geom);
+
+    target_rt->SetTransform(mat);
 
     RefPtr<ID2D1Brush> brush = _cairo_d2d_create_brush_for_pattern(d2dsurf,
 								   source);
     if (!brush) {
 	return CAIRO_INT_STATUS_UNSUPPORTED;
     }
 
-    d2dsurf->rt->DrawGeometry(trans_geom, brush, (FLOAT)style->line_width, strokeStyle);
-
-    d2dsurf->rt->SetTransform(D2D1::Matrix3x2F::Identity());
+    target_rt->DrawGeometry(trans_geom, brush, (FLOAT)style->line_width, strokeStyle);
+
+    target_rt->SetTransform(D2D1::Matrix3x2F::Identity());
+
+    if (target_rt.get() != d2dsurf->rt.get()) {
+	D2D1_RECT_F bounds;
+	trans_geom->GetWidenedBounds((FLOAT)style->line_width, strokeStyle, D2D1::IdentityMatrix(), &bounds);
+	cairo_rectangle_int_t bound_rect;
+	_cairo_d2d_round_out_to_int_rect(&bound_rect, bounds.left, bounds.top, bounds.right, bounds.bottom);
+	return _cairo_d2d_blend_temp_surface(d2dsurf, op, target_rt, clip, &bound_rect);
+    }
+
     return CAIRO_INT_STATUS_SUCCESS;
 }
 
 static cairo_int_status_t
 _cairo_d2d_fill(void			*surface,
 		cairo_operator_t	 op,
 		const cairo_pattern_t	*source,
 		cairo_path_fixed_t	*path,
 		cairo_fill_rule_t	 fill_rule,
 		double			 tolerance,
 		cairo_antialias_t	 antialias,
 		cairo_clip_t		*clip)
 {
     cairo_int_status_t status;
 
     cairo_d2d_surface_t *d2dsurf = static_cast<cairo_d2d_surface_t*>(surface);
+    cairo_box_t box;
+    bool is_box = _cairo_path_fixed_is_box(path, &box);
+
+    if (is_box && source->type == CAIRO_PATTERN_TYPE_SURFACE) {
+	const cairo_surface_pattern_t *surf_pattern = 
+	    reinterpret_cast<const cairo_surface_pattern_t*>(source);
+	cairo_int_status_t rv = _cairo_d2d_try_copy(d2dsurf, surf_pattern->surface,
+						    &box, &source->matrix, clip, op);
+
+	if (rv != CAIRO_INT_STATUS_UNSUPPORTED) {
+	    return rv;
+	}
+    }
 
     op = _cairo_d2d_simplify_operator(op, source);
 
-    if (op != CAIRO_OPERATOR_OVER && op != CAIRO_OPERATOR_ADD &&
-	op != CAIRO_OPERATOR_CLEAR) {
-	/** 
-	 * We don't really support ADD yet. True ADD support requires getting
-	 * the tesselated mesh from D2D, and blending that using D3D which has
-	 * an add operator available.
-	 */
+    if (op == CAIRO_OPERATOR_SOURCE) {
 	return CAIRO_INT_STATUS_UNSUPPORTED;
     }
 
-    _begin_draw_state(d2dsurf);
-    status = (cairo_int_status_t)_cairo_d2d_set_clip (d2dsurf, clip);
-
-    if (unlikely(status))
-	return status;
-
-
-    if (antialias == CAIRO_ANTIALIAS_NONE) {
-	d2dsurf->rt->SetAntialiasMode(D2D1_ANTIALIAS_MODE_ALIASED);
-    } else {
-	d2dsurf->rt->SetAntialiasMode(D2D1_ANTIALIAS_MODE_PER_PRIMITIVE);
-    }
-
-    cairo_box_t box;
-
     if (op == CAIRO_OPERATOR_CLEAR) {
 	if (_cairo_path_fixed_is_box(path, &box)) {
+	    _begin_draw_state(d2dsurf);
+	    status = (cairo_int_status_t)_cairo_d2d_set_clip (d2dsurf, clip);
+
+	    if (unlikely(status))
+		return status;
+
 	    return _cairo_d2d_clear_box (d2dsurf, clip, &box);
 	} else {
 	    return CAIRO_INT_STATUS_UNSUPPORTED;
 	}
     }
 
-    if (_cairo_path_fixed_is_box(path, &box)) {
+    RefPtr<ID2D1RenderTarget> target_rt = d2dsurf->rt;
+    
+#ifndef ALWAYS_MANUAL_COMPOSITE
+    if (op != CAIRO_OPERATOR_OVER) {
+#endif
+	target_rt = _cairo_d2d_get_temp_rt(d2dsurf, clip);
+	if (!target_rt) {
+	    return CAIRO_INT_STATUS_UNSUPPORTED;
+	}
+#ifndef ALWAYS_MANUAL_COMPOSITE
+    } else {
+	_begin_draw_state(d2dsurf);
+	status = (cairo_int_status_t)_cairo_d2d_set_clip (d2dsurf, clip);
+
+	if (unlikely(status))
+	    return status;
+    }
+#endif
+
+    if (antialias == CAIRO_ANTIALIAS_NONE) {
+	target_rt->SetAntialiasMode(D2D1_ANTIALIAS_MODE_ALIASED);
+    } else {
+	target_rt->SetAntialiasMode(D2D1_ANTIALIAS_MODE_PER_PRIMITIVE);
+    }
+
+    if (is_box) {
 	float x1 = _cairo_fixed_to_float(box.p1.x);
 	float y1 = _cairo_fixed_to_float(box.p1.y);    
 	float x2 = _cairo_fixed_to_float(box.p2.x);    
 	float y2 = _cairo_fixed_to_float(box.p2.y);
 	RefPtr<ID2D1Brush> brush = _cairo_d2d_create_brush_for_pattern(d2dsurf,
 								       source);
 	if (!brush) {
 	    return CAIRO_INT_STATUS_UNSUPPORTED;
 	}
 
-	d2dsurf->rt->FillRectangle(D2D1::RectF(x1,
-					       y1,
-					       x2,
-					       y2),
-				   brush);
+	target_rt->FillRectangle(D2D1::RectF(x1,
+					     y1,
+					     x2,
+					     y2),
+				 brush);
     } else {
 	RefPtr<ID2D1Geometry> d2dpath = _cairo_d2d_create_path_geometry_for_path(path, fill_rule, D2D1_FIGURE_BEGIN_FILLED);
 
 	RefPtr<ID2D1Brush> brush = _cairo_d2d_create_brush_for_pattern(d2dsurf,
 								       source);
 	if (!brush) {
 	    return CAIRO_INT_STATUS_UNSUPPORTED;
 	}
-	d2dsurf->rt->FillGeometry(d2dpath, brush);
+	target_rt->FillGeometry(d2dpath, brush);
     }
+
+    if (target_rt.get() != d2dsurf->rt.get()) {
+	double x1, y1, x2, y2;
+	_cairo_path_fixed_bounds(path, &x1, &y1, &x2, &y2);
+	cairo_rectangle_int_t bounds;
+	_cairo_d2d_round_out_to_int_rect(&bounds, x1, y1, x2, y2);
+	return _cairo_d2d_blend_temp_surface(d2dsurf, op, target_rt, clip, &bounds);
+    }
+
     return CAIRO_INT_STATUS_SUCCESS;
 }
 
 
 static cairo_int_status_t
 _cairo_d2d_show_glyphs (void			*surface,
 			cairo_operator_t	 op,
 			const cairo_pattern_t	*source,
@@ -2488,27 +3230,21 @@ static cairo_bool_t
     extents->height = size.height;
     return TRUE;
 }
 
 
 /** Helper functions. */
 
 cairo_surface_t*
-cairo_d2d_surface_create_for_hwnd(HWND wnd,
+cairo_d2d_surface_create_for_hwnd(cairo_device_t *cairo_device,
+				  HWND wnd,
 				  cairo_content_t content)
 {
-    if (!D3D10Factory::Device() || !D2DSurfFactory::Instance()) {
-	/**
-	 * FIXME: In the near future we can use cairo_device_t to pass in a
-	 * device.
-	 */
-	return _cairo_surface_create_in_error(_cairo_error(CAIRO_STATUS_NO_DEVICE));
-    }
-
+    cairo_d2d_device_t *d2d_device = reinterpret_cast<cairo_d2d_device_t*>(cairo_device);
     cairo_d2d_surface_t *newSurf = static_cast<cairo_d2d_surface_t*>(malloc(sizeof(cairo_d2d_surface_t)));
     new (newSurf) cairo_d2d_surface_t();
 
     _cairo_surface_init(&newSurf->base, &cairo_d2d_surface_backend, content);
 
     RECT rc;
     HRESULT hr;
 
@@ -2528,17 +3264,17 @@ cairo_d2d_surface_create_for_hwnd(HWND w
     sizePixels.height = rc.bottom - rc.top;
 
     if (!sizePixels.width) {
 	sizePixels.width = 1;
     }
     if (!sizePixels.height) {
 	sizePixels.height = 1;
     }
-    ID3D10Device1 *device = D3D10Factory::Device();
+    ID3D10Device1 *device = d2d_device->mD3D10Device;
     RefPtr<IDXGIDevice> dxgiDevice;
     RefPtr<IDXGIAdapter> dxgiAdapter;
     RefPtr<IDXGIFactory> dxgiFactory;
     D2D1_RENDER_TARGET_PROPERTIES props;    
     D2D1_BITMAP_PROPERTIES bitProps;
 
     device->QueryInterface(&dxgiDevice);
     dxgiDevice->GetAdapter(&dxgiAdapter);
@@ -2590,50 +3326,48 @@ cairo_d2d_surface_create_for_hwnd(HWND w
     size.width = sizePixels.width * dpiX;
     size.height = sizePixels.height * dpiY;
 
     props = D2D1::RenderTargetProperties(D2D1_RENDER_TARGET_TYPE_DEFAULT,
 					 D2D1::PixelFormat(DXGI_FORMAT_UNKNOWN, D2D1_ALPHA_MODE_PREMULTIPLIED),
 					 dpiX,
 					 dpiY,
 					 D2D1_RENDER_TARGET_USAGE_GDI_COMPATIBLE);
-    hr = D2DSurfFactory::Instance()->CreateDxgiSurfaceRenderTarget(newSurf->backBuf,
+    hr = sD2DFactory->CreateDxgiSurfaceRenderTarget(newSurf->backBuf,
 								   props,
 								   &newSurf->rt);
     if (FAILED(hr)) {
 	goto FAIL_HWND;
     }
 
     bitProps = D2D1::BitmapProperties(D2D1::PixelFormat(DXGI_FORMAT_UNKNOWN, 
 				      D2D1_ALPHA_MODE_PREMULTIPLIED));
     
     newSurf->rt->CreateSolidColorBrush(D2D1::ColorF(0, 1.0), &newSurf->solidColorBrush);
 
     _d2d_clear_surface(newSurf);
 
+    newSurf->device = d2d_device;
+    cairo_addref_device(cairo_device);
+
     return reinterpret_cast<cairo_surface_t*>(newSurf);
 
 FAIL_HWND:
     newSurf->~cairo_d2d_surface_t();
     free(newSurf);
     return _cairo_surface_create_in_error(_cairo_error(CAIRO_STATUS_NO_MEMORY));
 }
 
 cairo_surface_t *
-cairo_d2d_surface_create(cairo_format_t format,
+cairo_d2d_surface_create(cairo_device_t *device,
+			 cairo_format_t format,
                          int width,
                          int height)
 {
-    if (!D3D10Factory::Device() || !D2DSurfFactory::Instance()) {
-	/**
-	 * FIXME: In the near future we can use cairo_device_t to pass in a
-	 * device.
-	 */
-	return _cairo_surface_create_in_error(_cairo_error(CAIRO_STATUS_NO_DEVICE));
-    }
+    cairo_d2d_device_t *d2d_device = reinterpret_cast<cairo_d2d_device_t*>(device);
     cairo_d2d_surface_t *newSurf = static_cast<cairo_d2d_surface_t*>(malloc(sizeof(cairo_d2d_surface_t)));
     new (newSurf) cairo_d2d_surface_t();
 
     DXGI_FORMAT dxgiformat = DXGI_FORMAT_B8G8R8A8_UNORM;
     D2D1_ALPHA_MODE alpha = D2D1_ALPHA_MODE_PREMULTIPLIED;
     if (format == CAIRO_FORMAT_ARGB32) {
 	_cairo_surface_init(&newSurf->base, &cairo_d2d_surface_backend, CAIRO_CONTENT_COLOR_ALPHA);
     } else if (format == CAIRO_FORMAT_RGB24) {
@@ -2666,17 +3400,17 @@ cairo_d2d_surface_create(cairo_format_t 
     if (desc.Format != DXGI_FORMAT_A8_UNORM)
 	desc.MiscFlags = D3D10_RESOURCE_MISC_GDI_COMPATIBLE;
 
     RefPtr<ID3D10Texture2D> texture;
     RefPtr<IDXGISurface> dxgiSurface;
     D2D1_BITMAP_PROPERTIES bitProps;
     D2D1_RENDER_TARGET_PROPERTIES props;
 
-    hr = D3D10Factory::Device()->CreateTexture2D(&desc, NULL, &texture);
+    hr = d2d_device->mD3D10Device->CreateTexture2D(&desc, NULL, &texture);
 
     if (FAILED(hr)) {
 	goto FAIL_CREATE;
     }
 
     newSurf->surface = texture;
 
     /** Create the DXGI surface. */
@@ -2686,17 +3420,17 @@ cairo_d2d_surface_create(cairo_format_t 
     }
 
     props = D2D1::RenderTargetProperties(D2D1_RENDER_TARGET_TYPE_DEFAULT,
 					 D2D1::PixelFormat(DXGI_FORMAT_UNKNOWN, alpha));
 
     if (desc.MiscFlags & D3D10_RESOURCE_MISC_GDI_COMPATIBLE)
 	props.usage = D2D1_RENDER_TARGET_USAGE_GDI_COMPATIBLE;
 
-    hr = D2DSurfFactory::Instance()->CreateDxgiSurfaceRenderTarget(dxgiSurface,
+    hr = sD2DFactory->CreateDxgiSurfaceRenderTarget(dxgiSurface,
 								   props,
 								   &newSurf->rt);
 
     if (FAILED(hr)) {
 	goto FAIL_CREATE;
     }
 
     bitProps = D2D1::BitmapProperties(D2D1::PixelFormat(DXGI_FORMAT_UNKNOWN, 
@@ -2715,24 +3449,129 @@ cairo_d2d_surface_create(cairo_format_t 
 	    goto FAIL_CREATE;
 	}
     }
 
     newSurf->rt->CreateSolidColorBrush(D2D1::ColorF(0, 1.0), &newSurf->solidColorBrush);
 
     _d2d_clear_surface(newSurf);
 
+    newSurf->device = d2d_device;
+    cairo_addref_device(device);
+
     return reinterpret_cast<cairo_surface_t*>(newSurf);
 
 FAIL_CREATE:
     newSurf->~cairo_d2d_surface_t();
     free(newSurf);
     return _cairo_surface_create_in_error(_cairo_error(CAIRO_STATUS_NO_MEMORY));
 }
 
+cairo_surface_t *
+cairo_d2d_surface_create_for_handle(cairo_device_t *device, HANDLE handle, cairo_content_t content)
+{
+    if (!device) {
+	return _cairo_surface_create_in_error(_cairo_error(CAIRO_STATUS_NO_DEVICE));
+    }
+
+    cairo_d2d_device_t *d2d_device = reinterpret_cast<cairo_d2d_device_t*>(device);
+    cairo_d2d_surface_t *newSurf = static_cast<cairo_d2d_surface_t*>(malloc(sizeof(cairo_d2d_surface_t)));
+    new (newSurf) cairo_d2d_surface_t();
+
+    cairo_status_t status = CAIRO_STATUS_NO_MEMORY;
+    HRESULT hr;
+    RefPtr<ID3D10Texture2D> texture;
+    RefPtr<IDXGISurface> dxgiSurface;
+    D2D1_BITMAP_PROPERTIES bitProps;
+    D2D1_RENDER_TARGET_PROPERTIES props;
+    DXGI_FORMAT format;
+    DXGI_SURFACE_DESC desc;
+
+    hr = d2d_device->mD3D10Device->OpenSharedResource(handle,
+						      __uuidof(ID3D10Resource),
+						      (void**)&newSurf->surface);
+
+    if (FAILED(hr)) {
+	goto FAIL_CREATEHANDLE;
+    }
+
+    hr = newSurf->surface->QueryInterface(&dxgiSurface);
+
+    if (FAILED(hr)) {
+	goto FAIL_CREATEHANDLE;
+    }
+
+    dxgiSurface->GetDesc(&desc);
+    format = desc.Format;
+    
+    D2D1_ALPHA_MODE alpha = D2D1_ALPHA_MODE_PREMULTIPLIED;
+    if (format == DXGI_FORMAT_B8G8R8A8_UNORM) {
+	if (content == CAIRO_CONTENT_ALPHA) {
+	    status = CAIRO_STATUS_INVALID_CONTENT;
+	    goto FAIL_CREATEHANDLE;
+	}
+	_cairo_surface_init(&newSurf->base, &cairo_d2d_surface_backend, content);
+	if (content == CAIRO_CONTENT_COLOR) {
+	    alpha = D2D1_ALPHA_MODE_IGNORE;
+	}
+    } else if (format == DXGI_FORMAT_A8_UNORM) {
+	if (content != CAIRO_CONTENT_ALPHA) {
+	    status = CAIRO_STATUS_INVALID_CONTENT;
+	    goto FAIL_CREATEHANDLE;
+	}
+	_cairo_surface_init(&newSurf->base, &cairo_d2d_surface_backend, CAIRO_CONTENT_ALPHA);
+    } else {
+	status = CAIRO_STATUS_INVALID_FORMAT;
+	// We don't know how to support this format!
+	goto FAIL_CREATEHANDLE;
+    }
+
+    props = D2D1::RenderTargetProperties(D2D1_RENDER_TARGET_TYPE_DEFAULT,
+					 D2D1::PixelFormat(DXGI_FORMAT_UNKNOWN, alpha));
+
+    hr = sD2DFactory->CreateDxgiSurfaceRenderTarget(dxgiSurface,
+						    props,
+						    &newSurf->rt);
+
+    if (FAILED(hr)) {
+	goto FAIL_CREATEHANDLE;
+    }
+
+    bitProps = D2D1::BitmapProperties(D2D1::PixelFormat(DXGI_FORMAT_UNKNOWN, 
+				      alpha));
+
+    if (format != DXGI_FORMAT_A8_UNORM) {
+	/* For some reason creation of shared bitmaps for A8 UNORM surfaces
+	 * doesn't work even though the documentation suggests it does. The
+	 * function will return an error if we try */
+	hr = newSurf->rt->CreateSharedBitmap(IID_IDXGISurface,
+					     dxgiSurface,
+					     &bitProps,
+					     &newSurf->surfaceBitmap);
+
+	if (FAILED(hr)) {
+	    goto FAIL_CREATEHANDLE;
+	}
+    }
+
+    newSurf->rt->CreateSolidColorBrush(D2D1::ColorF(0, 1.0), &newSurf->solidColorBrush);
+
+    _d2d_clear_surface(newSurf);
+
+    newSurf->device = d2d_device;
+    cairo_addref_device(device);
+
+    return &newSurf->base;
+   
+FAIL_CREATEHANDLE:
+    newSurf->~cairo_d2d_surface_t();
+    free(newSurf);
+    return _cairo_surface_create_in_error(_cairo_error(status));
+}
+
 void cairo_d2d_scroll(cairo_surface_t *surface, int x, int y, cairo_rectangle_t *clip)
 {
     if (surface->type != CAIRO_SURFACE_TYPE_D2D) {
         return;
     }
     cairo_d2d_surface_t *d2dsurf = reinterpret_cast<cairo_d2d_surface_t*>(surface);
 
     /** For now, we invalidate our storing texture with this operation. */
@@ -2773,41 +3612,28 @@ void cairo_d2d_scroll(cairo_surface_t *s
 	rect.bottom = (UINT)(clip->y + clip->height);
     } else {
 	point.y = (UINT32)(clip->y + y);
 	rect.top = (UINT)clip->y;
 	rect.bottom = (UINT)(clip->y + clip->height - y);
     }
     ID3D10Texture2D *texture = _cairo_d2d_get_buffer_texture(d2dsurf);
 
-    D3D10Factory::Device()->CopyResource(texture, d2dsurf->surface);
-    D3D10Factory::Device()->CopySubresourceRegion(d2dsurf->surface,
+    d2dsurf->device->mD3D10Device->CopyResource(texture, d2dsurf->surface);
+    d2dsurf->device->mD3D10Device->CopySubresourceRegion(d2dsurf->surface,
 						  0,
 						  point.x,
 						  point.y,
 						  0,
 						  texture,
 						  0,
 						  &rect);
 
 }
 
-cairo_bool_t
-cairo_d2d_has_support()
-{
-    /**
-     * FIXME: We should be able to fix this in the near future when we pass in
-     * a cairo_device_t to our surface creation functions.
-     */
-    if (!D3D10Factory::Device() || !D2DSurfFactory::Instance()) {
-	return false;
-    }
-    return true;
-}
-
 HDC
 cairo_d2d_get_dc(cairo_surface_t *surface, cairo_bool_t retain_contents)
 {
     if (surface->type != CAIRO_SURFACE_TYPE_D2D) {
         return NULL;
     }
     cairo_d2d_surface_t *d2dsurf = reinterpret_cast<cairo_d2d_surface_t*>(surface);
 
--- a/gfx/cairo/cairo/src/cairo-dwrite-font.cpp
+++ b/gfx/cairo/cairo/src/cairo-dwrite-font.cpp
@@ -1257,42 +1257,62 @@ cairo_int_status_t
     cairo_dwrite_font_face_t *dwriteff = reinterpret_cast<cairo_dwrite_font_face_t*>(scaled_font->font_face);
     cairo_d2d_surface_t *dst = reinterpret_cast<cairo_d2d_surface_t*>(surface);
 
     /* We can only handle dwrite fonts */
     //XXX: this is checked by at least one caller
     if (cairo_scaled_font_get_type (scaled_font) != CAIRO_FONT_TYPE_DWRITE)
 	return CAIRO_INT_STATUS_UNSUPPORTED;
 
+    op = _cairo_d2d_simplify_operator(op, source);
 
-    /* We can only handle operator SOURCE or OVER with the destination
-     * having no alpha */
-    if (op != CAIRO_OPERATOR_SOURCE && op != CAIRO_OPERATOR_OVER)
-	return CAIRO_INT_STATUS_UNSUPPORTED;
+    /* We cannot handle operator SOURCE or CLEAR */
+    if (op == CAIRO_OPERATOR_SOURCE || op == CAIRO_OPERATOR_CLEAR) {
+	return CAIRO_INT_STATUS_UNSUPPORTED;
+    }
 
-    _cairo_d2d_begin_draw_state (dst);
-    _cairo_d2d_set_clip (dst, clip);
+    RefPtr<ID2D1RenderTarget> target_rt = dst->rt;
+    cairo_rectangle_int_t fontArea;
+#ifndef ALWAYS_MANUAL_COMPOSITE
+    if (op != CAIRO_OPERATOR_OVER) {
+#endif
+	target_rt = _cairo_d2d_get_temp_rt(dst, clip);
+
+	if (!target_rt) {
+	    return CAIRO_INT_STATUS_UNSUPPORTED;
+	}
+#ifndef ALWAYS_MANUAL_COMPOSITE
+    } else {
+	_cairo_d2d_begin_draw_state(dst);
+	status = (cairo_int_status_t)_cairo_d2d_set_clip (dst, clip);
+
+	if (unlikely(status))
+	    return status;
+    }
+#endif
 
-    D2D1_TEXT_ANTIALIAS_MODE cleartype = D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE;
+    D2D1_TEXT_ANTIALIAS_MODE highest_quality = D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE;
 
-    if (dst->base.content != CAIRO_CONTENT_COLOR) {
-	cleartype = D2D1_TEXT_ANTIALIAS_MODE_GRAYSCALE;
+    // If we're rendering to a temporary surface we cannot do sub-pixel AA.
+    if (dst->base.content != CAIRO_CONTENT_COLOR || dst->rt.get() != target_rt.get()) {
+	highest_quality = D2D1_TEXT_ANTIALIAS_MODE_GRAYSCALE;
     }
+
     switch (scaled_font->options.antialias) {
 	case CAIRO_ANTIALIAS_DEFAULT:
-	    dst->rt->SetTextAntialiasMode(cleartype);
+	    target_rt->SetTextAntialiasMode(highest_quality);
 	    break;
 	case CAIRO_ANTIALIAS_NONE:
-	    dst->rt->SetTextAntialiasMode(D2D1_TEXT_ANTIALIAS_MODE_ALIASED);
+	    target_rt->SetTextAntialiasMode(D2D1_TEXT_ANTIALIAS_MODE_ALIASED);
 	    break;
 	case CAIRO_ANTIALIAS_GRAY:
-	    dst->rt->SetTextAntialiasMode(D2D1_TEXT_ANTIALIAS_MODE_GRAYSCALE);
+	    target_rt->SetTextAntialiasMode(D2D1_TEXT_ANTIALIAS_MODE_GRAYSCALE);
 	    break;
 	case CAIRO_ANTIALIAS_SUBPIXEL:
-	    dst->rt->SetTextAntialiasMode(cleartype);
+	    target_rt->SetTextAntialiasMode(highest_quality);
 	    break;
     }
 
     /* It is vital that dx values for dxy_buf are calculated from the delta of
      * _logical_ x coordinates (not user x coordinates) or else the sum of all
      * previous dx values may start to diverge from the current glyph's x
      * coordinate due to accumulated rounding error. As a result strings could
      * be painted shorter or longer than expected. */
@@ -1344,17 +1364,39 @@ cairo_int_status_t
 	// The font matrix takes care of the scaling if we have a transform,
 	// emSize should be 1.
         run.fontEmSize = 1.0f;
     }
 
     D2D1::Matrix3x2F mat = _cairo_d2d_matrix_from_matrix(&dwritesf->mat);
 	
     if (transform) {
-	dst->rt->SetTransform(mat);
+	target_rt->SetTransform(mat);
+    }
+
+    if (dst->rt.get() != target_rt.get()) {
+	RefPtr<IDWriteGlyphRunAnalysis> analysis;
+	DWRITE_MATRIX dwmat = _cairo_dwrite_matrix_from_matrix(&dwritesf->mat);
+	DWriteFactory::Instance()->CreateGlyphRunAnalysis(&run,
+							  1.0f,
+							  transform ? &dwmat : 0,
+							  DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL_SYMMETRIC,
+							  DWRITE_MEASURING_MODE_NATURAL,
+							  0,
+							  0,
+							  &analysis);
+
+	RECT bounds;
+	analysis->GetAlphaTextureBounds(scaled_font->options.antialias == CAIRO_ANTIALIAS_NONE ?
+					DWRITE_TEXTURE_ALIASED_1x1 : DWRITE_TEXTURE_CLEARTYPE_3x1,
+					&bounds);
+	fontArea.x = bounds.left;
+	fontArea.y = bounds.top;
+	fontArea.width = bounds.right - bounds.left;
+	fontArea.height = bounds.bottom - bounds.top;
     }
 
     RefPtr<ID2D1Brush> brush = _cairo_d2d_create_brush_for_pattern(dst,
 								   source);
 
     if (!brush) {
 	delete [] indices;
 	delete [] offsets;
@@ -1369,22 +1411,26 @@ cairo_int_status_t
 	// The brush matrix needs to be multiplied with the inverted matrix
 	// as well, to move the brush into the space of the glyphs. Before
 	// the render target transformation.
 	brush->GetTransform(&mat_brush);
 	mat_brush = mat_brush * mat_inverse;
 	brush->SetTransform(&mat_brush);
     }
     
-    dst->rt->DrawGlyphRun(D2D1::Point2F(0, 0), &run, brush);
+    target_rt->DrawGlyphRun(D2D1::Point2F(0, 0), &run, brush);
     
     if (transform) {
-	dst->rt->SetTransform(D2D1::Matrix3x2F::Identity());
+	target_rt->SetTransform(D2D1::Matrix3x2F::Identity());
     }
 
     delete [] indices;
     delete [] offsets;
     delete [] advances;
+
+    if (target_rt.get() != dst->rt.get()) {
+	return _cairo_d2d_blend_temp_surface(dst, op, target_rt, clip, &fontArea);
+    }
 
     return CAIRO_INT_STATUS_SUCCESS;
 }
 
 #endif
--- a/gfx/cairo/cairo/src/cairo-rectangle.c
+++ b/gfx/cairo/cairo/src/cairo-rectangle.c
@@ -89,16 +89,36 @@ void
 
 	if (boxes[n].p1.y < extents->p1.y)
 	    extents->p1.y = boxes[n].p1.y;
 	if (boxes[n].p2.y > extents->p2.y)
 	    extents->p2.y = boxes[n].p2.y;
     }
 }
 
+/* This function will return 'true' if the containing_rectangle contains the
+ * contained_rectangle, and false otherwise.
+ */ 
+cairo_bool_t
+_cairo_rectangle_contains (const cairo_rectangle_int_t *containing_rectangle,
+			   const cairo_rectangle_int_t *contained_rectangle)
+{
+    if (containing_rectangle->x > contained_rectangle->x ||
+	containing_rectangle->y > contained_rectangle->y)
+	return FALSE;
+    
+    if (containing_rectangle->x + containing_rectangle->width <
+	contained_rectangle->x + contained_rectangle->width ||
+	containing_rectangle->y + containing_rectangle->height <
+	contained_rectangle->y + contained_rectangle->height)
+	return FALSE;
+
+    return TRUE;
+}
+
 /* XXX We currently have a confusing mix of boxes and rectangles as
  * exemplified by this function.  A #cairo_box_t is a rectangular area
  * represented by the coordinates of the upper left and lower right
  * corners, expressed in fixed point numbers.  A #cairo_rectangle_int_t is
  * also a rectangular area, but represented by the upper left corner
  * and the width and the height, as integer numbers.
  *
  * This function converts a #cairo_box_t to a #cairo_rectangle_int_t by
--- a/gfx/cairo/cairo/src/cairo-win32-refptr.h
+++ b/gfx/cairo/cairo/src/cairo-win32-refptr.h
@@ -102,16 +102,21 @@ public:
 	return &mPtr;
     }
 
     T* operator->()
     {
 	return mPtr;
     }
 
+    T* operator->() const
+    {
+	return mPtr;
+    }
+
     operator bool()
     {
 	return (mPtr ? true : false);
     }
 
     operator T*()
     {
 	return mPtr;
--- a/gfx/cairo/cairo/src/cairo-win32.h
+++ b/gfx/cairo/cairo/src/cairo-win32.h
@@ -121,41 +121,99 @@ cairo_win32_scaled_font_get_device_to_lo
  * Win32 DirectWrite font support
  */
 cairo_public cairo_font_face_t *
 cairo_dwrite_font_face_create_for_dwrite_fontface(void *dwrite_font, void *dwrite_font_face);
 
 #endif /* CAIRO_HAS_DWRITE_FONT */
 
 #if CAIRO_HAS_D2D_SURFACE
+
+struct _cairo_device
+{
+    int type;
+    int refcount;
+};
+typedef struct _cairo_device cairo_device_t;
+
+/**
+ * Create a D2D device
+ *
+ * \return New D2D device, NULL if creation failed.
+ */
+cairo_device_t *
+cairo_d2d_create_device();
+
+/**
+ * Releases a D2D device.
+ *
+ * \return References left to the device
+ */
+int
+cairo_release_device(cairo_device_t *device);
+
+/**
+ * Addrefs a D2D device.
+ *
+ * \return References to the device
+ */
+int
+cairo_addref_device(cairo_device_t *device);
+
+/**
+ * Flushes a D3D device. In most cases the surface backend will do this
+ * internally, but when using a surfaces created from a shared handle this
+ * should be executed manually when a different device is going to be accessing
+ * the same surface data. This will also block until the device is finished
+ * processing all work.
+ */
+void
+cairo_d2d_finish_device(cairo_device_t *device);
 
 /**
  * Create a D2D surface for an HWND
  *
+ * \param device Device used to create the surface
  * \param wnd Handle for the window
  * \param content Content of the window, should be COLOR_ALPHA for transparent windows
  * \return New cairo surface
  */
 cairo_public cairo_surface_t *
-cairo_d2d_surface_create_for_hwnd(HWND wnd, cairo_content_t content);
+cairo_d2d_surface_create_for_hwnd(cairo_device_t *device, HWND wnd, cairo_content_t content);
 
 /**
  * Create a D2D surface of a certain size.
  *
+ * \param device Device used to create the surface
  * \param format Cairo format of the surface
  * \param width Width of the surface
  * \param height Height of the surface
  * \return New cairo surface
  */
 cairo_public cairo_surface_t *
-cairo_d2d_surface_create(cairo_format_t format,
+cairo_d2d_surface_create(cairo_device_t *device,
+			 cairo_format_t format,
                          int width,
                          int height);
 
 /**
+ * Create a D3D surface from a Texture SharedHandle, this is obtained from a
+ * CreateTexture call on a D3D9 device. This has to be an A8R8G8B8 format
+ * or an A8 format, the treatment of the alpha channel can be indicated using
+ * the content parameter.
+ *
+ * \param device Device used to create the surface
+ * \param handle Shared handle to the texture we want to wrap
+ * \param content Content of the texture, COLOR_ALPHA for ARGB
+ * \return New cairo surface
+ */
+cairo_public cairo_surface_t *
+cairo_d2d_surface_create_for_handle(cairo_device_t *device, HANDLE handle, cairo_content_t content);
+
+/**
  * Present the backbuffer for a surface create for an HWND. This needs
  * to be called when the owner of the original window surface wants to
  * actually present the executed drawing operations to the screen.
  *
  * \param surface D2D surface.
  */
 void cairo_d2d_present_backbuffer(cairo_surface_t *surface);
 
@@ -168,25 +226,16 @@ void cairo_d2d_present_backbuffer(cairo_
  * \param x The x delta for the movement
  * \param y The y delta for the movement
  * \param clip The clip rectangle, the is the 'part' of the surface that needs
  * scrolling.
  */
 void cairo_d2d_scroll(cairo_surface_t *surface, int x, int y, cairo_rectangle_t *clip);
 
 /**
- * Verify if D2D surfaces are actually supported. This will confirm the needed
- * hardware is available.
- *
- * \return True if the support is available. If false surface creation will
- * return error surfaces.
- */
-cairo_bool_t cairo_d2d_has_support();
-
-/**
  * Get a DC for the current render target. When selecting the retention option this
  * call can be relatively slow, since it may require reading back contents from the
  * hardware surface.
  *
  * \note This must be matched by a call to ReleaseDC!
  *
  * \param retain_contents If true the current contents of the RT is copied to the DC,
  * otherwise the DC is initialized to transparent black.
--- a/gfx/cairo/cairo/src/cairoint.h
+++ b/gfx/cairo/cairo/src/cairoint.h
@@ -266,16 +266,20 @@ cairo_private void
 _cairo_box_to_doubles (const cairo_box_t *box,
 		       double *x1, double *y1,
 		       double *x2, double *y2);
 
 cairo_private void
 _cairo_box_from_rectangle (cairo_box_t                 *box,
 			   const cairo_rectangle_int_t *rectangle);
 
+cairo_private cairo_bool_t
+_cairo_rectangle_contains (const cairo_rectangle_int_t *containing_rectangle,
+			   const cairo_rectangle_int_t *contained_rectangle);
+
 cairo_private void
 _cairo_box_round_to_rectangle (const cairo_box_t     *box,
 			       cairo_rectangle_int_t *rectangle);
 
 cairo_private void
 _cairo_boxes_get_extents (const cairo_box_t *boxes,
 			  int num_boxes,
 			  cairo_box_t *extents);
--- a/gfx/layers/Makefile.in
+++ b/gfx/layers/Makefile.in
@@ -79,25 +79,29 @@ CPPSRCS = \
         ContainerLayerOGL.cpp \
         ImageLayerOGL.cpp \
         LayerManagerOGL.cpp \
         ThebesLayerOGL.cpp \
         $(NULL)
 
 ifeq ($(MOZ_WIDGET_TOOLKIT),windows)
 ifdef MOZ_ENABLE_D3D9_LAYER
-EXPORTS += LayerManagerD3D9.h
+EXPORTS += \
+        LayerManagerD3D9.h \
+        DeviceManagerD3D9.h \
+        $(NULL)
 
 CPPSRCS += \
         LayerManagerD3D9.cpp \
         ThebesLayerD3D9.cpp \
         ContainerLayerD3D9.cpp \
         ImageLayerD3D9.cpp \
         ColorLayerD3D9.cpp \
         CanvasLayerD3D9.cpp \
+        DeviceManagerD3D9.cpp \
         $(NULL)
 endif
 endif
 
 ifdef MOZ_IPC #{
 EXPORTS_NAMESPACES = mozilla/layers
 EXPORTS_mozilla/layers =\
         ShadowLayers.h \
--- a/gfx/layers/d3d9/CanvasLayerD3D9.cpp
+++ b/gfx/layers/d3d9/CanvasLayerD3D9.cpp
@@ -65,19 +65,27 @@ CanvasLayerD3D9::Initialize(const Data& 
     mGLBufferIsPremultiplied = aData.mGLBufferIsPremultiplied;
     mNeedsYFlip = PR_TRUE;
   } else {
     NS_ERROR("CanvasLayer created without mSurface or mGLContext?");
   }
 
   mBounds.SetRect(0, 0, aData.mSize.width, aData.mSize.height);
 
-  device()->CreateTexture(mBounds.width, mBounds.height, 1, 0,
-                          D3DFMT_A8R8G8B8, D3DPOOL_MANAGED,
-                          getter_AddRefs(mTexture), NULL);
+  if (mD3DManager->deviceManager()->HasDynamicTextures()) {
+    device()->CreateTexture(mBounds.width, mBounds.height, 1, D3DUSAGE_DYNAMIC,
+                            D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT,
+                            getter_AddRefs(mTexture), NULL);    
+  } else {
+    // D3DPOOL_MANAGED is fine here since we require Dynamic Textures for D3D9Ex
+    // devices.
+    device()->CreateTexture(mBounds.width, mBounds.height, 1, 0,
+                            D3DFMT_A8R8G8B8, D3DPOOL_MANAGED,
+                            getter_AddRefs(mTexture), NULL);
+  }
 }
 
 void
 CanvasLayerD3D9::Updated(const nsIntRect& aRect)
 {
   if (!mTexture) {
     NS_WARNING("CanvasLayerD3D9::Updated called but no texture present!");
     return;
@@ -225,17 +233,17 @@ CanvasLayerD3D9::RenderLayer()
   float opacity[4];
   /*
    * We always upload a 4 component float, but the shader will use only the
    * first component since it's declared as a 'float'.
    */
   opacity[0] = GetOpacity();
   device()->SetPixelShaderConstantF(0, opacity, 1);
 
-  mD3DManager->SetShaderMode(LayerManagerD3D9::RGBLAYER);
+  mD3DManager->SetShaderMode(DeviceManagerD3D9::RGBLAYER);
 
   if (!mGLBufferIsPremultiplied) {
     device()->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
   }
   device()->SetTexture(0, mTexture);
   device()->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);
   if (!mGLBufferIsPremultiplied) {
     device()->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE);
--- a/gfx/layers/d3d9/ColorLayerD3D9.cpp
+++ b/gfx/layers/d3d9/ColorLayerD3D9.cpp
@@ -71,15 +71,15 @@ ColorLayerD3D9::RenderLayer()
   // color is premultiplied, so we need to adjust all channels
   color[0] = (float)(mColor.r * GetOpacity());
   color[1] = (float)(mColor.g * GetOpacity());
   color[2] = (float)(mColor.b * GetOpacity());
   color[3] = (float)(mColor.a * GetOpacity());
 
   device()->SetPixelShaderConstantF(0, color, 1);
 
-  mD3DManager->SetShaderMode(LayerManagerD3D9::SOLIDCOLORLAYER);
+  mD3DManager->SetShaderMode(DeviceManagerD3D9::SOLIDCOLORLAYER);
 
   device()->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);
 }
 
 } /* layers */
 } /* mozilla */
--- a/gfx/layers/d3d9/ContainerLayerD3D9.cpp
+++ b/gfx/layers/d3d9/ContainerLayerD3D9.cpp
@@ -249,17 +249,17 @@ ContainerLayerD3D9::RenderLayer()
     float opacityVector[4];
     /*
      * We always upload a 4 component float, but the shader will use only the
      * first component since it's declared as a 'float'.
      */
     opacityVector[0] = opacity;
     device()->SetPixelShaderConstantF(0, opacityVector, 1);
 
-    mD3DManager->SetShaderMode(LayerManagerD3D9::RGBLAYER);
+    mD3DManager->SetShaderMode(DeviceManagerD3D9::RGBLAYER);
 
     device()->SetTexture(0, renderTexture);
     device()->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);
   }
 }
 
 } /* layers */
 } /* mozilla */
new file mode 100644
--- /dev/null
+++ b/gfx/layers/d3d9/DeviceManagerD3D9.cpp
@@ -0,0 +1,562 @@
+/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Corporation code.
+ *
+ * The Initial Developer of the Original Code is Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2009
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Bas Schouten <bschouten@mozilla.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "DeviceManagerD3D9.h"
+#include "LayerManagerD3D9Shaders.h"
+#include "ThebesLayerD3D9.h"
+#include "nsIServiceManager.h"
+#include "nsIConsoleService.h"
+#include "nsPrintfCString.h"
+
+namespace mozilla {
+namespace layers {
+
+const LPCWSTR kClassName       = L"D3D9WindowClass";
+
+#define USE_D3D9EX
+
+typedef IDirect3D9* (WINAPI*Direct3DCreate9Func)(
+  UINT SDKVersion
+);
+
+typedef HRESULT (WINAPI*Direct3DCreate9ExFunc)(
+  UINT SDKVersion,
+  IDirect3D9Ex **ppD3D
+);
+
+struct vertex {
+  float x, y;
+};
+
+SwapChainD3D9::SwapChainD3D9(DeviceManagerD3D9 *aDeviceManager)
+  : mDeviceManager(aDeviceManager)
+  , mWnd(0)
+{
+  mDeviceManager->mSwapChains.AppendElement(this);
+}
+
+SwapChainD3D9::~SwapChainD3D9()
+{
+  mDeviceManager->mSwapChains.RemoveElement(this);
+}
+
+bool
+SwapChainD3D9::Init(HWND hWnd)
+{
+  RECT r;
+  ::GetClientRect(hWnd, &r);
+
+  mWnd = hWnd;
+
+  D3DPRESENT_PARAMETERS pp;
+  memset(&pp, 0, sizeof(D3DPRESENT_PARAMETERS));
+
+  pp.BackBufferFormat = D3DFMT_UNKNOWN;
+  pp.SwapEffect = D3DSWAPEFFECT_COPY;
+  pp.Windowed = TRUE;
+  pp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
+  pp.hDeviceWindow = mWnd;
+  if (r.left == r.right || r.top == r.bottom) {
+    pp.BackBufferHeight = 1;
+    pp.BackBufferWidth = 1;
+  }
+
+  HRESULT hr = mDeviceManager->device()->
+    CreateAdditionalSwapChain(&pp,
+                              getter_AddRefs(mSwapChain));
+
+  if (FAILED(hr)) {
+    NS_WARNING("Failed to create swap chain for window.");
+    return false;
+  }
+
+  return true;
+}
+
+bool
+SwapChainD3D9::PrepareForRendering()
+{
+  RECT r;
+  if (!::GetClientRect(mWnd, &r)) {
+    return false;
+  }
+
+  if (!mDeviceManager->VerifyReadyForRendering()) {
+    return false;
+  }
+
+  if (!mSwapChain) {
+    Init(mWnd);
+  }
+
+  if (mSwapChain) {
+    nsRefPtr<IDirect3DSurface9> backBuffer;
+    mSwapChain->GetBackBuffer(0,
+                              D3DBACKBUFFER_TYPE_MONO,
+                              getter_AddRefs(backBuffer));
+
+    D3DSURFACE_DESC desc;
+    backBuffer->GetDesc(&desc);
+
+    if (desc.Width == r.right - r.left && desc.Height == r.bottom - r.top) {
+      mDeviceManager->device()->SetRenderTarget(0, backBuffer);
+      return true;
+    }
+
+    mSwapChain = nsnull;
+    
+    Init(mWnd);
+    
+    if (!mSwapChain) {
+      return false;
+    }
+    
+    mSwapChain->GetBackBuffer(0,
+                              D3DBACKBUFFER_TYPE_MONO,
+                              getter_AddRefs(backBuffer));
+
+    mDeviceManager->device()->SetRenderTarget(0, backBuffer);
+    
+    return true;
+  }
+  return false;
+}
+
+void
+SwapChainD3D9::Present(const nsIntRect &aRect)
+{
+  RECT r;
+  r.left = aRect.x;
+  r.top = aRect.y;
+  r.right = aRect.XMost();
+  r.bottom = aRect.YMost();
+
+  mSwapChain->Present(&r, &r, 0, 0, 0);
+}
+
+void
+SwapChainD3D9::Reset()
+{
+  mSwapChain = nsnull;
+}
+
+#define HAS_CAP(a, b) (((a) & (b)) == (b))
+#define LACKS_CAP(a, b) !(((a) & (b)) == (b))
+
+DeviceManagerD3D9::DeviceManagerD3D9()
+  : mHasDynamicTextures(false)
+{
+}
+
+bool
+DeviceManagerD3D9::Init()
+{
+  WNDCLASSW wc;
+  HRESULT hr;
+
+  if (!GetClassInfoW(GetModuleHandle(NULL), kClassName, &wc)) {
+      ZeroMemory(&wc, sizeof(WNDCLASSW));
+      wc.hInstance = GetModuleHandle(NULL);
+      wc.lpfnWndProc = ::DefWindowProc;
+      wc.lpszClassName = kClassName;
+      if (!RegisterClassW(&wc)) {
+          NS_WARNING("Failed to register window class for DeviceManager.");
+          return false;
+      }
+  }
+
+  mFocusWnd = CreateWindow(kClassName, L"D3D9Window", WS_OVERLAPPEDWINDOW,
+                           CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL,
+                           NULL, GetModuleHandle(NULL), NULL);
+
+  if (!mFocusWnd) {
+    NS_WARNING("Failed to create DeviceManagerD3D9 Window.");
+    return false;
+  }
+
+  HMODULE d3d9 = LoadLibraryW(L"d3d9.dll");
+  Direct3DCreate9Func d3d9Create = (Direct3DCreate9Func)
+    GetProcAddress(d3d9, "Direct3DCreate9");
+  Direct3DCreate9ExFunc d3d9CreateEx = (Direct3DCreate9ExFunc)
+    GetProcAddress(d3d9, "Direct3DCreate9Ex");
+  
+#ifdef USE_D3D9EX
+  if (d3d9CreateEx) {
+    hr = d3d9CreateEx(D3D_SDK_VERSION, getter_AddRefs(mD3D9Ex));
+    if (SUCCEEDED(hr)) {
+      mD3D9 = mD3D9Ex;
+    }
+  }
+#endif
+
+  if (!mD3D9) {
+    if (!d3d9Create) {
+      return false;
+    }
+
+    mD3D9 = dont_AddRef(d3d9Create(D3D_SDK_VERSION));
+
+    if (!mD3D9) {
+      return false;
+    }
+  }
+
+  D3DPRESENT_PARAMETERS pp;
+  memset(&pp, 0, sizeof(D3DPRESENT_PARAMETERS));
+
+  pp.BackBufferWidth = 1;
+  pp.BackBufferHeight = 1;
+  pp.BackBufferFormat = D3DFMT_A8R8G8B8;
+  pp.SwapEffect = D3DSWAPEFFECT_DISCARD;
+  pp.Windowed = TRUE;
+  pp.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT;
+  pp.hDeviceWindow = mFocusWnd;
+
+  if (mD3D9Ex) {
+    hr = mD3D9Ex->CreateDeviceEx(D3DADAPTER_DEFAULT,
+                                 D3DDEVTYPE_HAL,
+                                 mFocusWnd,
+                                 D3DCREATE_FPU_PRESERVE |
+                                 D3DCREATE_MULTITHREADED |
+                                 D3DCREATE_MIXED_VERTEXPROCESSING,
+                                 &pp,
+                                 NULL,
+                                 getter_AddRefs(mDeviceEx));
+    if (SUCCEEDED(hr)) {
+      mDevice = mDeviceEx;
+    }
+
+    D3DCAPS9 caps;
+    if (mDeviceEx->GetDeviceCaps(&caps)) {
+      if (LACKS_CAP(caps.Caps2, D3DCAPS2_DYNAMICTEXTURES)) {
+        // XXX - Should we actually hit this we'll need a CanvasLayer that
+        // supports static D3DPOOL_DEFAULT textures.
+        NS_WARNING("D3D9Ex device not used because of lack of support for \
+                   dynamic textures. This is unexpected.");
+        mDevice = nsnull;
+        mDeviceEx = nsnull;
+      }
+    }
+  }
+
+  if (!mDevice) {
+    hr = mD3D9->CreateDevice(D3DADAPTER_DEFAULT,
+                             D3DDEVTYPE_HAL,
+                             mFocusWnd,
+                             D3DCREATE_FPU_PRESERVE |
+                             D3DCREATE_MULTITHREADED |
+                             D3DCREATE_MIXED_VERTEXPROCESSING,
+                             &pp,
+                             getter_AddRefs(mDevice));
+
+    if (FAILED(hr)) {
+      NS_WARNING("Failed to create Device for DeviceManagerD3D9.");
+      return false;
+    }
+  }
+
+  if (!VerifyCaps()) {
+    return false;
+  }
+
+  hr = mDevice->CreateVertexShader((DWORD*)LayerQuadVS,
+                                   getter_AddRefs(mLayerVS));
+
+  if (FAILED(hr)) {
+    return false;
+  }
+
+  hr = mDevice->CreatePixelShader((DWORD*)RGBShaderPS,
+                                  getter_AddRefs(mRGBPS));
+
+  if (FAILED(hr)) {
+    return false;
+  }
+
+  hr = mDevice->CreatePixelShader((DWORD*)YCbCrShaderPS,
+                                  getter_AddRefs(mYCbCrPS));
+
+  if (FAILED(hr)) {
+    return false;
+  }
+
+  hr = mDevice->CreatePixelShader((DWORD*)SolidColorShaderPS,
+                                  getter_AddRefs(mSolidColorPS));
+
+  if (FAILED(hr)) {
+    return false;
+  }
+
+  hr = mDevice->CreateVertexBuffer(sizeof(vertex) * 4,
+                                   D3DUSAGE_WRITEONLY,
+                                   0,
+                                   D3DPOOL_DEFAULT,
+                                   getter_AddRefs(mVB),
+                                   NULL);
+
+  if (FAILED(hr)) {
+    return false;
+  }
+
+  vertex *vertices;
+  hr = mVB->Lock(0, 0, (void**)&vertices, 0);
+  if (FAILED(hr)) {
+    return false;
+  }
+
+  vertices[0].x = vertices[0].y = 0;
+  vertices[1].x = 1; vertices[1].y = 0;
+  vertices[2].x = 0; vertices[2].y = 1;
+  vertices[3].x = 1; vertices[3].y = 1;
+
+  mVB->Unlock();
+
+  hr = mDevice->SetStreamSource(0, mVB, 0, sizeof(vertex));
+  if (FAILED(hr)) {
+    return false;
+  }
+
+  D3DVERTEXELEMENT9 elements[] = {
+    { 0, 0, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT,
+      D3DDECLUSAGE_POSITION, 0 },
+    D3DDECL_END()
+  };
+
+  mDevice->CreateVertexDeclaration(elements, getter_AddRefs(mVD));
+
+  nsCOMPtr<nsIConsoleService>
+    console(do_GetService(NS_CONSOLESERVICE_CONTRACTID));
+
+  D3DADAPTER_IDENTIFIER9 identifier;
+  mD3D9->GetAdapterIdentifier(D3DADAPTER_DEFAULT, 0, &identifier);
+
+  if (console) {
+    nsString msg;
+    msg +=
+      NS_LITERAL_STRING("Direct3D 9 DeviceManager Initialized Succesfully.\nDriver: ");
+    msg += NS_ConvertUTF8toUTF16(
+      nsDependentCString((const char*)identifier.Driver));
+    msg += NS_LITERAL_STRING("\nDescription: ");
+    msg += NS_ConvertUTF8toUTF16(
+      nsDependentCString((const char*)identifier.Description));
+    msg += NS_LITERAL_STRING("\nVersion: ");
+    msg += NS_ConvertUTF8toUTF16(
+      nsPrintfCString("%d.%d.%d.%d",
+                      HIWORD(identifier.DriverVersion.HighPart),
+                      LOWORD(identifier.DriverVersion.HighPart),
+                      HIWORD(identifier.DriverVersion.LowPart),
+                      LOWORD(identifier.DriverVersion.LowPart)));
+    console->LogStringMessage(msg.get());
+  }
+
+  return true;
+}
+
+void
+DeviceManagerD3D9::SetupRenderState()
+{
+  mDevice->SetStreamSource(0, mVB, 0, sizeof(vertex));
+  mDevice->SetVertexDeclaration(mVD);
+  mDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
+  mDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
+  mDevice->SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_ADD);
+  mDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
+  mDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE);
+  mDevice->SetRenderState(D3DRS_SCISSORTESTENABLE, TRUE);
+  mDevice->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
+  mDevice->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
+  mDevice->SetSamplerState(1, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
+  mDevice->SetSamplerState(1, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
+  mDevice->SetSamplerState(2, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
+  mDevice->SetSamplerState(2, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
+}
+
+already_AddRefed<SwapChainD3D9>
+DeviceManagerD3D9::CreateSwapChain(HWND hWnd)
+{
+  nsRefPtr<SwapChainD3D9> swapChain = new SwapChainD3D9(this);
+  
+  if (!swapChain->Init(hWnd)) {
+    return nsnull;
+  }
+
+  return swapChain.forget();
+}
+
+void
+DeviceManagerD3D9::SetShaderMode(ShaderMode aMode)
+{
+  switch (aMode) {
+    case RGBLAYER:
+      mDevice->SetVertexShader(mLayerVS);
+      mDevice->SetPixelShader(mRGBPS);
+      break;
+    case YCBCRLAYER:
+      mDevice->SetVertexShader(mLayerVS);
+      mDevice->SetPixelShader(mYCbCrPS);
+      break;
+    case SOLIDCOLORLAYER:
+      mDevice->SetVertexShader(mLayerVS);
+      mDevice->SetPixelShader(mSolidColorPS);
+      break;
+  }
+}
+
+bool
+DeviceManagerD3D9::VerifyReadyForRendering()
+{
+  HRESULT hr = mDevice->TestCooperativeLevel();
+
+  if (SUCCEEDED(hr)) {
+    if (IsD3D9Ex()) {
+      hr = mDeviceEx->CheckDeviceState(mFocusWnd);
+      if (FAILED(hr)) {
+        D3DPRESENT_PARAMETERS pp;
+        memset(&pp, 0, sizeof(D3DPRESENT_PARAMETERS));
+
+        pp.BackBufferWidth = 1;
+        pp.BackBufferHeight = 1;
+        pp.BackBufferFormat = D3DFMT_A8R8G8B8;
+        pp.SwapEffect = D3DSWAPEFFECT_DISCARD;
+        pp.Windowed = TRUE;
+        pp.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT;
+        pp.hDeviceWindow = mFocusWnd;
+        
+        hr = mDeviceEx->ResetEx(&pp, NULL);
+        // Handle D3DERR_DEVICEREMOVED!
+        if (FAILED(hr)) {
+          return false;
+        }
+      }
+    }
+    return true;
+  }
+
+  if (hr != D3DERR_DEVICENOTRESET) {
+    return false;
+  }
+
+  for(unsigned int i = 0; i < mThebesLayers.Length(); i++) {
+    mThebesLayers[i]->CleanResources();
+  }
+  for(unsigned int i = 0; i < mSwapChains.Length(); i++) {
+    mSwapChains[i]->Reset();
+  }
+  
+  D3DPRESENT_PARAMETERS pp;
+  memset(&pp, 0, sizeof(D3DPRESENT_PARAMETERS));
+
+  pp.BackBufferWidth = 1;
+  pp.BackBufferHeight = 1;
+  pp.BackBufferFormat = D3DFMT_A8R8G8B8;
+  pp.SwapEffect = D3DSWAPEFFECT_DISCARD;
+  pp.Windowed = TRUE;
+  pp.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT;
+  pp.hDeviceWindow = mFocusWnd;
+
+  hr = mDevice->Reset(&pp);
+
+  if (FAILED(hr)) {
+    return false;
+  }
+
+  return true;
+}
+
+bool
+DeviceManagerD3D9::VerifyCaps()
+{
+  D3DCAPS9 caps;
+  HRESULT hr = mDevice->GetDeviceCaps(&caps);
+
+  if (FAILED(hr)) {
+    return false;
+  }
+
+  if (LACKS_CAP(caps.DevCaps, D3DDEVCAPS_TEXTUREVIDEOMEMORY)) {
+    return false;
+  }
+
+  if (LACKS_CAP(caps.PrimitiveMiscCaps, D3DPMISCCAPS_CULLNONE)) {
+    return false;
+  }
+
+  if (LACKS_CAP(caps.SrcBlendCaps, D3DPBLENDCAPS_ONE) ||
+      LACKS_CAP(caps.SrcBlendCaps, D3DBLEND_SRCALPHA) ||
+      LACKS_CAP(caps.DestBlendCaps, D3DPBLENDCAPS_INVSRCALPHA)) {
+    return false;
+  }
+
+  if (LACKS_CAP(caps.RasterCaps, D3DPRASTERCAPS_SCISSORTEST)) {
+    return false;
+  }
+
+  if (LACKS_CAP(caps.TextureCaps, D3DPTEXTURECAPS_ALPHA) ||
+      HAS_CAP(caps.TextureCaps, D3DPTEXTURECAPS_SQUAREONLY) ||
+      (HAS_CAP(caps.TextureCaps, D3DPTEXTURECAPS_POW2) &&
+       LACKS_CAP(caps.TextureCaps, D3DPTEXTURECAPS_NONPOW2CONDITIONAL))) {
+    return false;
+  }
+
+  if (LACKS_CAP(caps.TextureFilterCaps, D3DPTFILTERCAPS_MAGFLINEAR) ||
+      LACKS_CAP(caps.TextureFilterCaps, D3DPTFILTERCAPS_MINFLINEAR)) {
+    return false;
+  }
+
+  if (LACKS_CAP(caps.TextureAddressCaps, D3DPTADDRESSCAPS_CLAMP)) {
+    return false;
+  }
+
+  if (caps.MaxTextureHeight < 4096 ||
+      caps.MaxTextureWidth < 4096) {
+    return false;
+  }
+
+  if ((caps.PixelShaderVersion & 0xffff) < 0x200 ||
+      (caps.VertexShaderVersion & 0xffff) < 0x200) {
+    return false;
+  }
+
+  if (HAS_CAP(caps.Caps2, D3DCAPS2_DYNAMICTEXTURES)) {
+    mHasDynamicTextures = true;
+  }
+
+  return true;
+}
+
+} /* namespace layers */
+} /* namespace mozilla */
new file mode 100644
--- /dev/null
+++ b/gfx/layers/d3d9/DeviceManagerD3D9.h
@@ -0,0 +1,207 @@
+/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Corporation code.
+ *
+ * The Initial Developer of the Original Code is Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2009
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Bas Schouten <bschouten@mozilla.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef GFX_DEVICEMANAGERD3D9_H
+#define GFX_DEVICEMANAGERD3D9_H
+
+#include "gfxTypes.h"
+#include "nsRect.h"
+#include "nsAutoPtr.h"
+#include "d3d9.h"
+#include "nsTArray.h"
+
+namespace mozilla {
+namespace layers {
+
+class DeviceManagerD3D9;
+class ThebesLayerD3D9;
+
+/**
+ * SwapChain class, this class manages the swap chain belonging to a
+ * LayerManagerD3D9.
+ */
+class THEBES_API SwapChainD3D9
+{
+  NS_INLINE_DECL_REFCOUNTING(SwapChainD3D9)
+public:
+  ~SwapChainD3D9();
+
+  /**
+   * This function will prepare the device this swap chain belongs to for
+   * rendering to this swap chain. Only after calling this function can the
+   * swap chain be drawn to, and only until this function is called on another
+   * swap chain belonging to this device will the device draw to it. Passed in
+   * is the size of the swap chain. If the window size differs from the size
+   * during the last call to this function the swap chain will resize. Note that
+   * in no case does this function guarantee the backbuffer to still have its
+   * old content.
+   */
+  bool PrepareForRendering();
+
+  /**
+   * This function will present the selected rectangle of the swap chain to
+   * its associated window.
+   */
+  void Present(const nsIntRect &aRect);
+
+private:
+  friend class DeviceManagerD3D9;
+
+  SwapChainD3D9(DeviceManagerD3D9 *aDeviceManager);
+  
+  bool Init(HWND hWnd);
+
+  /**
+   * This causes us to release our swap chain, clearing out our resource usage
+   * so the master device may reset.
+   */
+  void Reset();
+
+  nsRefPtr<IDirect3DSwapChain9> mSwapChain;
+  nsRefPtr<DeviceManagerD3D9> mDeviceManager;
+  HWND mWnd;
+};
+
+/**
+ * Device manager, this class is used by the layer managers to share the D3D9
+ * device and create swap chains for the individual windows the layer managers
+ * belong to.
+ */
+class THEBES_API DeviceManagerD3D9
+{
+public:
+  DeviceManagerD3D9();
+
+  // We want the nsrefcnt return value. So we cannot use the inline refcnt macro
+  NS_IMPL_ADDREF(DeviceManagerD3D9)
+  NS_IMPL_RELEASE(DeviceManagerD3D9)
+
+  bool Init();
+
+  /**
+   * Sets up the render state for the device for layer rendering.
+   */
+  void SetupRenderState();
+
+  /**
+   * Create a swap chain setup to work with the specified window.
+   */
+  already_AddRefed<SwapChainD3D9> CreateSwapChain(HWND hWnd);
+
+  IDirect3DDevice9 *device() { return mDevice; }
+
+  bool IsD3D9Ex() { return mDeviceEx; }
+
+  bool HasDynamicTextures() { return mHasDynamicTextures; }
+
+  enum ShaderMode {
+    RGBLAYER,
+    YCBCRLAYER,
+    SOLIDCOLORLAYER
+  };
+
+  void SetShaderMode(ShaderMode aMode);
+
+  /**
+   * We keep a list of all thebes layers since we need their D3DPOOL_DEFAULT
+   * surfaces to be released when we want to reset the device.
+   */
+  nsTArray<ThebesLayerD3D9*> mThebesLayers;
+private:
+  friend class SwapChainD3D9;
+
+  /**
+   * This function verifies the device is ready for rendering, internally this
+   * will test the cooperative level of the device and reset the device if
+   * needed. If this returns false subsequent rendering calls may return errors.
+   */
+  bool VerifyReadyForRendering();
+
+  /* Array used to store all swap chains for device resets */
+  nsTArray<SwapChainD3D9*> mSwapChains;
+
+  /* The D3D device we use */
+  nsRefPtr<IDirect3DDevice9> mDevice;
+
+  /* The D3D9Ex device - only valid on Vista+ with WDDM */
+  nsRefPtr<IDirect3DDevice9Ex> mDeviceEx;
+
+  /* An instance of the D3D9 object */
+  nsRefPtr<IDirect3D9> mD3D9;
+
+  /* An instance of the D3D9Ex object - only valid on Vista+ with WDDM */
+  nsRefPtr<IDirect3D9Ex> mD3D9Ex;
+
+  /* Vertex shader used for layer quads */
+  nsRefPtr<IDirect3DVertexShader9> mLayerVS;
+
+  /* Pixel shader used for RGB textures */
+  nsRefPtr<IDirect3DPixelShader9> mRGBPS;
+
+  /* Pixel shader used for RGB textures */
+  nsRefPtr<IDirect3DPixelShader9> mYCbCrPS;
+
+  /* Pixel shader used for solid colors */
+  nsRefPtr<IDirect3DPixelShader9> mSolidColorPS;
+
+  /* Vertex buffer containing our basic vertex structure */
+  nsRefPtr<IDirect3DVertexBuffer9> mVB;
+
+  /* Our vertex declaration */
+  nsRefPtr<IDirect3DVertexDeclaration9> mVD;
+
+  /* Our focus window - this is really a dummy window we can associate our
+   * device with.
+   */
+  HWND mFocusWnd;
+
+  /* If this device supports dynamic textures */
+  bool mHasDynamicTextures;
+
+  nsAutoRefCnt mRefCnt;
+  NS_DECL_OWNINGTHREAD
+
+  /**
+   * Verifies all required device capabilities are present.
+   */
+  bool VerifyCaps();
+};
+
+} /* namespace layers */
+} /* namespace mozilla */
+
+#endif /* GFX_DEVICEMANAGERD3D9_H */
--- a/gfx/layers/d3d9/ImageLayerD3D9.cpp
+++ b/gfx/layers/d3d9/ImageLayerD3D9.cpp
@@ -180,17 +180,17 @@ ImageLayerD3D9::RenderLayer()
     float opacity[4];
     /*
      * We always upload a 4 component float, but the shader will
      * only use the the first component since it's declared as a 'float'.
      */
     opacity[0] = GetOpacity();
     device()->SetPixelShaderConstantF(0, opacity, 1);
 
-    mD3DManager->SetShaderMode(LayerManagerD3D9::YCBCRLAYER);
+    mD3DManager->SetShaderMode(DeviceManagerD3D9::YCBCRLAYER);
 
     device()->SetTexture(0, yuvImage->mYTexture);
     device()->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
     device()->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
     device()->SetTexture(1, yuvImage->mCbTexture);
     device()->SetSamplerState(1, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
     device()->SetSamplerState(1, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
     device()->SetTexture(2, yuvImage->mCrTexture);
@@ -222,33 +222,34 @@ ImageLayerD3D9::RenderLayer()
     float opacity[4];
     /*
      * We always upload a 4 component float, but the shader will
      * only use the the first component since it's declared as a 'float'.
      */
     opacity[0] = GetOpacity();
     device()->SetPixelShaderConstantF(0, opacity, 1);
 
-    mD3DManager->SetShaderMode(LayerManagerD3D9::RGBLAYER);
+    mD3DManager->SetShaderMode(DeviceManagerD3D9::RGBLAYER);
 
     device()->SetTexture(0, cairoImage->mTexture);
     device()->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);
   }
 }
 
 PlanarYCbCrImageD3D9::PlanarYCbCrImageD3D9(mozilla::layers::LayerManagerD3D9* aManager)
   : PlanarYCbCrImage(static_cast<ImageD3D9*>(this))
   , mManager(aManager)
   , mHasData(PR_FALSE)
 {
 }
 
 void
 PlanarYCbCrImageD3D9::SetData(const PlanarYCbCrImage::Data &aData)
 {
+  // XXX - For D3D9Ex we really should just copy to systemmem surfaces here.
   // For now, we copy the data
   int width_shift = 0;
   int height_shift = 0;
   if (aData.mYSize.width == aData.mCbCrSize.width &&
       aData.mYSize.height == aData.mCbCrSize.height) {
      // YV24 format
      width_shift = 0;
      height_shift = 0;
@@ -304,86 +305,126 @@ PlanarYCbCrImageD3D9::SetData(const Plan
   mHasData = PR_TRUE;
 }
 
 void
 PlanarYCbCrImageD3D9::AllocateTextures()
 {
 
 
-  D3DLOCKED_RECT lockrect;
+  D3DLOCKED_RECT lockrectY;
+  D3DLOCKED_RECT lockrectCb;
+  D3DLOCKED_RECT lockrectCr;
   PRUint8* src;
   PRUint8* dest;
-  //XXX: ensure correct usage flags
-  mManager->device()->CreateTexture(mData.mYSize.width, mData.mYSize.height,
-                          1, 0, D3DFMT_L8, D3DPOOL_MANAGED,
-                          getter_AddRefs(mYTexture), NULL);
+
+  nsRefPtr<IDirect3DSurface9> tmpSurfaceY;
+  nsRefPtr<IDirect3DSurface9> tmpSurfaceCb;
+  nsRefPtr<IDirect3DSurface9> tmpSurfaceCr;
 
+  if (mManager->deviceManager()->IsD3D9Ex()) {
+    // D3D9Ex does not support the managed pool, could use dynamic textures
+    // here. But since an Image is immutable static textures are probably a
+    // better idea.
+    mManager->device()->CreateTexture(mData.mYSize.width, mData.mYSize.height,
+                            1, 0, D3DFMT_L8, D3DPOOL_DEFAULT,
+                            getter_AddRefs(mYTexture), NULL);
+    mManager->device()->CreateTexture(mData.mCbCrSize.width, mData.mCbCrSize.height,
+                            1, 0, D3DFMT_L8, D3DPOOL_DEFAULT,
+                            getter_AddRefs(mCbTexture), NULL);
+    mManager->device()->CreateTexture(mData.mCbCrSize.width, mData.mCbCrSize.height,
+                            1, 0, D3DFMT_L8, D3DPOOL_DEFAULT,
+                            getter_AddRefs(mCrTexture), NULL);
+    mManager->device()->CreateOffscreenPlainSurface(mData.mYSize.width,
+                                                    mData.mYSize.height,
+                                                    D3DFMT_L8,
+                                                    D3DPOOL_SYSTEMMEM,
+                                                    getter_AddRefs(tmpSurfaceY),
+                                                    NULL);
+    mManager->device()->CreateOffscreenPlainSurface(mData.mCbCrSize.width,
+                                                    mData.mCbCrSize.height,
+                                                    D3DFMT_L8,
+                                                    D3DPOOL_SYSTEMMEM,
+                                                    getter_AddRefs(tmpSurfaceCb),
+                                                    NULL);
+    mManager->device()->CreateOffscreenPlainSurface(mData.mCbCrSize.width,
+                                                    mData.mCbCrSize.height,
+                                                    D3DFMT_L8,
+                                                    D3DPOOL_SYSTEMMEM,
+                                                    getter_AddRefs(tmpSurfaceCr),
+                                                    NULL);
+    tmpSurfaceY->LockRect(&lockrectY, NULL, 0);
+    tmpSurfaceCb->LockRect(&lockrectCb, NULL, 0);
+    tmpSurfaceCr->LockRect(&lockrectCr, NULL, 0);
+  } else {
+    mManager->device()->CreateTexture(mData.mYSize.width, mData.mYSize.height,
+                            1, 0, D3DFMT_L8, D3DPOOL_MANAGED,
+                            getter_AddRefs(mYTexture), NULL);
+    mManager->device()->CreateTexture(mData.mCbCrSize.width, mData.mCbCrSize.height,
+                            1, 0, D3DFMT_L8, D3DPOOL_MANAGED,
+                            getter_AddRefs(mCbTexture), NULL);
+    mManager->device()->CreateTexture(mData.mCbCrSize.width, mData.mCbCrSize.height,
+                            1, 0, D3DFMT_L8, D3DPOOL_MANAGED,
+                            getter_AddRefs(mCrTexture), NULL);
 
-  /* lock the entire texture */
-  mYTexture->LockRect(0, &lockrect, NULL, 0);
+    /* lock the entire texture */
+    mYTexture->LockRect(0, &lockrectY, NULL, 0);
+    mCbTexture->LockRect(0, &lockrectCb, NULL, 0);
+    mCrTexture->LockRect(0, &lockrectCr, NULL, 0);
+  }
 
   src  = mData.mYChannel;
   //FIX cast
-  dest = (PRUint8*)lockrect.pBits;
+  dest = (PRUint8*)lockrectY.pBits;
 
   // copy over data
   for (int h=0; h<mData.mYSize.height; h++) {
     memcpy(dest, src, mData.mYSize.width);
-    dest += lockrect.Pitch;
+    dest += lockrectY.Pitch;
     src += mData.mYStride;
   }
 
-  mYTexture->UnlockRect(0);
-
-  //XXX: ensure correct usage flags
-  mManager->device()->CreateTexture(mData.mCbCrSize.width, mData.mCbCrSize.height,
-                          1, 0, D3DFMT_L8, D3DPOOL_MANAGED,
-                          getter_AddRefs(mCbTexture), NULL);
-
-
-  /* lock the entire texture */
-  mCbTexture->LockRect(0, &lockrect, NULL, 0);
-
   src  = mData.mCbChannel;
   //FIX cast
-  dest = (PRUint8*)lockrect.pBits;
+  dest = (PRUint8*)lockrectCb.pBits;
 
   // copy over data
   for (int h=0; h<mData.mCbCrSize.height; h++) {
     memcpy(dest, src, mData.mCbCrSize.width);
-    dest += lockrect.Pitch;
+    dest += lockrectCb.Pitch;
     src += mData.mCbCrStride;
   }
 
-  mCbTexture->UnlockRect(0);
-
-
-  //XXX: ensure correct usage flags
-  mManager->device()->CreateTexture(mData.mCbCrSize.width, mData.mCbCrSize.height,
-                          1, 0, D3DFMT_L8, D3DPOOL_MANAGED,
-                          getter_AddRefs(mCrTexture), NULL);
-
-
-  /* lock the entire texture */
-  mCrTexture->LockRect(0, &lockrect, NULL, 0);
-
   src  = mData.mCrChannel;
   //FIX cast
-  dest = (PRUint8*)lockrect.pBits;
+  dest = (PRUint8*)lockrectCr.pBits;
 
   // copy over data
   for (int h=0; h<mData.mCbCrSize.height; h++) {
     memcpy(dest, src, mData.mCbCrSize.width);
-    dest += lockrect.Pitch;
+    dest += lockrectCr.Pitch;
     src += mData.mCbCrStride;
   }
 
-  mCrTexture->UnlockRect(0);
-
+  if (mManager->deviceManager()->IsD3D9Ex()) {
+    tmpSurfaceY->UnlockRect();
+    tmpSurfaceCb->UnlockRect();
+    tmpSurfaceCr->UnlockRect();
+    nsRefPtr<IDirect3DSurface9> dstSurface;
+    mYTexture->GetSurfaceLevel(0, getter_AddRefs(dstSurface));
+    mManager->device()->UpdateSurface(tmpSurfaceY, NULL, dstSurface, NULL);
+    mCbTexture->GetSurfaceLevel(0, getter_AddRefs(dstSurface));
+    mManager->device()->UpdateSurface(tmpSurfaceCb, NULL, dstSurface, NULL);
+    mCrTexture->GetSurfaceLevel(0, getter_AddRefs(dstSurface));
+    mManager->device()->UpdateSurface(tmpSurfaceCr, NULL, dstSurface, NULL);
+  } else {
+    mYTexture->UnlockRect(0);
+    mCbTexture->UnlockRect(0);
+    mCrTexture->UnlockRect(0);
+  }
 }
 
 void
 PlanarYCbCrImageD3D9::FreeTextures()
 {
 }
 
 already_AddRefed<gfxASurface>
@@ -421,41 +462,59 @@ CairoImageD3D9::SetData(const CairoImage
   nsRefPtr<gfxImageSurface> imageSurface =
     new gfxImageSurface(aData.mSize, gfxASurface::ImageFormatARGB32);
 
   nsRefPtr<gfxContext> context = new gfxContext(imageSurface);
 
   context->SetSource(aData.mSurface);
   context->Paint();
 
-  //XXX: make sure we're using the correct usage flags
-  mManager->device()->CreateTexture(aData.mSize.width, aData.mSize.height,
-                  1, 0, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED,
-                  getter_AddRefs(mTexture), NULL);
-
-  D3DLOCKED_RECT lockrect;
-  /* lock the entire texture */
-  mTexture->LockRect(0, &lockrect, NULL, 0);
-
-  PRUint8* src  = imageSurface->Data();
-  //FIX cast
-  PRUint8* dest = (PRUint8*)lockrect.pBits;
+  if (mManager->deviceManager()->IsD3D9Ex()) {
+    // D3D9Ex doesn't support managed textures. We could use dynamic textures
+    // here but since Images are immutable that probably isn't such a great
+    // idea.
+    mManager->device()->CreateTexture(aData.mSize.width, aData.mSize.height,
+                    1, 0, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT,
+                    getter_AddRefs(mTexture), NULL);
+    nsRefPtr<IDirect3DSurface9> surface;
+    mManager->device()->CreateOffscreenPlainSurface(aData.mSize.width,
+                                                    aData.mSize.height,
+                                                    D3DFMT_A8R8G8B8,
+                                                    D3DPOOL_SYSTEMMEM,
+                                                    getter_AddRefs(surface),
+                                                    NULL);
+    D3DLOCKED_RECT lockedRect;
+    surface->LockRect(&lockedRect, NULL, 0);
+    for (int y = 0; y < aData.mSize.height; y++) {
+      memcpy((char*)lockedRect.pBits + lockedRect.Pitch * y,
+             imageSurface->Data() + imageSurface->Stride() * y,
+             aData.mSize.width * 4);
+    }
+    surface->UnlockRect();
+    nsRefPtr<IDirect3DSurface9> dstSurface;
+    mTexture->GetSurfaceLevel(0, getter_AddRefs(dstSurface));
+    mManager->device()->UpdateSurface(surface, NULL, dstSurface, NULL);
+  } else {
+    mManager->device()->CreateTexture(aData.mSize.width, aData.mSize.height,
+                    1, 0, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED,
+                    getter_AddRefs(mTexture), NULL);
+    D3DLOCKED_RECT lockrect;
+    /* lock the entire texture */
+    mTexture->LockRect(0, &lockrect, NULL, 0);
 
-  // copy over data. If we don't need to do any swaping we can
-  // use memcpy
-  for (int i=0; i<aData.mSize.width*aData.mSize.height; i++) {
-    dest[0] = src[0];
-    dest[1] = src[1];
-    dest[2] = src[2];
-    dest[3] = src[3];
-    dest += 4;
-    src += 4;
+    // copy over data. If we don't need to do any swaping we can
+    // use memcpy
+    for (int y = 0; y < aData.mSize.height; y++) {
+      memcpy((char*)lockrect.pBits + lockrect.Pitch * y,
+             imageSurface->Data() + imageSurface->Stride() * y,
+             aData.mSize.width * 4);
+    }
+
+    mTexture->UnlockRect(0);
   }
-
-  mTexture->UnlockRect(0);
 }
 
 already_AddRefed<gfxASurface>
 CairoImageD3D9::GetAsSurface()
 {
   return nsnull;
 }
 
--- a/gfx/layers/d3d9/LayerManagerD3D9.cpp
+++ b/gfx/layers/d3d9/LayerManagerD3D9.cpp
@@ -38,182 +38,61 @@
 #include "LayerManagerD3D9.h"
 
 #include "ThebesLayerD3D9.h"
 #include "ContainerLayerD3D9.h"
 #include "ImageLayerD3D9.h"
 #include "ColorLayerD3D9.h"
 #include "CanvasLayerD3D9.h"
 
-#include "LayerManagerD3D9Shaders.h"
-
-#include "nsIServiceManager.h"
-#include "nsIConsoleService.h"
-#include "nsPrintfCString.h"
-
 namespace mozilla {
 namespace layers {
 
-struct vertex {
-  float x, y;
-};
-
-IDirect3D9 *LayerManagerD3D9::mD3D9 = NULL;
-
-typedef IDirect3D9* (WINAPI*Direct3DCreate9Func)(
-  UINT SDKVersion
-);
-
+DeviceManagerD3D9 *LayerManagerD3D9::mDeviceManager = nsnull;
 
 LayerManagerD3D9::LayerManagerD3D9(nsIWidget *aWidget)
 {
     mWidget = aWidget;
     mCurrentCallbackInfo.Callback = NULL;
     mCurrentCallbackInfo.CallbackData = NULL;
 }
 
 LayerManagerD3D9::~LayerManagerD3D9()
 {
-}
+  /* Important to release this first since it also holds a reference to the
+   * device manager
+   */
+  mSwapChain = nsnull;
 
-#define HAS_CAP(a, b) (((a) & (b)) == (b))
-#define LACKS_CAP(a, b) !(((a) & (b)) == (b))
+  if (mDeviceManager) {
+    if (!mDeviceManager->Release()) {
+      mDeviceManager = nsnull;
+    }
+  }
+}
 
 PRBool
 LayerManagerD3D9::Initialize()
 {
-  if (!mD3D9) {
-    Direct3DCreate9Func d3d9create = (Direct3DCreate9Func)
-      GetProcAddress(LoadLibraryW(L"d3d9.dll"), "Direct3DCreate9");
-    if (!d3d9create) {
-      return PR_FALSE;
-    }
+  if (!mDeviceManager) {
+    mDeviceManager = new DeviceManagerD3D9;
 
-    mD3D9 = d3d9create(D3D_SDK_VERSION);
-    if (!mD3D9) {
+    if (!mDeviceManager->Init()) {
+      mDeviceManager = nsnull;
       return PR_FALSE;
     }
   }
 
-  D3DPRESENT_PARAMETERS pp;
-  memset(&pp, 0, sizeof(D3DPRESENT_PARAMETERS));
-
-  pp.BackBufferFormat = D3DFMT_A8R8G8B8;
-  pp.SwapEffect = D3DSWAPEFFECT_COPY;
-  pp.Windowed = TRUE;
-  pp.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT;
-  pp.hDeviceWindow = (HWND)mWidget->GetNativeData(NS_NATIVE_WINDOW);
-
-  HRESULT hr = mD3D9->CreateDevice(D3DADAPTER_DEFAULT,
-                                   D3DDEVTYPE_HAL,
-                                   NULL,
-                                   D3DCREATE_FPU_PRESERVE |
-                                   D3DCREATE_MULTITHREADED |
-                                   D3DCREATE_MIXED_VERTEXPROCESSING,
-                                   &pp,
-                                   getter_AddRefs(mDevice));
-
-  if (FAILED(hr)) {
-    return PR_FALSE;
-  }
-
-  if (!VerifyCaps()) {
-    return PR_FALSE;
-  }
-
-  hr = mDevice->CreateVertexShader((DWORD*)LayerQuadVS,
-                                   getter_AddRefs(mLayerVS));
-
-  if (FAILED(hr)) {
-    return PR_FALSE;
-  }
-
-  hr = mDevice->CreatePixelShader((DWORD*)RGBShaderPS,
-                                  getter_AddRefs(mRGBPS));
-
-  if (FAILED(hr)) {
-    return PR_FALSE;
-  }
-
-  hr = mDevice->CreatePixelShader((DWORD*)YCbCrShaderPS,
-                                  getter_AddRefs(mYCbCrPS));
-
-  if (FAILED(hr)) {
-    return PR_FALSE;
-  }
-
-  hr = mDevice->CreatePixelShader((DWORD*)SolidColorShaderPS,
-                                  getter_AddRefs(mSolidColorPS));
-
-  if (FAILED(hr)) {
-    return PR_FALSE;
-  }
+  mDeviceManager->AddRef();
 
-  hr = mDevice->CreateVertexBuffer(sizeof(vertex) * 4,
-                                   0,
-                                   0,
-                                   D3DPOOL_MANAGED,
-                                   getter_AddRefs(mVB),
-                                   NULL);
-
-  if (FAILED(hr)) {
-    return PR_FALSE;
-  }
-
-  vertex *vertices;
-  hr = mVB->Lock(0, 0, (void**)&vertices, 0);
-  if (FAILED(hr)) {
-    return PR_FALSE;
-  }
-
-  vertices[0].x = vertices[0].y = 0;
-  vertices[1].x = 1; vertices[1].y = 0;
-  vertices[2].x = 0; vertices[2].y = 1;
-  vertices[3].x = 1; vertices[3].y = 1;
-
-  mVB->Unlock();
-
-  hr = mDevice->SetStreamSource(0, mVB, 0, sizeof(vertex));
-  if (FAILED(hr)) {
-    return PR_FALSE;
-  }
+  mSwapChain = mDeviceManager->
+    CreateSwapChain((HWND)mWidget->GetNativeData(NS_NATIVE_WINDOW));
 
-  D3DVERTEXELEMENT9 elements[] = {
-    { 0, 0, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT,
-      D3DDECLUSAGE_POSITION, 0 },
-    D3DDECL_END()
-  };
-
-  mDevice->CreateVertexDeclaration(elements, getter_AddRefs(mVD));
-
-  SetupRenderState();
-
-  nsCOMPtr<nsIConsoleService>
-    console(do_GetService(NS_CONSOLESERVICE_CONTRACTID));
-
-  D3DADAPTER_IDENTIFIER9 identifier;
-  mD3D9->GetAdapterIdentifier(D3DADAPTER_DEFAULT, 0, &identifier);
-
-  if (console) {
-    nsString msg;
-    msg +=
-      NS_LITERAL_STRING("Direct3D 9 LayerManager Initialized Succesfully.\nDriver: ");
-    msg += NS_ConvertUTF8toUTF16(
-      nsDependentCString((const char*)identifier.Driver));
-    msg += NS_LITERAL_STRING("\nDescription: ");
-    msg += NS_ConvertUTF8toUTF16(
-      nsDependentCString((const char*)identifier.Description));
-    msg += NS_LITERAL_STRING("\nVersion: ");
-    msg += NS_ConvertUTF8toUTF16(
-      nsPrintfCString("%d.%d.%d.%d",
-                      HIWORD(identifier.DriverVersion.HighPart),
-                      LOWORD(identifier.DriverVersion.HighPart),
-                      HIWORD(identifier.DriverVersion.LowPart),
-                      LOWORD(identifier.DriverVersion.LowPart)));
-    console->LogStringMessage(msg.get());
+  if (!mSwapChain) {
+    return PR_FALSE;
   }
 
   return PR_TRUE;
 }
 
 void
 LayerManagerD3D9::SetClippingRegion(const nsIntRegion &aClippingRegion)
 {
@@ -294,79 +173,56 @@ LayerManagerD3D9::CreateCanvasLayer()
 already_AddRefed<ImageContainer>
 LayerManagerD3D9::CreateImageContainer()
 {
   nsRefPtr<ImageContainer> container = new ImageContainerD3D9(this);
   return container.forget();
 }
 
 void
-LayerManagerD3D9::SetShaderMode(ShaderMode aMode)
-{
-  switch (aMode) {
-    case RGBLAYER:
-      mDevice->SetVertexShader(mLayerVS);
-      mDevice->SetPixelShader(mRGBPS);
-      break;
-    case YCBCRLAYER:
-      mDevice->SetVertexShader(mLayerVS);
-      mDevice->SetPixelShader(mYCbCrPS);
-      break;
-    case SOLIDCOLORLAYER:
-      mDevice->SetVertexShader(mLayerVS);
-      mDevice->SetPixelShader(mSolidColorPS);
-      break;
-  }
-}
-
-void
 LayerManagerD3D9::Render()
 {
-  if (!SetupBackBuffer()) {
+  if (!mSwapChain->PrepareForRendering()) {
     return;
   }
+  deviceManager()->SetupRenderState();
+
   SetupPipeline();
   nsIntRect rect;
   mWidget->GetClientBounds(rect);
 
-  mDevice->Clear(0, NULL, D3DCLEAR_TARGET, 0xffffffff, 0, 0);
+  device()->Clear(0, NULL, D3DCLEAR_TARGET, 0x00000000, 0, 0);
 
-  mDevice->BeginScene();
+  device()->BeginScene();
 
   if (mRootLayer) {
     const nsIntRect *clipRect = mRootLayer->GetLayer()->GetClipRect();
     RECT r;
     if (clipRect) {
       r.left = (LONG)clipRect->x;
       r.top = (LONG)clipRect->y;
       r.right = (LONG)(clipRect->x + clipRect->width);
       r.bottom = (LONG)(clipRect->y + clipRect->height);
     } else {
       r.left = r.top = 0;
       r.right = rect.width;
       r.bottom = rect.height;
     }
-    mDevice->SetScissorRect(&r);
+    device()->SetScissorRect(&r);
 
     mRootLayer->RenderLayer();
   }
 
-  mDevice->EndScene();
+  device()->EndScene();
 
   if (!mTarget) {
     const nsIntRect *r;
     for (nsIntRegionRectIterator iter(mClippingRegion);
          (r = iter.Next()) != nsnull;) {
-      RECT rect;
-      rect.left = r->x;
-      rect.top = r->y;
-      rect.right = r->XMost();
-      rect.bottom = r->YMost();
-
-      mDevice->Present(&rect, &rect, NULL, NULL);
+      mSwapChain->Present(*r);
     }
   } else {
     PaintToTarget();
   }
 }
 
 void
 LayerManagerD3D9::SetupPipeline()
@@ -382,186 +238,54 @@ LayerManagerD3D9::SetupPipeline()
   memset(&viewMatrix, 0, sizeof(viewMatrix));
   viewMatrix[0][0] = 2.0f / rect.width;
   viewMatrix[1][1] = -2.0f / rect.height;
   viewMatrix[2][2] = 1.0f;
   viewMatrix[3][0] = -1.0f;
   viewMatrix[3][1] = 1.0f;
   viewMatrix[3][3] = 1.0f;
 
-  HRESULT hr = mDevice->SetVertexShaderConstantF(8, &viewMatrix[0][0], 4);
+  HRESULT hr = device()->SetVertexShaderConstantF(8, &viewMatrix[0][0], 4);
 
   if (FAILED(hr)) {
     NS_WARNING("Failed to set projection shader constant!");
   }
 }
 
-PRBool
-LayerManagerD3D9::SetupBackBuffer()
-{
-  nsRefPtr<IDirect3DSurface9> backBuffer;
-  mDevice->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO,
-                         getter_AddRefs(backBuffer));
-
-  D3DSURFACE_DESC desc;
-  nsIntRect rect;
-  mWidget->GetClientBounds(rect);
-  backBuffer->GetDesc(&desc);
-
-  HRESULT hr = mDevice->TestCooperativeLevel();
-
-  /* The device is lost or something else is wrong, failure */
-  if (FAILED(hr) && hr != D3DERR_DEVICENOTRESET) {
-    return PR_FALSE;
-  }
-
-  /*
-   * If the backbuffer is the right size, and the device is not lost, we can
-   * safely render without doing anything.
-   */
-  if ((desc.Width == rect.width && desc.Height == rect.height) &&
-      SUCCEEDED(hr)) {
-    return PR_TRUE;
-  }
-
-  /*
-   * Our device is lost or our backbuffer needs resizing, start by clearing
-   * out all D3DPOOL_DEFAULT surfaces.
-   */
-  for(unsigned int i = 0; i < mThebesLayers.Length(); i++) {
-    mThebesLayers[i]->CleanResources();
-  }
-
-  backBuffer = NULL;
-
-  D3DPRESENT_PARAMETERS pp;
-  memset(&pp, 0, sizeof(D3DPRESENT_PARAMETERS));
-
-  pp.BackBufferFormat = D3DFMT_A8R8G8B8;
-  pp.SwapEffect = D3DSWAPEFFECT_COPY;
-  pp.Windowed = TRUE;
-  pp.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT;
-  pp.hDeviceWindow = (HWND)mWidget->GetNativeData(NS_NATIVE_WINDOW);
-
-  hr = mDevice->Reset(&pp);
-  if (FAILED(hr)) {
-    return PR_FALSE;
-  }
-
-  SetupRenderState();
-
-  return PR_TRUE;
-}
-
 void
 LayerManagerD3D9::PaintToTarget()
 {
   nsRefPtr<IDirect3DSurface9> backBuff;
   nsRefPtr<IDirect3DSurface9> destSurf;
-  mDevice->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO,
+  device()->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO,
                          getter_AddRefs(backBuff));
 
   D3DSURFACE_DESC desc;
   backBuff->GetDesc(&desc);
 
-  mDevice->CreateOffscreenPlainSurface(desc.Width, desc.Height,
+  device()->CreateOffscreenPlainSurface(desc.Width, desc.Height,
                                        D3DFMT_A8R8G8B8, D3DPOOL_SYSTEMMEM,
                                        getter_AddRefs(destSurf), NULL);
 
-  mDevice->GetRenderTargetData(backBuff, destSurf);
+  device()->GetRenderTargetData(backBuff, destSurf);
 
   D3DLOCKED_RECT rect;
   destSurf->LockRect(&rect, NULL, D3DLOCK_READONLY);
 
   nsRefPtr<gfxImageSurface> imageSurface =
     new gfxImageSurface((unsigned char*)rect.pBits,
                         gfxIntSize(desc.Width, desc.Height),
                         rect.Pitch,
                         gfxASurface::ImageFormatARGB32);
 
   mTarget->SetSource(imageSurface);
   mTarget->SetOperator(gfxContext::OPERATOR_OVER);
   mTarget->Paint();
   destSurf->UnlockRect();
 }
 
-void
-LayerManagerD3D9::SetupRenderState()
-{
-  mDevice->SetStreamSource(0, mVB, 0, sizeof(vertex));
-  mDevice->SetVertexDeclaration(mVD);
-  mDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
-  mDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
-  mDevice->SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_ADD);
-  mDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
-  mDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE);
-  mDevice->SetRenderState(D3DRS_SCISSORTESTENABLE, TRUE);
-  mDevice->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
-  mDevice->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
-  mDevice->SetSamplerState(1, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
-  mDevice->SetSamplerState(1, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
-  mDevice->SetSamplerState(2, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
-  mDevice->SetSamplerState(2, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
-}
-
-PRBool
-LayerManagerD3D9::VerifyCaps()
-{
-  D3DCAPS9 caps;
-  HRESULT hr = mDevice->GetDeviceCaps(&caps);
-
-  if (FAILED(hr)) {
-    return PR_FALSE;
-  }
-
-  if (LACKS_CAP(caps.DevCaps, D3DDEVCAPS_TEXTUREVIDEOMEMORY)) {
-    return PR_FALSE;
-  }
-
-  if (LACKS_CAP(caps.PrimitiveMiscCaps, D3DPMISCCAPS_CULLNONE)) {
-    return PR_FALSE;
-  }
-
-  if (LACKS_CAP(caps.SrcBlendCaps, D3DPBLENDCAPS_ONE) ||
-      LACKS_CAP(caps.SrcBlendCaps, D3DBLEND_SRCALPHA) ||
-      LACKS_CAP(caps.DestBlendCaps, D3DPBLENDCAPS_INVSRCALPHA)) {
-    return PR_FALSE;
-  }
-
-  if (LACKS_CAP(caps.RasterCaps, D3DPRASTERCAPS_SCISSORTEST)) {
-    return PR_FALSE;
-  }
-
-  if (LACKS_CAP(caps.TextureCaps, D3DPTEXTURECAPS_ALPHA) ||
-      HAS_CAP(caps.TextureCaps, D3DPTEXTURECAPS_SQUAREONLY) ||
-      (HAS_CAP(caps.TextureCaps, D3DPTEXTURECAPS_POW2) &&
-       LACKS_CAP(caps.TextureCaps, D3DPTEXTURECAPS_NONPOW2CONDITIONAL))) {
-    return PR_FALSE;
-  }
-
-  if (LACKS_CAP(caps.TextureFilterCaps, D3DPTFILTERCAPS_MAGFLINEAR) ||
-      LACKS_CAP(caps.TextureFilterCaps, D3DPTFILTERCAPS_MINFLINEAR)) {
-    return PR_FALSE;
-  }
-
-  if (LACKS_CAP(caps.TextureAddressCaps, D3DPTADDRESSCAPS_CLAMP)) {
-    return PR_FALSE;
-  }
-
-  if (caps.MaxTextureHeight < 4096 ||
-      caps.MaxTextureWidth < 4096) {
-    return PR_FALSE;
-  }
-
-  if ((caps.PixelShaderVersion & 0xffff) < 0x200 ||
-      (caps.VertexShaderVersion & 0xffff) < 0x200) {
-    return PR_FALSE;
-  }
-  return PR_TRUE;
-}
-
 LayerD3D9::LayerD3D9(LayerManagerD3D9 *aManager)
   : mD3DManager(aManager)
 {
 }
 
 } /* namespace layers */
 } /* namespace mozilla */
--- a/gfx/layers/d3d9/LayerManagerD3D9.h
+++ b/gfx/layers/d3d9/LayerManagerD3D9.h
@@ -41,16 +41,18 @@
 #include "Layers.h"
 
 #include <windows.h>
 #include <d3d9.h>
 
 #include "gfxContext.h"
 #include "nsIWidget.h"
 
+#include "DeviceManagerD3D9.h"
+
 namespace mozilla {
 namespace layers {
 
 class LayerD3D9;
 class ThebesLayerD3D9;
 
 /*
  * This is the LayerManager used for Direct3D 9. For now this will render on
@@ -117,95 +119,62 @@ public:
 
   virtual LayersBackend GetBackendType() { return LAYERS_D3D9; }
 
   /*
    * Helper methods.
    */
   void SetClippingEnabled(PRBool aEnabled);
 
-  IDirect3DDevice9 *device() const { return mDevice; }
+  void SetShaderMode(DeviceManagerD3D9::ShaderMode aMode)
+    { mDeviceManager->SetShaderMode(aMode); }
 
-  enum ShaderMode {
-    RGBLAYER,
-    YCBCRLAYER,
-    SOLIDCOLORLAYER
-  };
-
-  void SetShaderMode(ShaderMode aMode);
-
-  nsTArray<ThebesLayerD3D9*> mThebesLayers;
+  IDirect3DDevice9 *device() const { return mDeviceManager->device(); }
+  DeviceManagerD3D9 *deviceManager() const { return mDeviceManager; }
 
 private:
-  /* Direct3D9 instance */
-  static IDirect3D9 *mD3D9;
+  /* Device manager instance */
+  static DeviceManagerD3D9 *mDeviceManager;
+
+  /* Swap chain associated with this layer manager */
+  nsRefPtr<SwapChainD3D9> mSwapChain;
 
   /* Widget associated with this layer manager */
   nsIWidget *mWidget;
+
   /*
    * Context target, NULL when drawing directly to our swap chain.
    */
   nsRefPtr<gfxContext> mTarget;
 
-  nsRefPtr<IDirect3DDevice9> mDevice;
-
-  /* Vertex shader used for layer quads */
-  nsRefPtr<IDirect3DVertexShader9> mLayerVS;
-
-  /* Pixel shader used for RGB textures */
-  nsRefPtr<IDirect3DPixelShader9> mRGBPS;
-
-  /* Pixel shader used for RGB textures */
-  nsRefPtr<IDirect3DPixelShader9> mYCbCrPS;
-
-  /* Pixel shader used for solid colors */
-  nsRefPtr<IDirect3DPixelShader9> mSolidColorPS;
-
-  /* Vertex buffer containing our basic vertex structure */
-  nsRefPtr<IDirect3DVertexBuffer9> mVB;
-
-  /* Our vertex declaration */
-  nsRefPtr<IDirect3DVertexDeclaration9> mVD;
-
   /* Current root layer. */
   LayerD3D9 *mRootLayer;
 
   /* Callback info for current transaction */
   CallbackInfo mCurrentCallbackInfo;
 
   /*
    * Region we're clipping our current drawing to.
    */
   nsIntRegion mClippingRegion;
+
   /*
    * Render the current layer tree to the active target.
    */
   void Render();
+
   /*
    * Setup the pipeline.
    */
   void SetupPipeline();
-  /*
-   * Setup the backbuffer.
-   *
-   * \return PR_TRUE if setup was succesful
-   */
-  PRBool SetupBackBuffer();
-  /*
-   * Setup the render state for the surface.
-   */
-  void SetupRenderState();
+
   /*
    * Copies the content of our backbuffer to the set transaction target.
    */
   void PaintToTarget();
-  /*
-   * Verifies all required device capabilities are present.
-   */
-  PRBool VerifyCaps();
 
 };
 
 /*
  * General information and tree management for OGL layers.
  */
 class LayerD3D9
 {
--- a/gfx/layers/d3d9/ThebesLayerD3D9.cpp
+++ b/gfx/layers/d3d9/ThebesLayerD3D9.cpp
@@ -34,16 +34,19 @@
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "ThebesLayerD3D9.h"
 #include "gfxPlatform.h"
 
 #include "gfxWindowsPlatform.h"
+#ifdef CAIRO_HAS_D2D_SURFACE
+#include "gfxD2DSurface.h"
+#endif
 
 namespace mozilla {
 namespace layers {
 
 // Returns true if it's OK to save the contents of aLayer in an
 // opaque surface (a surface without an alpha channel).
 // If we can use a surface without an alpha channel, we should, because
 // it will often make painting of antialiased text faster and higher
@@ -64,22 +67,22 @@ UseOpaqueSurface(Layer* aLayer)
          UseOpaqueSurface(parent);
 }
 
 ThebesLayerD3D9::ThebesLayerD3D9(LayerManagerD3D9 *aManager)
   : ThebesLayer(aManager, NULL)
   , LayerD3D9(aManager)
 {
   mImplData = static_cast<LayerD3D9*>(this);
-  aManager->mThebesLayers.AppendElement(this);
+  aManager->deviceManager()->mThebesLayers.AppendElement(this);
 }
 
 ThebesLayerD3D9::~ThebesLayerD3D9()
 {
-  mD3DManager->mThebesLayers.RemoveElement(this);
+  mD3DManager->deviceManager()->mThebesLayers.RemoveElement(this);
 }
 
 /**
  * Retention threshold - amount of pixels intersection required to enable
  * layer content retention. This is a guesstimate. Profiling could be done to
  * figure out the optimal threshold.
  */
 #define RETENTION_THRESHOLD 16384
@@ -96,35 +99,34 @@ ThebesLayerD3D9::SetVisibleRegion(const 
 
   if (!mTexture) {
     // If we don't need to retain content initialize lazily. This is good also
     // because we might get mIsOpaqueSurface set later than the first call to
     // SetVisibleRegion.
     return;
   }
 
-  D3DFORMAT fmt = UseOpaqueSurface(this) ? D3DFMT_X8R8G8B8 : D3DFMT_A8R8G8B8;
+  D3DFORMAT fmt = (UseOpaqueSurface(this) && !mD2DSurface) ?
+                    D3DFMT_X8R8G8B8 : D3DFMT_A8R8G8B8;
 
   D3DSURFACE_DESC desc;
   mTexture->GetLevelDesc(0, &desc);
 
   if (fmt != desc.Format) {
     // The new format isn't compatible with the old texture, toss out the old
     // texture.
     mTexture = nsnull;
   }
 
   nsRefPtr<IDirect3DTexture9> oldTexture = mTexture;
 
   nsIntRect oldBounds = oldVisibleRegion.GetBounds();
   nsIntRect newBounds = mVisibleRegion.GetBounds();
-  
-  device()->CreateTexture(newBounds.width, newBounds.height, 1,
-                          D3DUSAGE_RENDERTARGET, fmt,
-                          D3DPOOL_DEFAULT, getter_AddRefs(mTexture), NULL);
+
+  CreateNewTexture(gfxIntSize(newBounds.width, newBounds.height));
 
   // Old visible region will become the region that is covered by both the
   // old and the new visible region.
   oldVisibleRegion.And(oldVisibleRegion, mVisibleRegion);
   // No point in retaining parts which were not valid.
   oldVisibleRegion.And(oldVisibleRegion, mValidRegion);
 
   nsIntRect largeRect = oldVisibleRegion.GetLargestRectangle();
@@ -186,133 +188,47 @@ ThebesLayerD3D9::InvalidateRegion(const 
 }
 
 void
 ThebesLayerD3D9::RenderLayer()
 {
   if (mVisibleRegion.IsEmpty()) {
     return;
   }
-  HRESULT hr;
 
   nsIntRect visibleRect = mVisibleRegion.GetBounds();
 
   // We differentiate between these formats since D3D9 will only allow us to
   // call GetDC on an opaque surface.
-  D3DFORMAT fmt = UseOpaqueSurface(this) ? D3DFMT_X8R8G8B8 : D3DFMT_A8R8G8B8;
+  D3DFORMAT fmt = (UseOpaqueSurface(this) && !mD2DSurface) ?
+                    D3DFMT_X8R8G8B8 : D3DFMT_A8R8G8B8;
+
   if (mTexture) {
     D3DSURFACE_DESC desc;
     mTexture->GetLevelDesc(0, &desc);
 
     if (fmt != desc.Format) {
       // The new format isn't compatible with the old texture, toss out the old
       // texture.
       mTexture = nsnull;
       mValidRegion.SetEmpty();
     }
   }
 
   if (!mTexture) {
-    device()->CreateTexture(visibleRect.width, visibleRect.height, 1,
-                            D3DUSAGE_RENDERTARGET, fmt,
-                            D3DPOOL_DEFAULT, getter_AddRefs(mTexture), NULL);
+    CreateNewTexture(gfxIntSize(visibleRect.width, visibleRect.height));
     mValidRegion.SetEmpty();
   }
 
   if (!mValidRegion.IsEqual(mVisibleRegion)) {
     nsIntRegion region;
     region.Sub(mVisibleRegion, mValidRegion);
-    nsIntRect bounds = region.GetBounds();
-
-    gfxASurface::gfxImageFormat imageFormat = gfxASurface::ImageFormatARGB32;
-    nsRefPtr<gfxASurface> destinationSurface;
-    nsRefPtr<gfxContext> context;
-
-    nsRefPtr<IDirect3DTexture9> tmpTexture;
-    device()->CreateTexture(bounds.width, bounds.height, 1,
-                            0, fmt,
-                            D3DPOOL_SYSTEMMEM, getter_AddRefs(tmpTexture), NULL);
-
-    nsRefPtr<IDirect3DSurface9> surf;
-    HDC dc;
-    if (UseOpaqueSurface(this)) {
-      hr = tmpTexture->GetSurfaceLevel(0, getter_AddRefs(surf));
-
-      if (FAILED(hr)) {
-        // Uh-oh, bail.
-        NS_WARNING("Failed to get texture surface level.");
-        return;
-      }
-
-      hr = surf->GetDC(&dc);
-
-      if (FAILED(hr)) {
-        NS_WARNING("Failed to get device context for texture surface.");
-        return;
-      }
-
-      destinationSurface = new gfxWindowsSurface(dc);
-    } else {
-      // XXX - We may consider retaining a SYSTEMMEM texture texture the size
-      // of our DEFAULT texture and then use UpdateTexture and add dirty rects
-      // to update in a single call.
-      destinationSurface =
-        gfxPlatform::GetPlatform()->
-          CreateOffscreenSurface(gfxIntSize(bounds.width,
-                                            bounds.height),
-                                 imageFormat);
-    }
 
-    context = new gfxContext(destinationSurface);
-    context->Translate(gfxPoint(-bounds.x, -bounds.y));
-    LayerManagerD3D9::CallbackInfo cbInfo = mD3DManager->GetCallbackInfo();
-    cbInfo.Callback(this, context, region, nsIntRegion(), cbInfo.CallbackData);
-
-    if (UseOpaqueSurface(this)) {
-      surf->ReleaseDC(dc);
-    } else {
-      D3DLOCKED_RECT r;
-      tmpTexture->LockRect(0, &r, NULL, 0);
-
-      nsRefPtr<gfxImageSurface> imgSurface =
-        new gfxImageSurface((unsigned char *)r.pBits,
-                            gfxIntSize(bounds.width,
-                                       bounds.height),
-                            r.Pitch,
-                            imageFormat);
-
-      context = new gfxContext(imgSurface);
-      context->SetSource(destinationSurface);
-      context->SetOperator(gfxContext::OPERATOR_SOURCE);
-      context->Paint();
+    DrawRegion(region);
 
-      imgSurface = NULL;
-
-      tmpTexture->UnlockRect(0);
-    }
-
-    nsRefPtr<IDirect3DSurface9> srcSurface;
-    nsRefPtr<IDirect3DSurface9> dstSurface;
-
-    mTexture->GetSurfaceLevel(0, getter_AddRefs(dstSurface));
-    tmpTexture->GetSurfaceLevel(0, getter_AddRefs(srcSurface));
-
-    nsIntRegionRectIterator iter(region);
-    const nsIntRect *iterRect;
-    while ((iterRect = iter.Next())) {
-      RECT rect;
-      rect.left = iterRect->x - bounds.x;
-      rect.top = iterRect->y - bounds.y;
-      rect.right = rect.left + iterRect->width;
-      rect.bottom = rect.top + iterRect->height;
-      POINT point;
-      point.x = iterRect->x - visibleRect.x;
-      point.y = iterRect->y - visibleRect.y;
-      device()->UpdateSurface(srcSurface, &rect, dstSurface, &point);
-    }
     mValidRegion = mVisibleRegion;
   }
 
   float quadTransform[4][4];
   /*
    * Matrix to transform the <0.0,0.0>, <1.0,1.0> quad to the correct position
    * and size. To get pixel perfect mapping we offset the quad half a pixel
    * to the top-left.
@@ -333,17 +249,17 @@ ThebesLayerD3D9::RenderLayer()
   float opacity[4];
   /*
    * We always upload a 4 component float, but the shader will use only the
    * first component since it's declared as a 'float'.
    */
   opacity[0] = GetOpacity();
   device()->SetPixelShaderConstantF(0, opacity, 1);
 
-  mD3DManager->SetShaderMode(LayerManagerD3D9::RGBLAYER);
+  mD3DManager->SetShaderMode(DeviceManagerD3D9::RGBLAYER);
 
   device()->SetTexture(0, mTexture);
   device()->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);
 }
 
 void
 ThebesLayerD3D9::CleanResources()
 {
@@ -357,10 +273,173 @@ ThebesLayerD3D9::GetLayer()
 }
 
 PRBool
 ThebesLayerD3D9::IsEmpty()
 {
   return !mTexture;
 }
 
+void
+ThebesLayerD3D9::DrawRegion(const nsIntRegion &aRegion)
+{
+  HRESULT hr;
+  nsIntRect visibleRect = mVisibleRegion.GetBounds();
+  nsRefPtr<gfxContext> context;
+
+#ifdef CAIRO_HAS_D2D_SURFACE
+  if (mD2DSurface) {
+    context = new gfxContext(mD2DSurface);
+    nsIntRegionRectIterator iter(aRegion);
+    context->Translate(gfxPoint(-visibleRect.x, -visibleRect.y));
+    context->NewPath();
+    const nsIntRect *iterRect;
+    while ((iterRect = iter.Next())) {
+      context->Rectangle(gfxRect(iterRect->x, iterRect->y, iterRect->width, iterRect->height));      
+    }
+    context->Clip();
+    if (mD2DSurface->GetContentType() != gfxASurface::CONTENT_COLOR) {
+      context->SetOperator(gfxContext::OPERATOR_CLEAR);
+      context->Paint();
+      context->SetOperator(gfxContext::OPERATOR_OVER);
+    }
+    LayerManagerD3D9::CallbackInfo cbInfo = mD3DManager->GetCallbackInfo();
+    cbInfo.Callback(this, context, aRegion, nsIntRegion(), cbInfo.CallbackData);
+    mD2DSurface->Flush();
+
+    // XXX - This call is quite expensive, we may want to consider doing our
+    // drawing in a seperate 'validation' iteration. And then flushing once for
+    // all the D2D surfaces we might have drawn, before doing our D3D9 rendering
+    // loop.
+    cairo_d2d_finish_device(gfxWindowsPlatform::GetPlatform()->GetD2DDevice());
+    return;
+  }
+#endif
+
+  D3DFORMAT fmt = UseOpaqueSurface(this) ? D3DFMT_X8R8G8B8 : D3DFMT_A8R8G8B8;
+  nsIntRect bounds = aRegion.GetBounds();
+
+  gfxASurface::gfxImageFormat imageFormat = gfxASurface::ImageFormatARGB32;
+  nsRefPtr<gfxASurface> destinationSurface;
+
+  nsRefPtr<IDirect3DTexture9> tmpTexture;
+  device()->CreateTexture(bounds.width, bounds.height, 1,
+                          0, fmt,
+                          D3DPOOL_SYSTEMMEM, getter_AddRefs(tmpTexture), NULL);
+
+  nsRefPtr<IDirect3DSurface9> surf;
+  HDC dc;
+  if (UseOpaqueSurface(this)) {
+    hr = tmpTexture->GetSurfaceLevel(0, getter_AddRefs(surf));
+
+    if (FAILED(hr)) {
+      // Uh-oh, bail.
+      NS_WARNING("Failed to get texture surface level.");
+      return;
+    }
+
+    hr = surf->GetDC(&dc);
+
+    if (FAILED(hr)) {
+      NS_WARNING("Failed to get device context for texture surface.");
+      return;
+    }
+
+    destinationSurface = new gfxWindowsSurface(dc);
+  } else {
+    // XXX - We may consider retaining a SYSTEMMEM texture texture the size
+    // of our DEFAULT texture and then use UpdateTexture and add dirty rects
+    // to update in a single call.
+    destinationSurface =
+    gfxPlatform::GetPlatform()->
+      CreateOffscreenSurface(gfxIntSize(bounds.width,
+                                        bounds.height),
+                             imageFormat);
+  }
+
+  context = new gfxContext(destinationSurface);
+  context->Translate(gfxPoint(-bounds.x, -bounds.y));
+  LayerManagerD3D9::CallbackInfo cbInfo = mD3DManager->GetCallbackInfo();
+  cbInfo.Callback(this, context, aRegion, nsIntRegion(), cbInfo.CallbackData);
+
+  if (UseOpaqueSurface(this)) {
+    surf->ReleaseDC(dc);
+  } else {
+    D3DLOCKED_RECT r;
+    tmpTexture->LockRect(0, &r, NULL, 0);
+
+    nsRefPtr<gfxImageSurface> imgSurface =
+    new gfxImageSurface((unsigned char *)r.pBits,
+                        gfxIntSize(bounds.width,
+                                   bounds.height),
+                        r.Pitch,
+                        imageFormat);
+
+    context = new gfxContext(imgSurface);
+    context->SetSource(destinationSurface);
+    context->SetOperator(gfxContext::OPERATOR_SOURCE);
+    context->Paint();
+
+    imgSurface = NULL;
+
+    tmpTexture->UnlockRect(0);
+  }
+
+  nsRefPtr<IDirect3DSurface9> srcSurface;
+  nsRefPtr<IDirect3DSurface9> dstSurface;
+
+  mTexture->GetSurfaceLevel(0, getter_AddRefs(dstSurface));
+  tmpTexture->GetSurfaceLevel(0, getter_AddRefs(srcSurface));
+
+  nsIntRegionRectIterator iter(aRegion);
+  const nsIntRect *iterRect;
+  while ((iterRect = iter.Next())) {
+    RECT rect;
+    rect.left = iterRect->x - bounds.x;
+    rect.top = iterRect->y - bounds.y;
+    rect.right = rect.left + iterRect->width;
+    rect.bottom = rect.top + iterRect->height;
+    POINT point;
+    point.x = iterRect->x - visibleRect.x;
+    point.y = iterRect->y - visibleRect.y;
+    device()->UpdateSurface(srcSurface, &rect, dstSurface, &point);
+  }
+}
+
+void
+ThebesLayerD3D9::CreateNewTexture(const gfxIntSize &aSize)
+{
+  if (aSize.width == 0 | aSize.height == 0) {
+    // Nothing to do.
+    return;
+  }
+
+  mTexture = nsnull;
+#ifdef CAIRO_HAS_D2D_SURFACE
+  if (gfxWindowsPlatform::GetPlatform()->GetRenderMode() ==
+      gfxWindowsPlatform::RENDER_DIRECT2D) {
+        if (mD3DManager->deviceManager()->IsD3D9Ex()) {
+          // We should have D3D9Ex where we have D2D.
+          HANDLE sharedHandle = 0;
+          device()->CreateTexture(aSize.width, aSize.height, 1,
+                                  D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8,
+                                  D3DPOOL_DEFAULT, getter_AddRefs(mTexture), &sharedHandle);
+
+          mD2DSurface = new gfxD2DSurface(sharedHandle, UseOpaqueSurface(this) ?
+            gfxASurface::CONTENT_COLOR : gfxASurface::CONTENT_COLOR_ALPHA);
+
+          // If there's an error, go on and do what we always do.
+          if (mD2DSurface->CairoStatus()) {
+            mD2DSurface = nsnull;
+            mTexture = nsnull;
+          }
+        }
+  }
+#endif
+  if (!mTexture) {
+    device()->CreateTexture(aSize.width, aSize.height, 1,
+                            D3DUSAGE_RENDERTARGET, UseOpaqueSurface(this) ? D3DFMT_X8R8G8B8 : D3DFMT_A8R8G8B8,
+                            D3DPOOL_DEFAULT, getter_AddRefs(mTexture), NULL);
+  }
+}
+
 } /* namespace layers */
 } /* namespace mozilla */
--- a/gfx/layers/d3d9/ThebesLayerD3D9.h
+++ b/gfx/layers/d3d9/ThebesLayerD3D9.h
@@ -37,17 +37,16 @@
 
 #ifndef GFX_THEBESLAYERD3D9_H
 #define GFX_THEBESLAYERD3D9_H
 
 #include "Layers.h"
 #include "LayerManagerD3D9.h"
 #include "gfxImageSurface.h"
 
-
 namespace mozilla {
 namespace layers {
 
 class ThebesLayerD3D9 : public ThebesLayer,
                         public LayerD3D9
 {
 public:
   ThebesLayerD3D9(LayerManagerD3D9 *aManager);
@@ -65,13 +64,22 @@ public:
   virtual void RenderLayer();
   virtual void CleanResources();
 
 private:
   /*
    * D3D9 texture
    */
   nsRefPtr<IDirect3DTexture9> mTexture;
+
+  /* This contains the D2D surface if we have one */
+  nsRefPtr<gfxASurface> mD2DSurface;
+
+  /* Have a region of our layer drawn */
+  void DrawRegion(const nsIntRegion &aRegion);
+
+  /* Create a new texture */
+  void CreateNewTexture(const gfxIntSize &aSize);
 };
 
 } /* layers */
 } /* mozilla */
 #endif /* GFX_THEBESLAYERD3D9_H */
--- a/gfx/thebes/gfxD2DSurface.cpp
+++ b/gfx/thebes/gfxD2DSurface.cpp
@@ -31,31 +31,46 @@
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "gfxD2DSurface.h"
 #include "cairo.h"
 #include "cairo-win32.h"
+#include "gfxWindowsPlatform.h"
 
 gfxD2DSurface::gfxD2DSurface(HWND aWnd, gfxContentType aContent)
 {
-    Init(cairo_d2d_surface_create_for_hwnd(aWnd, (cairo_content_t)aContent));
+    Init(cairo_d2d_surface_create_for_hwnd(
+        gfxWindowsPlatform::GetPlatform()->GetD2DDevice(),
+        aWnd,
+        (cairo_content_t)aContent));
+}
+
+gfxD2DSurface::gfxD2DSurface(HANDLE handle, gfxContentType aContent)
+{
+    Init(cairo_d2d_surface_create_for_handle(
+        gfxWindowsPlatform::GetPlatform()->GetD2DDevice(),
+        handle,
+	(cairo_content_t)aContent));
 }
 
 gfxD2DSurface::gfxD2DSurface(cairo_surface_t *csurf)
 {
     Init(csurf, PR_TRUE);
 }
 
 gfxD2DSurface::gfxD2DSurface(const gfxIntSize& size,
                              gfxImageFormat imageFormat)
 {
-    Init(cairo_d2d_surface_create((cairo_format_t)imageFormat, size.width, size.height));
+    Init(cairo_d2d_surface_create(
+        gfxWindowsPlatform::GetPlatform()->GetD2DDevice(),
+        (cairo_format_t)imageFormat,
+        size.width, size.height));
 }
 
 gfxD2DSurface::~gfxD2DSurface()
 {
 }
 
 void
 gfxD2DSurface::Present()
--- a/gfx/thebes/gfxD2DSurface.h
+++ b/gfx/thebes/gfxD2DSurface.h
@@ -46,16 +46,17 @@ class THEBES_API gfxD2DSurface : public 
 public:
 
     gfxD2DSurface(HWND wnd,
                   gfxContentType aContent);
 
     gfxD2DSurface(const gfxIntSize& size,
                   gfxImageFormat imageFormat = ImageFormatRGB24);
 
+    gfxD2DSurface(HANDLE handle, gfxContentType aContent);
 
     gfxD2DSurface(cairo_surface_t *csurf);
 
     virtual ~gfxD2DSurface();
 
 
     void Present();
     void Scroll(const nsIntPoint &aDelta, const nsIntRect &aClip);
--- a/gfx/thebes/gfxWindowsPlatform.cpp
+++ b/gfx/thebes/gfxWindowsPlatform.cpp
@@ -165,16 +165,17 @@ gfxWindowsPlatform::gfxWindowsPlatform()
 #else
     mRenderMode = RENDER_GDI;
 #endif
 
     nsCOMPtr<nsIPrefBranch2> pref = do_GetService(NS_PREFSERVICE_CONTRACTID);
 
 #ifdef CAIRO_HAS_D2D_SURFACE
     NS_RegisterMemoryReporter(new D2DCacheReporter());
+    mD2DDevice = NULL;
 #endif
 #ifdef CAIRO_HAS_DWRITE_FONT
     nsresult rv;
     PRBool useDirectWrite = PR_FALSE;
 
     rv = pref->GetBoolPref(
         "gfx.font_rendering.directwrite.enabled", &useDirectWrite);
     if (NS_FAILED(rv)) {
@@ -208,17 +209,18 @@ gfxWindowsPlatform::gfxWindowsPlatform()
 #ifndef CAIRO_HAS_DDRAW_SURFACE
             if (rmode == RENDER_DDRAW || rmode == RENDER_DDRAW_GL)
                 rmode = RENDER_IMAGE_STRETCH24;
 #endif
             if (rmode == RENDER_DIRECT2D) {
 #ifndef CAIRO_HAS_D2D_SURFACE
                 return;
 #else
-                if (!cairo_d2d_has_support()) {
+		mD2DDevice = cairo_d2d_create_device();
+                if (!mD2DDevice) {
                     return;
                 }
 #ifdef CAIRO_HAS_DWRITE_FONT
                 if (!GetDWriteFactory()) {
 #endif
                     // D2D doesn't work without DirectWrite.
                     return;
 #ifdef CAIRO_HAS_DWRITE_FONT
@@ -230,16 +232,21 @@ gfxWindowsPlatform::gfxWindowsPlatform()
         }
     }
 }
 
 gfxWindowsPlatform::~gfxWindowsPlatform()
 {
     // not calling FT_Done_FreeType because cairo may still hold references to
     // these FT_Faces.  See bug 458169.
+#ifdef CAIRO_HAS_D2D_SURFACE
+    if (mD2DDevice) {
+	cairo_release_device(mD2DDevice);
+    }
+#endif
 }
 
 gfxPlatformFontList*
 gfxWindowsPlatform::CreatePlatformFontList()
 {
 #ifdef MOZ_FT2_FONTS
     return new gfxFT2FontList();
 #else
--- a/gfx/thebes/gfxWindowsPlatform.h
+++ b/gfx/thebes/gfxWindowsPlatform.h
@@ -209,16 +209,19 @@ public:
 
     static PRInt32 WindowsOSVersion();
 
     virtual void FontsPrefsChanged(nsIPrefBranch *aPrefBranch, const char *aPref);
 
 #ifdef CAIRO_HAS_DWRITE_FONT
     IDWriteFactory *GetDWriteFactory() { return mDWriteFactory; }
 #endif
+#ifdef CAIRO_HAS_D2D_SURFACE
+    cairo_device_t *GetD2DDevice() { return mD2DDevice; }
+#endif
 
 #ifdef MOZ_FT2_FONTS
     FT_Library GetFTLibrary();
 #endif
 
 protected:
     void InitDisplayCaps();
 
@@ -228,16 +231,19 @@ protected:
     PRBool mUseClearTypeAlways;
 
 private:
     void Init();
 
 #ifdef CAIRO_HAS_DWRITE_FONT
     nsRefPtr<IDWriteFactory> mDWriteFactory;
 #endif
+#ifdef CAIRO_HAS_D2D_SURFACE
+    cairo_device_t *mD2DDevice;
+#endif
 
     virtual qcms_profile* GetPlatformCMSOutputProfile();
 
     // TODO: unify this with mPrefFonts (NB: holds families, not fonts) in gfxPlatformFontList
     nsDataHashtable<nsCStringHashKey, nsTArray<nsRefPtr<gfxFontEntry> > > mPrefFonts;
 };
 
 #endif /* GFX_WINDOWS_PLATFORM_H */
--- a/ipc/glue/GeckoChildProcessHost.cpp
+++ b/ipc/glue/GeckoChildProcessHost.cpp
@@ -126,38 +126,54 @@ void GeckoChildProcessHost::InitWindowsG
     } else {
       mGroupId.AssignLiteral("-");
     }
   }
 }
 #endif
 
 bool
-GeckoChildProcessHost::SyncLaunch(std::vector<std::string> aExtraOpts)
+GeckoChildProcessHost::SyncLaunch(std::vector<std::string> aExtraOpts, int aTimeoutMs)
 {
 #ifdef XP_WIN
   InitWindowsGroupID();
 #endif
 
+  PRIntervalTime timeoutTicks = (aTimeoutMs > 0) ? 
+    PR_MillisecondsToInterval(aTimeoutMs) : PR_INTERVAL_NO_TIMEOUT;
   MessageLoop* ioLoop = XRE_GetIOMessageLoop();
   NS_ASSERTION(MessageLoop::current() != ioLoop, "sync launch from the IO thread NYI");
 
   ioLoop->PostTask(FROM_HERE,
                    NewRunnableMethod(this,
                                      &GeckoChildProcessHost::PerformAsyncLaunch,
                                      aExtraOpts));
-
   // NB: this uses a different mechanism than the chromium parent
   // class.
   MonitorAutoEnter mon(mMonitor);
+  PRIntervalTime waitStart = PR_IntervalNow();
+  PRIntervalTime current;
+
+  // We'll receive several notifications, we need to exit when we
+  // have either successfully launched or have timed out.
   while (!mLaunched) {
-    mon.Wait();
+    mon.Wait(timeoutTicks);
+
+    if (timeoutTicks != PR_INTERVAL_NO_TIMEOUT) {
+      current = PR_IntervalNow();
+      PRIntervalTime elapsed = current - waitStart;
+      if (elapsed > timeoutTicks) {
+        break;
+      }
+      timeoutTicks = timeoutTicks - elapsed;
+      waitStart = current;
+    }
   }
 
-  return true;
+  return mLaunched;
 }
 
 bool
 GeckoChildProcessHost::AsyncLaunch(std::vector<std::string> aExtraOpts)
 {
 #ifdef XP_WIN
   InitWindowsGroupID();
 #endif
--- a/ipc/glue/GeckoChildProcessHost.h
+++ b/ipc/glue/GeckoChildProcessHost.h
@@ -59,17 +59,17 @@ protected:
 public:
   typedef base::ProcessHandle ProcessHandle;
 
   GeckoChildProcessHost(GeckoProcessType aProcessType=GeckoProcessType_Default,
                         base::WaitableEventWatcher::Delegate* aDelegate=nsnull);
 
   ~GeckoChildProcessHost();
 
-  bool SyncLaunch(std::vector<std::string> aExtraOpts=std::vector<std::string>());
+  bool SyncLaunch(std::vector<std::string> aExtraOpts=std::vector<std::string>(), int32 timeoutMs=0);
   bool AsyncLaunch(std::vector<std::string> aExtraOpts=std::vector<std::string>());
   bool PerformAsyncLaunch(std::vector<std::string> aExtraOpts=std::vector<std::string>());
 
   virtual void OnChannelConnected(int32 peer_pid);
   virtual void OnMessageReceived(const IPC::Message& aMsg);
   virtual void OnChannelError();
 
   void InitializeChannel();
--- a/ipc/ipdl/test/cxx/Makefile.in
+++ b/ipc/ipdl/test/cxx/Makefile.in
@@ -73,16 +73,17 @@ IPDLTESTS = \
   TestRPCShutdownRace \
   TestRacyRPCReplies  \
   TestSanity  \
   TestSelfManageRoot \
   TestShmem \
   TestShutdown \
   TestStackHooks \
   TestSyncWakeup \
+  TestSyncHang \
   $(NULL)
 
 ifeq ($(OS_ARCH),Linux)
 IPDLTESTS += TestSysVShmem
 endif
 
 IPDLTESTSRCS = $(addsuffix .cpp,$(IPDLTESTS))
 IPDLTESTHDRS = $(addprefix $(srcdir)/,$(addsuffix .h,$(IPDLTESTS)))
new file mode 100644
--- /dev/null
+++ b/ipc/ipdl/test/cxx/PTestSyncHang.ipdl
@@ -0,0 +1,15 @@
+
+namespace mozilla {
+namespace _ipdltest {
+
+
+protocol PTestSyncHang {
+
+child:
+    __delete__();
+
+};
+
+
+} // namespace mozilla
+} // namespace _ipdltest
new file mode 100644
--- /dev/null
+++ b/ipc/ipdl/test/cxx/TestSyncHang.cpp
@@ -0,0 +1,71 @@
+#include "TestSyncHang.h"
+#include "mozilla/ipc/GeckoChildProcessHost.h"
+
+#include "IPDLUnitTests.h"      // fail etc.
+
+using std::vector;
+using std::string;
+
+namespace mozilla {
+namespace _ipdltest {
+
+//-----------------------------------------------------------------------------
+// parent
+
+mozilla::ipc::GeckoChildProcessHost* gSyncHangSubprocess;
+
+TestSyncHangParent::TestSyncHangParent()
+{
+    MOZ_COUNT_CTOR(TestSyncHangParent);
+}
+
+TestSyncHangParent::~TestSyncHangParent()
+{
+    MOZ_COUNT_DTOR(TestSyncHangParent);
+}
+
+void
+DeleteSyncHangSubprocess(MessageLoop* uiLoop)
+{
+  delete gSyncHangSubprocess;
+}
+
+void
+DeferredSyncHangParentShutdown()
+{
+  // ping to DeleteSubprocess
+  XRE_GetIOMessageLoop()->PostTask(
+      FROM_HERE,
+      NewRunnableFunction(DeleteSyncHangSubprocess, MessageLoop::current()));
+}
+
+void
+TestSyncHangParent::Main()
+{
+  vector<string> args;
+  args.push_back("fake/path");
+  gSyncHangSubprocess = new mozilla::ipc::GeckoChildProcessHost(GeckoProcessType_Plugin);
+  bool launched = gSyncHangSubprocess->SyncLaunch(args, 2);
+  if (launched)
+    fail("Calling SyncLaunch with an invalid path should return false");
+
+  MessageLoop::current()->PostTask(
+  				   FROM_HERE, NewRunnableFunction(DeferredSyncHangParentShutdown));
+  Close();
+}
+
+//-----------------------------------------------------------------------------
+// child
+
+TestSyncHangChild::TestSyncHangChild()
+{
+    MOZ_COUNT_CTOR(TestSyncHangChild);
+}
+
+TestSyncHangChild::~TestSyncHangChild()
+{
+    MOZ_COUNT_DTOR(TestSyncHangChild);
+}
+
+} // namespace _ipdltest
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/ipc/ipdl/test/cxx/TestSyncHang.h
@@ -0,0 +1,56 @@
+#ifndef mozilla__ipdltest_TestSyncHang_h
+#define mozilla__ipdltest_TestSyncHang_h 1
+
+#include "mozilla/_ipdltest/IPDLUnitTests.h"
+
+#include "mozilla/_ipdltest/PTestSyncHangParent.h"
+#include "mozilla/_ipdltest/PTestSyncHangChild.h"
+
+namespace mozilla {
+namespace _ipdltest {
+
+
+class TestSyncHangParent :
+    public PTestSyncHangParent
+{
+public:
+    TestSyncHangParent();
+    virtual ~TestSyncHangParent();
+
+    void Main();
+
+protected:    
+    NS_OVERRIDE
+    virtual void ActorDestroy(ActorDestroyReason why)
+    {
+        if (NormalShutdown != why)
+            fail("unexpected destruction!");  
+        passed("ok");
+        QuitParent();
+    }
+};
+
+
+class TestSyncHangChild :
+    public PTestSyncHangChild
+{
+public:
+    TestSyncHangChild();
+    virtual ~TestSyncHangChild();
+
+protected:
+    NS_OVERRIDE
+    virtual void ActorDestroy(ActorDestroyReason why)
+    {
+        if (NormalShutdown != why)
+            fail("unexpected destruction!");
+        QuitChild();
+    }
+};
+
+
+} // namespace _ipdltest
+} // namespace mozilla
+
+
+#endif // ifndef mozilla__ipdltest_TestSyncHang_h
--- a/ipc/ipdl/test/cxx/ipdl.mk
+++ b/ipc/ipdl/test/cxx/ipdl.mk
@@ -25,10 +25,11 @@ IPDLSRCS =					\
   PTestSelfManage.ipdl				\
   PTestSelfManageRoot.ipdl			\
   PTestShmem.ipdl				\
   PTestShutdown.ipdl				\
   PTestShutdownSub.ipdl				\
   PTestShutdownSubsub.ipdl			\
   PTestStackHooks.ipdl				\
   PTestSyncWakeup.ipdl				\
+  PTestSyncHang.ipdl                            \
   PTestSysVShmem.ipdl				\
   $(NULL)
--- a/layout/base/nsCSSFrameConstructor.cpp
+++ b/layout/base/nsCSSFrameConstructor.cpp
@@ -7606,23 +7606,24 @@ UpdateViewsForTree(nsIFrame* aFrame, nsI
   nsIAtom* childList = nsnull;
 
   do {
     nsIFrame* child = aFrame->GetFirstChild(childList);
     while (child) {
       if (!(child->GetStateBits() & NS_FRAME_OUT_OF_FLOW)
           || (child->GetStateBits() & NS_FRAME_IS_OVERFLOW_CONTAINER)) {
         // only do frames that don't have placeholders
-        if (nsGkAtoms::placeholderFrame == child->GetType()) { // placeholder
-          // get out of flow frame and start over there
+        if (nsGkAtoms::placeholderFrame == child->GetType()) {
+          // do the out-of-flow frame and its continuations
           nsIFrame* outOfFlowFrame =
             nsPlaceholderFrame::GetRealFrameForPlaceholder(child);
-
-          DoApplyRenderingChangeToTree(outOfFlowFrame, aViewManager,
-                                       aFrameManager, aChange);
+          do {
+            DoApplyRenderingChangeToTree(outOfFlowFrame, aViewManager,
+                                         aFrameManager, aChange);
+          } while (outOfFlowFrame = outOfFlowFrame->GetNextContinuation());
         } else if (childList == nsGkAtoms::popupList) {
           DoApplyRenderingChangeToTree(child, aViewManager,
                                        aFrameManager, aChange);
         } else {  // regular frame
           if ((child->GetStateBits() & NS_FRAME_HAS_CONTAINER_LAYER) &&
               (aChange & nsChangeHint_RepaintFrame)) {
             FrameLayerBuilder::InvalidateThebesLayerContents(child,
               child->GetOverflowRectRelativeToSelf());
--- a/layout/base/nsDocumentViewer.cpp
+++ b/layout/base/nsDocumentViewer.cpp
@@ -3323,29 +3323,46 @@ nsresult nsDocViewerSelectionListener::I
  * not all content (images included) can receive focus.
  */
 
 nsresult
 DocumentViewerImpl::GetPopupNode(nsIDOMNode** aNode)
 {
   NS_ENSURE_ARG_POINTER(aNode);
 
+  *aNode = nsnull;
+
   // get the document
   nsIDocument* document = GetDocument();
   NS_ENSURE_TRUE(document, NS_ERROR_FAILURE);
 
   // get the private dom window
   nsCOMPtr<nsPIDOMWindow> window(document->GetWindow());
   NS_ENSURE_TRUE(window, NS_ERROR_NOT_AVAILABLE);
   if (window) {
     nsCOMPtr<nsPIWindowRoot> root = window->GetTopWindowRoot();
     NS_ENSURE_TRUE(root, NS_ERROR_FAILURE);
 
     // get the popup node
-    NS_IF_ADDREF(*aNode = root->GetPopupNode());
+    nsCOMPtr<nsIDOMNode> node = root->GetPopupNode();
+#ifdef MOZ_XUL
+    if (!node) {
+      nsPIDOMWindow* rootWindow = root->GetWindow();
+      if (rootWindow) {
+        nsCOMPtr<nsIDocument> rootDoc = do_QueryInterface(rootWindow->GetExtantDocument());
+        if (rootDoc) {
+          nsXULPopupManager* pm = nsXULPopupManager::GetInstance();
+          if (pm) {
+            node = pm->GetLastTriggerPopupNode(rootDoc);
+          }
+        }
+      }
+    }
+#endif
+    node.swap(*aNode);
   }
 
   return NS_OK;
 }
 
 // GetPopupLinkNode: return popup link node or fail
 nsresult
 DocumentViewerImpl::GetPopupLinkNode(nsIDOMNode** aNode)
--- a/layout/base/nsFrameManager.cpp
+++ b/layout/base/nsFrameManager.cpp
@@ -17,16 +17,17 @@
  * The Original Code is mozilla.org code.
  *
  * The Initial Developer of the Original Code is
  * Netscape Communications Corporation.
  * Portions created by the Initial Developer are Copyright (C) 1998
  * the Initial Developer. All Rights Reserved.
  *
  * Contributor(s):
+ *   Mats Palmgren <matspal@gmail.com>
  *
  * Alternatively, the contents of this file may be used under the terms of
  * either of the GNU General Public License Version 2 or later (the "GPL"),
  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  * in which case the provisions of the GPL or the LGPL are applicable instead
  * of those above. If you wish to allow use of your version of this file only
  * under the terms of either the GPL or the LGPL, and not to allow others to
  * use your version of this file under the terms of the MPL, indicate your
@@ -766,22 +767,23 @@ ElementForStyleContext(nsIContent* aPare
   nsIContent* content = aParentContent ? aParentContent : aFrame->GetContent();
   return content->AsElement();
 }
 
 nsresult
 nsFrameManager::ReparentStyleContext(nsIFrame* aFrame)
 {
   if (nsGkAtoms::placeholderFrame == aFrame->GetType()) {
-    // Also reparent the out-of-flow
+    // Also reparent the out-of-flow and all its continuations.
     nsIFrame* outOfFlow =
       nsPlaceholderFrame::GetRealFrameForPlaceholder(aFrame);
     NS_ASSERTION(outOfFlow, "no out-of-flow frame");
-
-    ReparentStyleContext(outOfFlow);
+    do {
+      ReparentStyleContext(outOfFlow);
+    } while (outOfFlow = outOfFlow->GetNextContinuation());
   }
 
   // DO NOT verify the style tree before reparenting.  The frame
   // tree has already been changed, so this check would just fail.
   nsStyleContext* oldContext = aFrame->GetStyleContext();
   // XXXbz can oldContext really ever be null?
   if (oldContext) {
     nsRefPtr<nsStyleContext> newContext;
@@ -1465,23 +1467,25 @@ nsFrameManager::ReResolveStyleContext(ns
               // be (eg a reresolve starting at <body> that involves reflowing
               // the <body> would miss reflowing fixed-pos nodes that also need
               // reflow).  In the cases when the out-of-flow _is_ a geometric
               // descendant of a frame we already have a reflow hint for,
               // reflow coalescing should keep us from doing the work twice.
 
               // |nsFrame::GetParentStyleContextFrame| checks being out
               // of flow so that this works correctly.
-              ReResolveStyleContext(aPresContext, outOfFlowFrame,
-                                    content, aChangeList,
-                                    NS_SubtractHint(aMinChange,
-                                                    nsChangeHint_ReflowFrame),
-                                    childRestyleHint,
-                                    fireAccessibilityEvents,
-                                    aRestyleTracker);
+              do {
+                ReResolveStyleContext(aPresContext, outOfFlowFrame,
+                                      content, aChangeList,
+                                      NS_SubtractHint(aMinChange,
+                                                      nsChangeHint_ReflowFrame),
+                                      childRestyleHint,
+                                      fireAccessibilityEvents,
+                                      aRestyleTracker);
+              } while (outOfFlowFrame = outOfFlowFrame->GetNextContinuation());
 
               // reresolve placeholder's context under the same parent
               // as the out-of-flow frame
               ReResolveStyleContext(aPresContext, child, content,
                                     aChangeList, aMinChange,
                                     childRestyleHint,
                                     fireAccessibilityEvents,
                                     aRestyleTracker);
--- a/modules/libpref/src/init/all.js
+++ b/modules/libpref/src/init/all.js
@@ -1254,23 +1254,27 @@ pref("gestures.enable_single_finger_inpu
 //pref("editor.encode_entity",                 "html");
 
 pref("editor.resizing.preserve_ratio",       true);
 pref("editor.positioning.offset",            0);
 
 pref("dom.max_chrome_script_run_time", 20);
 pref("dom.max_script_run_time", 10);
 
+#ifndef DEBUG
 // How long a plugin is allowed to process a synchronous IPC message
 // before we consider it "hung".
-#ifndef DEBUG
 pref("dom.ipc.plugins.timeoutSecs", 45);
+// How long a plugin launch is allowed to take before
+// we consider it failed.
+pref("dom.ipc.plugins.processLaunchTimeoutSecs", 45);
 #else
 // No timeout in DEBUG builds
 pref("dom.ipc.plugins.timeoutSecs", 0);
+pref("dom.ipc.plugins.processLaunchTimeoutSecs", 0);
 #endif
 
 #ifndef ANDROID
 #ifndef XP_MACOSX
 #ifdef XP_UNIX
 // Linux plugins using Xt instead of Xembed don't work out-of-process yet.
 pref("dom.ipc.plugins.enabled.libvlcplugin.so", false);
 pref("dom.ipc.plugins.enabled.nppdf.so", false);
--- a/profile/dirserviceprovider/src/nsProfileLock.cpp
+++ b/profile/dirserviceprovider/src/nsProfileLock.cpp
@@ -137,38 +137,38 @@ nsProfileLock::~nsProfileLock()
 
 #if defined (XP_UNIX)
 
 static int setupPidLockCleanup;
 
 PRCList nsProfileLock::mPidLockList =
     PR_INIT_STATIC_CLIST(&nsProfileLock::mPidLockList);
 
-void nsProfileLock::RemovePidLockFiles()
+void nsProfileLock::RemovePidLockFiles(PRBool aFatalSignal)
 {
     while (!PR_CLIST_IS_EMPTY(&mPidLockList))
     {
         nsProfileLock *lock = static_cast<nsProfileLock*>(mPidLockList.next);
-        lock->Unlock();
+        lock->Unlock(aFatalSignal);
     }
 }
 
 static struct sigaction SIGHUP_oldact;
 static struct sigaction SIGINT_oldact;
 static struct sigaction SIGQUIT_oldact;
 static struct sigaction SIGILL_oldact;
 static struct sigaction SIGABRT_oldact;
 static struct sigaction SIGSEGV_oldact;
 static struct sigaction SIGTERM_oldact;
 
 void nsProfileLock::FatalSignalHandler(int signo, siginfo_t *info,
                                        void *context)
 {
     // Remove any locks still held.
-    RemovePidLockFiles();
+    RemovePidLockFiles(PR_TRUE);
 
     // Chain to the old handler, which may exit.
     struct sigaction *oldact = nsnull;
 
     switch (signo) {
       case SIGHUP:
         oldact = &SIGHUP_oldact;
         break;
@@ -380,17 +380,17 @@ nsresult nsProfileLock::LockWithSymlink(
         mHaveLock = PR_TRUE;
         mPidLockFileName = strdup(fileName);
         if (mPidLockFileName)
         {
             PR_APPEND_LINK(this, &mPidLockList);
             if (!setupPidLockCleanup++)
             {
                 // Clean up on normal termination.
-                atexit(RemovePidLockFiles);
+                atexit(RemovePidLockFilesExiting);
 
                 // Clean up on abnormal termination, using POSIX sigaction.
                 // Don't arm a handler if the signal is being ignored, e.g.,
                 // because mozilla is run via nohup.
                 if (!sDisableSignalHandling) {
                     struct sigaction act, oldact;
                     act.sa_sigaction = FatalSignalHandler;
                     act.sa_flags = SA_SIGINFO;
@@ -647,17 +647,17 @@ nsresult nsProfileLock::Lock(nsILocalFil
 #endif
 
     mHaveLock = PR_TRUE;
 
     return rv;
 }
 
 
-nsresult nsProfileLock::Unlock()
+nsresult nsProfileLock::Unlock(PRBool aFatalSignal)
 {
     nsresult rv = NS_OK;
 
     if (mHaveLock)
     {
 #if defined (XP_WIN)
         if (mLockFileHandle != INVALID_HANDLE_VALUE)
         {
@@ -670,17 +670,24 @@ nsresult nsProfileLock::Unlock()
             DosClose(mLockFileHandle);
             mLockFileHandle = -1;
         }
 #elif defined (XP_UNIX)
         if (mPidLockFileName)
         {
             PR_REMOVE_LINK(this);
             (void) unlink(mPidLockFileName);
-            free(mPidLockFileName);
+
+            // Only free mPidLockFileName if we're not in the fatal signal
+            // handler.  The problem is that a call to free() might be the
+            // cause of this fatal signal.  If so, calling free() might cause
+            // us to wait on the malloc implementation's lock.  We're already
+            // holding this lock, so we'll deadlock. See bug 522332.
+            if (!aFatalSignal)
+                free(mPidLockFileName);
             mPidLockFileName = nsnull;
         }
         else if (mLockFileDesc != -1)
         {
             close(mLockFileDesc);
             mLockFileDesc = -1;
             // Don't remove it
         }
--- a/profile/dirserviceprovider/src/nsProfileLock.h
+++ b/profile/dirserviceprovider/src/nsProfileLock.h
@@ -77,27 +77,43 @@ public:
      *
      * @param aProfileDir  [in] The profile directory to lock.
      * @param aUnlocker    [out] Optional. This is only returned when locking
      *                     fails with NS_ERROR_FILE_ACCESS_DENIED, and may not
      *                     be returned at all.
      * @throws NS_ERROR_FILE_ACCESS_DENIED if the profile is locked.
      */
     nsresult                Lock(nsILocalFile* aProfileDir, nsIProfileUnlocker* *aUnlocker);
-    nsresult                Unlock();
+
+    /**
+     * Unlock a profile directory.  If you're unlocking the directory because
+     * the application is in the process of shutting down because of a fatal
+     * signal, set aFatalSignal to PR_TRUE.
+     */
+    nsresult                Unlock(PRBool aFatalSignal = PR_FALSE);
         
 private:
     PRPackedBool            mHaveLock;
 
 #if defined (XP_WIN)
     HANDLE                  mLockFileHandle;
 #elif defined (XP_OS2)
     LHANDLE                 mLockFileHandle;
 #elif defined (XP_UNIX)
-    static void             RemovePidLockFiles();
+
+    static void             RemovePidLockFilesExiting()
+    {
+      // We can't implement this function with a default parameter on
+      // RemovePidLockFiles(aFatalSignal) since we register
+      //    atexit(RemovePidLockFilesExiting).
+
+      RemovePidLockFiles(PR_FALSE);
+    }
+
+    static void             RemovePidLockFiles(PRBool aFatalSignal);
     static void             FatalSignalHandler(int signo, siginfo_t *info,
                                                void *context);
     static PRCList          mPidLockList;
 
     nsresult                LockWithFcntl(const nsACString& lockFilePath);
 
     /**
      * @param aHaveFcntlLock if true, we've already acquired an fcntl lock so this
--- a/toolkit/components/console/hudservice/HUDService.jsm
+++ b/toolkit/components/console/hudservice/HUDService.jsm
@@ -2480,18 +2480,20 @@ JSTerm.prototype = {
   COMPLETE_BACKWARD: 1,
   COMPLETE_HINT_ONLY: 2,
 
   init: function JST_init()
   {
     this.createSandbox();
     this.inputNode = this.mixins.inputNode;
     this.scrollToNode = this.mixins.scrollToNode;
-    let eventHandler = this.keyDown();
-    this.inputNode.addEventListener('keypress', eventHandler, false);
+    let eventHandlerKeyDown = this.keyDown();
+    this.inputNode.addEventListener('keypress', eventHandlerKeyDown, false);
+    let eventHandlerInput = this.inputEventHandler();
+    this.inputNode.addEventListener('input', eventHandlerInput, false);
     this.outputNode = this.mixins.outputNode;
     if (this.mixins.cssClassOverride) {
       this.cssClassOverride = this.mixins.cssClassOverride;
     }
   },
 
   get codeInputString()
   {
@@ -2609,16 +2611,26 @@ JSTerm.prototype = {
 
     while (outputNode.firstChild) {
       outputNode.removeChild(outputNode.firstChild);
     }
 
     outputNode.lastTimestamp = 0;
   },
 
+  inputEventHandler: function JSTF_inputEventHandler()
+  {
+    var self = this;
+    function handleInputEvent(aEvent) {
+      self.inputNode.setAttribute("rows",
+        Math.min(8, self.inputNode.value.split("\n").length));
+    }
+    return handleInputEvent;
+  },
+
   keyDown: function JSTF_keyDown(aEvent)
   {
     var self = this;
     function handleKeyDown(aEvent) {
       // ctrl-a
       var setTimeout = aEvent.target.ownerDocument.defaultView.setTimeout;
       var target = aEvent.target;
       var tmp;
@@ -2652,16 +2664,17 @@ JSTerm.prototype = {
         // TODO: expand the inputNode height by one line
         return;
       }
       else {
         switch(aEvent.keyCode) {
           case 13:
             // return
             self.execute();
+            aEvent.preventDefault();
             break;
           case 38:
             // up arrow: history previous
             if (self.caretInFirstLine()){
               self.historyPeruse(true);
               if (aEvent.cancelable) {
                 let inputEnd = self.inputNode.value.length;
                 self.inputNode.setSelectionRange(inputEnd, inputEnd);
@@ -2766,17 +2779,17 @@ JSTerm.prototype = {
     this.inputNode.blur();
     this.inputNode.focus();
   },
 
   caretInFirstLine: function JSTF_caretInFirstLine()
   {
     var firstLineBreak = this.codeInputString.indexOf("\n");
     return ((firstLineBreak == -1) ||
-            (this.codeInputString.selectionStart <= firstLineBreak));
+            (this.inputNode.selectionStart <= firstLineBreak));
   },
 
   caretInLastLine: function JSTF_caretInLastLine()
   {
     var lastLineBreak = this.codeInputString.lastIndexOf("\n");
     return (this.inputNode.selectionEnd > lastLineBreak);
   },
 
@@ -2946,16 +2959,18 @@ JSTermFirefoxMixin.prototype = {
    * just the input node used under the console output
    *
    * @returns void
    */
   generateUI: function JSTF_generateUI()
   {
     let inputNode = this.xulElementFactory("textbox");
     inputNode.setAttribute("class", "jsterm-input-node");
+    inputNode.setAttribute("multiline", "true");
+    inputNode.setAttribute("rows", "1");
 
     if (this.existingConsoleNode == undefined) {
       // create elements
       let term = this.elementFactory("div");
       term.setAttribute("class", "jsterm-wrapper-node");
       term.setAttribute("flex", "1");
 
       let outputNode = this.elementFactory("div");
--- a/toolkit/components/console/hudservice/tests/browser/browser_HUDServiceTestsAll.js
+++ b/toolkit/components/console/hudservice/tests/browser/browser_HUDServiceTestsAll.js
@@ -568,16 +568,49 @@ function testCompletion()
 
   // Test pressing shift_tab.
   jsterm.complete(jsterm.COMPLETE_BACKWARD);
   is(input.value, "document.getElementById", "'document.getElem' untab completion");
   is(input.selectionStart, 16, "start selection is alright");
   is(input.selectionEnd, 23, "end selection is alright");
 }
 
+function testJSInputExpand()
+{
+  let HUD = HUDService.hudWeakReferences[hudId].get();
+  let jsterm = HUD.jsterm;
+  let input = jsterm.inputNode;
+  input.focus();
+
+  is(input.getAttribute("multiline"), "true", "multiline is enabled");
+
+  // Tests if the inputNode expands.
+  input.value = "hello\nworld\n";
+  let length = input.value.length;
+  input.selectionEnd = length;
+  input.selectionStart = length;
+  // Performs an "d". This will trigger/test for the input event that should
+  // change the "row" attribute of the inputNode.
+  EventUtils.synthesizeKey("d", {});
+  is(input.getAttribute("rows"), "3", "got 3 rows");
+
+  // Add some more rows. Tests for the 8 row limit.
+  input.value = "row1\nrow2\nrow3\nrow4\nrow5\nrow6\nrow7\nrow8\nrow9\nrow10\n";
+  length = input.value.length;
+  input.selectionEnd = length;
+  input.selectionStart = length;
+  EventUtils.synthesizeKey("d", {});
+  is(input.getAttribute("rows"), "8", "got 8 rows");
+
+  // Test if the inputNode shrinks again.
+  input.value = "";
+  EventUtils.synthesizeKey("d", {});
+  is(input.getAttribute("rows"), "1", "got 1 row");
+}
+
 function testExecutionScope()
 {
   content.location.href = TEST_URI;
 
   let HUD = HUDService.hudWeakReferences[hudId].get();
   let jsterm = HUD.jsterm;
 
   jsterm.clearOutput();
@@ -839,12 +872,13 @@ function test() {
       testConsoleHistory();
       testOutputOrder();
       testGroups();
       testNullUndefinedOutput();
       testJSInputAndOutputStyling();
       testExecutionScope();
       testCompletion();
       testPropertyProvider();
+      testJSInputExpand();
       testNet();
     });
   }, false);
 }
--- a/toolkit/themes/pinstripe/global/headsUpDisplay.css
+++ b/toolkit/themes/pinstripe/global/headsUpDisplay.css
@@ -152,16 +152,20 @@
     font-size: 9pt;
     background: url("chrome://global/skin/icons/commandline.png") 4px 2px
         no-repeat !important;
     border: none !important;
     padding: 0px 0px 0px 16px !important;
     -moz-appearance: none !important;
 }
 
+.jsterm-input-node textarea {
+    overflow-x: hidden;
+}
+
 .jsterm-output-line {
     font-size: 1.2em;
 }
 
 /* these need to be revised ... */
 .hud-console-filter-toolbar {
     padding: 1px 0px;
     -moz-box-align: center;
--- a/toolkit/themes/winstripe/global/headsUpDisplay.css
+++ b/toolkit/themes/winstripe/global/headsUpDisplay.css
@@ -151,16 +151,20 @@
     font-size: 9pt;
     background: url("chrome://global/skin/icons/commandline.png") 4px 3px
         no-repeat !important;
     border: none !important;
     padding: 0px 0px 0px 16px !important;
     -moz-appearance: none !important;
 }
 
+.jsterm-input-node textarea {
+    overflow-x: hidden;
+}
+
 .jsterm-output-line {
     font-size: 1.2em;
 }
 
 .hud-console-filter-toolbar {
     padding: 1px 0px;
     -moz-box-align: center;
 }
--- a/xpcom/base/nsSystemInfo.cpp
+++ b/xpcom/base/nsSystemInfo.cpp
@@ -128,23 +128,29 @@ nsSystemInfo::Init()
 }
 
 void
 nsSystemInfo::SetInt32Property(const nsAString &aPropertyName,
                                const PRInt32 aValue)
 {
   NS_WARN_IF_FALSE(aValue > 0, "Unable to read system value");
   if (aValue > 0) {
-    nsresult rv = SetPropertyAsInt32(aPropertyName, aValue);
+#ifdef DEBUG
+    nsresult rv =
+#endif
+      SetPropertyAsInt32(aPropertyName, aValue);
     NS_WARN_IF_FALSE(NS_SUCCEEDED(rv), "Unable to set property");
   }
 }
 
 void
 nsSystemInfo::SetUint64Property(const nsAString &aPropertyName,
                                 const PRUint64 aValue)
 {
   NS_WARN_IF_FALSE(aValue > 0, "Unable to read system value");
   if (aValue > 0) {
-    nsresult rv = SetPropertyAsUint64(aPropertyName, aValue);
+#ifdef DEBUG
+    nsresult rv =
+#endif
+      SetPropertyAsUint64(aPropertyName, aValue);
     NS_WARN_IF_FALSE(NS_SUCCEEDED(rv), "Unable to set property");
   }
 }
--- a/xpcom/tests/TestArray.cpp
+++ b/xpcom/tests/TestArray.cpp
@@ -108,17 +108,20 @@ const char* AssertEqual(PRInt32 aValue1,
     exit(1);
   }
   return "ERROR";
 }
 
 void DumpArray(nsISupportsArray* aArray, PRInt32 aExpectedCount, PRInt32 aElementIDs[], PRInt32 aExpectedTotal)
 {
   PRUint32 cnt = 0;
-  nsresult rv = aArray->Count(&cnt);
+#ifdef DEBUG
+  nsresult rv =
+#endif
+    aArray->Count(&cnt);
   NS_ASSERTION(NS_SUCCEEDED(rv), "Count failed");
   PRInt32 count = cnt;
   PRInt32 index;
 
   fprintf(stdout, "object count %d = %d %s\n", Foo::gCount, aExpectedTotal, 
           AssertEqual(Foo::gCount, aExpectedTotal));
   fprintf(stdout, "array count %d = %d %s\n", count, aExpectedCount,
           AssertEqual(count, aExpectedCount));
--- a/xpcom/tests/TestCRT.cpp
+++ b/xpcom/tests/TestCRT.cpp
@@ -56,27 +56,41 @@ PRIntn sign(PRIntn val) {
 }
 
 
 // Verify that nsCRT versions of string comparison routines get the
 // same answers as the native non-unicode versions. We only pass in
 // iso-latin-1 strings, so the comparison must be valid.
 static void Check(const char* s1, const char* s2, PRIntn n)
 {
-  PRIntn clib = PL_strcmp(s1, s2);
-  PRIntn clib_n = PL_strncmp(s1, s2, n);
+#ifdef DEBUG
+  PRIntn clib =
+#endif
+    PL_strcmp(s1, s2);
+
+#ifdef DEBUG
+  PRIntn clib_n =
+#endif
+    PL_strncmp(s1, s2, n);
 
   nsAutoString t1,t2; 
   t1.AssignWithConversion(s1);
   t2.AssignWithConversion(s2);
   const PRUnichar* us1 = t1.get();
   const PRUnichar* us2 = t2.get();
 
-  PRIntn u2 = nsCRT::strcmp(us1, us2);
-  PRIntn u2_n = nsCRT::strncmp(us1, us2, n);
+#ifdef DEBUG
+  PRIntn u2 =
+#endif
+    nsCRT::strcmp(us1, us2);
+
+#ifdef DEBUG
+  PRIntn u2_n =
+#endif
+    nsCRT::strncmp(us1, us2, n);
 
   NS_ASSERTION(sign(clib) == sign(u2), "strcmp");
   NS_ASSERTION(sign(clib_n) == sign(u2_n), "strncmp");
 }
 
 struct Test {
   const char* s1;
   const char* s2;
--- a/xpcom/tests/TestPipes.cpp
+++ b/xpcom/tests/TestPipes.cpp
@@ -322,17 +322,21 @@ TestShortWrites(nsIInputStream* in, nsIO
         total += writeCount;
 
         if (gTrace)
             printf("wrote %d bytes: %s\n", writeCount, buf);
         PR_smprintf_free(buf);
         //printf("calling Flush\n");
         out->Flush();
         //printf("calling WaitForReceipt\n");
-        const PRUint32 received = receiver->WaitForReceipt(writeCount);
+
+#ifdef DEBUG
+        const PRUint32 received =
+#endif
+          receiver->WaitForReceipt(writeCount);
         NS_ASSERTION(received == writeCount, "received wrong amount");
     }
     rv = out->Close();
     if (NS_FAILED(rv)) return rv;
 
     thread->Shutdown();
 
     printf("wrote %d bytes\n", total);