Merge m-i to m-c, a=merge
authorPhil Ringnalda <philringnalda@gmail.com>
Sat, 13 Feb 2016 19:18:53 -0800
changeset 320531 e355cacefc881ba360d412853b57e8e060e966f4
parent 320462 a669f998ccc3ac2db708a0d9258245fcc65efb65 (current diff)
parent 320530 3c7cf3cca248c91c9f674e513ed0a797d3da7374 (diff)
child 320536 29246bfbc091ddfaaa6d53f0b1dfcf7da19a615b
child 320542 acc7a80ef7f2d46baa2b7ed1959903796cb26899
push id5913
push userjlund@mozilla.com
push dateMon, 25 Apr 2016 16:57:49 +0000
treeherdermozilla-beta@dcaf0a6fa115 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone47.0a1
first release with
nightly linux32
e355cacefc88 / 47.0a1 / 20160214030236 / files
nightly linux64
e355cacefc88 / 47.0a1 / 20160214030236 / files
nightly mac
e355cacefc88 / 47.0a1 / 20160214030236 / files
nightly win32
e355cacefc88 / 47.0a1 / 20160214030236 / files
nightly win64
e355cacefc88 / 47.0a1 / 20160214030236 / files
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
releases
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge m-i to m-c, a=merge
browser/locales/en-US/chrome/browser/browser.dtd
gfx/2d/DrawTargetD2D.cpp
gfx/2d/DrawTargetD2D.h
gfx/2d/SourceSurfaceD2D.cpp
gfx/2d/SourceSurfaceD2D.h
gfx/2d/SourceSurfaceD2DTarget.cpp
gfx/2d/SourceSurfaceD2DTarget.h
js/src/jit-test/tests/gc/withStatementOffThread.js
--- a/browser/base/content/browser-context.inc
+++ b/browser/base/content/browser-context.inc
@@ -52,17 +52,39 @@
       <menuseparator id="spell-suggestions-separator"/>
       <menuitem id="context-openlinkincurrent"
                 label="&openLinkCmdInCurrent.label;"
                 accesskey="&openLinkCmdInCurrent.accesskey;"
                 oncommand="gContextMenu.openLinkInCurrent();"/>
       <menuitem id="context-openlinkintab"
                 label="&openLinkCmdInTab.label;"
                 accesskey="&openLinkCmdInTab.accesskey;"
-                oncommand="gContextMenu.openLinkInTab();"/>
+                usercontextid="0"
+                oncommand="gContextMenu.openLinkInTab(event);"/>
+
+      <menu id="context-openlinkinusercontext-menu"
+            label="&openLinkCmdInContainerTab.label;"
+            accesskey="&openLinkCmdInContainerTab.accesskey;"
+            hidden="true">
+        <menupopup oncommand="gContextMenu.openLinkInTab(event);">
+          <menuitem label="&userContextPersonal.label;"
+                    usercontextid="1"
+                    accesskey="&userContextPersonal.accesskey;"/>
+          <menuitem label="&userContextWork.label;"
+                    usercontextid="2"
+                    accesskey="&userContextWork.accesskey;"/>
+          <menuitem label="&userContextBanking.label;"
+                    usercontextid="3"
+                    accesskey="&userContextBanking.accesskey;"/>
+          <menuitem label="&userContextShopping.label;"
+                    usercontextid="4"
+                    accesskey="&userContextShopping.accesskey;"/>
+        </menupopup>
+      </menu>
+
       <menuitem id="context-openlink"
                 label="&openLinkCmd.label;"
                 accesskey="&openLinkCmd.accesskey;"
                 oncommand="gContextMenu.openLink();"/>
       <menuitem id="context-openlinkprivate"
                 label="&openLinkInPrivateWindowCmd.label;"
                 accesskey="&openLinkInPrivateWindowCmd.accesskey;"
                 oncommand="gContextMenu.openLinkInPrivateWindow();"/>
--- a/browser/base/content/browser-safebrowsing.js
+++ b/browser/base/content/browser-safebrowsing.js
@@ -3,34 +3,42 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 // Note: this file is not shipped (through jar.mn)
 // if MOZ_SAFE_BROWSING is not defined.
 
 var gSafeBrowsing = {
 
   setReportPhishingMenu: function() {
-    // A phishing page will have a specific about:blocked content documentURI
-    var uri = gBrowser.currentURI;
-    var isPhishingPage = uri && uri.spec.startsWith("about:blocked?e=phishingBlocked");
+    // In order to detect whether or not we're at the phishing warning
+    // page, we have to check the documentURI instead of the currentURI.
+    // This is because when the DocShell loads an error page, the
+    // currentURI stays at the original target, while the documentURI
+    // will point to the internal error page we loaded instead.
+    var docURI = gBrowser.selectedBrowser.documentURI;
+    var isPhishingPage =
+      docURI && docURI.spec.startsWith("about:blocked?e=phishingBlocked");
 
     // Show/hide the appropriate menu item.
     document.getElementById("menu_HelpPopup_reportPhishingtoolmenu")
             .hidden = isPhishingPage;
     document.getElementById("menu_HelpPopup_reportPhishingErrortoolmenu")
             .hidden = !isPhishingPage;
 
     var broadcasterId = isPhishingPage
                         ? "reportPhishingErrorBroadcaster"
                         : "reportPhishingBroadcaster";
 
     var broadcaster = document.getElementById(broadcasterId);
     if (!broadcaster)
       return;
 
+    // Now look at the currentURI to learn which page we were trying
+    // to browse to.
+    let uri = gBrowser.currentURI;
     if (uri && (uri.schemeIs("http") || uri.schemeIs("https")))
       broadcaster.removeAttribute("disabled");
     else
       broadcaster.setAttribute("disabled", true);
   },
 
   /**
    * Used to report a phishing page or a false positive
--- a/browser/base/content/nsContextMenu.js
+++ b/browser/base/content/nsContextMenu.js
@@ -139,19 +139,21 @@ nsContextMenu.prototype = {
       } catch (ex) {}
 
       this.linkTextStr = this.selectionInfo.linkText;
       this.onPlainTextLink = true;
     }
 
     var shouldShow = this.onSaveableLink || isMailtoInternal || this.onPlainTextLink;
     var isWindowPrivate = PrivateBrowsingUtils.isWindowPrivate(window);
+    var showContainers = Services.prefs.getBoolPref("privacy.userContext.enabled");
     this.showItem("context-openlink", shouldShow && !isWindowPrivate);
     this.showItem("context-openlinkprivate", shouldShow);
     this.showItem("context-openlinkintab", shouldShow);
+    this.showItem("context-openlinkinusercontext-menu", shouldShow && showContainers);
     this.showItem("context-openlinkincurrent", this.onPlainTextLink);
     this.showItem("context-sep-open", shouldShow);
   },
 
   initNavigationItems: function CM_initNavigationItems() {
     var shouldShow = !(this.isContentSelected || this.onLink || this.onImage ||
                        this.onCanvas || this.onVideo || this.onAudio ||
                        this.onTextInput || this.onSocial);
@@ -955,17 +957,17 @@ nsContextMenu.prototype = {
   // Open linked-to URL in a new private window.
   openLinkInPrivateWindow : function () {
     urlSecurityCheck(this.linkURL, this.principal);
     openLinkIn(this.linkURL, "window",
                this._openLinkInParameters({ private: true }));
   },
 
   // Open linked-to URL in a new tab.
-  openLinkInTab: function() {
+  openLinkInTab: function(event) {
     urlSecurityCheck(this.linkURL, this.principal);
     let referrerURI = gContextMenuContentData.documentURIObject;
 
     // if the mixedContentChannel is present and the referring URI passes
     // a same origin check with the target URI, we can preserve the users
     // decision of disabling MCB on a page for it's child tabs.
     let persistAllowMixedContentInChildTab = false;
 
@@ -976,16 +978,17 @@ nsContextMenu.prototype = {
         sm.checkSameOriginURI(referrerURI, targetURI, false);
         persistAllowMixedContentInChildTab = true;
       }
       catch (e) { }
     }
 
     let params = this._openLinkInParameters({
       allowMixedContent: persistAllowMixedContentInChildTab,
+      userContextId: event.target.getAttribute('usercontextid'),
     });
     openLinkIn(this.linkURL, "tab", params);
   },
 
   // open URL in current tab
   openLinkInCurrent: function() {
     urlSecurityCheck(this.linkURL, this.principal);
     openLinkIn(this.linkURL, "current", this._openLinkInParameters());
--- a/browser/components/safebrowsing/content/test/browser.ini
+++ b/browser/components/safebrowsing/content/test/browser.ini
@@ -1,12 +1,10 @@
 [DEFAULT]
 support-files = head.js
 
 [browser_forbidden.js]
 [browser_bug400731.js]
 skip-if = e10s
 [browser_bug415846.js]
-skip-if = true
-# Disabled because it seems to now touch network resources
-# skip-if = os == "mac"
+skip-if = os == "mac" || e10s
 # Disabled on Mac because of its bizarre special-and-unique
 # snowflake of a help menu.
--- a/browser/components/safebrowsing/content/test/browser_bug415846.js
+++ b/browser/components/safebrowsing/content/test/browser_bug415846.js
@@ -1,62 +1,86 @@
 /* Check for the correct behaviour of the report web forgery/not a web forgery
 menu items.
 
 Mac makes this astonishingly painful to test since their help menu is special magic,
 but we can at least test it on the other platforms.*/
-var menu;
 
-function test() {
-  waitForExplicitFinish();
-
-  gBrowser.selectedTab = gBrowser.addTab();
+const NORMAL_PAGE = "http://example.com";
+const PHISH_PAGE = "http://www.itisatrap.org/firefox/its-a-trap.html";
 
-  // Navigate to a normal site
-  gBrowser.addEventListener("DOMContentLoaded", testNormal, false);
-  content.location = "http://example.com/";
-}
+/**
+ * Opens a new tab and browses to some URL, tests for the existence
+ * of the phishing menu items, and then runs a test function to check
+ * the state of the menu once opened. This function will take care of
+ * opening and closing the menu.
+ *
+ * @param url (string)
+ *        The URL to browse the tab to.
+ * @param testFn (function)
+ *        The function to run once the menu has been opened. This
+ *        function will be passed the "reportMenu" and "errorMenu"
+ *        DOM nodes as arguments, in that order. This function
+ *        should not yield anything.
+ * @returns Promise
+ */
+function check_menu_at_page(url, testFn) {
+  return BrowserTestUtils.withNewTab({
+    gBrowser,
+    url: "about:blank",
+  }, function*(browser) {
+    // We don't get load events when the DocShell redirects to error
+    // pages, but we do get DOMContentLoaded, so we'll wait for that.
+    let dclPromise = ContentTask.spawn(browser, null, function*() {
+      yield ContentTaskUtils.waitForEvent(this, "DOMContentLoaded", false);
+    });
+    browser.loadURI(url);
+    yield dclPromise;
 
-function testNormal() {
-  gBrowser.removeEventListener("DOMContentLoaded", testNormal, false);
+    let menu = document.getElementById("menu_HelpPopup");
+    ok(menu, "Help menu should exist");
+
+    let reportMenu =
+      document.getElementById("menu_HelpPopup_reportPhishingtoolmenu");
+    ok(reportMenu, "Report phishing menu item should exist");
+
+    let errorMenu =
+      document.getElementById("menu_HelpPopup_reportPhishingErrortoolmenu");
+    ok(errorMenu, "Report phishing error menu item should exist");
 
-  // open the menu, to force it to update
-  menu = document.getElementById("menu_HelpPopup");
-  ok(menu, "Help menu should exist!");
+    let menuOpen = BrowserTestUtils.waitForEvent(menu, "popupshown");
+    menu.openPopup(null, "", 0, 0, false, null);
+    yield menuOpen;
 
-  menu.addEventListener("popupshown", testNormal_PopupListener, false);
-  menu.openPopup(null, "", 0, 0, false, null);
+    testFn(reportMenu, errorMenu);
+
+    let menuClose = BrowserTestUtils.waitForEvent(menu, "popuphidden");
+    menu.hidePopup();
+    yield menuClose;
+  });
 }
 
-function testNormal_PopupListener() {
-  menu.removeEventListener("popupshown", testNormal_PopupListener, false);
-
-  var reportMenu = document.getElementById("menu_HelpPopup_reportPhishingtoolmenu");
-  var errorMenu = document.getElementById("menu_HelpPopup_reportPhishingErrortoolmenu");
-  is(reportMenu.hidden, false, "Report phishing menu should be visible on normal sites");
-  is(errorMenu.hidden, true, "Report error menu item should be hidden on normal sites");
-  menu.hidePopup();
-
-  // Now launch the phishing test.  Can't use onload here because error pages don't
-  // fire normal load events.
-  window.addEventListener("DOMContentLoaded", testPhishing, true);
-  content.location = "http://www.itisatrap.org/firefox/its-a-trap.html";
-}
+/**
+ * Tests that we show the "Report this page" menu item at a normal
+ * page.
+ */
+add_task(function*() {
+  yield check_menu_at_page(NORMAL_PAGE, (reportMenu, errorMenu) => {
+    ok(!reportMenu.hidden,
+       "Report phishing menu should be visible on normal sites");
+    ok(errorMenu.hidden,
+       "Report error menu item should be hidden on normal sites");
+  });
+});
 
-function testPhishing() {
-  window.removeEventListener("DOMContentLoaded", testPhishing, true);
-
-  menu.addEventListener("popupshown", testPhishing_PopupListener, false);
-  menu.openPopup(null, "", 0, 0, false, null);
-}
-
-function testPhishing_PopupListener() {
-  menu.removeEventListener("popupshown", testPhishing_PopupListener, false);
+/**
+ * Tests that we show the "Report this page is okay" menu item at
+ * a reported attack site.
+ */
+add_task(function*() {
+  yield check_menu_at_page(PHISH_PAGE, (reportMenu, errorMenu) => {
+    ok(reportMenu.hidden,
+       "Report phishing menu should be hidden on phishing sites");
+    ok(!errorMenu.hidden,
+       "Report error menu item should be visible on phishing sites");
+  });
+});
 
-  var reportMenu = document.getElementById("menu_HelpPopup_reportPhishingtoolmenu");
-  var errorMenu = document.getElementById("menu_HelpPopup_reportPhishingErrortoolmenu");
-  is(reportMenu.hidden, true, "Report phishing menu should be hidden on phishing sites");
-  is(errorMenu.hidden, false, "Report error menu item should be visible on phishing sites");
-  menu.hidePopup();
-
-  gBrowser.removeCurrentTab();
-  finish();
-}
--- a/browser/locales/en-US/chrome/browser/browser.dtd
+++ b/browser/locales/en-US/chrome/browser/browser.dtd
@@ -524,16 +524,18 @@ These should match what Safari and other
 <!ENTITY openLinkInPrivateWindowCmd.label "Open Link in New Private Window">
 <!ENTITY openLinkInPrivateWindowCmd.accesskey "P">
 <!ENTITY openLinkCmdInCurrent.label     "Open Link">
 <!ENTITY openLinkCmdInCurrent.accesskey "O">
 <!ENTITY openFrameCmdInTab.label      "Open Frame in New Tab">
 <!ENTITY openFrameCmdInTab.accesskey  "T">
 <!ENTITY openFrameCmd.label           "Open Frame in New Window">
 <!ENTITY openFrameCmd.accesskey       "W">
+<!ENTITY openLinkCmdInContainerTab.label "Open Link in New Container Tab">
+<!ENTITY openLinkCmdInContainerTab.accesskey "C">
 <!ENTITY showOnlyThisFrameCmd.label     "Show Only This Frame">
 <!ENTITY showOnlyThisFrameCmd.accesskey "S">
 <!ENTITY reloadCmd.commandkey         "r">
 <!ENTITY reloadFrameCmd.label         "Reload Frame">
 <!ENTITY reloadFrameCmd.accesskey     "R">
 <!ENTITY viewPartialSourceForSelectionCmd.label "View Selection Source">
 <!ENTITY viewPartialSourceForMathMLCmd.label    "View MathML Source">
 <!-- LOCALIZATION NOTE (viewPartialSourceCmd.accesskey): This accesskey is used for both 
--- a/docshell/base/nsDocShell.cpp
+++ b/docshell/base/nsDocShell.cpp
@@ -3487,32 +3487,29 @@ nsDocShell::CanAccessItem(nsIDocShellTre
 
   if (aTargetItem == aAccessingItem) {
     // A frame is allowed to navigate itself.
     return true;
   }
 
   nsCOMPtr<nsIDocShell> targetDS = do_QueryInterface(aTargetItem);
   nsCOMPtr<nsIDocShell> accessingDS = do_QueryInterface(aAccessingItem);
-  if (!!targetDS != !!accessingDS) {
-    // We must be able to convert both or neither to nsIDocShell.
+  if (!targetDS || !accessingDS) {
+    // We must be able to convert both to nsIDocShell.
     return false;
   }
 
-  if (targetDS && accessingDS &&
-      (targetDS->GetIsInBrowserElement() !=
-         accessingDS->GetIsInBrowserElement() ||
-       targetDS->GetAppId() != accessingDS->GetAppId())) {
+  if (targetDS->GetIsInBrowserElement() != accessingDS->GetIsInBrowserElement() ||
+      targetDS->GetAppId() != accessingDS->GetAppId()) {
     return false;
   }
 
   // A private document can't access a non-private one, and vice versa.
-  if (aTargetItem->GetDocument()->GetLoadContext()->UsePrivateBrowsing() !=
-      aAccessingItem->GetDocument()->GetLoadContext()->UsePrivateBrowsing())
-  {
+  if (static_cast<nsDocShell*>(targetDS.get())->UsePrivateBrowsing() !=
+      static_cast<nsDocShell*>(accessingDS.get())->UsePrivateBrowsing()) {
     return false;
   }
 
 
   nsCOMPtr<nsIDocShellTreeItem> accessingRoot;
   aAccessingItem->GetSameTypeRootTreeItem(getter_AddRefs(accessingRoot));
 
   if (aTargetItem == accessingRoot) {
--- a/docshell/test/navigation/file_document_write_1.html
+++ b/docshell/test/navigation/file_document_write_1.html
@@ -1,22 +1,30 @@
 <html>
   <head>
     <script>
       function run() {
         document.open();
         document.write("<h5 id='dynamic'>document.written content</h5>");
         document.close();
         window.history.go(-1);
-        opener.setTimeout("isTestDynamic()", 2500);
       }
 
       function start() {
         if (++opener.testCount == 1) {
           setTimeout(run, 0);
         }
       }
+
+      window.addEventListener("pageshow",
+        function() {
+          ++opener.file_document_write_1_loadCount;
+          if (opener.file_document_write_1_loadCount == 2) {
+            opener.setTimeout("isTestDynamic()", 0);
+          }
+          opener.ok(opener.file_document_write_1_loadCount <= 2);
+        });
     </script>
   </head>
   <body onload="start();">
     <h5>static content</h5>
   </body>
 </html>
--- a/docshell/test/navigation/test_sessionhistory.html
+++ b/docshell/test/navigation/test_sessionhistory.html
@@ -44,16 +44,17 @@ function nextTest_() {
     testWindow = window.open(testFiles.shift(), "", "width=300,height=300");
     testWindow.onunload = function () { } //XXX
   } else {
     SimpleTest.finish();
   }
 }
 
 // Needed by file_document_write_1.html
+window.file_document_write_1_loadCount = 0;
 function isTestDynamic() {
   var dyn = testWindow.document.getElementById("dynamic");
   is(dyn, null, "Should have gone back to the static page!");
   nextTest();
   testWindow.close();
 }
 
 function nextTest() {
--- a/dom/animation/AnimationUtils.cpp
+++ b/dom/animation/AnimationUtils.cpp
@@ -6,16 +6,17 @@
 
 #include "AnimationUtils.h"
 
 #include "nsCSSParser.h" // For nsCSSParser
 #include "nsDebug.h"
 #include "nsIAtom.h"
 #include "nsIContent.h"
 #include "nsString.h"
+#include "mozilla/Attributes.h"
 #include "mozilla/ComputedTimingFunction.h" // ComputedTimingFunction
 #include "mozilla/dom/Element.h" // For dom::Element
 
 namespace mozilla {
 
 /* static */ void
 AnimationUtils::LogAsyncAnimationFailure(nsCString& aMessage,
                                          const nsIContent* aContent)
@@ -64,17 +65,17 @@ AnimationUtils::ParseEasing(const dom::E
       }
       switch (list->mValue.GetUnit()) {
         case eCSSUnit_Enumerated:
           // Return Nothing() if "linear" is passed in.
           if (list->mValue.GetIntValue() ==
               NS_STYLE_TRANSITION_TIMING_FUNCTION_LINEAR) {
             return Nothing();
           }
-          // Fall through
+          MOZ_FALLTHROUGH;
         case eCSSUnit_Cubic_Bezier:
         case eCSSUnit_Steps: {
           nsTimingFunction timingFunction;
           nsRuleNode::ComputeTimingFunction(list->mValue, timingFunction);
           ComputedTimingFunction computedTimingFunction;
           computedTimingFunction.Init(timingFunction);
           return Some(computedTimingFunction);
         }
--- a/dom/asmjscache/AsmJSCache.cpp
+++ b/dom/asmjscache/AsmJSCache.cpp
@@ -999,17 +999,18 @@ ParentRunnable::Run()
     case eSendingMetadataForRead: {
       AssertIsOnOwningThread();
       MOZ_ASSERT(mOpenMode == eOpenForRead);
 
       mState = eWaitingToOpenCacheFileForRead;
 
       // Metadata is now open.
       if (!SendOnOpenMetadataForRead(mMetadata)) {
-        Unused << Send__delete__(this, JS::AsmJSCache_InternalError);
+        Fail();
+        return NS_OK;
       }
 
       return NS_OK;
     }
 
     case eReadyToOpenCacheFileForRead: {
       AssertIsOnIOThread();
       MOZ_ASSERT(mOpenMode == eOpenForRead);
@@ -1033,17 +1034,18 @@ ParentRunnable::Run()
 
       // The entry is now open.
       MOZ_ASSERT(!mOpened);
       mOpened = true;
 
       FileDescriptor::PlatformHandleType handle =
         FileDescriptor::PlatformHandleType(PR_FileDesc2NativeHandle(mFileDesc));
       if (!SendOnOpenCacheFile(mFileSize, FileDescriptor(handle))) {
-        Unused << Send__delete__(this, JS::AsmJSCache_InternalError);
+        Fail();
+        return NS_OK;
       }
 
       return NS_OK;
     }
 
     case eFailing: {
       AssertIsOnOwningThread();
 
--- a/dom/base/Console.cpp
+++ b/dom/base/Console.cpp
@@ -1542,17 +1542,17 @@ FlushOutput(JSContext* aCx, Sequence<JS:
 }
 
 } // namespace
 
 bool
 Console::ProcessArguments(JSContext* aCx,
                           const Sequence<JS::Value>& aData,
                           Sequence<JS::Value>& aSequence,
-                          Sequence<JS::Value>& aStyles) const
+                          Sequence<nsString>& aStyles) const
 {
   AssertIsOnMainThread();
 
   if (aData.IsEmpty()) {
     return true;
   }
 
   if (aData.Length() == 1 || !aData[0].isString()) {
@@ -1688,23 +1688,28 @@ Console::ProcessArguments(JSContext* aCx
           JS::Rooted<JSString*> jsString(aCx, JS::ToString(aCx, v));
           if (!jsString) {
             return false;
           }
 
           int32_t diff = aSequence.Length() - aStyles.Length();
           if (diff > 0) {
             for (int32_t i = 0; i < diff; i++) {
-              if (!aStyles.AppendElement(JS::NullValue(), fallible)) {
+              if (!aStyles.AppendElement(NullString(), fallible)) {
                 return false;
               }
             }
           }
 
-          if (!aStyles.AppendElement(JS::StringValue(jsString), fallible)) {
+          nsAutoJSString string;
+          if (!string.init(aCx, jsString)) {
+            return false;
+          }
+
+          if (!aStyles.AppendElement(string, fallible)) {
             return false;
           }
         }
         break;
       }
 
       case 's':
         if (index < aData.Length()) {
--- a/dom/base/Console.h
+++ b/dom/base/Console.h
@@ -164,17 +164,17 @@ private:
   //
   // The aStyles array is populated with the style strings that the function
   // finds based the format string. The index of the styles matches the indexes
   // of elements that need the custom styling from aSequence. For elements with
   // no custom styling the array is padded with null elements.
   bool
   ProcessArguments(JSContext* aCx, const Sequence<JS::Value>& aData,
                    Sequence<JS::Value>& aSequence,
-                   Sequence<JS::Value>& aStyles) const;
+                   Sequence<nsString>& aStyles) const;
 
   void
   MakeFormatString(nsCString& aFormat, int32_t aInteger, int32_t aMantissa,
                    char aCh) const;
 
   // Stringify and Concat all the JS::Value in a single string using ' ' as
   // separator.
   void
--- a/dom/base/nsRange.cpp
+++ b/dom/base/nsRange.cpp
@@ -146,43 +146,92 @@ GetNextRangeCommonAncestor(nsINode* aNod
     if (!aNode->IsDescendantOfCommonAncestorForRangeInSelection()) {
       return nullptr;
     }
     aNode = aNode->GetParentNode();
   }
   return aNode;
 }
 
+/**
+ * A Comparator suitable for mozilla::BinarySearchIf for searching a collection
+ * of nsRange* for an overlap of (mNode, mStartOffset) .. (mNode, mEndOffset).
+ */
+struct IsItemInRangeComparator
+{
+  nsINode* mNode;
+  uint32_t mStartOffset;
+  uint32_t mEndOffset;
+
+  int operator()(const nsRange* const aRange) const
+  {
+    int32_t cmp = nsContentUtils::ComparePoints(mNode, mEndOffset,
+                                                aRange->GetStartParent(),
+                                                aRange->StartOffset());
+    if (cmp == 1) {
+      cmp = nsContentUtils::ComparePoints(mNode, mStartOffset,
+                                          aRange->GetEndParent(),
+                                          aRange->EndOffset());
+      if (cmp == -1) {
+        return 0;
+      }
+      return 1;
+    }
+    return -1;
+  }
+};
+
 /* static */ bool
 nsRange::IsNodeSelected(nsINode* aNode, uint32_t aStartOffset,
                         uint32_t aEndOffset)
 {
   NS_PRECONDITION(aNode, "bad arg");
 
   nsINode* n = GetNextRangeCommonAncestor(aNode);
   NS_ASSERTION(n || !aNode->IsSelectionDescendant(),
                "orphan selection descendant");
+
+  // Collect the potential ranges and their selection objects.
+  RangeHashTable ancestorSelectionRanges;
+  nsTHashtable<nsPtrHashKey<Selection>> ancestorSelections;
+  uint32_t maxRangeCount = 0;
   for (; n; n = GetNextRangeCommonAncestor(n->GetParentNode())) {
     RangeHashTable* ranges =
       static_cast<RangeHashTable*>(n->GetProperty(nsGkAtoms::range));
     for (auto iter = ranges->ConstIter(); !iter.Done(); iter.Next()) {
       nsRange* range = iter.Get()->GetKey();
       if (range->IsInSelection() && !range->Collapsed()) {
-        int32_t cmp = nsContentUtils::ComparePoints(aNode, aEndOffset,
-                                                    range->GetStartParent(),
-                                                    range->StartOffset());
-        if (cmp == 1) {
-          cmp = nsContentUtils::ComparePoints(aNode, aStartOffset,
-                                              range->GetEndParent(),
-                                              range->EndOffset());
-          if (cmp == -1) {
-            return true;
-          }
+        ancestorSelectionRanges.PutEntry(range);
+        Selection* selection = range->mSelection;
+        ancestorSelections.PutEntry(selection);
+        maxRangeCount = std::max(maxRangeCount, selection->RangeCount());
+      }
+    }
+  }
+
+  if (!ancestorSelectionRanges.IsEmpty()) {
+    nsTArray<const nsRange*> sortedRanges(maxRangeCount);
+    for (auto iter = ancestorSelections.ConstIter(); !iter.Done(); iter.Next()) {
+      Selection* selection = iter.Get()->GetKey();
+      // Sort the found ranges for |selection| in document order
+      // (Selection::GetRangeAt returns its ranges ordered).
+      for (uint32_t i = 0, len = selection->RangeCount(); i < len; ++i) {
+        nsRange* range = selection->GetRangeAt(i);
+        if (ancestorSelectionRanges.Contains(range)) {
+          sortedRanges.AppendElement(range);
         }
       }
+      MOZ_ASSERT(!sortedRanges.IsEmpty());
+      // Binary search the now sorted ranges.
+      IsItemInRangeComparator comparator = { aNode, aStartOffset, aEndOffset };
+      size_t unused;
+      if (mozilla::BinarySearchIf(sortedRanges, 0, sortedRanges.Length(), comparator, &unused)) {
+        return true;
+      }
+      sortedRanges.ClearAndRetainStorage();
     }
   }
   return false;
 }
 
 /******************************************************
  * constructor/destructor
  ******************************************************/
@@ -3100,16 +3149,22 @@ nsRange::Constructor(const GlobalObject&
   if (!window || !window->GetDoc()) {
     aRv.Throw(NS_ERROR_FAILURE);
     return nullptr;
   }
 
   return window->GetDoc()->CreateRange(aRv);
 }
 
+static bool ExcludeIfNextToNonSelectable(nsIContent* aContent)
+{
+  return aContent->IsNodeOfType(nsINode::eTEXT) &&
+    aContent->HasFlag(NS_CREATE_FRAME_IF_NON_WHITESPACE);
+}
+
 void
 nsRange::ExcludeNonSelectableNodes(nsTArray<RefPtr<nsRange>>* aOutRanges)
 {
   MOZ_ASSERT(mIsPositioned);
   MOZ_ASSERT(mEndParent);
   MOZ_ASSERT(mStartParent);
 
   nsRange* range = this;
@@ -3118,31 +3173,42 @@ nsRange::ExcludeNonSelectableNodes(nsTAr
     nsCOMPtr<nsIContentIterator> iter = NS_NewPreContentIterator();
     nsresult rv = iter->Init(range);
     if (NS_FAILED(rv)) {
       return;
     }
 
     bool added = false;
     bool seenSelectable = false;
+    // |firstNonSelectableContent| is the first node in a consecutive sequence
+    // of non-IsSelectable nodes.  When we find a selectable node after such
+    // a sequence we'll end the last nsRange, create a new one and restart
+    // the outer loop.
     nsIContent* firstNonSelectableContent = nullptr;
     while (true) {
       ErrorResult err;
       nsINode* node = iter->GetCurrentNode();
       iter->Next();
       bool selectable = true;
       nsIContent* content =
         node && node->IsContent() ? node->AsContent() : nullptr;
       if (content) {
-        nsIFrame* frame = content->GetPrimaryFrame();
-        for (nsIContent* p = content; !frame && (p = p->GetParent()); ) {
-          frame = p->GetPrimaryFrame();
+        if (firstNonSelectableContent && ExcludeIfNextToNonSelectable(content)) {
+          // Ignorable whitespace next to a sequence of non-selectable nodes
+          // counts as non-selectable (bug 1216001).
+          selectable = false;
         }
-        if (frame) {
-          frame->IsSelectable(&selectable, nullptr);
+        if (selectable) {
+          nsIFrame* frame = content->GetPrimaryFrame();
+          for (nsIContent* p = content; !frame && (p = p->GetParent()); ) {
+            frame = p->GetPrimaryFrame();
+          }
+          if (frame) {
+            frame->IsSelectable(&selectable, nullptr);
+          }
         }
       }
 
       if (!selectable) {
         if (!firstNonSelectableContent) {
           firstNonSelectableContent = content;
         }
         if (iter->IsDone() && seenSelectable) {
--- a/dom/base/nsRange.h
+++ b/dom/base/nsRange.h
@@ -247,16 +247,24 @@ public:
  *
  *  XXX - callers responsibility to ensure node in same doc as range!
  *
  *****************************************************************************/
   static nsresult CompareNodeToRange(nsINode* aNode, nsRange* aRange,
                                      bool *outNodeBefore,
                                      bool *outNodeAfter);
 
+  /**
+   * Return true if any part of (aNode, aStartOffset) .. (aNode, aEndOffset)
+   * overlaps any nsRange in aNode's GetNextRangeCommonAncestor ranges (i.e.
+   * where aNode is a descendant of a range's common ancestor node).
+   * If a nsRange starts in (aNode, aEndOffset) or if it ends in
+   * (aNode, aStartOffset) then it is non-overlapping and the result is false
+   * for that nsRange.  Collapsed ranges always counts as non-overlapping.
+   */
   static bool IsNodeSelected(nsINode* aNode, uint32_t aStartOffset,
                              uint32_t aEndOffset);
 
   static void CollectClientRects(nsLayoutUtils::RectCallback* aCollector,
                                  nsRange* aRange,
                                  nsINode* aStartParent, int32_t aStartOffset,
                                  nsINode* aEndParent, int32_t aEndOffset,
                                  bool aClampToEdge, bool aFlushLayout);
@@ -293,16 +301,24 @@ protected:
    * ancestor for the range.  This method uses the selection bits and
    * nsGkAtoms::range property on the nodes to quickly find the ancestor.
    * That is, it's a faster version of GetCommonAncestor that only works
    * for ranges in a Selection.  The method will assert and the behavior
    * is undefined if called on a range where IsInSelection() is false.
    */
   nsINode* GetRegisteredCommonAncestor();
 
+  // Helper to IsNodeSelected.
+  static bool IsNodeInSortedRanges(nsINode* aNode,
+                                   uint32_t aStartOffset,
+                                   uint32_t aEndOffset,
+                                   const nsTArray<const nsRange*>& aRanges,
+                                   size_t aRangeStart,
+                                   size_t aRangeEnd);
+
   struct MOZ_STACK_CLASS AutoInvalidateSelection
   {
     explicit AutoInvalidateSelection(nsRange* aRange) : mRange(aRange)
     {
 #ifdef DEBUG
       mWasInSelection = mRange->IsInSelection();
 #endif
       if (!mRange->IsInSelection() || mIsNested) {
--- a/dom/base/nsScreen.cpp
+++ b/dom/base/nsScreen.cpp
@@ -128,19 +128,25 @@ nsScreen::GetRect(nsRect& aRect)
 
   nsDeviceContext *context = GetDeviceContext();
 
   if (!context) {
     return NS_ERROR_FAILURE;
   }
 
   context->GetRect(aRect);
+  LayoutDevicePoint screenTopLeftDev =
+    LayoutDevicePixel::FromAppUnits(aRect.TopLeft(),
+                                    context->AppUnitsPerDevPixel());
+  DesktopPoint screenTopLeftDesk =
+    screenTopLeftDev / context->GetDesktopToDeviceScale();
 
-  aRect.x = nsPresContext::AppUnitsToIntCSSPixels(aRect.x);
-  aRect.y = nsPresContext::AppUnitsToIntCSSPixels(aRect.y);
+  aRect.x = NSToIntRound(screenTopLeftDesk.x);
+  aRect.y = NSToIntRound(screenTopLeftDesk.y);
+
   aRect.height = nsPresContext::AppUnitsToIntCSSPixels(aRect.height);
   aRect.width = nsPresContext::AppUnitsToIntCSSPixels(aRect.width);
 
   return NS_OK;
 }
 
 nsresult
 nsScreen::GetAvailRect(nsRect& aRect)
@@ -151,20 +157,31 @@ nsScreen::GetAvailRect(nsRect& aRect)
   }
 
   nsDeviceContext *context = GetDeviceContext();
 
   if (!context) {
     return NS_ERROR_FAILURE;
   }
 
+  nsRect r;
+  context->GetRect(r);
+  LayoutDevicePoint screenTopLeftDev =
+    LayoutDevicePixel::FromAppUnits(r.TopLeft(),
+                                    context->AppUnitsPerDevPixel());
+  DesktopPoint screenTopLeftDesk =
+    screenTopLeftDev / context->GetDesktopToDeviceScale();
+
   context->GetClientRect(aRect);
 
-  aRect.x = nsPresContext::AppUnitsToIntCSSPixels(aRect.x);
-  aRect.y = nsPresContext::AppUnitsToIntCSSPixels(aRect.y);
+  aRect.x = NSToIntRound(screenTopLeftDesk.x) +
+            nsPresContext::AppUnitsToIntCSSPixels(aRect.x - r.x);
+  aRect.y = NSToIntRound(screenTopLeftDesk.y) +
+            nsPresContext::AppUnitsToIntCSSPixels(aRect.y - r.y);
+
   aRect.height = nsPresContext::AppUnitsToIntCSSPixels(aRect.height);
   aRect.width = nsPresContext::AppUnitsToIntCSSPixels(aRect.width);
 
   return NS_OK;
 }
 
 mozilla::dom::ScreenOrientation*
 nsScreen::Orientation() const
--- a/dom/base/test/test_user_select.html
+++ b/dom/base/test/test_user_select.html
@@ -7,17 +7,17 @@
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
 
 <style type="text/css">
 @font-face {
   font-family: Ahem;
   src: url("Ahem.ttf");
 }
 body { font-family: Ahem; font-size: 20px; }
-s { -moz-user-select: none; }
+s, .non-selectable { -moz-user-select: none; }
 n { display: none; }
 a { position:absolute; bottom: 0; right:0; }
 .text { -moz-user-select: text; }
 </style>
 
 </head>
 <body>
 
@@ -29,16 +29,26 @@ a { position:absolute; bottom: 0; right:
 <div id="test6">aaaaaaabbbbbbbb<x><s>ccccccc</s></x></div>
 <div id="test7">aaaaaaa<x><s><n>bbbb</n>bbbb</s></x>ccccccc</div>
 <div id="test8"><x><s>aa<n>aaa</n>aa</s></x>bbbbbbbbccccccc</div>
 <div id="test9">aaaaaaabbbbbbbb<x><s>cc<n>ccccc</n></s></x></div>
 <div id="testA">aaaaaaa<n>bbb<s>bbbbb</s></n>ccccccc</div>
 <div id="testB"><n><s>aaaa</s>aaa</n>bbbbbbbbccccccc</div>
 <div id="testC">aaaaaaabbbbbbbb<n>cc<s>c</s>cccc</n></div>
 <div id="testE">aaa<s id="testEc1">aaaa<a class="text">bbbb</a>dd<a>cccc</a>ddddddd</s>eeee</div>
+<div id="testF">aaaa
+<div class="non-selectable">x</div>
+<div class="non-selectable">x</div>
+<div class="non-selectable">x</div>
+bbbb</div>
+<div id="testG" style="white-space:pre">aaaa
+<div class="non-selectable">x</div>
+<div class="non-selectable">x</div>
+<div class="non-selectable">x</div>
+bbbb</div>
 
 <iframe id="testD" src="data:text/html,<body>aaaa<span style='-moz-user-select:none'>bbbb</span>cccc"></iframe>
 
 <pre id="test">
 <script class="testbody" type="text/javascript">
 
 function test()
 {
@@ -95,19 +105,21 @@ function test()
   }
 
   function checkRangeText(text, index)
   {
     var r = window.getSelection().getRangeAt(index);
     is(NL(r.toString()), text, e.id + ": range["+index+"].toString()")
   }
 
-  function node(e, index)
+  function node(e, arg)
   {
-    return index == -1 ? e : e.childNodes[index];
+    if (typeof arg == "number")
+      return arg == -1 ? e : e.childNodes[arg];
+    return arg;
   }
 
   function checkRangeCount(n, e)
   {
     var sel = window.getSelection();
     is(sel.rangeCount, n, e.id + ": Selection range count");
   }
 
@@ -253,16 +265,32 @@ function test()
   checkRangeText('ccccccc', 0);
   checkText('', e);
   shiftClick(e, 20);
   checkRangeText('aaaaaabbbbbbbb', 0);
   checkText('aaaaaabbbbbbbb', e);
   checkRanges([[0,1,-1,1]], e);
   doneTest(e);
 
+  clear();
+  e = document.getElementById('testF');
+  synthesizeMouse(e, 1, 1, {});
+  synthesizeMouse(e, 400, 100, { shiftKey: true });
+  checkText("aaaa bbbb", e);
+  checkRanges([[0,0,-1,1],[6,0,6,5]], e);
+  doneTest(e);
+
+  clear();
+  e = document.getElementById('testG');
+  synthesizeMouse(e, 1, 1, {});
+  synthesizeMouse(e, 400, 180, { shiftKey: true });
+  checkText("aaaa bbbb", e); // XXX this doesn't seem right - bug 1247799
+  checkRanges([[0,0,-1,1],[2,0,-1,3],[4,0,-1,5],[6,0,6,5]], e);
+  doneTest(e);
+
   // ======================================================
   // ==================== Script tests ====================
   // ======================================================
 
   clear();
   e = document.getElementById('testD');
   clear(e.contentWindow);
   sel = e.contentWindow.getSelection();
--- a/dom/bindings/Codegen.py
+++ b/dom/bindings/Codegen.py
@@ -26,18 +26,19 @@ LEGACYCALLER_HOOK_NAME = '_legacycaller'
 HASINSTANCE_HOOK_NAME = '_hasInstance'
 RESOLVE_HOOK_NAME = '_resolve'
 MAY_RESOLVE_HOOK_NAME = '_mayResolve'
 ENUMERATE_HOOK_NAME = '_enumerate'
 ENUM_ENTRY_VARIABLE_NAME = 'strings'
 INSTANCE_RESERVED_SLOTS = 1
 
 
-def memberReservedSlot(member):
-    return "(DOM_INSTANCE_RESERVED_SLOTS + %d)" % member.slotIndex
+def memberReservedSlot(member, descriptor):
+    return ("(DOM_INSTANCE_RESERVED_SLOTS + %d)" %
+            member.slotIndices[descriptor.interface.identifier.name])
 
 
 def toStringBool(arg):
     return str(not not arg).lower()
 
 
 def toBindingNamespace(arg):
     return re.sub("((_workers)?$)", "Binding\\1", arg)
@@ -2144,17 +2145,17 @@ def isMaybeExposedIn(member, descriptor)
     return not descriptor.workers or member.isExposedInAnyWorker()
 
 
 def clearableCachedAttrs(descriptor):
     return (m for m in descriptor.interface.members if
             m.isAttr() and
             # Constants should never need clearing!
             m.dependsOn != "Nothing" and
-            m.slotIndex is not None)
+            m.slotIndices is not None)
 
 
 def MakeClearCachedValueNativeName(member):
     return "ClearCached%sValue" % MakeNativeName(member.identifier.name)
 
 
 def MakeJSImplClearCachedValueNativeName(member):
     return "_" + MakeClearCachedValueNativeName(member)
@@ -3800,18 +3801,16 @@ class CGUpdateMemberSlotsMethod(CGAbstra
                 body += fill(
                     """
 
                     if (!get_${member}(aCx, aWrapper, aObject, args)) {
                       return false;
                     }
                     // Getter handled setting our reserved slots
                     """,
-                    slot=memberReservedSlot(m),
-                    interface=self.descriptor.interface.identifier.name,
                     member=m.identifier.name)
 
         body += "\nreturn true;\n"
         return body
 
 
 class CGClearCachedValueMethod(CGAbstractMethod):
     def __init__(self, descriptor, member):
@@ -3823,17 +3822,17 @@ class CGClearCachedValueMethod(CGAbstrac
         else:
             args = []
             returnType = 'void'
         args.append(Argument(descriptor.nativeType + '*', 'aObject'))
         name = MakeClearCachedValueNativeName(member)
         CGAbstractMethod.__init__(self, descriptor, name, returnType, args)
 
     def definition_body(self):
-        slotIndex = memberReservedSlot(self.member)
+        slotIndex = memberReservedSlot(self.member, self.descriptor)
         if self.member.getExtendedAttribute("StoreInSlot"):
             # We have to root things and save the old value in case
             # regetting fails, so we can restore it.
             declObj = "JS::Rooted<JSObject*> obj(aCx);\n"
             noopRetval = " true"
             saveMember = (
                 "JS::Rooted<JS::Value> oldValue(aCx, js::GetReservedSlot(obj, %s));\n" %
                 slotIndex)
@@ -7366,17 +7365,17 @@ class CGPerSignatureCall(CGThing):
         if (returnsNewObject and
             self.returnType.isGeckoInterface()):
             wrapCode += dedent(
                 """
                 static_assert(!IsPointer<decltype(result)>::value,
                               "NewObject implies that we need to keep the object alive with a strong reference.");
                 """)
 
-        setSlot = self.idlNode.isAttr() and self.idlNode.slotIndex is not None
+        setSlot = self.idlNode.isAttr() and self.idlNode.slotIndices is not None
         if setSlot:
             # For attributes in slots, we want to do some
             # post-processing once we've wrapped them.
             successCode = "break;\n"
         else:
             successCode = None
 
         resultTemplateValues = {
@@ -7413,17 +7412,17 @@ class CGPerSignatureCall(CGThing):
                     "if (!JS_FreezeObject(cx, rvalObj)) {\n"
                     "  return false;\n"
                     "}\n")
                 if self.idlNode.type.nullable():
                     freezeValue = CGIfWrapper(freezeValue,
                                               "args.rval().isObject()")
                 postSteps += freezeValue.define()
             postSteps += ("js::SetReservedSlot(reflector, %s, args.rval());\n" %
-                          memberReservedSlot(self.idlNode))
+                          memberReservedSlot(self.idlNode, self.descriptor))
             # For the case of Cached attributes, go ahead and preserve our
             # wrapper if needed.  We need to do this because otherwise the
             # wrapper could get garbage-collected and the cached value would
             # suddenly disappear, but the whole premise of cached values is that
             # they never change without explicit action on someone's part.  We
             # don't do this for StoreInSlot, since those get dealt with during
             # wrapper setup, and failure would involve us trying to clear an
             # already-preserved wrapper.
@@ -7998,17 +7997,17 @@ class CGSetterCall(CGPerSignatureCall):
             useCounterName = None
         CGPerSignatureCall.__init__(self, None,
                                     [FakeArgument(argType, attr, allowTreatNonCallableAsNull=True)],
                                     nativeMethodName, attr.isStatic(),
                                     descriptor, attr, setter=True, useCounterName=useCounterName)
 
     def wrap_return_value(self):
         attr = self.idlNode
-        if self.descriptor.wrapperCache and attr.slotIndex is not None:
+        if self.descriptor.wrapperCache and attr.slotIndices is not None:
             if attr.getExtendedAttribute("StoreInSlot"):
                 args = "cx, self"
             else:
                 args = "self"
             clearSlot = ("%s(%s);\n" %
                          (MakeClearCachedValueNativeName(self.idlNode), args))
         else:
             clearSlot = ""
@@ -8545,17 +8544,17 @@ class CGSpecializedGetter(CGAbstractStat
         if self.attr.maplikeOrSetlike:
             # If the interface is maplike/setlike, there will be one getter
             # method for the size property of the backing object. Due to having
             # to unpack the backing object from the slot, this requires its own
             # generator.
             return getMaplikeOrSetlikeSizeGetterBody(self.descriptor, self.attr)
         nativeName = CGSpecializedGetter.makeNativeName(self.descriptor,
                                                         self.attr)
-        if self.attr.slotIndex is not None:
+        if self.attr.slotIndices is not None:
             if self.descriptor.hasXPConnectImpls:
                 raise TypeError("Interface '%s' has XPConnect impls, so we "
                                 "can't use our slot for property '%s'!" %
                                 (self.descriptor.interface.identifier.name,
                                  self.attr.identifier.name))
             prefix = fill(
                 """
                 // Have to either root across the getter call or reget after.
@@ -8571,17 +8570,17 @@ class CGSpecializedGetter(CGAbstractStat
                     args.rval().set(cachedVal);
                     // The cached value is in the compartment of reflector,
                     // so wrap into the caller compartment as needed.
                     return ${maybeWrap}(cx, args.rval());
                   }
                 }
 
                 """,
-                slot=memberReservedSlot(self.attr),
+                slot=memberReservedSlot(self.attr, self.descriptor),
                 maybeWrap=getMaybeWrapValueFuncForType(self.attr.type))
         else:
             prefix = ""
 
         return (prefix +
                 CGGetterCall(self.attr.type, nativeName,
                              self.descriptor, self.attr).define())
 
@@ -8822,20 +8821,23 @@ class CGMemberJITInfo(CGThing):
                 isMovable=toStringBool(movable),
                 isEliminatable=toStringBool(eliminatable),
                 isAlwaysInSlot=toStringBool(alwaysInSlot),
                 isLazilyCachedInSlot=toStringBool(lazilyInSlot),
                 isTypedMethod=toStringBool(isTypedMethod),
                 slotIndex=slotIndex)
             return initializer.rstrip()
 
-        slotAssert = dedent(
-            """
-            static_assert(%s <= JSJitInfo::maxSlotIndex, "We won't fit");
-            """ % slotIndex)
+        slotAssert = fill(
+            """
+            static_assert(${slotIndex} <= JSJitInfo::maxSlotIndex, "We won't fit");
+            static_assert(${slotIndex} < ${classReservedSlots}, "There is no slot for us");
+            """,
+            slotIndex=slotIndex,
+            classReservedSlots=INSTANCE_RESERVED_SLOTS + self.descriptor.interface.totalMembersInSlots)
         if args is not None:
             argTypes = "%s_argTypes" % infoName
             args = [CGMemberJITInfo.getJSArgType(arg.type) for arg in args]
             args.append("JSJitInfo::ArgTypeListEnd")
             argTypesDecl = (
                 "static const JSJitInfo::ArgType %s[] = { %s };\n" %
                 (argTypes, ", ".join(args)))
             return fill(
@@ -8873,20 +8875,20 @@ class CGMemberJITInfo(CGThing):
             getterinfal = "infallible" in self.descriptor.getExtendedAttributes(self.member, getter=True)
 
             movable = self.mayBeMovable() and getterinfal
             eliminatable = self.mayBeEliminatable() and getterinfal
             aliasSet = self.aliasSet()
 
             getterinfal = getterinfal and infallibleForMember(self.member, self.member.type, self.descriptor)
             isAlwaysInSlot = self.member.getExtendedAttribute("StoreInSlot")
-            if self.member.slotIndex is not None:
+            if self.member.slotIndices is not None:
                 assert isAlwaysInSlot or self.member.getExtendedAttribute("Cached")
                 isLazilyCachedInSlot = not isAlwaysInSlot
-                slotIndex = memberReservedSlot(self.member)
+                slotIndex = memberReservedSlot(self.member, self.descriptor)
                 # We'll statically assert that this is not too big in
                 # CGUpdateMemberSlotsMethod, in the case when
                 # isAlwaysInSlot is true.
             else:
                 isLazilyCachedInSlot = False
                 slotIndex = "0"
 
             result = self.defineJitInfo(getterinfo, getter, "Getter",
@@ -15323,17 +15325,17 @@ def getMaplikeOrSetlikeBackingObject(des
         bool created = false;
         if (!Get${func_prefix}BackingObject(cx, obj, ${slot}, &backingObj, &created)) {
           $*{errorReturn}
         }
         if (created) {
           PreserveWrapper<${selfType}>(self);
         }
         """,
-        slot=memberReservedSlot(maplikeOrSetlike),
+        slot=memberReservedSlot(maplikeOrSetlike, descriptor),
         func_prefix=func_prefix,
         errorReturn=getMaplikeOrSetlikeErrorReturn(helperImpl),
         selfType=descriptor.nativeType)
     return ret
 
 
 def getMaplikeOrSetlikeSizeGetterBody(descriptor, attr):
     """
--- a/dom/bindings/parser/WebIDL.py
+++ b/dom/bindings/parser/WebIDL.py
@@ -973,17 +973,19 @@ class IDLInterface(IDLObjectWithScope, I
         # Compute slot indices for our members before we pull in unforgeable
         # members from our parent. Also, maplike/setlike declarations get a
         # slot to hold their backing object.
         for member in self.members:
             if ((member.isAttr() and
                  (member.getExtendedAttribute("StoreInSlot") or
                   member.getExtendedAttribute("Cached"))) or
                 member.isMaplikeOrSetlike()):
-                member.slotIndex = self.totalMembersInSlots
+                if member.slotIndices is None:
+                    member.slotIndices = dict()
+                member.slotIndices[self.identifier.name] = self.totalMembersInSlots
                 self.totalMembersInSlots += 1
                 if member.getExtendedAttribute("StoreInSlot"):
                     self._ownMembersInSlots += 1
 
         if self.parent:
             # Make sure we don't shadow any of the [Unforgeable] attributes on
             # our ancestor interfaces.  We don't have to worry about
             # consequential interfaces here, because those have already been
@@ -3594,17 +3596,17 @@ class IDLIterable(IDLMaplikeOrSetlikeOrI
 # MaplikeOrSetlike adds ES6 map-or-set-like traits to an interface.
 class IDLMaplikeOrSetlike(IDLMaplikeOrSetlikeOrIterableBase):
 
     def __init__(self, location, identifier, maplikeOrSetlikeType,
                  readonly, keyType, valueType):
         IDLMaplikeOrSetlikeOrIterableBase.__init__(self, location, identifier, maplikeOrSetlikeType,
                                                    keyType, valueType, IDLInterfaceMember.Tags.MaplikeOrSetlike)
         self.readonly = readonly
-        self.slotIndex = None
+        self.slotIndices = None
 
         # When generating JSAPI access code, we need to know the backing object
         # type prefix to create the correct function. Generate here for reuse.
         if self.isMaplike():
             self.prefix = 'Map'
         elif self.isSetlike():
             self.prefix = 'Set'
 
@@ -3788,17 +3790,17 @@ class IDLAttribute(IDLInterfaceMember):
         self.readonly = readonly
         self.inherit = inherit
         self.static = static
         self.lenientThis = False
         self._unforgeable = False
         self.stringifier = stringifier
         self.enforceRange = False
         self.clamp = False
-        self.slotIndex = None
+        self.slotIndices = None
         assert maplikeOrSetlike is None or isinstance(maplikeOrSetlike, IDLMaplikeOrSetlike)
         self.maplikeOrSetlike = maplikeOrSetlike
         self.dependsOn = "Everything"
         self.affects = "Everything"
 
         if static and identifier.name == "prototype":
             raise WebIDLError("The identifier of a static attribute must not be 'prototype'",
                               [location])
--- a/dom/canvas/CanvasRenderingContext2D.cpp
+++ b/dom/canvas/CanvasRenderingContext2D.cpp
@@ -1565,19 +1565,17 @@ CanvasRenderingContext2D::ClearTarget()
   }
 }
 
 void
 CanvasRenderingContext2D::ReturnTarget()
 {
   if (mTarget && mBufferProvider) {
     CurrentState().transform = mTarget->GetTransform();
-    DrawTarget* oldDT = mTarget;
-    mTarget = nullptr;
-    mBufferProvider->ReturnAndUseDT(oldDT);
+    mBufferProvider->ReturnAndUseDT(mTarget.forget());
   }
 }
 
 NS_IMETHODIMP
 CanvasRenderingContext2D::InitializeWithSurface(nsIDocShell* aShell,
                                                 gfxASurface* aSurface,
                                                 int32_t aWidth,
                                                 int32_t aHeight)
@@ -4911,16 +4909,19 @@ CanvasRenderingContext2D::DrawWindow(nsG
     }
 
     thebes = new gfxContext(drawDT);
     thebes->SetMatrix(gfxMatrix::Scaling(matrix._11, matrix._22));
   }
 
   nsCOMPtr<nsIPresShell> shell = presContext->PresShell();
   Unused << shell->RenderDocument(r, renderDocFlags, backgroundColor, thebes);
+  // If this canvas was contained in the drawn window, the pre-transaction callback
+  // may have returned its DT. If so, we must reacquire it here.
+  EnsureTarget();
   if (drawDT) {
     RefPtr<SourceSurface> snapshot = drawDT->Snapshot();
     RefPtr<DataSourceSurface> data = snapshot->GetDataSurface();
 
     DataSourceSurface::MappedSurface rawData;
     if (NS_WARN_IF(!data->Map(DataSourceSurface::READ, &rawData))) {
         aError.Throw(NS_ERROR_FAILURE);
         return;
--- a/dom/canvas/WebGL2ContextFramebuffers.cpp
+++ b/dom/canvas/WebGL2ContextFramebuffers.cpp
@@ -15,38 +15,43 @@ namespace mozilla {
 
 static bool
 GetFBInfoForBlit(const WebGLFramebuffer* fb, const char* const fbInfo,
                  GLsizei* const out_samples,
                  const webgl::FormatInfo** const out_colorFormat,
                  const webgl::FormatInfo** const out_depthFormat,
                  const webgl::FormatInfo** const out_stencilFormat)
 {
-    *out_samples = 1; // TODO
+    *out_samples = 0;
     *out_colorFormat = nullptr;
     *out_depthFormat = nullptr;
     *out_stencilFormat = nullptr;
 
     if (fb->ColorAttachment(0).IsDefined()) {
         const auto& attachment = fb->ColorAttachment(0);
+        *out_samples = attachment.Samples();
         *out_colorFormat = attachment.Format()->format;
     }
 
     if (fb->DepthStencilAttachment().IsDefined()) {
         const auto& attachment = fb->DepthStencilAttachment();
+        *out_samples = attachment.Samples();
+
         *out_depthFormat = attachment.Format()->format;
         *out_stencilFormat = *out_depthFormat;
     } else {
         if (fb->DepthAttachment().IsDefined()) {
             const auto& attachment = fb->DepthAttachment();
+            *out_samples = attachment.Samples();
             *out_depthFormat = attachment.Format()->format;
         }
 
         if (fb->StencilAttachment().IsDefined()) {
             const auto& attachment = fb->StencilAttachment();
+            *out_samples = attachment.Samples();
             *out_stencilFormat = attachment.Format()->format;
         }
     }
     return true;
 }
 
 static void
 GetBackbufferFormats(const WebGLContextOptions& options,
@@ -128,17 +133,17 @@ WebGL2Context::BlitFramebuffer(GLint src
             return;
 
         if (!GetFBInfoForBlit(mBoundReadFramebuffer, "READ_FRAMEBUFFER", &srcSamples,
                               &srcColorFormat, &srcDepthFormat, &srcStencilFormat))
         {
             return;
         }
     } else {
-        srcSamples = 1; // Always 1.
+        srcSamples = 0; // Always 0.
 
         GetBackbufferFormats(mOptions, &srcColorFormat, &srcDepthFormat,
                              &srcStencilFormat);
     }
 
     GLsizei dstSamples;
     const webgl::FormatInfo* dstColorFormat = nullptr;
     const webgl::FormatInfo* dstDepthFormat = nullptr;
@@ -216,23 +221,23 @@ WebGL2Context::BlitFramebuffer(GLint src
     if (mask & LOCAL_GL_STENCIL_BUFFER_BIT &&
         dstStencilFormat != srcStencilFormat)
     {
         ErrorInvalidOperation("blitFramebuffer: Stencil buffer formats must"
                               " match if selected.");
         return;
     }
 
-    if (dstSamples != 1) {
+    if (dstSamples != 0) {
         ErrorInvalidOperation("blitFramebuffer: DRAW_FRAMEBUFFER may not have"
                               " multiple samples.");
         return;
     }
 
-    if (srcSamples != 1) {
+    if (srcSamples != 0) {
         if (mask & LOCAL_GL_COLOR_BUFFER_BIT &&
             dstColorFormat != srcColorFormat)
         {
             ErrorInvalidOperation("blitFramebuffer: Color buffer formats must"
                                   " match if selected, when reading from a"
                                   " multisampled source.");
             return;
         }
--- a/dom/canvas/WebGL2ContextRenderbuffers.cpp
+++ b/dom/canvas/WebGL2ContextRenderbuffers.cpp
@@ -10,63 +10,62 @@
 #include "WebGLContextUtils.h"
 
 namespace mozilla {
 
 void
 WebGL2Context::GetInternalformatParameter(JSContext* cx, GLenum target,
                                           GLenum internalformat, GLenum pname,
                                           JS::MutableHandleValue retval,
-                                          ErrorResult& rv)
+                                          ErrorResult& out_rv)
 {
-  if (IsContextLost())
-    return;
+    const char funcName[] = "getInternalfomratParameter";
+    if (IsContextLost())
+        return;
 
-  if (target != LOCAL_GL_RENDERBUFFER) {
-    return ErrorInvalidEnumInfo("getInternalfomratParameter: target must be "
-                                "RENDERBUFFER. Was:", target);
-  }
+    if (target != LOCAL_GL_RENDERBUFFER) {
+        ErrorInvalidEnum("%s: `target` must be RENDERBUFFER, was: 0x%04x.", funcName,
+                         target);
+        return;
+    }
 
-  // GL_INVALID_ENUM is generated if internalformat is not color-,
-  // depth-, or stencil-renderable.
-  // TODO: When format table queries lands.
-
-  if (pname != LOCAL_GL_SAMPLES) {
-    return ErrorInvalidEnumInfo("getInternalformatParameter: pname must be SAMPLES. "
-                                "Was:", pname);
-  }
+    // GL_INVALID_ENUM is generated if internalformat is not color-, depth-, or
+    // stencil-renderable.
+    // TODO: When format table queries lands.
 
-  GLint* samples = nullptr;
-  GLint sampleCount = 0;
-  gl->fGetInternalformativ(LOCAL_GL_RENDERBUFFER, internalformat,
-                           LOCAL_GL_NUM_SAMPLE_COUNTS, 1, &sampleCount);
-  if (sampleCount > 0) {
-    samples = new GLint[sampleCount];
-    gl->fGetInternalformativ(LOCAL_GL_RENDERBUFFER, internalformat, LOCAL_GL_SAMPLES,
-                             sampleCount, samples);
-  }
+    if (pname != LOCAL_GL_SAMPLES) {
+        ErrorInvalidEnumInfo("%s: `pname` must be SAMPLES, was 0x%04x.", funcName, pname);
+        return;
+    }
 
-  JSObject* obj = dom::Int32Array::Create(cx, this, sampleCount, samples);
-  if (!obj) {
-    rv = NS_ERROR_OUT_OF_MEMORY;
-  }
+    GLint* samples = nullptr;
+    GLint sampleCount = 0;
+    gl->fGetInternalformativ(LOCAL_GL_RENDERBUFFER, internalformat,
+                             LOCAL_GL_NUM_SAMPLE_COUNTS, 1, &sampleCount);
+    if (sampleCount > 0) {
+        samples = new GLint[sampleCount];
+        gl->fGetInternalformativ(LOCAL_GL_RENDERBUFFER, internalformat, LOCAL_GL_SAMPLES,
+                                 sampleCount, samples);
+    }
 
-  delete[] samples;
+    JSObject* obj = dom::Int32Array::Create(cx, this, sampleCount, samples);
+    if (!obj) {
+        out_rv = NS_ERROR_OUT_OF_MEMORY;
+    }
 
-  retval.setObjectOrNull(obj);
+    delete[] samples;
+
+    retval.setObjectOrNull(obj);
 }
 
 void
 WebGL2Context::RenderbufferStorageMultisample(GLenum target, GLsizei samples,
                                               GLenum internalFormat,
                                               GLsizei width, GLsizei height)
 {
-  const char funcName[] = "renderbufferStorageMultisample";
-  if (IsContextLost())
-    return;
+    const char funcName[] = "renderbufferStorageMultisample";
+    if (IsContextLost())
+        return;
 
-  //RenderbufferStorage_base(funcName, target, samples, internalFormat, width, height);
-
-  ErrorInvalidOperation("%s: Multisampling is still under development, and is currently"
-                        " disabled.", funcName);
+    RenderbufferStorage_base(funcName, target, samples, internalFormat, width, height);
 }
 
 } // namespace mozilla
--- a/dom/canvas/WebGLContext.cpp
+++ b/dom/canvas/WebGLContext.cpp
@@ -101,17 +101,16 @@ WebGLContextOptions::WebGLContextOptions
 
 WebGLContext::WebGLContext()
     : WebGLContextUnchecked(nullptr)
     , mBufferFetchingIsVerified(false)
     , mBufferFetchingHasPerVertex(false)
     , mMaxFetchedVertices(0)
     , mMaxFetchedInstances(0)
     , mBypassShaderValidation(false)
-    , mGLMaxSamples(1)
     , mNeedsFakeNoAlpha(false)
     , mNeedsFakeNoDepth(false)
     , mNeedsFakeNoStencil(false)
 {
     mGeneration = 0;
     mInvalidated = false;
     mCapturedFrameInvalidated = false;
     mShouldPresent = true;
--- a/dom/canvas/WebGLContext.h
+++ b/dom/canvas/WebGLContext.h
@@ -1109,17 +1109,16 @@ protected:
     int32_t mGLMaxTextureUnits;
     int32_t mGLMaxTextureImageUnits;
     int32_t mGLMaxVertexTextureImageUnits;
     int32_t mGLMaxVaryingVectors;
     int32_t mGLMaxFragmentUniformVectors;
     int32_t mGLMaxVertexUniformVectors;
     uint32_t  mGLMaxTransformFeedbackSeparateAttribs;
     GLuint  mGLMaxUniformBufferBindings;
-    GLsizei mGLMaxSamples;
 
     // What is supported:
     uint32_t mGLMaxColorAttachments;
     uint32_t mGLMaxDrawBuffers;
     // What we're allowing:
     uint32_t mImplMaxColorAttachments;
     uint32_t mImplMaxDrawBuffers;
 
--- a/dom/canvas/WebGLContextGL.cpp
+++ b/dom/canvas/WebGLContextGL.cpp
@@ -168,27 +168,23 @@ WebGLContext::BindRenderbuffer(GLenum ta
 
     if (!ValidateObjectAllowDeletedOrNull("bindRenderbuffer", wrb))
         return;
 
     // silently ignore a deleted buffer
     if (wrb && wrb->IsDeleted())
         return;
 
-    MakeContextCurrent();
-
-    // Sometimes we emulate renderbuffers (depth-stencil emu), so there's not
-    // always a 1-1 mapping from `wrb` to GL name. Just have `wrb` handle it.
+    // Usually, we would now call into glBindRenderbuffer. However, since we have to
+    // potentially emulate packed-depth-stencil, there's not a specific renderbuffer that
+    // we know we should bind here.
+    // Instead, we do all renderbuffer binding lazily.
+
     if (wrb) {
-        wrb->BindRenderbuffer();
-#ifdef ANDROID
-        wrb->mIsRB = true;
-#endif
-    } else {
-        gl->fBindRenderbuffer(target, 0);
+        wrb->mHasBeenBound = true;
     }
 
     mBoundRenderbuffer = wrb;
 }
 
 void WebGLContext::BlendEquation(GLenum mode)
 {
     if (IsContextLost())
@@ -1063,26 +1059,17 @@ WebGLContext::IsRenderbuffer(WebGLRender
         return false;
 
     if (!ValidateObjectAllowDeleted("isRenderBuffer", rb))
         return false;
 
     if (rb->IsDeleted())
         return false;
 
-#ifdef ANDROID
-    if (gl->WorkAroundDriverBugs() &&
-        gl->Renderer() == GLRenderer::AndroidEmulator)
-    {
-         return rb->mIsRB;
-    }
-#endif
-
-    MakeContextCurrent();
-    return gl->fIsRenderbuffer(rb->PrimaryGLName());
+    return rb->mHasBeenBound;
 }
 
 bool
 WebGLContext::IsShader(WebGLShader* shader)
 {
     if (IsContextLost())
         return false;
 
@@ -1794,76 +1781,51 @@ WebGLContext::ReadPixels(GLint x, GLint 
     if (!needAlphaFilled)
         return;
 
     SetFullAlpha(data, format, type, width, height, rowStride.value());
 }
 
 void
 WebGLContext::RenderbufferStorage_base(const char* funcName, GLenum target,
-                                       GLsizei samples,
-                                       GLenum internalFormat, GLsizei width,
-                                       GLsizei height)
+                                       GLsizei samples, GLenum internalFormat,
+                                       GLsizei width, GLsizei height)
 {
     if (IsContextLost())
         return;
 
-    if (!mBoundRenderbuffer) {
-        ErrorInvalidOperation("%s: Called on renderbuffer 0.", funcName);
-        return;
-    }
-
     if (target != LOCAL_GL_RENDERBUFFER) {
         ErrorInvalidEnumInfo("`target`", funcName, target);
         return;
     }
 
-    if (samples < 0 || samples > mGLMaxSamples) {
-        ErrorInvalidValue("%s: `samples` is out of the valid range.", funcName);
+    if (!mBoundRenderbuffer) {
+        ErrorInvalidOperation("%s: Called on renderbuffer 0.", funcName);
+        return;
+    }
+
+    if (samples < 0) {
+        ErrorInvalidValue("%s: `samples` must be >= 0.", funcName);
         return;
     }
 
     if (width < 0 || height < 0) {
-        ErrorInvalidValue("%s: Width and height must be >= 0.", funcName);
-        return;
-    }
-
-    if (uint32_t(width) > mImplMaxRenderbufferSize ||
-        uint32_t(height) > mImplMaxRenderbufferSize)
-    {
-        ErrorInvalidValue("%s: Width or height exceeds maximum renderbuffer"
-                          " size.", funcName);
+        ErrorInvalidValue("%s: `width` and `height` must be >= 0.", funcName);
         return;
     }
 
-    const auto usage = mFormatUsage->GetRBUsage(internalFormat);
-    if (!usage) {
-        ErrorInvalidEnumInfo("`internalFormat`", funcName, internalFormat);
-        return;
-    }
-
-    // Validation complete.
-
-    MakeContextCurrent();
-
-    GetAndFlushUnderlyingGLErrors();
-    mBoundRenderbuffer->RenderbufferStorage(samples, usage, width, height);
-    GLenum error = GetAndFlushUnderlyingGLErrors();
-    if (error) {
-        GenerateWarning("%s generated error %s", funcName,
-                        ErrorName(error));
-        return;
-    }
+    mBoundRenderbuffer->RenderbufferStorage(funcName, uint32_t(samples), internalFormat,
+                                            uint32_t(width), uint32_t(height));
 }
 
 void
 WebGLContext::RenderbufferStorage(GLenum target, GLenum internalFormat, GLsizei width, GLsizei height)
 {
-    RenderbufferStorage_base("renderbufferStorage", target, 0,
-                             internalFormat, width, height);
+    RenderbufferStorage_base("renderbufferStorage", target, 0, internalFormat, width,
+                             height);
 }
 
 void
 WebGLContext::Scissor(GLint x, GLint y, GLsizei width, GLsizei height)
 {
     if (IsContextLost())
         return;
 
@@ -2318,16 +2280,18 @@ WebGLContext::CreateFramebuffer()
     return globj.forget();
 }
 
 already_AddRefed<WebGLRenderbuffer>
 WebGLContext::CreateRenderbuffer()
 {
     if (IsContextLost())
         return nullptr;
+
+    MakeContextCurrent();
     RefPtr<WebGLRenderbuffer> globj = new WebGLRenderbuffer(this);
     return globj.forget();
 }
 
 void
 WebGLContext::Viewport(GLint x, GLint y, GLsizei width, GLsizei height)
 {
     if (IsContextLost())
--- a/dom/canvas/WebGLContextUtils.cpp
+++ b/dom/canvas/WebGLContextUtils.cpp
@@ -722,16 +722,18 @@ WebGLContext::AssertCachedBindings()
 
     MOZ_ASSERT(mBoundVertexArray);
     WebGLBuffer* curBuff = mBoundVertexArray->mElementArrayBuffer;
     bound = curBuff ? curBuff->mGLName : 0;
     AssertUintParamCorrect(gl, LOCAL_GL_ELEMENT_ARRAY_BUFFER_BINDING, bound);
 
     MOZ_ASSERT(!GetAndFlushUnderlyingGLErrors());
 #endif
+
+    // We do not check the renderbuffer binding, because we never rely on it matching.
 }
 
 void
 WebGLContext::AssertCachedState()
 {
 #ifdef DEBUG
     MakeContextCurrent();
 
--- a/dom/canvas/WebGLContextValidate.cpp
+++ b/dom/canvas/WebGLContextValidate.cpp
@@ -781,33 +781,28 @@ WebGLContext::InitAndValidateGL()
         mImplMaxCubeMapTextureSize = MINVALUE_GL_MAX_CUBE_MAP_TEXTURE_SIZE;
         mImplMaxRenderbufferSize = MINVALUE_GL_MAX_RENDERBUFFER_SIZE;
 
         mImplMax3DTextureSize = MINVALUE_GL_MAX_3D_TEXTURE_SIZE;
         mImplMaxArrayTextureLayers = MINVALUE_GL_MAX_ARRAY_TEXTURE_LAYERS;
 
         mGLMaxTextureImageUnits = MINVALUE_GL_MAX_TEXTURE_IMAGE_UNITS;
         mGLMaxVertexTextureImageUnits = MINVALUE_GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS;
-
-        mGLMaxSamples = 1;
     } else {
         gl->fGetIntegerv(LOCAL_GL_MAX_TEXTURE_SIZE, (GLint*)&mImplMaxTextureSize);
         gl->fGetIntegerv(LOCAL_GL_MAX_CUBE_MAP_TEXTURE_SIZE, (GLint*)&mImplMaxCubeMapTextureSize);
         gl->fGetIntegerv(LOCAL_GL_MAX_RENDERBUFFER_SIZE, (GLint*)&mImplMaxRenderbufferSize);
 
         if (!gl->GetPotentialInteger(LOCAL_GL_MAX_3D_TEXTURE_SIZE, (GLint*)&mImplMax3DTextureSize))
             mImplMax3DTextureSize = 0;
         if (!gl->GetPotentialInteger(LOCAL_GL_MAX_ARRAY_TEXTURE_LAYERS, (GLint*)&mImplMaxArrayTextureLayers))
             mImplMaxArrayTextureLayers = 0;
 
         gl->fGetIntegerv(LOCAL_GL_MAX_TEXTURE_IMAGE_UNITS, &mGLMaxTextureImageUnits);
         gl->fGetIntegerv(LOCAL_GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, &mGLMaxVertexTextureImageUnits);
-
-        if (!gl->GetPotentialInteger(LOCAL_GL_MAX_SAMPLES, (GLint*)&mGLMaxSamples))
-            mGLMaxSamples = 1;
     }
 
     // If we don't support a target, its max size is 0. We should only floor-to-POT if the
     // value if it's non-zero. (NB log2(0) is -Inf, so zero isn't an integer power-of-two)
     const auto fnFloorPOTIfSupported = [](uint32_t& val) {
         if (val) {
             val = FloorPOT(val);
         }
--- a/dom/canvas/WebGLFormats.cpp
+++ b/dom/canvas/WebGLFormats.cpp
@@ -411,30 +411,51 @@ BytesPerPixel(const PackingInfo& packing
 //////////////////////////////////////////////////////////////////////////////////////////
 //////////////////////////////////////////////////////////////////////////////////////////
 //////////////////////////////////////////////////////////////////////////////////////////
 //////////////////////////////////////////////////////////////////////////////////////////
 //////////////////////////////////////////////////////////////////////////////////////////
 //////////////////////////////////////////////////////////////////////////////////////////
 // FormatUsageAuthority
 
-
-
 bool
 FormatUsageInfo::IsUnpackValid(const PackingInfo& key,
                                const DriverUnpackInfo** const out_value) const
 {
     auto itr = validUnpacks.find(key);
     if (itr == validUnpacks.end())
         return false;
 
     *out_value = &(itr->second);
     return true;
 }
 
+void
+FormatUsageInfo::ResolveMaxSamples(gl::GLContext* gl)
+{
+    MOZ_ASSERT(!this->maxSamplesKnown);
+    MOZ_ASSERT(this->maxSamples == 0);
+    MOZ_ASSERT(gl->IsCurrent());
+
+    this->maxSamplesKnown = true;
+
+    const GLenum internalFormat = this->format->sizedFormat;
+    if (!internalFormat)
+        return;
+
+    if (!gl->IsSupported(gl::GLFeature::internalformat_query))
+        return; // Leave it at 0.
+
+    GLint maxSamplesGL = 0;
+    gl->fGetInternalformativ(LOCAL_GL_RENDERBUFFER, internalFormat, LOCAL_GL_SAMPLES, 1,
+                             &maxSamplesGL);
+
+    this->maxSamples = maxSamplesGL;
+}
+
 ////////////////////////////////////////
 
 static void
 AddSimpleUnsized(FormatUsageAuthority* fua, GLenum unpackFormat, GLenum unpackType,
                  EffectiveFormat effFormat)
 {
     auto usage = fua->EditUsage(effFormat);
     usage->isFilterable = true;
--- a/dom/canvas/WebGLFormats.h
+++ b/dom/canvas/WebGLFormats.h
@@ -243,34 +243,43 @@ GLenum ComponentType(const FormatInfo* f
 */
 ////////////////////////////////////////
 
 struct FormatUsageInfo
 {
     const FormatInfo* const format;
     bool isRenderable;
     bool isFilterable;
+
     std::map<PackingInfo, DriverUnpackInfo> validUnpacks;
     const DriverUnpackInfo* idealUnpack;
+
     const GLint* textureSwizzleRGBA;
 
+    bool maxSamplesKnown;
+    uint32_t maxSamples;
+
     static const GLint kLuminanceSwizzleRGBA[4];
     static const GLint kAlphaSwizzleRGBA[4];
     static const GLint kLumAlphaSwizzleRGBA[4];
 
     explicit FormatUsageInfo(const FormatInfo* _format)
         : format(_format)
         , isRenderable(false)
         , isFilterable(false)
         , idealUnpack(nullptr)
         , textureSwizzleRGBA(nullptr)
+        , maxSamplesKnown(false)
+        , maxSamples(0)
     { }
 
     bool IsUnpackValid(const PackingInfo& key,
                        const DriverUnpackInfo** const out_value) const;
+
+    void ResolveMaxSamples(gl::GLContext* gl);
 };
 
 class FormatUsageAuthority
 {
     std::map<EffectiveFormat, FormatUsageInfo> mUsageMap;
 
     std::map<GLenum, const FormatUsageInfo*> mRBFormatMap;
     std::map<GLenum, const FormatUsageInfo*> mSizedTexFormatMap;
--- a/dom/canvas/WebGLFramebuffer.cpp
+++ b/dom/canvas/WebGLFramebuffer.cpp
@@ -64,16 +64,27 @@ WebGLFBAttachPoint::Format() const
         return Texture()->ImageInfoAt(mTexImageTarget, mTexImageLevel).mFormat;
 
     if (Renderbuffer())
         return Renderbuffer()->Format();
 
     return nullptr;
 }
 
+uint32_t
+WebGLFBAttachPoint::Samples() const
+{
+    MOZ_ASSERT(IsDefined());
+
+    if (mRenderbufferPtr)
+        return mRenderbufferPtr->Samples();
+
+    return 0;
+}
+
 bool
 WebGLFBAttachPoint::HasAlpha() const
 {
     return Format()->format->hasAlpha;
 }
 
 const webgl::FormatUsageInfo*
 WebGLFramebuffer::GetFormatForAttachment(const WebGLFBAttachPoint& attachment) const
@@ -389,21 +400,21 @@ WebGLFBAttachPoint::FinalizeAttachment(g
                                              LOCAL_GL_STENCIL_ATTACHMENT, glName,
                                              mipLevel, layer);
             } else {
                 gl->fFramebufferTextureLayer(LOCAL_GL_FRAMEBUFFER, attachment, glName,
                                              mipLevel, layer);
             }
             break;
         }
-        return ;
+        return;
     }
 
     if (Renderbuffer()) {
-        Renderbuffer()->FramebufferRenderbuffer(attachment);
+        Renderbuffer()->DoFramebufferRenderbuffer(attachment);
         return;
     }
 
     MOZ_CRASH();
 }
 
 JS::Value
 WebGLFBAttachPoint::GetParameter(const char* funcName, WebGLContext* webgl, JSContext* cx,
@@ -785,59 +796,101 @@ WebGLFramebuffer::HasIncompleteAttachmen
 
     for (const auto& cur : mMoreColorAttachments) {
         hasIncomplete |= fnIsIncomplete(cur);
     }
 
     return hasIncomplete;
 }
 
-static bool
-MatchOrReplaceSize(const WebGLFBAttachPoint& cur, uint32_t* const out_width,
-                   uint32_t* const out_height)
-{
-    if (!cur.HasImage())
-        return true;
-
-    uint32_t width;
-    uint32_t height;
-    cur.Size(&width, &height);
-
-    if (!*out_width) {
-        MOZ_ASSERT(!*out_height);
-        *out_width = width;
-        *out_height = height;
-        return true;
-    }
-
-    return (width == *out_width &&
-            height == *out_height);
-}
-
 bool
 WebGLFramebuffer::AllImageRectsMatch() const
 {
     MOZ_ASSERT(HasDefinedAttachments());
     DebugOnly<nsCString> fbStatusInfo;
     MOZ_ASSERT(!HasIncompleteAttachments(&fbStatusInfo));
 
+    bool needsInit = true;
     uint32_t width = 0;
     uint32_t height = 0;
-    bool imageRectsMatch = true;
+
+    const auto fnInitializeOrMatch = [&needsInit, &width,
+                                      &height](const WebGLFBAttachPoint& attach)
+    {
+        if (!attach.HasImage())
+            return true;
+
+        uint32_t curWidth;
+        uint32_t curHeight;
+        attach.Size(&curWidth, &curHeight);
 
-    imageRectsMatch &= MatchOrReplaceSize(mColorAttachment0,       &width, &height);
-    imageRectsMatch &= MatchOrReplaceSize(mDepthAttachment,        &width, &height);
-    imageRectsMatch &= MatchOrReplaceSize(mStencilAttachment,      &width, &height);
-    imageRectsMatch &= MatchOrReplaceSize(mDepthStencilAttachment, &width, &height);
+        if (needsInit) {
+            needsInit = false;
+            width = curWidth;
+            height = curHeight;
+            return true;
+        }
+
+        return (curWidth == width &&
+                curHeight == height);
+    };
+
+    bool matches = true;
+
+    matches &= fnInitializeOrMatch(mColorAttachment0      );
+    matches &= fnInitializeOrMatch(mDepthAttachment       );
+    matches &= fnInitializeOrMatch(mStencilAttachment     );
+    matches &= fnInitializeOrMatch(mDepthStencilAttachment);
 
     for (const auto& cur : mMoreColorAttachments) {
-        imageRectsMatch &= MatchOrReplaceSize(cur, &width, &height);
+        matches &= fnInitializeOrMatch(cur);
     }
 
-    return imageRectsMatch;
+    return matches;
+}
+
+bool
+WebGLFramebuffer::AllImageSamplesMatch() const
+{
+    MOZ_ASSERT(HasDefinedAttachments());
+    DebugOnly<nsCString> fbStatusInfo;
+    MOZ_ASSERT(!HasIncompleteAttachments(&fbStatusInfo));
+
+    bool needsInit = true;
+    uint32_t samples = 0;
+
+    const auto fnInitializeOrMatch = [&needsInit,
+                                      &samples](const WebGLFBAttachPoint& attach)
+    {
+        if (!attach.HasImage())
+          return true;
+
+        const uint32_t curSamples = attach.Samples();
+
+        if (needsInit) {
+            needsInit = false;
+            samples = curSamples;
+            return true;
+        }
+
+        return (curSamples == samples);
+    };
+
+    bool matches = true;
+
+    matches &= fnInitializeOrMatch(mColorAttachment0      );
+    matches &= fnInitializeOrMatch(mDepthAttachment       );
+    matches &= fnInitializeOrMatch(mStencilAttachment     );
+    matches &= fnInitializeOrMatch(mDepthStencilAttachment);
+
+    for (const auto& cur : mMoreColorAttachments) {
+        matches &= fnInitializeOrMatch(cur);
+    }
+
+    return matches;
 }
 
 FBStatus
 WebGLFramebuffer::PrecheckFramebufferStatus(nsCString* const out_info) const
 {
     MOZ_ASSERT(mContext->mBoundDrawFramebuffer == this ||
                mContext->mBoundReadFramebuffer == this);
 
@@ -845,17 +898,21 @@ WebGLFramebuffer::PrecheckFramebufferSta
         return LOCAL_GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT; // No attachments
 
     if (HasIncompleteAttachments(out_info))
         return LOCAL_GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
 
     if (!AllImageRectsMatch())
         return LOCAL_GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS; // Inconsistent sizes
 
+    if (!AllImageSamplesMatch())
+        return LOCAL_GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE; // Inconsistent samples
+
     if (!mContext->IsWebGL2()) {
+        // INCOMPLETE_DIMENSIONS doesn't exist in GLES3.
         const auto depthOrStencilCount = int(mDepthAttachment.IsDefined()) +
                                          int(mStencilAttachment.IsDefined()) +
                                          int(mDepthStencilAttachment.IsDefined());
         if (depthOrStencilCount > 1)
             return LOCAL_GL_FRAMEBUFFER_UNSUPPORTED;
     }
 
     return LOCAL_GL_FRAMEBUFFER_COMPLETE;
--- a/dom/canvas/WebGLFramebuffer.h
+++ b/dom/canvas/WebGLFramebuffer.h
@@ -44,27 +44,27 @@ private:
     template<typename T>
     friend class PlacementArray;
 
     WebGLFBAttachPoint()
         : mFB(nullptr)
         , mAttachmentPoint(0)
     { }
 
-
 public:
     WebGLFBAttachPoint(WebGLFramebuffer* fb, GLenum attachmentPoint);
     ~WebGLFBAttachPoint();
 
     void Unlink();
 
     bool IsDefined() const;
     bool IsDeleteRequested() const;
 
     const webgl::FormatUsageInfo* Format() const;
+    uint32_t Samples() const;
 
     bool HasAlpha() const;
     bool IsReadableFloat() const;
 
     void Clear();
 
     void SetTexImage(WebGLTexture* tex, TexImageTarget target, GLint level);
     void SetTexImageLayer(WebGLTexture* tex, TexImageTarget target, GLint level,
@@ -93,17 +93,16 @@ public:
         return mTexImageLevel;
     }
     void AttachmentName(nsCString* out) const;
 
     bool HasUninitializedImageData() const;
     void SetImageDataStatus(WebGLImageDataStatus x);
 
     void Size(uint32_t* const out_width, uint32_t* const out_height) const;
-    //const WebGLRectangleObject& RectangleObject() const;
 
     bool HasImage() const;
     bool IsComplete(WebGLContext* webgl, nsCString* const out_info) const;
 
     void FinalizeAttachment(gl::GLContext* gl, GLenum attachmentLoc) const;
 
     JS::Value GetParameter(const char* funcName, WebGLContext* webgl, JSContext* cx,
                            GLenum target, GLenum attachment, GLenum pname,
@@ -224,16 +223,17 @@ public:
     void FramebufferTexture2D(GLenum attachment, TexImageTarget texImageTarget,
                               WebGLTexture* tex, GLint level);
     void FramebufferTextureLayer(GLenum attachment, WebGLTexture* tex, GLint level,
                                  GLint layer);
 
     bool HasDefinedAttachments() const;
     bool HasIncompleteAttachments(nsCString* const out_info) const;
     bool AllImageRectsMatch() const;
+    bool AllImageSamplesMatch() const;
     FBStatus PrecheckFramebufferStatus(nsCString* const out_info) const;
     FBStatus CheckFramebufferStatus(nsCString* const out_info) const;
 
     const webgl::FormatUsageInfo*
     GetFormatForAttachment(const WebGLFBAttachPoint& attachment) const;
 
     const WebGLFBAttachPoint& ColorAttachment(size_t colorAttachmentId) const {
         MOZ_ASSERT(colorAttachmentId < 1 + mMoreColorAttachments.Size());
--- a/dom/canvas/WebGLRenderbuffer.cpp
+++ b/dom/canvas/WebGLRenderbuffer.cpp
@@ -10,240 +10,246 @@
 #include "ScopedGLHelpers.h"
 #include "WebGLContext.h"
 #include "WebGLStrongTypes.h"
 #include "WebGLTexture.h"
 
 namespace mozilla {
 
 static GLenum
-DepthStencilDepthFormat(gl::GLContext* gl)
+DepthFormatForDepthStencilEmu(gl::GLContext* gl)
 {
     // We might not be able to get 24-bit, so let's pretend!
     if (gl->IsGLES() && !gl->IsExtensionSupported(gl::GLContext::OES_depth24))
         return LOCAL_GL_DEPTH_COMPONENT16;
 
     return LOCAL_GL_DEPTH_COMPONENT24;
 }
 
-static bool
-NeedsDepthStencilEmu(gl::GLContext* gl, GLenum internalFormat)
-{
-    MOZ_ASSERT(internalFormat != LOCAL_GL_DEPTH_STENCIL);
-
-    if (internalFormat != LOCAL_GL_DEPTH24_STENCIL8)
-        return false;
-
-    if (gl->IsSupported(gl::GLFeature::packed_depth_stencil))
-        return false;
-
-    return true;
-}
-
 JSObject*
 WebGLRenderbuffer::WrapObject(JSContext* cx, JS::Handle<JSObject*> givenProto)
 {
     return dom::WebGLRenderbufferBinding::Wrap(cx, this, givenProto);
 }
 
+static GLuint
+DoCreateRenderbuffer(gl::GLContext* gl)
+{
+    MOZ_ASSERT(gl->IsCurrent());
+
+    GLuint ret = 0;
+    gl->fGenRenderbuffers(1, &ret);
+    return ret;
+}
+
+static bool
+EmulatePackedDepthStencil(gl::GLContext* gl)
+{
+    return !gl->IsSupported(gl::GLFeature::packed_depth_stencil);
+}
+
 WebGLRenderbuffer::WebGLRenderbuffer(WebGLContext* webgl)
     : WebGLContextBoundObject(webgl)
-    , mPrimaryRB(0)
+    , mPrimaryRB( DoCreateRenderbuffer(webgl->gl) )
+    , mEmulatePackedDepthStencil( EmulatePackedDepthStencil(webgl->gl) )
     , mSecondaryRB(0)
     , mFormat(nullptr)
+    , mSamples(0)
     , mImageDataStatus(WebGLImageDataStatus::NoImageData)
-    , mSamples(1)
-    , mIsUsingSecondary(false)
-#ifdef ANDROID
-    , mIsRB(false)
-#endif
+    , mHasBeenBound(false)
 {
-    mContext->MakeContextCurrent();
-
-    mContext->gl->fGenRenderbuffers(1, &mPrimaryRB);
-
-    if (!mContext->gl->IsSupported(gl::GLFeature::packed_depth_stencil)) {
-        mContext->gl->fGenRenderbuffers(1, &mSecondaryRB);
-    }
-
     mContext->mRenderbuffers.insertBack(this);
 }
 
 void
 WebGLRenderbuffer::Delete()
 {
     mContext->MakeContextCurrent();
 
     mContext->gl->fDeleteRenderbuffers(1, &mPrimaryRB);
     if (mSecondaryRB)
         mContext->gl->fDeleteRenderbuffers(1, &mSecondaryRB);
 
     LinkedListElement<WebGLRenderbuffer>::removeFrom(mContext->mRenderbuffers);
-#ifdef ANDROID
-    mIsRB = false;
-#endif
 }
 
 int64_t
 WebGLRenderbuffer::MemoryUsage() const
 {
     // If there is no defined format, we're not taking up any memory
     if (!mFormat)
         return 0;
 
-    auto bytesPerPixel = mFormat->format->estimatedBytesPerPixel;
-    uint64_t pixels = uint64_t(mWidth) * uint64_t(mHeight);
-
-    uint64_t totalSize = pixels * bytesPerPixel;
+    const auto bytesPerPixel = mFormat->format->estimatedBytesPerPixel;
+    const int64_t pixels = int64_t(mWidth) * int64_t(mHeight);
 
-    // If we have the same bytesPerPixel whether or not we have a secondary RB.
-    if (mSecondaryRB && !mIsUsingSecondary) {
-        totalSize += 2; // 1x1xRGBA4
-    }
-
-    return int64_t(totalSize);
+    const int64_t totalSize = pixels * bytesPerPixel;
+    return totalSize;
 }
 
-void
-WebGLRenderbuffer::BindRenderbuffer() const
-{
-    /* Do this explicitly here, since the meaning changes for depth-stencil emu.
-     * Under normal circumstances, there's only one RB: `mPrimaryRB`.
-     * `mSecondaryRB` is used when we have to pretend that the renderbuffer is
-     * DEPTH_STENCIL, when it's actually one DEPTH buffer `mPrimaryRB` and one
-     * STENCIL buffer `mSecondaryRB`.
-     *
-     * In the DEPTH_STENCIL emulation case, we're actually juggling two RBs, but
-     * we can only bind one of them at a time. We choose to unconditionally bind
-     * the depth RB. When we need to ask about the stencil buffer (say, how many
-     * stencil bits we have), we temporarily bind the stencil RB, so that it
-     * looks like we're just asking the question of a combined DEPTH_STENCIL
-     * buffer.
-     */
-    mContext->gl->fBindRenderbuffer(LOCAL_GL_RENDERBUFFER, mPrimaryRB);
-}
-
-static void
-RenderbufferStorageMaybeMultisample(gl::GLContext* gl, GLsizei samples,
-                                    GLenum internalFormat, GLsizei width,
-                                    GLsizei height)
+static GLenum
+DoRenderbufferStorageMaybeMultisample(gl::GLContext* gl, GLsizei samples,
+                                      GLenum internalFormat, GLsizei width,
+                                      GLsizei height)
 {
     MOZ_ASSERT_IF(samples >= 1, gl->IsSupported(gl::GLFeature::framebuffer_multisample));
-    MOZ_ASSERT(samples >= 0);
-    MOZ_ASSERT(samples <= gl->MaxSamples());
 
-    // certain OpenGL ES renderbuffer formats may not exist on desktop OpenGL
-    GLenum internalFormatForGL = internalFormat;
-
+    // Certain OpenGL ES renderbuffer formats may not exist on desktop OpenGL.
     switch (internalFormat) {
     case LOCAL_GL_RGBA4:
     case LOCAL_GL_RGB5_A1:
-        // 16-bit RGBA formats are not supported on desktop GL
+        // 16-bit RGBA formats are not supported on desktop GL.
         if (!gl->IsGLES())
-            internalFormatForGL = LOCAL_GL_RGBA8;
+            internalFormat = LOCAL_GL_RGBA8;
         break;
 
     case LOCAL_GL_RGB565:
-        // the RGB565 format is not supported on desktop GL
+        // RGB565 is not supported on desktop GL.
         if (!gl->IsGLES())
-            internalFormatForGL = LOCAL_GL_RGB8;
+            internalFormat = LOCAL_GL_RGB8;
         break;
 
     case LOCAL_GL_DEPTH_COMPONENT16:
         if (!gl->IsGLES() || gl->IsExtensionSupported(gl::GLContext::OES_depth24))
-            internalFormatForGL = LOCAL_GL_DEPTH_COMPONENT24;
+            internalFormat = LOCAL_GL_DEPTH_COMPONENT24;
         else if (gl->IsSupported(gl::GLFeature::packed_depth_stencil))
-            internalFormatForGL = LOCAL_GL_DEPTH24_STENCIL8;
+            internalFormat = LOCAL_GL_DEPTH24_STENCIL8;
         break;
 
     case LOCAL_GL_DEPTH_STENCIL:
-        // We emulate this in WebGLRenderbuffer if we don't have the requisite extension.
-        internalFormatForGL = LOCAL_GL_DEPTH24_STENCIL8;
+        MOZ_CRASH("GL_DEPTH_STENCIL is not valid here.");
         break;
 
     default:
         break;
     }
 
+    gl::GLContext::LocalErrorScope errorScope(*gl);
+
     if (samples > 0) {
         gl->fRenderbufferStorageMultisample(LOCAL_GL_RENDERBUFFER, samples,
-                                            internalFormatForGL, width, height);
+                                            internalFormat, width, height);
     } else {
-        gl->fRenderbufferStorage(LOCAL_GL_RENDERBUFFER, internalFormatForGL, width,
-                                 height);
+        gl->fRenderbufferStorage(LOCAL_GL_RENDERBUFFER, internalFormat, width, height);
     }
+
+    return errorScope.GetError();
 }
 
-void
-WebGLRenderbuffer::RenderbufferStorage(GLsizei samples,
-                                       const webgl::FormatUsageInfo* format,
-                                       GLsizei width, GLsizei height)
+GLenum
+WebGLRenderbuffer::DoRenderbufferStorage(uint32_t samples,
+                                         const webgl::FormatUsageInfo* format,
+                                         uint32_t width, uint32_t height)
 {
     MOZ_ASSERT(mContext->mBoundRenderbuffer == this);
 
-
     gl::GLContext* gl = mContext->gl;
-    MOZ_ASSERT(samples >= 0 && samples <= 256); // Sanity check.
+    MOZ_ASSERT(samples <= 256); // Sanity check.
 
     GLenum primaryFormat = format->format->sizedFormat;
     GLenum secondaryFormat = 0;
 
-    if (NeedsDepthStencilEmu(mContext->gl, primaryFormat)) {
-        primaryFormat = DepthStencilDepthFormat(gl);
+    if (mEmulatePackedDepthStencil && primaryFormat == LOCAL_GL_DEPTH24_STENCIL8) {
+        primaryFormat = DepthFormatForDepthStencilEmu(gl);
         secondaryFormat = LOCAL_GL_STENCIL_INDEX8;
     }
 
-    RenderbufferStorageMaybeMultisample(gl, samples, primaryFormat, width,
-                                        height);
+    gl->fBindRenderbuffer(LOCAL_GL_RENDERBUFFER, mPrimaryRB);
+    GLenum error = DoRenderbufferStorageMaybeMultisample(gl, samples, primaryFormat,
+                                                         width, height);
+    if (error)
+        return error;
+
+    if (secondaryFormat) {
+        if (!mSecondaryRB) {
+            gl->fGenRenderbuffers(1, &mSecondaryRB);
+        }
+
+        gl->fBindRenderbuffer(LOCAL_GL_RENDERBUFFER, mSecondaryRB);
+        error = DoRenderbufferStorageMaybeMultisample(gl, samples, secondaryFormat,
+                                                      width, height);
+        if (error)
+            return error;
+    } else if (mSecondaryRB) {
+        gl->fDeleteRenderbuffers(1, &mSecondaryRB);
+        mSecondaryRB = 0;
+    }
+
+    return 0;
+}
 
-    if (mSecondaryRB) {
-        // We can't leave the secondary RB unspecified either, since we should
-        // handle the case where we attach a non-depth-stencil RB to a
-        // depth-stencil attachment point, or attach this depth-stencil RB to a
-        // non-depth-stencil attachment point.
-        gl::ScopedBindRenderbuffer autoRB(gl, mSecondaryRB);
-        if (secondaryFormat) {
-            RenderbufferStorageMaybeMultisample(gl, samples, secondaryFormat, width,
-                                                height);
-        } else {
-            RenderbufferStorageMaybeMultisample(gl, samples, LOCAL_GL_RGBA4, 1, 1);
-        }
+void
+WebGLRenderbuffer::RenderbufferStorage(const char* funcName, uint32_t samples,
+                                       GLenum internalFormat, uint32_t width,
+                                       uint32_t height)
+{
+    const auto usage = mContext->mFormatUsage->GetRBUsage(internalFormat);
+    if (!usage) {
+        mContext->ErrorInvalidEnum("%s: Invalid `internalFormat`: 0x%04x.", funcName,
+                                   internalFormat);
+        return;
+    }
+
+    if (width > mContext->mImplMaxRenderbufferSize ||
+        height > mContext->mImplMaxRenderbufferSize)
+    {
+        mContext->ErrorInvalidValue("%s: Width or height exceeds maximum renderbuffer"
+                                    " size.",
+                                    funcName);
+        return;
+    }
+
+    mContext->MakeContextCurrent();
+
+    if (!usage->maxSamplesKnown) {
+        const_cast<webgl::FormatUsageInfo*>(usage)->ResolveMaxSamples(mContext->gl);
+    }
+    MOZ_ASSERT(usage->maxSamplesKnown);
+
+    if (samples > usage->maxSamples) {
+        mContext->ErrorInvalidValue("%s: `samples` is out of the valid range.", funcName);
+        return;
+    }
+
+    // Validation complete.
+
+    const GLenum error = DoRenderbufferStorage(samples, usage, width, height);
+    if (error) {
+        const char* errorName = mContext->ErrorName(error);
+        mContext->GenerateWarning("%s generated error %s", funcName, errorName);
+        return;
     }
 
     mSamples = samples;
-    mFormat = format;
+    mFormat = usage;
     mWidth = width;
     mHeight = height;
     mImageDataStatus = WebGLImageDataStatus::UninitializedImageData;
-    mIsUsingSecondary = bool(secondaryFormat);
 
     InvalidateStatusOfAttachedFBs();
 }
 
 void
-WebGLRenderbuffer::FramebufferRenderbuffer(GLenum attachment) const
+WebGLRenderbuffer::DoFramebufferRenderbuffer(GLenum attachment) const
 {
     gl::GLContext* gl = mContext->gl;
-    if (attachment != LOCAL_GL_DEPTH_STENCIL_ATTACHMENT) {
-        gl->fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER, attachment,
+
+    if (attachment == LOCAL_GL_DEPTH_STENCIL_ATTACHMENT) {
+        const GLuint stencilRB = (mSecondaryRB ? mSecondaryRB : mPrimaryRB);
+        gl->fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER,
+                                     LOCAL_GL_DEPTH_ATTACHMENT,
                                      LOCAL_GL_RENDERBUFFER, mPrimaryRB);
+        gl->fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER,
+                                     LOCAL_GL_STENCIL_ATTACHMENT,
+                                     LOCAL_GL_RENDERBUFFER, stencilRB);
         return;
     }
 
-    GLuint stencilRB = mPrimaryRB;
-    if (mIsUsingSecondary) {
-        MOZ_ASSERT(mSecondaryRB);
-        stencilRB = mSecondaryRB;
-    }
-    gl->fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER,
-                                 LOCAL_GL_DEPTH_ATTACHMENT,
+    gl->fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER, attachment,
                                  LOCAL_GL_RENDERBUFFER, mPrimaryRB);
-    gl->fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER,
-                                 LOCAL_GL_STENCIL_ATTACHMENT,
-                                 LOCAL_GL_RENDERBUFFER, stencilRB);
 }
 
 GLint
 WebGLRenderbuffer::GetRenderbufferParameter(RBTarget target,
                                             RBParam pname) const
 {
     gl::GLContext* gl = mContext->gl;
 
@@ -261,16 +267,17 @@ WebGLRenderbuffer::GetRenderbufferParame
     case LOCAL_GL_RENDERBUFFER_WIDTH:
     case LOCAL_GL_RENDERBUFFER_HEIGHT:
     case LOCAL_GL_RENDERBUFFER_RED_SIZE:
     case LOCAL_GL_RENDERBUFFER_GREEN_SIZE:
     case LOCAL_GL_RENDERBUFFER_BLUE_SIZE:
     case LOCAL_GL_RENDERBUFFER_ALPHA_SIZE:
     case LOCAL_GL_RENDERBUFFER_DEPTH_SIZE:
         {
+            gl->fBindRenderbuffer(LOCAL_GL_RENDERBUFFER, mPrimaryRB);
             GLint i = 0;
             gl->fGetRenderbufferParameteriv(target.get(), pname.get(), &i);
             return i;
         }
 
     case LOCAL_GL_RENDERBUFFER_INTERNAL_FORMAT:
         {
             GLenum ret = 0;
@@ -280,18 +287,17 @@ WebGLRenderbuffer::GetRenderbufferParame
                 if (!mContext->IsWebGL2() && ret == LOCAL_GL_DEPTH24_STENCIL8) {
                     ret = LOCAL_GL_DEPTH_STENCIL;
                 }
             }
             return ret;
         }
     }
 
-    MOZ_ASSERT(false,
-               "This function should only be called with valid `pname`.");
+    MOZ_ASSERT(false, "This function should only be called with valid `pname`.");
     return 0;
 }
 
 NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_0(WebGLRenderbuffer)
 
 NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(WebGLRenderbuffer, AddRef)
 NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(WebGLRenderbuffer, Release)
 
--- a/dom/canvas/WebGLRenderbuffer.h
+++ b/dom/canvas/WebGLRenderbuffer.h
@@ -21,17 +21,36 @@ struct FormatUsageInfo;
 class WebGLRenderbuffer final
     : public nsWrapperCache
     , public WebGLRefCountedObject<WebGLRenderbuffer>
     , public LinkedListElement<WebGLRenderbuffer>
     , public WebGLRectangleObject
     , public WebGLContextBoundObject
     , public WebGLFramebufferAttachable
 {
+    friend class WebGLContext;
+    friend class WebGLFramebuffer;
+    friend class WebGLFBAttachPoint;
+
 public:
+    const GLuint mPrimaryRB;
+protected:
+    const bool mEmulatePackedDepthStencil;
+    GLuint mSecondaryRB;
+    const webgl::FormatUsageInfo* mFormat;
+    GLsizei mSamples;
+
+    WebGLImageDataStatus mImageDataStatus;
+
+    bool mHasBeenBound;
+
+public:
+    NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(WebGLRenderbuffer)
+    NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(WebGLRenderbuffer)
+
     explicit WebGLRenderbuffer(WebGLContext* webgl);
 
     void Delete();
 
     bool HasUninitializedImageData() const {
         MOZ_ASSERT(mImageDataStatus != WebGLImageDataStatus::NoImageData);
         return mImageDataStatus == WebGLImageDataStatus::UninitializedImageData;
     }
@@ -41,58 +60,36 @@ public:
             MOZ_ASSERT(!mWidth && !mHeight);
             return false;
         }
         return true;
     }
 
     GLsizei Samples() const { return mSamples; }
 
-    GLuint PrimaryGLName() const { return mPrimaryRB; }
-
     const webgl::FormatUsageInfo* Format() const { return mFormat; }
 
     int64_t MemoryUsage() const;
 
     WebGLContext* GetParentObject() const {
         return mContext;
     }
 
-    void BindRenderbuffer() const;
-    void RenderbufferStorage(GLsizei samples, const webgl::FormatUsageInfo* format,
-                             GLsizei width, GLsizei height);
-    void FramebufferRenderbuffer(GLenum attachment) const;
+    void RenderbufferStorage(const char* funcName, uint32_t samples,
+                             GLenum internalFormat, uint32_t width, uint32_t height);
     // Only handles a subset of `pname`s.
     GLint GetRenderbufferParameter(RBTarget target, RBParam pname) const;
 
     virtual JSObject* WrapObject(JSContext* cx, JS::Handle<JSObject*> givenProto) override;
 
-    NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(WebGLRenderbuffer)
-    NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(WebGLRenderbuffer)
-
 protected:
     ~WebGLRenderbuffer() {
         DeleteOnce();
     }
 
-    GLuint mPrimaryRB;
-    GLuint mSecondaryRB;
-    const webgl::FormatUsageInfo* mFormat;
-    WebGLImageDataStatus mImageDataStatus;
-    GLsizei mSamples;
-    bool mIsUsingSecondary;
-#ifdef ANDROID
-    // Bug 1140459: Some drivers (including our test slaves!) don't
-    // give reasonable answers for IsRenderbuffer, maybe others.
-    // This shows up on Android 2.3 emulator.
-    //
-    // So we track the `is a Renderbuffer` state ourselves.
-    bool mIsRB;
-#endif
-
-    friend class WebGLContext;
-    friend class WebGLFramebuffer;
-    friend class WebGLFBAttachPoint;
+    void DoFramebufferRenderbuffer(GLenum attachment) const;
+    GLenum DoRenderbufferStorage(uint32_t samples, const webgl::FormatUsageInfo* format,
+                                 uint32_t width, uint32_t height);
 };
 
 } // namespace mozilla
 
 #endif // WEBGL_RENDERBUFFER_H_
new file mode 100644
--- /dev/null
+++ b/dom/canvas/crashtests/1246775-1.html
@@ -0,0 +1,15 @@
+<html>
+<head>
+<script>
+function boom()
+{
+  var canvas = document.getElementById("canvas");
+  var ctx = SpecialPowers.wrap(canvas.getContext("2d"));
+  ctx.drawWindow(window, 0, 0, canvas.width, canvas.height, "red");
+}
+</script>
+</head>
+<body onload="boom();">
+<canvas id="canvas" width="10" height="10"></canvas>
+</body>
+</html>
--- a/dom/canvas/crashtests/crashtests.list
+++ b/dom/canvas/crashtests/crashtests.list
@@ -24,9 +24,10 @@ load 1161277-1.html
 load 1183363.html
 load 1190705.html
 load 1223740-1.html
 load 1225381-1.html
 skip-if(azureCairo) load 1229983-1.html
 load 1229932-1.html
 load 1233613.html
 load 1244850-1.html
+load 1246775-1.html
 load texImage2D.html
--- a/dom/events/TouchEvent.cpp
+++ b/dom/events/TouchEvent.cpp
@@ -189,17 +189,16 @@ TouchEvent::PrefEnabled(JSContext* aCx, 
       static bool sIsTouchDeviceSupportPresent = false;
       // On Windows and GTK3 we auto-detect based on device support.
       if (!sDidCheckTouchDeviceSupport) {
         sDidCheckTouchDeviceSupport = true;
         sIsTouchDeviceSupportPresent = WidgetUtils::IsTouchDeviceSupportPresent();
       }
       prefValue = sIsTouchDeviceSupportPresent;
 #else
-      NS_WARNING("dom.w3c_touch_events.enabled=2 not implemented!");
       prefValue = false;
 #endif
     } else {
       prefValue = !!flag;
     }
   }
   if (prefValue) {
     nsContentUtils::InitializeTouchEventTable();
--- a/dom/media/mediasource/MediaSource.cpp
+++ b/dom/media/mediasource/MediaSource.cpp
@@ -482,30 +482,16 @@ MediaSource::NotifyEvicted(double aStart
 {
   MOZ_ASSERT(NS_IsMainThread());
   MSE_DEBUG("NotifyEvicted(aStart=%f, aEnd=%f)", aStart, aEnd);
   // Cycle through all SourceBuffers and tell them to evict data in
   // the given range.
   mSourceBuffers->Evict(aStart, aEnd);
 }
 
-#if defined(DEBUG)
-void
-MediaSource::Dump(const char* aPath)
-{
-  char buf[255];
-  PR_snprintf(buf, sizeof(buf), "%s/mediasource-%p", aPath, this);
-  PR_MkDir(buf, 0700);
-
-  if (mSourceBuffers) {
-    mSourceBuffers->Dump(buf);
-  }
-}
-#endif
-
 void
 MediaSource::GetMozDebugReaderData(nsAString& aString)
 {
   mDecoder->GetMozDebugReaderData(aString);
 }
 
 nsPIDOMWindowInner*
 MediaSource::GetParentObject() const
--- a/dom/media/mediasource/MediaSource.h
+++ b/dom/media/mediasource/MediaSource.h
@@ -95,22 +95,16 @@ public:
     return mPrincipal;
   }
 
   // Called by SourceBuffers to notify this MediaSource that data has
   // been evicted from the buffered data. The start and end times
   // that were evicted are provided.
   void NotifyEvicted(double aStart, double aEnd);
 
-#if defined(DEBUG)
-  // Dump the contents of each SourceBuffer to a series of files under aPath.
-  // aPath must exist.  Debug only, invoke from your favourite debugger.
-  void Dump(const char* aPath);
-#endif
-
   // Returns a string describing the state of the MediaSource internal
   // buffered data. Used for debugging purposes.
   void GetMozDebugReaderData(nsAString& aString);
 
 private:
   // MediaSourceDecoder uses DurationChange to set the duration
   // without hitting the checks in SetDuration.
   friend class mozilla::MediaSourceDecoder;
--- a/dom/media/mediasource/MediaSourceDecoder.cpp
+++ b/dom/media/mediasource/MediaSourceDecoder.cpp
@@ -251,16 +251,22 @@ MediaSourceDecoder::GetDuration()
   MOZ_ASSERT(NS_IsMainThread());
   return ExplicitDuration();
 }
 
 MediaDecoderOwner::NextFrameStatus
 MediaSourceDecoder::NextFrameBufferedStatus()
 {
   MOZ_ASSERT(NS_IsMainThread());
+
+  if (!mMediaSource ||
+      mMediaSource->ReadyState() == dom::MediaSourceReadyState::Closed) {
+    return MediaDecoderOwner::NEXT_FRAME_UNAVAILABLE;
+  }
+
   // Next frame hasn't been decoded yet.
   // Use the buffered range to consider if we have the next frame available.
   TimeUnit currentPosition = TimeUnit::FromMicroseconds(CurrentPosition());
   TimeInterval interval(currentPosition,
                         currentPosition + media::TimeUnit::FromMicroseconds(DEFAULT_NEXT_FRAME_AVAILABLE_BUFFERED),
                         MediaSourceDemuxer::EOS_FUZZ);
   return GetBuffered().Contains(interval)
     ? MediaDecoderOwner::NEXT_FRAME_AVAILABLE
--- a/dom/media/mediasource/MediaSourceDemuxer.cpp
+++ b/dom/media/mediasource/MediaSourceDemuxer.cpp
@@ -17,17 +17,17 @@
 namespace mozilla {
 
 typedef TrackInfo::TrackType TrackType;
 using media::TimeUnit;
 using media::TimeIntervals;
 
 MediaSourceDemuxer::MediaSourceDemuxer()
   : mTaskQueue(new TaskQueue(GetMediaThreadPool(MediaThreadType::PLAYBACK),
-                             /* aSupportsTailDispatch = */ true))
+                             /* aSupportsTailDispatch = */ false))
   , mMonitor("MediaSourceDemuxer")
 {
   MOZ_ASSERT(NS_IsMainThread());
 }
 
 // Due to inaccuracies in determining buffer end
 // frames (Bug 1065207). This value is based on the end of frame
 // default value used in Blink, kDefaultBufferDurationInMs.
--- a/dom/media/mediasource/SourceBuffer.cpp
+++ b/dom/media/mediasource/SourceBuffer.cpp
@@ -34,37 +34,16 @@ extern mozilla::LogModule* GetMediaSourc
 #define MSE_API(arg, ...) MOZ_LOG(GetMediaSourceAPILog(), mozilla::LogLevel::Debug, ("SourceBuffer(%p:%s)::%s: " arg, this, mType.get(), __func__, ##__VA_ARGS__))
 
 namespace mozilla {
 
 using media::TimeUnit;
 
 namespace dom {
 
-class BufferAppendRunnable : public nsRunnable {
-public:
-  BufferAppendRunnable(SourceBuffer* aSourceBuffer,
-                       uint32_t aUpdateID)
-  : mSourceBuffer(aSourceBuffer)
-  , mUpdateID(aUpdateID)
-  {
-  }
-
-  NS_IMETHOD Run() override final {
-
-    mSourceBuffer->BufferAppend(mUpdateID);
-
-    return NS_OK;
-  }
-
-private:
-  RefPtr<SourceBuffer> mSourceBuffer;
-  uint32_t mUpdateID;
-};
-
 void
 SourceBuffer::SetMode(SourceBufferAppendMode aMode, ErrorResult& aRv)
 {
   typedef mozilla::SourceBufferContentManager::AppendState AppendState;
 
   MOZ_ASSERT(NS_IsMainThread());
   MSE_API("SetMode(aMode=%d)", aMode);
   if (!IsAttached() || mUpdating) {
@@ -221,20 +200,23 @@ SourceBuffer::Abort(ErrorResult& aRv)
   mAttributes->SetAppendWindowStart(0);
   mAttributes->SetAppendWindowEnd(PositiveInfinity<double>());
 }
 
 void
 SourceBuffer::AbortBufferAppend()
 {
   if (mUpdating) {
-    mPendingAppend.DisconnectIfExists();
-    // TODO: Abort stream append loop algorithms.
-    // cancel any pending buffer append.
-    mContentManager->AbortAppendData();
+    if (mPendingAppend.Exists()) {
+      mPendingAppend.Disconnect();
+      mContentManager->AbortAppendData();
+      // Some data may have been added by the Segment Parser Loop.
+      // Check if we need to update the duration.
+      CheckEndTime();
+    }
     AbortUpdating();
   }
 }
 
 void
 SourceBuffer::Remove(double aStart, double aEnd, ErrorResult& aRv)
 {
   MOZ_ASSERT(NS_IsMainThread());
@@ -304,17 +286,16 @@ SourceBuffer::Ended()
   mMediaSource->GetDecoder()->NotifyDataArrived();
 }
 
 SourceBuffer::SourceBuffer(MediaSource* aMediaSource, const nsACString& aType)
   : DOMEventTargetHelper(aMediaSource->GetParentObject())
   , mMediaSource(aMediaSource)
   , mUpdating(false)
   , mActive(false)
-  , mUpdateID(0)
   , mType(aType)
 {
   MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(aMediaSource);
   mEvictionThreshold = Preferences::GetUint("media.mediasource.eviction_threshold",
                                             100 * (1 << 20));
   bool generateTimestamps = false;
   if (aType.LowerCaseEqualsLiteral("audio/mpeg") ||
@@ -376,43 +357,37 @@ SourceBuffer::QueueAsyncSimpleEvent(cons
 }
 
 void
 SourceBuffer::StartUpdating()
 {
   MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(!mUpdating);
   mUpdating = true;
-  mUpdateID++;
   QueueAsyncSimpleEvent("updatestart");
 }
 
 void
 SourceBuffer::StopUpdating()
 {
   MOZ_ASSERT(NS_IsMainThread());
   if (!mUpdating) {
-    // The buffer append algorithm has been interrupted by abort().
-    //
-    // If the sequence appendBuffer(), abort(), appendBuffer() occurs before
-    // the first StopUpdating() runnable runs, then a second StopUpdating()
-    // runnable will be scheduled, but still only one (the first) will queue
-    // events.
+    // The buffer append or range removal algorithm  has been interrupted by
+    // abort().
     return;
   }
   mUpdating = false;
   QueueAsyncSimpleEvent("update");
   QueueAsyncSimpleEvent("updateend");
 }
 
 void
 SourceBuffer::AbortUpdating()
 {
   MOZ_ASSERT(NS_IsMainThread());
-  MOZ_ASSERT(mUpdating);
   mUpdating = false;
   QueueAsyncSimpleEvent("abort");
   QueueAsyncSimpleEvent("updateend");
 }
 
 void
 SourceBuffer::CheckEndTime()
 {
@@ -433,50 +408,37 @@ SourceBuffer::AppendData(const uint8_t* 
   RefPtr<MediaByteBuffer> data = PrepareAppend(aData, aLength, aRv);
   if (!data) {
     return;
   }
   mContentManager->AppendData(data, mAttributes->GetTimestampOffset());
 
   StartUpdating();
 
-  nsCOMPtr<nsIRunnable> task = new BufferAppendRunnable(this, mUpdateID);
-  NS_DispatchToMainThread(task);
+  BufferAppend();
 }
 
 void
-SourceBuffer::BufferAppend(uint32_t aUpdateID)
+SourceBuffer::BufferAppend()
 {
-  if (!mUpdating || aUpdateID != mUpdateID) {
-    // The buffer append algorithm has been interrupted by abort().
-    //
-    // If the sequence appendBuffer(), abort(), appendBuffer() occurs before
-    // the first StopUpdating() runnable runs, then a second StopUpdating()
-    // runnable will be scheduled, but still only one (the first) will queue
-    // events.
-    return;
-  }
-
+  MOZ_ASSERT(mUpdating);
   MOZ_ASSERT(mMediaSource);
   MOZ_ASSERT(!mPendingAppend.Exists());
 
   mPendingAppend.Begin(mContentManager->BufferAppend()
                        ->Then(AbstractThread::MainThread(), __func__, this,
                               &SourceBuffer::AppendDataCompletedWithSuccess,
                               &SourceBuffer::AppendDataErrored));
 }
 
 void
 SourceBuffer::AppendDataCompletedWithSuccess(bool aHasActiveTracks)
 {
+  MOZ_ASSERT(mUpdating);
   mPendingAppend.Complete();
-  if (!mUpdating) {
-    // The buffer append algorithm has been interrupted by abort().
-    return;
-  }
 
   if (aHasActiveTracks) {
     if (!mActive) {
       mActive = true;
       mMediaSource->SourceBufferIsActive(this);
     }
   }
   if (mActive) {
@@ -489,36 +451,35 @@ SourceBuffer::AppendDataCompletedWithSuc
   CheckEndTime();
 
   StopUpdating();
 }
 
 void
 SourceBuffer::AppendDataErrored(nsresult aError)
 {
+  MOZ_ASSERT(mUpdating);
   mPendingAppend.Complete();
+
   switch (aError) {
     case NS_ERROR_ABORT:
       // Nothing further to do as the trackbuffer has been shutdown.
       // or append was aborted and abort() has handled all the events.
       break;
     default:
       AppendError(true);
       break;
   }
 }
 
 void
 SourceBuffer::AppendError(bool aDecoderError)
 {
   MOZ_ASSERT(NS_IsMainThread());
-  if (!mUpdating) {
-    // The buffer append algorithm has been interrupted by abort().
-    return;
-  }
+
   mContentManager->ResetParserState();
 
   mUpdating = false;
 
   QueueAsyncSimpleEvent("error");
   QueueAsyncSimpleEvent("updateend");
 
   if (aDecoderError) {
@@ -620,26 +581,16 @@ SourceBuffer::Evict(double aStart, doubl
   double evictTime = aEnd;
   const double safety_threshold = 5;
   if (currentTime + safety_threshold >= evictTime) {
     evictTime -= safety_threshold;
   }
   mContentManager->EvictBefore(TimeUnit::FromSeconds(evictTime));
 }
 
-#if defined(DEBUG)
-void
-SourceBuffer::Dump(const char* aPath)
-{
-  if (mContentManager) {
-    mContentManager->Dump(aPath);
-  }
-}
-#endif
-
 NS_IMPL_CYCLE_COLLECTION_CLASS(SourceBuffer)
 
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(SourceBuffer)
   // Tell the TrackBuffer to end its current SourceBufferResource.
   SourceBufferContentManager* manager = tmp->mContentManager;
   if (manager) {
     manager->Detach();
   }
--- a/dom/media/mediasource/SourceBuffer.h
+++ b/dom/media/mediasource/SourceBuffer.h
@@ -208,20 +208,16 @@ public:
   // Runs the range removal algorithm as defined by the MSE spec.
   void RangeRemoval(double aStart, double aEnd);
 
   bool IsActive() const
   {
     return mActive;
   }
 
-#if defined(DEBUG)
-  void Dump(const char* aPath);
-#endif
-
 private:
   ~SourceBuffer();
 
   friend class AsyncEventRunner<SourceBuffer>;
   friend class BufferAppendRunnable;
   friend class mozilla::TrackBuffersManager;
   void DispatchSimpleEvent(const char* aName);
   void QueueAsyncSimpleEvent(const char* aName);
@@ -233,17 +229,17 @@ private:
 
   // If the media segment contains data beyond the current duration,
   // then run the duration change algorithm with new duration set to the
   // maximum of the current duration and the group end timestamp.
   void CheckEndTime();
 
   // Shared implementation of AppendBuffer overloads.
   void AppendData(const uint8_t* aData, uint32_t aLength, ErrorResult& aRv);
-  void BufferAppend(uint32_t aAppendID);
+  void BufferAppend();
 
   // Implement the "Append Error Algorithm".
   // Will call endOfStream() with "decode" error if aDecodeError is true.
   // 3.5.3 Append Error Algorithm
   // http://w3c.github.io/media-source/#sourcebuffer-append-error
   void AppendError(bool aDecoderError);
 
   // Implements the "Prepare Append Algorithm". Returns MediaByteBuffer object
@@ -261,21 +257,16 @@ private:
 
   RefPtr<SourceBufferContentManager> mContentManager;
   RefPtr<SourceBufferAttributes> mAttributes;
 
   bool mUpdating;
 
   mozilla::Atomic<bool> mActive;
 
-  // Each time mUpdating is set to true, mUpdateID will be incremented.
-  // This allows for a queued AppendData task to identify if it was earlier
-  // aborted and another AppendData queued.
-  uint32_t mUpdateID;
-
   MozPromiseRequestHolder<SourceBufferContentManager::AppendPromise> mPendingAppend;
   const nsCString mType;
 
   RefPtr<TimeRanges> mBuffered;
 };
 
 } // namespace dom
 
--- a/dom/media/mediasource/SourceBufferContentManager.h
+++ b/dom/media/mediasource/SourceBufferContentManager.h
@@ -103,19 +103,15 @@ public:
   {
     return AppendState::WAITING_FOR_SEGMENT;
   }
 
   virtual void SetGroupStartTimestamp(const media::TimeUnit& aGroupStartTimestamp) {}
   virtual void RestartGroupStartTimestamp() {}
   virtual media::TimeUnit GroupEndTimestamp() = 0;
 
-#if defined(DEBUG)
-  virtual void Dump(const char* aPath) { }
-#endif
-
 protected:
   virtual ~SourceBufferContentManager() { }
 };
 
 } // namespace mozilla
 
 #endif /* MOZILLA_SOURCEBUFFERCONTENTMANAGER_H_ */
--- a/dom/media/mediasource/SourceBufferList.cpp
+++ b/dom/media/mediasource/SourceBufferList.cpp
@@ -171,26 +171,16 @@ SourceBufferList::DispatchSimpleEvent(co
 void
 SourceBufferList::QueueAsyncSimpleEvent(const char* aName)
 {
   MSE_DEBUG("Queue event '%s'", aName);
   nsCOMPtr<nsIRunnable> event = new AsyncEventRunner<SourceBufferList>(this, aName);
   NS_DispatchToMainThread(event);
 }
 
-#if defined(DEBUG)
-void
-SourceBufferList::Dump(const char* aPath)
-{
-  for (uint32_t i = 0; i < mSourceBuffers.Length(); ++i) {
-    mSourceBuffers[i]->Dump(aPath);
-  }
-}
-#endif
-
 SourceBufferList::SourceBufferList(MediaSource* aMediaSource)
   : DOMEventTargetHelper(aMediaSource->GetParentObject())
   , mMediaSource(aMediaSource)
 {
   MOZ_ASSERT(aMediaSource);
 }
 
 MediaSource*
--- a/dom/media/mediasource/SourceBufferList.h
+++ b/dom/media/mediasource/SourceBufferList.h
@@ -79,20 +79,16 @@ public:
 
   // Append a SourceBuffer to the list. No event is fired.
   void AppendSimple(SourceBuffer* aSourceBuffer);
 
   // Remove all SourceBuffers from mSourceBuffers.
   //  No event is fired and no action is performed on the sourcebuffers.
   void ClearSimple();
 
-#if defined(DEBUG)
-  void Dump(const char* aPath);
-#endif
-
 private:
   ~SourceBufferList();
 
   friend class AsyncEventRunner<SourceBufferList>;
   void DispatchSimpleEvent(const char* aName);
   void QueueAsyncSimpleEvent(const char* aName);
 
   RefPtr<MediaSource> mMediaSource;
--- a/dom/media/mediasource/TrackBuffersManager.cpp
+++ b/dom/media/mediasource/TrackBuffersManager.cpp
@@ -91,34 +91,27 @@ TrackBuffersManager::TrackBuffersManager
   , mAppendState(AppendState::WAITING_FOR_SEGMENT)
   , mBufferFull(false)
   , mFirstInitializationSegmentReceived(false)
   , mNewMediaSegmentStarted(false)
   , mActiveTrack(false)
   , mType(aType)
   , mParser(ContainerParser::CreateForMIMEType(aType))
   , mProcessedInput(0)
-  , mAppendRunning(false)
   , mTaskQueue(aParentDecoder->GetDemuxer()->GetTaskQueue())
   , mSourceBufferAttributes(aAttributes)
   , mParentDecoder(new nsMainThreadPtrHolder<MediaSourceDecoder>(aParentDecoder, false /* strict */))
-  , mMediaSourceDuration(mTaskQueue, Maybe<double>(), "TrackBuffersManager::mMediaSourceDuration (Mirror)")
-  , mAbort(false)
   , mEvictionThreshold(Preferences::GetUint("media.mediasource.eviction_threshold",
                                             100 * (1 << 20)))
   , mEvictionOccurred(false)
   , mMonitor("TrackBuffersManager")
+  , mAppendRunning(false)
+  , mSegmentParserLoopRunning(false)
 {
   MOZ_ASSERT(NS_IsMainThread(), "Must be instanciated on the main thread");
-  RefPtr<TrackBuffersManager> self = this;
-  nsCOMPtr<nsIRunnable> task =
-    NS_NewRunnableFunction([self] () {
-      self->mMediaSourceDuration.Connect(self->mParentDecoder->CanonicalExplicitDuration());
-    });
-  GetTaskQueue()->Dispatch(task.forget());
 }
 
 TrackBuffersManager::~TrackBuffersManager()
 {
   ShutdownDemuxers();
 }
 
 bool
@@ -137,76 +130,69 @@ TrackBuffersManager::AppendData(MediaByt
   return true;
 }
 
 void
 TrackBuffersManager::AppendIncomingBuffer(IncomingBuffer aData)
 {
   MOZ_ASSERT(OnTaskQueue());
   mIncomingBuffers.AppendElement(aData);
-  mAbort = false;
 }
 
 RefPtr<TrackBuffersManager::AppendPromise>
 TrackBuffersManager::BufferAppend()
 {
   MOZ_ASSERT(NS_IsMainThread());
   MSE_DEBUG("");
 
+  mAppendRunning = true;
   return InvokeAsync(GetTaskQueue(), this,
                      __func__, &TrackBuffersManager::InitSegmentParserLoop);
 }
 
-// Abort any pending AppendData.
-// We don't really care about really aborting our inner loop as by spec the
-// process is happening asynchronously, as such where and when we would abort is
-// non-deterministic. The SourceBuffer also makes sure BufferAppend
-// isn't called should the appendBuffer be immediately aborted.
-// We do however want to ensure that no new task will be dispatched on our task
-// queue and only let the current one finish its job. For this we set mAbort
-// to true.
+// The MSE spec requires that we abort the current SegmentParserLoop
+// which is then followed by a call to ResetParserState.
+// However due to our asynchronous design this causes inherent difficulities.
+// As the spec behaviour is non deterministic anyway, we instead wait until the
+// current AppendData has completed its run.
 void
 TrackBuffersManager::AbortAppendData()
 {
   MOZ_ASSERT(NS_IsMainThread());
   MSE_DEBUG("");
 
-  mAbort = true;
+  MonitorAutoLock mon(mMonitor);
+  while (mAppendRunning) {
+    mon.Wait();
+  }
 }
 
 void
 TrackBuffersManager::ResetParserState()
 {
   MOZ_ASSERT(NS_IsMainThread());
-  MOZ_ASSERT(!mAppendRunning, "AbortAppendData must have been called");
+  MOZ_RELEASE_ASSERT(!mAppendRunning, "Append is running, abort must have been called");
   MSE_DEBUG("");
 
   // 1. If the append state equals PARSING_MEDIA_SEGMENT and the input buffer contains some complete coded frames, then run the coded frame processing algorithm until all of these complete coded frames have been processed.
-  if (mAppendState == AppendState::PARSING_MEDIA_SEGMENT) {
-    nsCOMPtr<nsIRunnable> task =
-      NS_NewRunnableMethod(this, &TrackBuffersManager::FinishCodedFrameProcessing);
-    GetTaskQueue()->Dispatch(task.forget());
-  } else {
-    nsCOMPtr<nsIRunnable> task =
-      NS_NewRunnableMethod(this, &TrackBuffersManager::CompleteResetParserState);
-    GetTaskQueue()->Dispatch(task.forget());
-  }
+  // SourceBuffer.abort() has ensured that all complete coded frames have been
+  // processed. As such, we don't need to check for the value of mAppendState.
+  nsCOMPtr<nsIRunnable> task =
+    NS_NewRunnableMethod(this, &TrackBuffersManager::CompleteResetParserState);
+  GetTaskQueue()->Dispatch(task.forget());
 
-  // Our ResetParserState is really asynchronous, the current task has been
-  // interrupted and will complete shortly (or has already completed).
-  // We must however present to the main thread a stable, reset state.
-  // So we run the following operation now in the main thread.
   // 7. Set append state to WAITING_FOR_SEGMENT.
   SetAppendState(AppendState::WAITING_FOR_SEGMENT);
 }
 
 RefPtr<TrackBuffersManager::RangeRemovalPromise>
 TrackBuffersManager::RangeRemoval(TimeUnit aStart, TimeUnit aEnd)
 {
   MOZ_ASSERT(NS_IsMainThread());
+  MOZ_RELEASE_ASSERT(!mAppendRunning, "Append is running");
   MSE_DEBUG("From %.2f to %.2f", aStart.ToSeconds(), aEnd.ToSeconds());
 
   mEnded = false;
 
   return InvokeAsync(GetTaskQueue(), this, __func__,
                      &TrackBuffersManager::CodedFrameRemovalWithPromise,
                      TimeInterval(aStart, aEnd));
 }
@@ -304,64 +290,23 @@ TrackBuffersManager::Ended()
   mEnded = true;
 }
 
 void
 TrackBuffersManager::Detach()
 {
   MOZ_ASSERT(NS_IsMainThread());
   MSE_DEBUG("");
-
-  // Abort pending operations if any.
-  AbortAppendData();
-
-  RefPtr<TrackBuffersManager> self = this;
-  nsCOMPtr<nsIRunnable> task =
-    NS_NewRunnableFunction([self] () {
-      // Clear our sourcebuffer
-      self->CodedFrameRemoval(TimeInterval(TimeUnit::FromSeconds(0),
-                                           TimeUnit::FromInfinity()));
-      self->mProcessingPromise.RejectIfExists(NS_ERROR_ABORT, __func__);
-      self->mAppendPromise.RejectIfExists(NS_ERROR_ABORT, __func__);
-      self->mMediaSourceDuration.DisconnectIfConnected();
-    });
-  GetTaskQueue()->Dispatch(task.forget());
-}
-
-#if defined(DEBUG)
-void
-TrackBuffersManager::Dump(const char* aPath)
-{
-
-}
-#endif
-
-void
-TrackBuffersManager::FinishCodedFrameProcessing()
-{
-  MOZ_ASSERT(OnTaskQueue());
-
-  if (mProcessingRequest.Exists()) {
-    NS_WARNING("Processing request pending");
-    mProcessingRequest.Disconnect();
-  }
-  // The spec requires us to complete parsing synchronously any outstanding
-  // frames in the current media segment. This can't be implemented in a way
-  // that makes sense.
-  // As such we simply completely ignore the result of any pending input buffer.
-  // TODO: Link to W3C bug.
-
-  CompleteResetParserState();
 }
 
 void
 TrackBuffersManager::CompleteResetParserState()
 {
   MOZ_ASSERT(OnTaskQueue());
-  MOZ_ASSERT(!mAppendRunning);
+  MOZ_RELEASE_ASSERT(!mSegmentParserLoopRunning);
   MSE_DEBUG("");
 
   for (auto& track : GetTracksList()) {
     // 2. Unset the last decode timestamp on all track buffers.
     // 3. Unset the last frame duration on all track buffers.
     // 4. Unset the highest end timestamp on all track buffers.
     // 5. Set the need random access point flag on all track buffers to true.
     track->ResetAppendState();
@@ -487,29 +432,21 @@ TrackBuffersManager::CodedFrameRemovalWi
   bool rv = CodedFrameRemoval(aInterval);
   return RangeRemovalPromise::CreateAndResolve(rv, __func__);
 }
 
 bool
 TrackBuffersManager::CodedFrameRemoval(TimeInterval aInterval)
 {
   MOZ_ASSERT(OnTaskQueue());
-  MOZ_ASSERT(!mAppendRunning, "Logic error: Append in progress");
+  MOZ_ASSERT(!mSegmentParserLoopRunning, "Logic error: Append in progress");
   MSE_DEBUG("From %.2fs to %.2f",
             aInterval.mStart.ToSeconds(), aInterval.mEnd.ToSeconds());
 
-  if (mMediaSourceDuration.Ref().isNothing() ||
-      IsNaN(mMediaSourceDuration.Ref().ref())) {
-    MSE_DEBUG("Nothing to remove, aborting");
-    return false;
-  }
-  TimeUnit duration{TimeUnit::FromSeconds(mMediaSourceDuration.Ref().ref())};
-
 #if DEBUG
-  MSE_DEBUG("duration:%.2f", duration.ToSeconds());
   if (HasVideo()) {
     MSE_DEBUG("before video ranges=%s",
               DumpTimeRanges(mVideoTracks.mBufferedRanges).get());
   }
   if (HasAudio()) {
     MSE_DEBUG("before audio ranges=%s",
               DumpTimeRanges(mAudioTracks.mBufferedRanges).get());
   }
@@ -522,17 +459,24 @@ TrackBuffersManager::CodedFrameRemoval(T
 
   bool dataRemoved = false;
 
   // 3. For each track buffer in this source buffer, run the following steps:
   for (auto track : GetTracksList()) {
     MSE_DEBUGV("Processing %s track", track->mInfo->mMimeType.get());
     // 1. Let remove end timestamp be the current value of duration
     // See bug: https://www.w3.org/Bugs/Public/show_bug.cgi?id=28727
-    TimeUnit removeEndTimestamp = std::max(duration, track->mBufferedRanges.GetEnd());
+    // At worse we will remove all frames until the end, unless a key frame is
+    // found between the current interval's end and the trackbuffer's end.
+    TimeUnit removeEndTimestamp = track->mBufferedRanges.GetEnd();
+
+    if (start > removeEndTimestamp) {
+      // Nothing to remove.
+      continue;
+    }
 
     // 2. If this track buffer has a random access point timestamp that is greater than or equal to end,
     // then update remove end timestamp to that random access point timestamp.
     if (end < track->mBufferedRanges.GetEnd()) {
       for (auto& frame : track->mBuffers.LastElement()) {
         if (frame->mKeyframe && frame->mTime >= end.ToMicroseconds()) {
           removeEndTimestamp = TimeUnit::FromMicroseconds(frame->mTime);
           break;
@@ -590,18 +534,19 @@ TrackBuffersManager::UpdateBufferedRange
 
   mOfficialGroupEndTimestamp = mGroupEndTimestamp;
 }
 
 RefPtr<TrackBuffersManager::AppendPromise>
 TrackBuffersManager::InitSegmentParserLoop()
 {
   MOZ_ASSERT(OnTaskQueue());
+  MOZ_RELEASE_ASSERT(mAppendPromise.IsEmpty());
+  MSE_DEBUG("");
 
-  MOZ_ASSERT(mAppendPromise.IsEmpty() && !mAppendRunning);
   RefPtr<AppendPromise> p = mAppendPromise.Ensure(__func__);
 
   AppendIncomingBuffers();
   SegmentParserLoop();
 
   return p;
 }
 
@@ -625,16 +570,19 @@ TrackBuffersManager::AppendIncomingBuffe
     TimeInterval(TimeUnit::FromSeconds(mSourceBufferAttributes->GetAppendWindowStart()),
                  TimeUnit::FromSeconds(mSourceBufferAttributes->GetAppendWindowEnd()));
 }
 
 void
 TrackBuffersManager::SegmentParserLoop()
 {
   MOZ_ASSERT(OnTaskQueue());
+
+  mSegmentParserLoopRunning = true;
+
   while (true) {
     // 1. If the input buffer is empty, then jump to the need more data step below.
     if (!mInputBuffer || mInputBuffer->IsEmpty()) {
       NeedMoreData();
       return;
     }
     // 2. If the input buffer contains bytes that violate the SourceBuffer
     // byte stream format specification, then run the append error algorithm with
@@ -728,17 +676,17 @@ TrackBuffersManager::SegmentParserLoop()
       }
 
       // 3. If the input buffer contains one or more complete coded frames, then run the coded frame processing algorithm.
       RefPtr<TrackBuffersManager> self = this;
       mProcessingRequest.Begin(CodedFrameProcessing()
           ->Then(GetTaskQueue(), __func__,
                  [self] (bool aNeedMoreData) {
                    self->mProcessingRequest.Complete();
-                   if (aNeedMoreData || self->mAbort) {
+                   if (aNeedMoreData) {
                      self->NeedMoreData();
                    } else {
                      self->ScheduleSegmentParserLoop();
                    }
                  },
                  [self] (nsresult aRejectValue) {
                    self->mProcessingRequest.Complete();
                    self->RejectAppend(aRejectValue, __func__);
@@ -747,28 +695,38 @@ TrackBuffersManager::SegmentParserLoop()
     }
   }
 }
 
 void
 TrackBuffersManager::NeedMoreData()
 {
   MSE_DEBUG("");
-  if (!mAbort) {
-    RestoreCachedVariables();
+  RestoreCachedVariables();
+  mAppendRunning = false;
+  mSegmentParserLoopRunning = false;
+  {
+    // Wake-up any pending Abort()
+    MonitorAutoLock mon(mMonitor);
+    mon.NotifyAll();
   }
-  mAppendRunning = false;
   mAppendPromise.ResolveIfExists(mActiveTrack, __func__);
 }
 
 void
 TrackBuffersManager::RejectAppend(nsresult aRejectValue, const char* aName)
 {
   MSE_DEBUG("rv=%d", aRejectValue);
   mAppendRunning = false;
+  mSegmentParserLoopRunning = false;
+  {
+    // Wake-up any pending Abort()
+    MonitorAutoLock mon(mMonitor);
+    mon.NotifyAll();
+  }
   mAppendPromise.RejectIfExists(aRejectValue, aName);
 }
 
 void
 TrackBuffersManager::ScheduleSegmentParserLoop()
 {
   nsCOMPtr<nsIRunnable> task =
     NS_NewRunnableMethod(this, &TrackBuffersManager::SegmentParserLoop);
@@ -835,22 +793,17 @@ TrackBuffersManager::ResetDemuxingState(
                              &TrackBuffersManager::OnDemuxerResetDone,
                              &TrackBuffersManager::OnDemuxerInitFailed));
 }
 
 void
 TrackBuffersManager::OnDemuxerResetDone(nsresult)
 {
   MOZ_ASSERT(OnTaskQueue());
-  MSE_DEBUG("mAbort:%d", static_cast<bool>(mAbort));
   mDemuxerInitRequest.Complete();
-  if (mAbort) {
-    RejectAppend(NS_ERROR_ABORT, __func__);
-    return;
-  }
   // mInputDemuxer shouldn't have been destroyed while a demuxer init/reset
   // request was being processed. See bug 1239983.
   MOZ_DIAGNOSTIC_ASSERT(mInputDemuxer);
 
   // Recreate track demuxers.
   uint32_t numVideos = mInputDemuxer->GetNumberTracks(TrackInfo::kVideoTrack);
   if (numVideos) {
     // We currently only handle the first video track.
@@ -912,23 +865,18 @@ TrackBuffersManager::InitializationSegme
                              &TrackBuffersManager::OnDemuxerInitDone,
                              &TrackBuffersManager::OnDemuxerInitFailed));
 }
 
 void
 TrackBuffersManager::OnDemuxerInitDone(nsresult)
 {
   MOZ_ASSERT(OnTaskQueue());
-  MSE_DEBUG("mAbort:%d", static_cast<bool>(mAbort));
   mDemuxerInitRequest.Complete();
 
-  if (mAbort) {
-    RejectAppend(NS_ERROR_ABORT, __func__);
-    return;
-  }
   // mInputDemuxer shouldn't have been destroyed while a demuxer init/reset
   // request was being processed. See bug 1239983.
   MOZ_DIAGNOSTIC_ASSERT(mInputDemuxer);
 
   MediaInfo info;
 
   uint32_t numVideos = mInputDemuxer->GetNumberTracks(TrackInfo::kVideoTrack);
   if (numVideos) {
@@ -1178,19 +1126,18 @@ TrackBuffersManager::CodedFrameProcessin
   return p;
 }
 
 void
 TrackBuffersManager::OnDemuxFailed(TrackType aTrack,
                                    DemuxerFailureReason aFailure)
 {
   MOZ_ASSERT(OnTaskQueue());
-  MSE_DEBUG("Failed to demux %s, failure:%d mAbort:%d",
-            aTrack == TrackType::kVideoTrack ? "video" : "audio",
-            aFailure, static_cast<bool>(mAbort));
+  MSE_DEBUG("Failed to demux %s, failure:%d",
+            aTrack == TrackType::kVideoTrack ? "video" : "audio", aFailure);
   switch (aFailure) {
     case DemuxerFailureReason::END_OF_STREAM:
     case DemuxerFailureReason::WAITING_FOR_DATA:
       if (aTrack == TrackType::kVideoTrack) {
         DoDemuxAudio();
       } else {
         CompleteCodedFrameProcessing();
       }
@@ -1207,25 +1154,20 @@ TrackBuffersManager::OnDemuxFailed(Track
       break;
   }
 }
 
 void
 TrackBuffersManager::DoDemuxVideo()
 {
   MOZ_ASSERT(OnTaskQueue());
-  MSE_DEBUG("mAbort:%d", static_cast<bool>(mAbort));
   if (!HasVideo()) {
     DoDemuxAudio();
     return;
   }
-  if (mAbort) {
-    RejectProcessing(NS_ERROR_ABORT, __func__);
-    return;
-  }
   mVideoTracks.mDemuxRequest.Begin(mVideoTracks.mDemuxer->GetSamples(-1)
                              ->Then(GetTaskQueue(), __func__, this,
                                     &TrackBuffersManager::OnVideoDemuxCompleted,
                                     &TrackBuffersManager::OnVideoDemuxFailed));
 }
 
 void
 TrackBuffersManager::OnVideoDemuxCompleted(RefPtr<MediaTrackDemuxer::SamplesHolder> aSamples)
@@ -1236,25 +1178,20 @@ TrackBuffersManager::OnVideoDemuxComplet
   mVideoTracks.mQueuedSamples.AppendElements(aSamples->mSamples);
   DoDemuxAudio();
 }
 
 void
 TrackBuffersManager::DoDemuxAudio()
 {
   MOZ_ASSERT(OnTaskQueue());
-  MSE_DEBUG("mAbort:%d", static_cast<bool>(mAbort));
   if (!HasAudio()) {
     CompleteCodedFrameProcessing();
     return;
   }
-  if (mAbort) {
-    RejectProcessing(NS_ERROR_ABORT, __func__);
-    return;
-  }
   mAudioTracks.mDemuxRequest.Begin(mAudioTracks.mDemuxer->GetSamples(-1)
                              ->Then(GetTaskQueue(), __func__, this,
                                     &TrackBuffersManager::OnAudioDemuxCompleted,
                                     &TrackBuffersManager::OnAudioDemuxFailed));
 }
 
 void
 TrackBuffersManager::OnAudioDemuxCompleted(RefPtr<MediaTrackDemuxer::SamplesHolder> aSamples)
@@ -1265,17 +1202,16 @@ TrackBuffersManager::OnAudioDemuxComplet
   mAudioTracks.mQueuedSamples.AppendElements(aSamples->mSamples);
   CompleteCodedFrameProcessing();
 }
 
 void
 TrackBuffersManager::CompleteCodedFrameProcessing()
 {
   MOZ_ASSERT(OnTaskQueue());
-  MSE_DEBUG("mAbort:%d", static_cast<bool>(mAbort));
 
   // 1. For each coded frame in the media segment run the following steps:
   // Coded Frame Processing steps 1.1 to 1.21.
   ProcessFrames(mVideoTracks.mQueuedSamples, mVideoTracks);
   mVideoTracks.mQueuedSamples.Clear();
 
 #if defined(DEBUG)
   if (HasVideo()) {
@@ -1336,32 +1272,22 @@ TrackBuffersManager::CompleteCodedFrameP
 
   // 8. Jump to the loop top step above.
   ResolveProcessing(false, __func__);
 }
 
 void
 TrackBuffersManager::RejectProcessing(nsresult aRejectValue, const char* aName)
 {
-  if (mAbort) {
-    // mAppendPromise will be resolved immediately upon mProcessingPromise
-    // completing.
-    mAppendRunning = false;
-  }
   mProcessingPromise.RejectIfExists(aRejectValue, __func__);
 }
 
 void
 TrackBuffersManager::ResolveProcessing(bool aResolveValue, const char* aName)
 {
-  if (mAbort) {
-    // mAppendPromise will be resolved immediately upon mProcessingPromise
-    // completing.
-    mAppendRunning = false;
-  }
   mProcessingPromise.ResolveIfExists(aResolveValue, __func__);
 }
 
 void
 TrackBuffersManager::CheckSequenceDiscontinuity(const TimeUnit& aPresentationTime)
 {
   if (mSourceBufferAttributes->GetAppendMode() == SourceBufferAppendMode::Sequence &&
       mGroupStartTimestamp.isSome()) {
--- a/dom/media/mediasource/TrackBuffersManager.h
+++ b/dom/media/mediasource/TrackBuffersManager.h
@@ -93,20 +93,16 @@ public:
   uint32_t SkipToNextRandomAccessPoint(TrackInfo::TrackType aTrack,
                                        const media::TimeUnit& aTimeThreadshold,
                                        bool& aFound);
   already_AddRefed<MediaRawData> GetSample(TrackInfo::TrackType aTrack,
                                            const media::TimeUnit& aFuzz,
                                            bool& aError);
   media::TimeUnit GetNextRandomAccessPoint(TrackInfo::TrackType aTrack);
 
-#if defined(DEBUG)
-  void Dump(const char* aPath) override;
-#endif
-
   void AddSizeOfResources(MediaSourceDecoder::ResourceSizes* aSizes);
 
 private:
   // for MediaSourceDemuxer::GetMozDebugReaderData
   friend class MediaSourceDemuxer;
   virtual ~TrackBuffersManager();
   // All following functions run on the taskqueue.
   RefPtr<AppendPromise> InitSegmentParserLoop();
@@ -118,19 +114,17 @@ private:
   void CreateDemuxerforMIMEType();
   void ResetDemuxingState();
   void NeedMoreData();
   void RejectAppend(nsresult aRejectValue, const char* aName);
   // Will return a promise that will be resolved once all frames of the current
   // media segment have been processed.
   RefPtr<CodedFrameProcessingPromise> CodedFrameProcessing();
   void CompleteCodedFrameProcessing();
-  // Called by ResetParserState. Complete parsing the input buffer for the
-  // current media segment.
-  void FinishCodedFrameProcessing();
+  // Called by ResetParserState.
   void CompleteResetParserState();
   RefPtr<RangeRemovalPromise>
     CodedFrameRemovalWithPromise(media::TimeInterval aInterval);
   bool CodedFrameRemoval(media::TimeInterval aInterval);
   void SetAppendState(AppendState aAppendState);
 
   bool HasVideo() const
   {
@@ -305,20 +299,16 @@ private:
                            const media::TimeInterval& aInterval);
   void UpdateBufferedRanges();
   void RejectProcessing(nsresult aRejectValue, const char* aName);
   void ResolveProcessing(bool aResolveValue, const char* aName);
   MozPromiseRequestHolder<CodedFrameProcessingPromise> mProcessingRequest;
   MozPromiseHolder<CodedFrameProcessingPromise> mProcessingPromise;
 
   MozPromiseHolder<AppendPromise> mAppendPromise;
-  // Set to true while SegmentParserLoop is running. This is used for diagnostic
-  // purposes only. We can't rely on mAppendPromise to be empty as it is only
-  // cleared in a follow up task.
-  bool mAppendRunning;
 
   // Trackbuffers definition.
   nsTArray<TrackData*> GetTracksList();
   TrackData& GetTracksData(TrackType aTrack)
   {
     switch(aTrack) {
       case TrackType::kVideoTrack:
         return mVideoTracks;
@@ -344,31 +334,32 @@ private:
   media::TimeUnit mTimestampOffset;
   media::TimeUnit mLastTimestampOffset;
   void RestoreCachedVariables();
 
   // Strong references to external objects.
   RefPtr<dom::SourceBufferAttributes> mSourceBufferAttributes;
   nsMainThreadPtrHandle<MediaSourceDecoder> mParentDecoder;
 
-  // MediaSource duration mirrored from MediaDecoder on the main thread..
-  Mirror<Maybe<double>> mMediaSourceDuration;
-
-  // Set to true if abort was called.
-  Atomic<bool> mAbort;
   // Set to true if mediasource state changed to ended.
   Atomic<bool> mEnded;
 
   // Global size of this source buffer content.
   Atomic<int64_t> mSizeSourceBuffer;
   uint32_t mEvictionThreshold;
   Atomic<bool> mEvictionOccurred;
 
   // Monitor to protect following objects accessed across multipple threads.
+  // mMonitor is also notified if the value of mAppendRunning becomes false.
   mutable Monitor mMonitor;
+  // Set to true while SegmentParserLoop is running.
+  Atomic<bool> mAppendRunning;
+  // Set to true while SegmentParserLoop is running.
+  // This is for diagnostic only. Only accessed on the task queue.
+  bool mSegmentParserLoopRunning;
   // Stable audio and video track time ranges.
   media::TimeIntervals mVideoBufferedRanges;
   media::TimeIntervals mAudioBufferedRanges;
   media::TimeUnit mOfficialGroupEndTimestamp;
   // MediaInfo of the first init segment read.
   MediaInfo mInfo;
 };
 
--- a/dom/webidl/Console.webidl
+++ b/dom/webidl/Console.webidl
@@ -47,20 +47,17 @@ dictionary ConsoleEvent {
   (unsigned long long or DOMString) innerID;
   DOMString level = "";
   DOMString filename = "";
   unsigned long lineNumber = 0;
   unsigned long columnNumber = 0;
   DOMString functionName = "";
   double timeStamp = 0;
   sequence<any> arguments;
-
-  // This array will only hold strings or null elements.
-  sequence<any> styles;
-
+  sequence<DOMString?> styles;
   boolean private = false;
   // stacktrace is handled via a getter in some cases so we can construct it
   // lazily.  Note that we're not making this whole thing an interface because
   // consumers expect to see own properties on it, which would mean making the
   // props unforgeable, which means lots of JSFunction allocations.  Maybe we
   // should fix those consumers, of course....
   // sequence<ConsoleStackEntry> stacktrace;
   DOMString groupName = "";
--- a/dom/webidl/Navigator.webidl
+++ b/dom/webidl/Navigator.webidl
@@ -185,27 +185,27 @@ interface NavigatorMobileId {
     [NewObject, Func="Navigator::HasMobileIdSupport"]
     Promise<any> getMobileIdAssertion(optional MobileIdOptions options);
 };
 Navigator implements NavigatorMobileId;
 #endif // MOZ_B2G
 
 // nsIDOMNavigator
 partial interface Navigator {
-  [Throws]
+  [Throws, Constant, Cached]
   readonly attribute DOMString oscpu;
   // WebKit/Blink support this; Trident/Presto do not.
   readonly attribute DOMString vendor;
   // WebKit/Blink supports this (hardcoded ""); Trident/Presto do not.
   readonly attribute DOMString vendorSub;
   // WebKit/Blink supports this (hardcoded "20030107"); Trident/Presto don't
   readonly attribute DOMString productSub;
   // WebKit/Blink/Trident/Presto support this.
   readonly attribute boolean cookieEnabled;
-  [Throws]
+  [Throws, Constant, Cached]
   readonly attribute DOMString buildID;
   [Throws, CheckAnyPermissions="power", UnsafeInPrerendering]
   readonly attribute MozPowerManager mozPower;
 
   // WebKit/Blink/Trident/Presto support this.
   [Throws]
   boolean javaEnabled();
 
--- a/embedding/components/webbrowserpersist/nsWebBrowserPersist.cpp
+++ b/embedding/components/webbrowserpersist/nsWebBrowserPersist.cpp
@@ -2386,42 +2386,47 @@ nsresult
 nsWebBrowserPersist::FixRedirectedChannelEntry(nsIChannel *aNewChannel)
 {
     NS_ENSURE_ARG_POINTER(aNewChannel);
 
     // Iterate through existing open channels looking for one with a URI
     // matching the one specified.
     nsCOMPtr<nsIURI> originalURI;
     aNewChannel->GetOriginalURI(getter_AddRefs(originalURI));
+    nsISupports* matchingKey = nullptr;
     for (auto iter = mOutputMap.Iter(); !iter.Done(); iter.Next()) {
         nsISupports* key = iter.Key();
         nsCOMPtr<nsIChannel> thisChannel = do_QueryInterface(key);
         nsCOMPtr<nsIURI> thisURI;
 
         thisChannel->GetOriginalURI(getter_AddRefs(thisURI));
 
         // Compare this channel's URI to the one passed in.
         bool matchingURI = false;
         thisURI->Equals(originalURI, &matchingURI);
         if (matchingURI) {
-            // If a match is found, remove the data entry with the old channel
-            // key and re-add it with the new channel key.
-            nsAutoPtr<OutputData> outputData;
-            mOutputMap.RemoveAndForget(key, outputData);
-            NS_ENSURE_TRUE(outputData, NS_ERROR_FAILURE);
-
-            // Store data again with new channel unless told to ignore redirects
-            if (!(mPersistFlags & PERSIST_FLAGS_IGNORE_REDIRECTED_DATA)) {
-                nsCOMPtr<nsISupports> keyPtr = do_QueryInterface(aNewChannel);
-                mOutputMap.Put(keyPtr, outputData.forget());
-            }
-
+            matchingKey = key;
             break;
         }
     }
+
+    if (matchingKey) {
+        // If a match was found, remove the data entry with the old channel
+        // key and re-add it with the new channel key.
+        nsAutoPtr<OutputData> outputData;
+        mOutputMap.RemoveAndForget(matchingKey, outputData);
+        NS_ENSURE_TRUE(outputData, NS_ERROR_FAILURE);
+
+        // Store data again with new channel unless told to ignore redirects.
+        if (!(mPersistFlags & PERSIST_FLAGS_IGNORE_REDIRECTED_DATA)) {
+            nsCOMPtr<nsISupports> keyPtr = do_QueryInterface(aNewChannel);
+            mOutputMap.Put(keyPtr, outputData.forget());
+        }
+    }
+
     return NS_OK;
 }
 
 void
 nsWebBrowserPersist::CalcTotalProgress()
 {
     mTotalCurrentProgress = 0;
     mTotalMaxProgress = 0;
--- a/gfx/2d/2D.h
+++ b/gfx/2d/2D.h
@@ -31,18 +31,16 @@
 #endif
 
 struct _cairo_surface;
 typedef _cairo_surface cairo_surface_t;
 
 struct _cairo_scaled_font;
 typedef _cairo_scaled_font cairo_scaled_font_t;
 
-struct ID3D10Device1;
-struct ID3D10Texture2D;
 struct ID3D11Texture2D;
 struct ID3D11Device;
 struct ID2D1Device;
 struct IDWriteRenderingParams;
 struct IDWriteFont;
 struct IDWriteFontFamily;
 struct IDWriteFontFace;
 
@@ -1359,24 +1357,16 @@ public:
 
 #ifdef XP_DARWIN
   static already_AddRefed<DrawTarget> CreateDrawTargetForCairoCGContext(CGContextRef cg, const IntSize& aSize);
   static already_AddRefed<GlyphRenderingOptions>
     CreateCGGlyphRenderingOptions(const Color &aFontSmoothingBackgroundColor);
 #endif
 
 #ifdef WIN32
-  static already_AddRefed<DrawTarget> CreateDrawTargetForD3D10Texture(ID3D10Texture2D *aTexture, SurfaceFormat aFormat);
-  static already_AddRefed<DrawTarget>
-    CreateDualDrawTargetForD3D10Textures(ID3D10Texture2D *aTextureA,
-                                         ID3D10Texture2D *aTextureB,
-                                         SurfaceFormat aFormat);
-
-  static void SetDirect3D10Device(ID3D10Device1 *aDevice);
-  static ID3D10Device1 *GetDirect3D10Device();
   static already_AddRefed<DrawTarget> CreateDrawTargetForD3D11Texture(ID3D11Texture2D *aTexture, SurfaceFormat aFormat);
 
   static void SetDirect3D11Device(ID3D11Device *aDevice);
   static ID3D11Device *GetDirect3D11Device();
   static ID2D1Device *GetD2D1Device();
   static bool SupportsD2D1();
 
   static already_AddRefed<GlyphRenderingOptions>
@@ -1389,17 +1379,16 @@ public:
   static already_AddRefed<ScaledFont>
     CreateScaledFontForDWriteFont(IDWriteFont* aFont,
                                   IDWriteFontFamily* aFontFamily,
                                   IDWriteFontFace* aFontFace,
                                   Float aSize);
 
 private:
   static ID2D1Device *mD2D1Device;
-  static ID3D10Device1 *mD3D10Device;
   static ID3D11Device *mD3D11Device;
 #endif
 
   static DrawEventRecorder *mRecorder;
 };
 
 } // namespace gfx
 } // namespace mozilla
deleted file mode 100644
--- a/gfx/2d/DrawTargetD2D.cpp
+++ /dev/null
@@ -1,2831 +0,0 @@
-/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include <initguid.h>
-#include "DrawTargetD2D.h"
-#include "SourceSurfaceD2D.h"
-#include "SourceSurfaceD2D1.h"
-#include "SourceSurfaceD2DTarget.h"
-#include "ShadersD2D.h"
-#include "PathD2D.h"
-#include "GradientStopsD2D.h"
-#include "ScaledFontDWrite.h"
-#include "ImageScaling.h"
-#include "Logging.h"
-#include "Tools.h"
-#include <algorithm>
-#include "FilterNodeSoftware.h"
-
-#include "FilterNodeD2D1.h"
-#include "ExtendInputEffectD2D1.h"
-
-#include <cmath>
-#include <dwrite.h>
-
-// decltype is not usable for overloaded functions.
-typedef HRESULT (WINAPI*D2D1CreateFactoryFunc)(
-    D2D1_FACTORY_TYPE factoryType,
-    REFIID iid,
-    CONST D2D1_FACTORY_OPTIONS *pFactoryOptions,
-    void **factory
-);
-
-using namespace std;
-
-namespace mozilla {
-namespace gfx {
-
-struct Vertex {
-  float x;
-  float y;
-};
-
-ID2D1Factory *DrawTargetD2D::mFactory;
-IDWriteFactory *DrawTargetD2D::mDWriteFactory;
-uint64_t DrawTargetD2D::mVRAMUsageDT;
-uint64_t DrawTargetD2D::mVRAMUsageSS;
-
-// Helper class to restore surface contents that was clipped out but may have
-// been altered by a drawing call.
-class AutoSaveRestoreClippedOut
-{
-public:
-  AutoSaveRestoreClippedOut(DrawTargetD2D *aDT)
-    : mDT(aDT)
-  {}
-
-  void Save() {
-    if (!mDT->mPushedClips.size()) {
-      return;
-    }
-
-    mDT->Flush();
-
-    RefPtr<ID3D10Texture2D> tmpTexture;
-    IntSize size = mDT->mSize;
-    SurfaceFormat format = mDT->mFormat;
-
-    CD3D10_TEXTURE2D_DESC desc(DXGIFormat(format), size.width, size.height,
-                               1, 1);
-    desc.BindFlags = D3D10_BIND_RENDER_TARGET | D3D10_BIND_SHADER_RESOURCE;
-
-    HRESULT hr = mDT->mDevice->CreateTexture2D(&desc, nullptr, getter_AddRefs(tmpTexture));
-    if (FAILED(hr)) {
-      gfxCriticalError(CriticalLog::DefaultOptions(Factory::ReasonableSurfaceSize(size))) << "[D2D] 1 CreateTexture2D failure " << size << " Code: " << hexa(hr) << " format " << (int)format;
-      return;
-    }
-    mDT->mDevice->CopyResource(tmpTexture, mDT->mTexture);
-
-    D2D1_BITMAP_PROPERTIES props = D2D1::BitmapProperties(D2DPixelFormat(format));
-
-    RefPtr<IDXGISurface> surf;
-
-    tmpTexture->QueryInterface((IDXGISurface**)getter_AddRefs(surf));
-
-    hr = mDT->mRT->CreateSharedBitmap(IID_IDXGISurface, surf,
-                                      &props, getter_AddRefs(mOldSurfBitmap));
-
-    if (FAILED(hr)) {
-      gfxCriticalError() << "[D2D] CreateSharedBitmap failure " << size << " Code: " << hexa(hr);
-      return;
-    }
-
-    IntRect clipBounds;
-    mClippedArea = mDT->GetClippedGeometry(&clipBounds);
-
-    if (!clipBounds.IsEqualEdges(IntRect(IntPoint(0, 0), mDT->mSize))) {
-      // We still need to take into account clipBounds if it contains additional
-      // clipping information.
-      RefPtr<ID2D1RectangleGeometry> rectGeom;
-      factory()->CreateRectangleGeometry(D2D1::Rect(Float(clipBounds.x),
-                                                    Float(clipBounds.y),
-                                                    Float(clipBounds.XMost()),
-                                                    Float(clipBounds.YMost())),
-                                         getter_AddRefs(rectGeom));
-
-      mClippedArea = IntersectGeometry(mClippedArea, rectGeom);
-    }
-  }
-
-  ID2D1Factory *factory() { return mDT->factory(); }
-
-  ~AutoSaveRestoreClippedOut()
-  {
-    if (!mOldSurfBitmap) {
-      return;
-    }
-
-    ID2D1RenderTarget *rt = mDT->mRT;
-
-    // Write the area that was clipped out back to the surface. This all
-    // happens in device space.
-    rt->SetTransform(D2D1::IdentityMatrix());
-    mDT->mTransformDirty = true;
-
-    RefPtr<ID2D1RectangleGeometry> rectGeom;
-    factory()->CreateRectangleGeometry(
-      D2D1::RectF(0, 0, float(mDT->mSize.width), float(mDT->mSize.height)),
-      getter_AddRefs(rectGeom));
-
-    RefPtr<ID2D1PathGeometry> invClippedArea;
-    factory()->CreatePathGeometry(getter_AddRefs(invClippedArea));
-    RefPtr<ID2D1GeometrySink> sink;
-    invClippedArea->Open(getter_AddRefs(sink));
-
-    rectGeom->CombineWithGeometry(mClippedArea, D2D1_COMBINE_MODE_EXCLUDE, nullptr, sink);
-    sink->Close();
-
-    RefPtr<ID2D1BitmapBrush> brush;
-    HRESULT hr = rt->CreateBitmapBrush(mOldSurfBitmap, D2D1::BitmapBrushProperties(), D2D1::BrushProperties(), getter_AddRefs(brush));
-    if (FAILED(hr)) {
-      gfxCriticalNote << "[D2D] CreateBitmapBrush failure " << hexa(hr);
-      return;
-    }
-
-    rt->FillGeometry(invClippedArea, brush);
-  }
-
-private:
-
-  DrawTargetD2D *mDT;
-
-  // If we have an operator unbound by the source, this will contain a bitmap
-  // with the old dest surface data.
-  RefPtr<ID2D1Bitmap> mOldSurfBitmap;
-  // This contains the area drawing is clipped to.
-  RefPtr<ID2D1Geometry> mClippedArea;
-};
-
-ID2D1Factory *D2DFactory()
-{
-  return DrawTargetD2D::factory();
-}
-
-DrawTargetD2D::DrawTargetD2D()
-  : mCurrentCachedLayer(0)
-  , mClipsArePushed(false)
-  , mPrivateData(nullptr)
-{
-}
-
-DrawTargetD2D::~DrawTargetD2D()
-{
-  if (mRT) {  
-    PopAllClips();
-
-    mRT->EndDraw();
-
-    mVRAMUsageDT -= GetByteSize();
-  }
-  if (mTempRT) {
-    mTempRT->EndDraw();
-
-    mVRAMUsageDT -= GetByteSize();
-  }
-
-  if (mSnapshot) {
-    // We may hold the only reference. MarkIndependent will clear mSnapshot;
-    // keep the snapshot object alive so it doesn't get destroyed while
-    // MarkIndependent is running.
-    RefPtr<SourceSurfaceD2DTarget> deathGrip = mSnapshot;
-    // mSnapshot can be treated as independent of this DrawTarget since we know
-    // this DrawTarget won't change again.
-    deathGrip->MarkIndependent();
-    // mSnapshot will be cleared now.
-  }
-
-  for (int i = 0; i < kLayerCacheSize; i++) {
-    if (mCachedLayers[i]) {
-      mCachedLayers[i] = nullptr;
-      mVRAMUsageDT -= GetByteSize();
-    }
-  }
-
-  // Targets depending on us can break that dependency, since we're obviously not going to
-  // be modified in the future.
-  for (TargetSet::iterator iter = mDependentTargets.begin();
-       iter != mDependentTargets.end(); iter++) {
-    (*iter)->mDependingOnTargets.erase(this);
-  }
-  // Our dependencies on other targets no longer matter.
-  for (TargetSet::iterator iter = mDependingOnTargets.begin();
-       iter != mDependingOnTargets.end(); iter++) {
-    (*iter)->mDependentTargets.erase(this);
-  }
-}
-
-/*
- * DrawTarget Implementation
- */
-already_AddRefed<SourceSurface>
-DrawTargetD2D::Snapshot()
-{
-  if (!mSnapshot) {
-    mSnapshot = new SourceSurfaceD2DTarget(this, mTexture, mFormat);
-    Flush();
-  }
-
-  RefPtr<SourceSurface> snapshot(mSnapshot);
-  return snapshot.forget();
-}
-
-void
-DrawTargetD2D::Flush()
-{
-  PopAllClips();
-
-  HRESULT hr = mRT->Flush();
-
-  if (FAILED(hr)) {
-    gfxWarning() << "Error reported when trying to flush D2D rendertarget. Code: " << hexa(hr);
-  }
-
-  // We no longer depend on any target.
-  for (TargetSet::iterator iter = mDependingOnTargets.begin();
-       iter != mDependingOnTargets.end(); iter++) {
-    (*iter)->mDependentTargets.erase(this);
-  }
-  mDependingOnTargets.clear();
-}
-
-void
-DrawTargetD2D::AddDependencyOnSource(SourceSurfaceD2DTarget* aSource)
-{
-  if (aSource->mDrawTarget && !mDependingOnTargets.count(aSource->mDrawTarget)) {
-    aSource->mDrawTarget->mDependentTargets.insert(this);
-    mDependingOnTargets.insert(aSource->mDrawTarget);
-  }
-}
-
-already_AddRefed<ID2D1Bitmap>
-DrawTargetD2D::GetBitmapForSurface(SourceSurface *aSurface,
-                                   Rect &aSource)
-{
-  RefPtr<ID2D1Bitmap> bitmap;
-
-  switch (aSurface->GetType()) {
-
-  case SurfaceType::D2D1_BITMAP:
-    {
-      SourceSurfaceD2D *srcSurf = static_cast<SourceSurfaceD2D*>(aSurface);
-      bitmap = srcSurf->GetBitmap();
-    }
-    break;
-  case SurfaceType::D2D1_DRAWTARGET:
-    {
-      SourceSurfaceD2DTarget *srcSurf = static_cast<SourceSurfaceD2DTarget*>(aSurface);
-      bitmap = srcSurf->GetBitmap(mRT);
-      AddDependencyOnSource(srcSurf);
-    }
-    break;
-  default:
-    {
-      RefPtr<DataSourceSurface> srcSurf = aSurface->GetDataSurface();
-
-      if (!srcSurf) {
-        gfxDebug() << "Not able to deal with non-data source surface.";
-        return nullptr;
-      }
-
-      // We need to include any pixels that are overlapped by aSource
-      Rect sourceRect(aSource);
-      sourceRect.RoundOut();
-
-      if (sourceRect.IsEmpty()) {
-        gfxDebug() << "Bitmap source is empty. DrawBitmap will silently fail.";
-        return nullptr;
-      }
-
-      if (sourceRect.width > mRT->GetMaximumBitmapSize() ||
-          sourceRect.height > mRT->GetMaximumBitmapSize()) {
-        gfxDebug() << "Bitmap source larger than texture size specified. DrawBitmap will silently fail.";
-        // Don't know how to deal with this yet.
-        return nullptr;
-      }
-
-      HRESULT hr;
-      {
-        DataSourceSurface::ScopedMap srcMap(srcSurf, DataSourceSurface::READ);
-        if (MOZ2D_WARN_IF(!srcMap.IsMapped())) {
-          return nullptr;
-        }
-
-        int stride = srcMap.GetStride();
-        unsigned char *data = srcMap.GetData() +
-                              (uint32_t)sourceRect.y * stride +
-                              (uint32_t)sourceRect.x * BytesPerPixel(srcSurf->GetFormat());
-
-        D2D1_BITMAP_PROPERTIES props =
-          D2D1::BitmapProperties(D2DPixelFormat(srcSurf->GetFormat()));
-        hr = mRT->CreateBitmap(D2D1::SizeU(UINT32(sourceRect.width), UINT32(sourceRect.height)), data, stride, props, getter_AddRefs(bitmap));
-      }
-      if (FAILED(hr)) {
-        IntSize size(sourceRect.width, sourceRect.height);
-        gfxCriticalError(CriticalLog::DefaultOptions(Factory::ReasonableSurfaceSize(size))) << "[D2D] 1CreateBitmap failure " << size << " Code: " << hexa(hr) << " format " << (int)srcSurf->GetFormat();
-        return nullptr;
-      }
-
-      // subtract the integer part leaving the fractional part
-      aSource.x -= (uint32_t)aSource.x;
-      aSource.y -= (uint32_t)aSource.y;
-    }
-    break;
-  }
-
-  return bitmap.forget();
-}
-
-already_AddRefed<ID2D1Image>
-DrawTargetD2D::GetImageForSurface(SourceSurface *aSurface)
-{
-  RefPtr<ID2D1Image> image;
-
-  Rect r(Point(), Size(aSurface->GetSize()));
-  image = GetBitmapForSurface(aSurface, r);
-
-  return image.forget();
-}
-
-void
-DrawTargetD2D::DrawSurface(SourceSurface *aSurface,
-                           const Rect &aDest,
-                           const Rect &aSource,
-                           const DrawSurfaceOptions &aSurfOptions,
-                           const DrawOptions &aOptions)
-{
-  RefPtr<ID2D1Bitmap> bitmap;
-
-  ID2D1RenderTarget *rt = GetRTForOperation(aOptions.mCompositionOp, ColorPattern(Color()));
-  
-  PrepareForDrawing(rt);
-
-  rt->SetAntialiasMode(D2DAAMode(aOptions.mAntialiasMode));
-
-  Rect srcRect = aSource;
-
-  bitmap = GetBitmapForSurface(aSurface, srcRect);
-  if (!bitmap) {
-      return;
-  }
- 
-  rt->DrawBitmap(bitmap, D2DRect(aDest), aOptions.mAlpha, D2DFilter(aSurfOptions.mFilter), D2DRect(srcRect));
-
-  FinalizeRTForOperation(aOptions.mCompositionOp, ColorPattern(Color()), aDest);
-}
-
-void
-DrawTargetD2D::DrawFilter(FilterNode *aNode,
-                          const Rect &aSourceRect,
-                          const Point &aDestPoint,
-                          const DrawOptions &aOptions)
-{
-  RefPtr<ID2D1DeviceContext> dc;
-  HRESULT hr;
-  
-  hr = mRT->QueryInterface((ID2D1DeviceContext**)getter_AddRefs(dc));
-
-  if (SUCCEEDED(hr) && aNode->GetBackendType() == FILTER_BACKEND_DIRECT2D1_1) {
-    ID2D1RenderTarget *rt = GetRTForOperation(aOptions.mCompositionOp, ColorPattern(Color()));
-  
-    PrepareForDrawing(rt);
-
-    rt->SetAntialiasMode(D2DAAMode(aOptions.mAntialiasMode));
-    hr = rt->QueryInterface((ID2D1DeviceContext**)getter_AddRefs(dc));
-
-    if (SUCCEEDED(hr)) {
-      FilterNodeD2D1* node = static_cast<FilterNodeD2D1*>(aNode);
-      node->WillDraw(this);
-
-      dc->DrawImage(node->OutputEffect(), D2DPoint(aDestPoint), D2DRect(aSourceRect));
-
-      Rect destRect = aSourceRect;
-      destRect.MoveBy(aDestPoint);
-      FinalizeRTForOperation(aOptions.mCompositionOp, ColorPattern(Color()), destRect);
-      return;
-    }
-  }
-
-  if (aNode->GetBackendType() != FILTER_BACKEND_SOFTWARE) {
-    gfxWarning() << "Invalid filter backend passed to DrawTargetD2D!";
-    return;
-  }
-
-  FilterNodeSoftware* filter = static_cast<FilterNodeSoftware*>(aNode);
-  filter->Draw(this, aSourceRect, aDestPoint, aOptions);
-}
-
-void
-DrawTargetD2D::MaskSurface(const Pattern &aSource,
-                           SourceSurface *aMask,
-                           Point aOffset,
-                           const DrawOptions &aOptions)
-{
-  RefPtr<ID2D1Bitmap> bitmap;
-
-  ID2D1RenderTarget *rt = GetRTForOperation(aOptions.mCompositionOp, ColorPattern(Color()));
-
-  PrepareForDrawing(rt);
-
-  // FillOpacityMask only works if the antialias mode is MODE_ALIASED
-  rt->SetAntialiasMode(D2D1_ANTIALIAS_MODE_ALIASED);
-
-  IntSize size = aMask->GetSize();
-  Rect maskRect = Rect(0.f, 0.f, size.width, size.height);
-  bitmap = GetBitmapForSurface(aMask, maskRect);
-  if (!bitmap) {
-       return;
-  }
-
-  Rect dest = Rect(aOffset.x, aOffset.y, size.width, size.height);
-  RefPtr<ID2D1Brush> brush = CreateBrushForPattern(aSource, aOptions.mAlpha);
-  rt->FillOpacityMask(bitmap, brush, D2D1_OPACITY_MASK_CONTENT_GRAPHICS, D2DRect(dest), D2DRect(maskRect));
-
-  FinalizeRTForOperation(aOptions.mCompositionOp, ColorPattern(Color()), dest);
-}
-
-void
-DrawTargetD2D::DrawSurfaceWithShadow(SourceSurface *aSurface,
-                                     const Point &aDest,
-                                     const Color &aColor,
-                                     const Point &aOffset,
-                                     Float aSigma,
-                                     CompositionOp aOperator)
-{
-  RefPtr<ID3D10ShaderResourceView> srView = nullptr;
-  if (aSurface->GetType() != SurfaceType::D2D1_DRAWTARGET) {
-    return;
-  }
-
-  SetScissorToRect(nullptr);
-
-  // XXX - This function is way too long, it should be split up soon to make
-  // it more graspable!
-
-  Flush();
-
-  AutoSaveRestoreClippedOut restoreClippedOut(this);
-
-  if (!IsOperatorBoundByMask(aOperator)) {
-    restoreClippedOut.Save();
-  }
-
-  srView = static_cast<SourceSurfaceD2DTarget*>(aSurface)->GetSRView();
-  if (!srView) {
-    return;
-  }
-
-  EnsureViews();
-
-  if (!mTempRTView) {
-    // This view is only needed in this path.
-    HRESULT hr = mDevice->CreateRenderTargetView(mTempTexture, nullptr, getter_AddRefs(mTempRTView));
-
-    if (FAILED(hr)) {
-      gfxWarning() << "Failure to create RenderTargetView. Code: " << hexa(hr);
-      return;
-    }
-  }
-
-
-  RefPtr<ID3D10RenderTargetView> destRTView = mRTView;
-  RefPtr<ID3D10Texture2D> destTexture;
-  HRESULT hr;
-
-  RefPtr<ID3D10Texture2D> maskTexture;
-  RefPtr<ID3D10ShaderResourceView> maskSRView;
-  IntRect clipBounds;
-  if (mPushedClips.size()) {
-    EnsureClipMaskTexture(&clipBounds);
-
-    mDevice->CreateShaderResourceView(mCurrentClipMaskTexture, nullptr, getter_AddRefs(maskSRView));
-  }
-
-  IntSize srcSurfSize;
-  ID3D10RenderTargetView *rtViews;
-  D3D10_VIEWPORT viewport;
-
-  UINT stride = sizeof(Vertex);
-  UINT offset = 0;
-  ID3D10Buffer *buff = mPrivateData->mVB;
-
-  mDevice->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
-  mDevice->IASetVertexBuffers(0, 1, &buff, &stride, &offset);
-  mDevice->IASetInputLayout(mPrivateData->mInputLayout);
-
-  mPrivateData->mEffect->GetVariableByName("QuadDesc")->AsVector()->
-    SetFloatVector(ShaderConstantRectD3D10(-1.0f, 1.0f, 2.0f, -2.0f));
-  mPrivateData->mEffect->GetVariableByName("TexCoords")->AsVector()->
-    SetFloatVector(ShaderConstantRectD3D10(0, 0, 1.0f, 1.0f));
-
-  // If we create a downsampled source surface we need to correct aOffset for that.
-  Point correctedOffset = aOffset + aDest;
-
-  // The 'practical' scaling factors.
-  Float dsFactorX = 1.0f;
-  Float dsFactorY = 1.0f;
-
-  if (aSigma > 1.7f) {
-    // In this case 9 samples of our original will not cover it. Generate the
-    // mip levels for the original and create a downsampled version from
-    // them. We generate a version downsampled so that a kernel for a sigma
-    // of 1.7 will produce the right results.
-    float blurWeights[9] = { 0.234671f, 0.197389f, 0.197389f, 0.117465f, 0.117465f, 0.049456f, 0.049456f, 0.014732f, 0.014732f };
-    mPrivateData->mEffect->GetVariableByName("BlurWeights")->SetRawValue(blurWeights, 0, sizeof(blurWeights));
-    
-    CD3D10_TEXTURE2D_DESC desc(DXGI_FORMAT_B8G8R8A8_UNORM,
-                               aSurface->GetSize().width,
-                               aSurface->GetSize().height);
-    desc.BindFlags = D3D10_BIND_RENDER_TARGET | D3D10_BIND_SHADER_RESOURCE;
-    desc.MiscFlags = D3D10_RESOURCE_MISC_GENERATE_MIPS;
-
-    RefPtr<ID3D10Texture2D> mipTexture;
-    hr = mDevice->CreateTexture2D(&desc, nullptr, getter_AddRefs(mipTexture));
-
-    if (FAILED(hr)) {
-      gfxCriticalError(CriticalLog::DefaultOptions(Factory::ReasonableSurfaceSize(aSurface->GetSize()))) << "[D2D] 2 CreateTexture2D failure " << aSurface->GetSize() << " Code: " << hexa(hr);
-      return;
-    }
-
-    IntSize dsSize = IntSize(int32_t(aSurface->GetSize().width * (1.7f / aSigma)),
-                             int32_t(aSurface->GetSize().height * (1.7f / aSigma)));
-
-    if (dsSize.width < 1) {
-      dsSize.width = 1;
-    }
-    if (dsSize.height < 1) {
-      dsSize.height = 1;
-    }
-
-    dsFactorX = dsSize.width / Float(aSurface->GetSize().width);
-    dsFactorY = dsSize.height / Float(aSurface->GetSize().height);
-    correctedOffset.x *= dsFactorX;
-    correctedOffset.y *= dsFactorY;
-
-    desc = CD3D10_TEXTURE2D_DESC(DXGI_FORMAT_B8G8R8A8_UNORM,
-                                 dsSize.width,
-                                 dsSize.height, 1, 1);
-    desc.BindFlags = D3D10_BIND_RENDER_TARGET | D3D10_BIND_SHADER_RESOURCE;
-    RefPtr<ID3D10Texture2D> tmpDSTexture;
-    hr = mDevice->CreateTexture2D(&desc, nullptr, getter_AddRefs(tmpDSTexture));
-
-    if (FAILED(hr)) {
-      gfxCriticalError(CriticalLog::DefaultOptions(Factory::ReasonableSurfaceSize(dsSize))) << "[D2D] 3 CreateTexture2D failure " << dsSize << " Code: " << hexa(hr);
-      return;
-    }
-
-    D3D10_BOX box;
-    box.left = box.top = box.front = 0;
-    box.back = 1;
-    box.right = aSurface->GetSize().width;
-    box.bottom = aSurface->GetSize().height;
-    mDevice->CopySubresourceRegion(mipTexture, 0, 0, 0, 0, static_cast<SourceSurfaceD2DTarget*>(aSurface)->mTexture, 0, &box);
-
-    mDevice->CreateShaderResourceView(mipTexture, nullptr,  getter_AddRefs(srView));
-    mDevice->GenerateMips(srView);
-
-    RefPtr<ID3D10RenderTargetView> dsRTView;
-    RefPtr<ID3D10ShaderResourceView> dsSRView;
-    mDevice->CreateRenderTargetView(tmpDSTexture, nullptr,  getter_AddRefs(dsRTView));
-    mDevice->CreateShaderResourceView(tmpDSTexture, nullptr,  getter_AddRefs(dsSRView));
-
-    // We're not guaranteed the texture we created will be empty, we've
-    // seen old content at least on NVidia drivers.
-    float color[4] = { 0, 0, 0, 0 };
-    mDevice->ClearRenderTargetView(dsRTView, color);
-
-    rtViews = dsRTView;
-    mDevice->OMSetRenderTargets(1, &rtViews, nullptr);
-
-    viewport.MaxDepth = 1;
-    viewport.MinDepth = 0;
-    viewport.Height = dsSize.height;
-    viewport.Width = dsSize.width;
-    viewport.TopLeftX = 0;
-    viewport.TopLeftY = 0;
-
-    mDevice->RSSetViewports(1, &viewport);
-    mPrivateData->mEffect->GetVariableByName("tex")->AsShaderResource()->SetResource(srView);
-    mPrivateData->mEffect->GetTechniqueByName("SampleTexture")->
-      GetPassByIndex(0)->Apply(0);
-
-    mDevice->OMSetBlendState(GetBlendStateForOperator(CompositionOp::OP_OVER), nullptr, 0xffffffff);
-
-    mDevice->Draw(4, 0);
-    
-    srcSurfSize = dsSize;
-
-    srView = dsSRView;
-  } else {
-    // In this case generate a kernel to draw the blur directly to the temp
-    // surf in one direction and to final in the other.
-    float blurWeights[9];
-
-    float normalizeFactor = 1.0f;
-    if (aSigma != 0) {
-      normalizeFactor = 1.0f / Float(sqrt(2 * M_PI * pow(aSigma, 2)));
-    }
-
-    blurWeights[0] = normalizeFactor;
-
-    // XXX - We should actually optimize for Sigma = 0 here. We could use a
-    // much simpler shader and save a lot of texture lookups.
-    for (int i = 1; i < 9; i += 2) {
-      if (aSigma != 0) {
-        blurWeights[i] = blurWeights[i + 1] = normalizeFactor *
-          exp(-pow(float((i + 1) / 2), 2) / (2 * pow(aSigma, 2)));
-      } else {
-        blurWeights[i] = blurWeights[i + 1] = 0;
-      }
-    }
-    
-    mPrivateData->mEffect->GetVariableByName("BlurWeights")->SetRawValue(blurWeights, 0, sizeof(blurWeights));
-
-    viewport.MaxDepth = 1;
-    viewport.MinDepth = 0;
-    viewport.Height = aSurface->GetSize().height;
-    viewport.Width = aSurface->GetSize().width;
-    viewport.TopLeftX = 0;
-    viewport.TopLeftY = 0;
-
-    mDevice->RSSetViewports(1, &viewport);
-
-    srcSurfSize = aSurface->GetSize();
-  }
-
-  // We may need to draw to a different intermediate surface if our temp
-  // texture isn't big enough.
-  bool needBiggerTemp = srcSurfSize.width > mSize.width ||
-                        srcSurfSize.height > mSize.height;
-
-  RefPtr<ID3D10RenderTargetView> tmpRTView;
-  RefPtr<ID3D10ShaderResourceView> tmpSRView;
-  RefPtr<ID3D10Texture2D> tmpTexture;
-  
-  IntSize tmpSurfSize = mSize;
-
-  if (!needBiggerTemp) {
-    tmpRTView = mTempRTView;
-    tmpSRView = mSRView;
-
-    // There could still be content here!
-    float color[4] = { 0, 0, 0, 0 };
-    mDevice->ClearRenderTargetView(tmpRTView, color);
-  } else {
-    CD3D10_TEXTURE2D_DESC desc(DXGI_FORMAT_B8G8R8A8_UNORM,
-                               srcSurfSize.width,
-                               srcSurfSize.height,
-                               1, 1);
-    desc.BindFlags = D3D10_BIND_RENDER_TARGET | D3D10_BIND_SHADER_RESOURCE;
-
-    mDevice->CreateTexture2D(&desc, nullptr,  getter_AddRefs(tmpTexture));
-    mDevice->CreateRenderTargetView(tmpTexture, nullptr,  getter_AddRefs(tmpRTView));
-    mDevice->CreateShaderResourceView(tmpTexture, nullptr,  getter_AddRefs(tmpSRView));
-
-    tmpSurfSize = srcSurfSize;
-  }
-
-  rtViews = tmpRTView;
-  mDevice->OMSetRenderTargets(1, &rtViews, nullptr);
-
-  mPrivateData->mEffect->GetVariableByName("tex")->AsShaderResource()->SetResource(srView);
-
-  // Premultiplied!
-  float shadowColor[4] = { aColor.r * aColor.a, aColor.g * aColor.a,
-                           aColor.b * aColor.a, aColor.a };
-  mPrivateData->mEffect->GetVariableByName("ShadowColor")->AsVector()->
-    SetFloatVector(shadowColor);
-
-  float pixelOffset = 1.0f / float(srcSurfSize.width);
-  float blurOffsetsH[9] = { 0, pixelOffset, -pixelOffset,
-                            2.0f * pixelOffset, -2.0f * pixelOffset,
-                            3.0f * pixelOffset, -3.0f * pixelOffset,
-                            4.0f * pixelOffset, - 4.0f * pixelOffset };
-
-  pixelOffset = 1.0f / float(tmpSurfSize.height);
-  float blurOffsetsV[9] = { 0, pixelOffset, -pixelOffset,
-                            2.0f * pixelOffset, -2.0f * pixelOffset,
-                            3.0f * pixelOffset, -3.0f * pixelOffset,
-                            4.0f * pixelOffset, - 4.0f * pixelOffset };
-
-  mPrivateData->mEffect->GetVariableByName("BlurOffsetsH")->
-    SetRawValue(blurOffsetsH, 0, sizeof(blurOffsetsH));
-  mPrivateData->mEffect->GetVariableByName("BlurOffsetsV")->
-    SetRawValue(blurOffsetsV, 0, sizeof(blurOffsetsV));
-
-  mPrivateData->mEffect->GetTechniqueByName("SampleTextureWithShadow")->
-    GetPassByIndex(0)->Apply(0);
-
-  mDevice->Draw(4, 0);
-
-  viewport.MaxDepth = 1;
-  viewport.MinDepth = 0;
-  viewport.Height = mSize.height;
-  viewport.Width = mSize.width;
-  viewport.TopLeftX = 0;
-  viewport.TopLeftY = 0;
-
-  mDevice->RSSetViewports(1, &viewport);
-
-  mPrivateData->mEffect->GetVariableByName("tex")->AsShaderResource()->SetResource(tmpSRView);
-
-  rtViews = destRTView;
-  mDevice->OMSetRenderTargets(1, &rtViews, nullptr);
-
-  Point shadowDest = aDest + aOffset;
-
-  mPrivateData->mEffect->GetVariableByName("QuadDesc")->AsVector()->
-    SetFloatVector(ShaderConstantRectD3D10(-1.0f + ((shadowDest.x / mSize.width) * 2.0f),
-                                           1.0f - (shadowDest.y / mSize.height * 2.0f),
-                                           (Float(aSurface->GetSize().width) / mSize.width) * 2.0f,
-                                           (-Float(aSurface->GetSize().height) / mSize.height) * 2.0f));
-  mPrivateData->mEffect->GetVariableByName("TexCoords")->AsVector()->
-    SetFloatVector(ShaderConstantRectD3D10(0, 0, Float(srcSurfSize.width) / tmpSurfSize.width,
-                                                 Float(srcSurfSize.height) / tmpSurfSize.height));
-
-  if (mPushedClips.size()) {
-    mPrivateData->mEffect->GetVariableByName("mask")->AsShaderResource()->SetResource(maskSRView);
-    mPrivateData->mEffect->GetVariableByName("MaskTexCoords")->AsVector()->
-      SetFloatVector(ShaderConstantRectD3D10(shadowDest.x / mSize.width, shadowDest.y / mSize.height,
-                                             Float(aSurface->GetSize().width) / mSize.width,
-                                             Float(aSurface->GetSize().height) / mSize.height));
-    mPrivateData->mEffect->GetTechniqueByName("SampleTextureWithShadow")->
-      GetPassByIndex(2)->Apply(0);
-    SetScissorToRect(&clipBounds);
-  } else {
-    mPrivateData->mEffect->GetTechniqueByName("SampleTextureWithShadow")->
-      GetPassByIndex(1)->Apply(0);
-  }
-
-  mDevice->OMSetBlendState(GetBlendStateForOperator(aOperator), nullptr, 0xffffffff);
-
-  mDevice->Draw(4, 0);
-
-  srView = static_cast<SourceSurfaceD2DTarget*>(aSurface)->GetSRView();
-  if (!srView) {
-    return;
-  }
-
-  mPrivateData->mEffect->GetVariableByName("QuadDesc")->AsVector()->
-    SetFloatVector(ShaderConstantRectD3D10(-1.0f + ((aDest.x / mSize.width) * 2.0f),
-                                           1.0f - (aDest.y / mSize.height * 2.0f),
-                                           (Float(aSurface->GetSize().width) / mSize.width) * 2.0f,
-                                           (-Float(aSurface->GetSize().height) / mSize.height) * 2.0f));
-  mPrivateData->mEffect->GetVariableByName("tex")->AsShaderResource()->SetResource(static_cast<SourceSurfaceD2DTarget*>(aSurface)->GetSRView());
-  mPrivateData->mEffect->GetVariableByName("TexCoords")->AsVector()->
-    SetFloatVector(ShaderConstantRectD3D10(0, 0, 1.0f, 1.0f));
-
-  if (mPushedClips.size()) {
-    mPrivateData->mEffect->GetVariableByName("MaskTexCoords")->AsVector()->
-      SetFloatVector(ShaderConstantRectD3D10(aDest.x / mSize.width, aDest.y / mSize.height,
-                                             Float(aSurface->GetSize().width) / mSize.width,
-                                             Float(aSurface->GetSize().height) / mSize.height));
-    mPrivateData->mEffect->GetTechniqueByName("SampleMaskedTexture")->
-      GetPassByIndex(0)->Apply(0);
-    // We've set the scissor rect here for the previous draw call.
-  } else {
-    mPrivateData->mEffect->GetTechniqueByName("SampleTexture")->
-      GetPassByIndex(0)->Apply(0);
-  }
-
-  mDevice->OMSetBlendState(GetBlendStateForOperator(aOperator), nullptr, 0xffffffff);
-
-  mDevice->Draw(4, 0);
-}
-
-void
-DrawTargetD2D::ClearRect(const Rect &aRect)
-{
-  MarkChanged();
-  PushClipRect(aRect);
-
-  PopAllClips();
-
-  AutoSaveRestoreClippedOut restoreClippedOut(this);
-
-  D2D1_RECT_F clipRect;
-  bool isPixelAligned;
-  bool pushedClip = false;
-  if (mTransform.IsRectilinear() &&
-      GetDeviceSpaceClipRect(clipRect, isPixelAligned)) {
-    if (mTransformDirty ||
-        !mTransform.IsIdentity()) {
-      mRT->SetTransform(D2D1::IdentityMatrix());
-      mTransformDirty = true;
-    }
-
-    mRT->PushAxisAlignedClip(clipRect, isPixelAligned ? D2D1_ANTIALIAS_MODE_ALIASED : D2D1_ANTIALIAS_MODE_PER_PRIMITIVE);
-    pushedClip = true;
-  } else {
-    FlushTransformToRT();
-    restoreClippedOut.Save();
-  }
-
-  mRT->Clear(D2D1::ColorF(0, 0.0f));
-
-  if (pushedClip) {
-    mRT->PopAxisAlignedClip();
-  }
-
-  PopClip();
-  return;
-}
-
-void
-DrawTargetD2D::CopySurface(SourceSurface *aSurface,
-                           const IntRect &aSourceRect,
-                           const IntPoint &aDestination)
-{
-  MarkChanged();
-
-  Rect srcRect(Float(aSourceRect.x), Float(aSourceRect.y),
-               Float(aSourceRect.width), Float(aSourceRect.height));
-  Rect dstRect(Float(aDestination.x), Float(aDestination.y),
-               Float(aSourceRect.width), Float(aSourceRect.height));
-
-  mRT->SetTransform(D2D1::IdentityMatrix());
-  mTransformDirty = true;
-  mRT->PushAxisAlignedClip(D2DRect(dstRect), D2D1_ANTIALIAS_MODE_ALIASED);
-  mRT->Clear(D2D1::ColorF(0, 0.0f));
-  mRT->PopAxisAlignedClip();
-
-  RefPtr<ID2D1Bitmap> bitmap = GetBitmapForSurface(aSurface, srcRect);
-  if (!bitmap) {
-    return;
-  }
-
-  if (aSurface->GetFormat() == SurfaceFormat::A8) {
-    RefPtr<ID2D1SolidColorBrush> brush;
-    mRT->CreateSolidColorBrush(D2D1::ColorF(D2D1::ColorF::White),
-                               D2D1::BrushProperties(), getter_AddRefs(brush));
-    mRT->SetAntialiasMode(D2D1_ANTIALIAS_MODE_ALIASED);
-    mRT->FillOpacityMask(bitmap, brush, D2D1_OPACITY_MASK_CONTENT_GRAPHICS);
-  } else {
-    mRT->DrawBitmap(bitmap, D2DRect(dstRect), 1.0f,
-            D2D1_BITMAP_INTERPOLATION_MODE_LINEAR,
-            D2DRect(srcRect));
-  }
-}
-
-void
-DrawTargetD2D::FillRect(const Rect &aRect,
-                        const Pattern &aPattern,
-                        const DrawOptions &aOptions)
-{
-  ID2D1RenderTarget *rt = GetRTForOperation(aOptions.mCompositionOp, aPattern);
-
-  PrepareForDrawing(rt);
-
-  rt->SetAntialiasMode(D2DAAMode(aOptions.mAntialiasMode));
-
-  RefPtr<ID2D1Brush> brush = CreateBrushForPattern(aPattern, aOptions.mAlpha);
-
-  if (brush) {
-    rt->FillRectangle(D2DRect(aRect), brush);
-  }
-
-  FinalizeRTForOperation(aOptions.mCompositionOp, aPattern, aRect);
-}
-
-void
-DrawTargetD2D::StrokeRect(const Rect &aRect,
-                          const Pattern &aPattern,
-                          const StrokeOptions &aStrokeOptions,
-                          const DrawOptions &aOptions)
-{
-  ID2D1RenderTarget *rt = GetRTForOperation(aOptions.mCompositionOp, aPattern);
-
-  PrepareForDrawing(rt);
-
-  rt->SetAntialiasMode(D2DAAMode(aOptions.mAntialiasMode));
-
-  RefPtr<ID2D1Brush> brush = CreateBrushForPattern(aPattern, aOptions.mAlpha);
-
-  RefPtr<ID2D1StrokeStyle> strokeStyle = CreateStrokeStyleForOptions(aStrokeOptions);
-
-  if (brush && strokeStyle) {
-    rt->DrawRectangle(D2DRect(aRect), brush, aStrokeOptions.mLineWidth, strokeStyle);
-  }
-
-  FinalizeRTForOperation(aOptions.mCompositionOp, aPattern, aRect);
-}
-
-void
-DrawTargetD2D::StrokeLine(const Point &aStart,
-                          const Point &aEnd,
-                          const Pattern &aPattern,
-                          const StrokeOptions &aStrokeOptions,
-                          const DrawOptions &aOptions)
-{
-  ID2D1RenderTarget *rt = GetRTForOperation(aOptions.mCompositionOp, aPattern);
-
-  PrepareForDrawing(rt);
-
-  rt->SetAntialiasMode(D2DAAMode(aOptions.mAntialiasMode));
-
-  RefPtr<ID2D1Brush> brush = CreateBrushForPattern(aPattern, aOptions.mAlpha);
-
-  RefPtr<ID2D1StrokeStyle> strokeStyle = CreateStrokeStyleForOptions(aStrokeOptions);
-
-  if (brush && strokeStyle) {
-    rt->DrawLine(D2DPoint(aStart), D2DPoint(aEnd), brush, aStrokeOptions.mLineWidth, strokeStyle);
-  }
-
-  FinalizeRTForOperation(aOptions.mCompositionOp, aPattern, Rect(0, 0, Float(mSize.width), Float(mSize.height)));
-}
-
-void
-DrawTargetD2D::Stroke(const Path *aPath,
-                      const Pattern &aPattern,
-                      const StrokeOptions &aStrokeOptions,
-                      const DrawOptions &aOptions)
-{
-  if (aPath->GetBackendType() != BackendType::DIRECT2D) {
-    gfxDebug() << *this << ": Ignoring drawing call for incompatible path.";
-    return;
-  }
-
-  const PathD2D *d2dPath = static_cast<const PathD2D*>(aPath);
-
-  ID2D1RenderTarget *rt = GetRTForOperation(aOptions.mCompositionOp, aPattern);
-
-  PrepareForDrawing(rt);
-
-  rt->SetAntialiasMode(D2DAAMode(aOptions.mAntialiasMode));
-
-  RefPtr<ID2D1Brush> brush = CreateBrushForPattern(aPattern, aOptions.mAlpha);
-
-  RefPtr<ID2D1StrokeStyle> strokeStyle = CreateStrokeStyleForOptions(aStrokeOptions);
-
-  if (brush && strokeStyle) {
-    rt->DrawGeometry(d2dPath->mGeometry, brush, aStrokeOptions.mLineWidth, strokeStyle);
-  }
-
-  FinalizeRTForOperation(aOptions.mCompositionOp, aPattern, Rect(0, 0, Float(mSize.width), Float(mSize.height)));
-}
-
-void
-DrawTargetD2D::Fill(const Path *aPath,
-                    const Pattern &aPattern,
-                    const DrawOptions &aOptions)
-{
-  if (aPath->GetBackendType() != BackendType::DIRECT2D) {
-    gfxDebug() << *this << ": Ignoring drawing call for incompatible path.";
-    return;
-  }
-
-  const PathD2D *d2dPath = static_cast<const PathD2D*>(aPath);
-
-  ID2D1RenderTarget *rt = GetRTForOperation(aOptions.mCompositionOp, aPattern);
-
-  PrepareForDrawing(rt);
-
-  rt->SetAntialiasMode(D2DAAMode(aOptions.mAntialiasMode));
-
-  RefPtr<ID2D1Brush> brush = CreateBrushForPattern(aPattern, aOptions.mAlpha);
-
-  if (brush) {
-    rt->FillGeometry(d2dPath->mGeometry, brush);
-  }
-
-  Rect bounds;
-  if (aOptions.mCompositionOp != CompositionOp::OP_OVER) {
-    D2D1_RECT_F d2dbounds;
-    d2dPath->mGeometry->GetBounds(D2D1::IdentityMatrix(), &d2dbounds);
-    bounds = ToRect(d2dbounds);
-  }
-  FinalizeRTForOperation(aOptions.mCompositionOp, aPattern, bounds);
-}
-
-void
-DrawTargetD2D::FillGlyphs(ScaledFont *aFont,
-                          const GlyphBuffer &aBuffer,
-                          const Pattern &aPattern,
-                          const DrawOptions &aOptions,
-                          const GlyphRenderingOptions* aRenderOptions)
-{
-  if (aFont->GetType() != FontType::DWRITE) {
-    gfxDebug() << *this << ": Ignoring drawing call for incompatible font.";
-    return;
-  }
-
-  ScaledFontDWrite *font = static_cast<ScaledFontDWrite*>(aFont);
-
-  IDWriteRenderingParams *params = nullptr;
-  if (aRenderOptions) {
-    if (aRenderOptions->GetType() != FontType::DWRITE) {
-      gfxDebug() << *this << ": Ignoring incompatible GlyphRenderingOptions.";
-      // This should never happen.
-      MOZ_ASSERT(false);
-    } else {
-      params = static_cast<const GlyphRenderingOptionsDWrite*>(aRenderOptions)->mParams;
-    }
-  }
-
-  AntialiasMode aaMode = font->GetDefaultAAMode();
-
-  if (aOptions.mAntialiasMode != AntialiasMode::DEFAULT) {
-    aaMode = aOptions.mAntialiasMode;
-  }
-
-  if (mFormat == SurfaceFormat::B8G8R8A8 && mPermitSubpixelAA &&
-      aOptions.mCompositionOp == CompositionOp::OP_OVER && aPattern.GetType() == PatternType::COLOR &&
-      aaMode == AntialiasMode::SUBPIXEL) {
-    if (FillGlyphsManual(font, aBuffer,
-                         static_cast<const ColorPattern*>(&aPattern)->mColor,
-                         params, aOptions)) {
-      return;
-    }
-  }
-
-  ID2D1RenderTarget *rt = GetRTForOperation(aOptions.mCompositionOp, aPattern);
-
-  PrepareForDrawing(rt);
-
-  D2D1_TEXT_ANTIALIAS_MODE d2dAAMode = D2D1_TEXT_ANTIALIAS_MODE_DEFAULT;
-
-  switch (aaMode) {
-  case AntialiasMode::NONE:
-    d2dAAMode = D2D1_TEXT_ANTIALIAS_MODE_ALIASED;
-    break;
-  case AntialiasMode::GRAY:
-    d2dAAMode = D2D1_TEXT_ANTIALIAS_MODE_GRAYSCALE;
-    break;
-  case AntialiasMode::SUBPIXEL:
-    d2dAAMode = D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE;
-    break;
-  default:
-    d2dAAMode = D2D1_TEXT_ANTIALIAS_MODE_DEFAULT;
-  }
-
-  if (d2dAAMode == D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE &&
-      mFormat != SurfaceFormat::B8G8R8X8) {
-    d2dAAMode = D2D1_TEXT_ANTIALIAS_MODE_GRAYSCALE;
-  }
-
-  rt->SetTextAntialiasMode(d2dAAMode);
-
-  if (rt != mRT || params != mTextRenderingParams) {
-    rt->SetTextRenderingParams(params);
-    if (rt == mRT) {
-      mTextRenderingParams = params;
-    }
-  }
-
-  RefPtr<ID2D1Brush> brush = CreateBrushForPattern(aPattern, aOptions.mAlpha);
-
-  AutoDWriteGlyphRun autoRun;
-  DWriteGlyphRunFromGlyphs(aBuffer, font, &autoRun);
-
-  if (brush) {
-    rt->DrawGlyphRun(D2D1::Point2F(), &autoRun, brush);
-  }
-
-  FinalizeRTForOperation(aOptions.mCompositionOp, aPattern, Rect(0, 0, (Float)mSize.width, (Float)mSize.height));
-}
-
-void
-DrawTargetD2D::Mask(const Pattern &aSource,
-                    const Pattern &aMask,
-                    const DrawOptions &aOptions)
-{
-  ID2D1RenderTarget *rt = GetRTForOperation(aOptions.mCompositionOp, aSource);
-  
-  PrepareForDrawing(rt);
-
-  RefPtr<ID2D1Brush> brush = CreateBrushForPattern(aSource, aOptions.mAlpha);
-  RefPtr<ID2D1Brush> maskBrush = CreateBrushForPattern(aMask, 1.0f);
-
-  RefPtr<ID2D1Layer> layer;
-
-  layer = GetCachedLayer();
-
-  rt->PushLayer(D2D1::LayerParameters(D2D1::InfiniteRect(), nullptr,
-                                      D2D1_ANTIALIAS_MODE_PER_PRIMITIVE,
-                                      D2D1::IdentityMatrix(),
-                                      1.0f, maskBrush),
-                layer);
-
-  Rect rect(0, 0, (Float)mSize.width, (Float)mSize.height);
-  Matrix mat = mTransform;
-  mat.Invert();
-  
-  rt->FillRectangle(D2DRect(mat.TransformBounds(rect)), brush);
-  PopCachedLayer(rt);
-
-  FinalizeRTForOperation(aOptions.mCompositionOp, aSource, Rect(0, 0, (Float)mSize.width, (Float)mSize.height));
-}
-
-void
-DrawTargetD2D::PushClip(const Path *aPath)
-{
-  if (aPath->GetBackendType() != BackendType::DIRECT2D) {
-    gfxDebug() << *this << ": Ignoring clipping call for incompatible path.";
-    return;
-  }
-
-  mCurrentClipMaskTexture = nullptr;
-  mCurrentClippedGeometry = nullptr;
-
-  RefPtr<PathD2D> pathD2D = static_cast<PathD2D*>(const_cast<Path*>(aPath));
-
-  PushedClip clip;
-  clip.mTransform = D2DMatrix(mTransform);
-  clip.mPath = pathD2D;
-  
-  pathD2D->mGeometry->GetBounds(clip.mTransform, &clip.mBounds);
-  
-  clip.mLayer = GetCachedLayer();
-
-  mPushedClips.push_back(clip);
-
-  // The transform of clips is relative to the world matrix, since we use the total
-  // transform for the clips, make the world matrix identity.
-  mRT->SetTransform(D2D1::IdentityMatrix());
-  mTransformDirty = true;
-
-  if (mClipsArePushed) {
-    PushD2DLayer(mRT, pathD2D->mGeometry, clip.mLayer, clip.mTransform);
-  }
-}
-
-void
-DrawTargetD2D::PushClipRect(const Rect &aRect)
-{
-  mCurrentClipMaskTexture = nullptr;
-  mCurrentClippedGeometry = nullptr;
-  if (!mTransform.IsRectilinear()) {
-    // Whoops, this isn't a rectangle in device space, Direct2D will not deal
-    // with this transform the way we want it to.
-    // See remarks: http://msdn.microsoft.com/en-us/library/dd316860%28VS.85%29.aspx
-
-    RefPtr<PathBuilder> pathBuilder = CreatePathBuilder();
-    pathBuilder->MoveTo(aRect.TopLeft());
-    pathBuilder->LineTo(aRect.TopRight());
-    pathBuilder->LineTo(aRect.BottomRight());
-    pathBuilder->LineTo(aRect.BottomLeft());
-    pathBuilder->Close();
-    RefPtr<Path> path = pathBuilder->Finish();
-    return PushClip(path);
-  }
-
-  PushedClip clip;
-  Rect rect = mTransform.TransformBounds(aRect);
-  IntRect intRect;
-  clip.mIsPixelAligned = rect.ToIntRect(&intRect);
-
-  // Do not store the transform, just store the device space rectangle directly.
-  clip.mBounds = D2DRect(rect);
-
-  mPushedClips.push_back(clip);
-
-  mRT->SetTransform(D2D1::IdentityMatrix());
-  mTransformDirty = true;
-
-  if (mClipsArePushed) {
-    mRT->PushAxisAlignedClip(clip.mBounds, clip.mIsPixelAligned ? D2D1_ANTIALIAS_MODE_ALIASED : D2D1_ANTIALIAS_MODE_PER_PRIMITIVE);
-  }
-}
-
-void
-DrawTargetD2D::PopClip()
-{
-  mCurrentClipMaskTexture = nullptr;
-  mCurrentClippedGeometry = nullptr;
-  if (mClipsArePushed) {
-    if (mPushedClips.back().mLayer) {
-      PopCachedLayer(mRT);
-    } else {
-      mRT->PopAxisAlignedClip();
-    }
-  }
-  mPushedClips.pop_back();
-}
-
-already_AddRefed<SourceSurface> 
-DrawTargetD2D::CreateSourceSurfaceFromData(unsigned char *aData,
-                                           const IntSize &aSize,
-                                           int32_t aStride,
-                                           SurfaceFormat aFormat) const
-{
-  RefPtr<SourceSurfaceD2D> newSurf = new SourceSurfaceD2D();
-
-  if (!newSurf->InitFromData(aData, aSize, aStride, aFormat, mRT)) {
-    return nullptr;
-  }
-
-  return newSurf.forget();
-}
-
-already_AddRefed<SourceSurface> 
-DrawTargetD2D::OptimizeSourceSurface(SourceSurface *aSurface) const
-{
-  if (aSurface->GetType() == SurfaceType::D2D1_BITMAP ||
-      aSurface->GetType() == SurfaceType::D2D1_DRAWTARGET) {
-    RefPtr<SourceSurface> surface(aSurface);
-    return surface.forget();
-  }
-
-  RefPtr<DataSourceSurface> data = aSurface->GetDataSurface();
-
-  DataSourceSurface::MappedSurface map;
-  if (!data->Map(DataSourceSurface::MapType::READ, &map)) {
-    return nullptr;
-  }
-
-  RefPtr<SourceSurfaceD2D> newSurf = new SourceSurfaceD2D();
-  bool success = newSurf->InitFromData(map.mData, data->GetSize(), map.mStride, data->GetFormat(), mRT);
-
-  data->Unmap();
-
-  if (!success) {
-    return data.forget();
-  }
-  return newSurf.forget();
-}
-
-already_AddRefed<SourceSurface>
-DrawTargetD2D::CreateSourceSurfaceFromNativeSurface(const NativeSurface &aSurface) const
-{
-  if (aSurface.mType != NativeSurfaceType::D3D10_TEXTURE) {
-    gfxDebug() << *this << ": Failure to create source surface from non-D3D10 texture native surface.";
-    return nullptr;
-  }
-  RefPtr<SourceSurfaceD2D> newSurf = new SourceSurfaceD2D();
-
-  if (!newSurf->InitFromTexture(static_cast<ID3D10Texture2D*>(aSurface.mSurface),
-                                aSurface.mFormat,
-                                mRT))
-  {
-    gfxWarning() << *this << ": Failed to create SourceSurface from texture.";
-    return nullptr;
-  }
-
-  return newSurf.forget();
-}
-
-already_AddRefed<DrawTarget>
-DrawTargetD2D::CreateSimilarDrawTarget(const IntSize &aSize, SurfaceFormat aFormat) const
-{
-  RefPtr<DrawTargetD2D> newTarget =
-    new DrawTargetD2D();
-
-  if (!newTarget->Init(aSize, aFormat)) {
-    gfxDebug() << *this << ": Failed to create optimal draw target. Size: " << aSize;
-    return nullptr;
-  }
-
-  return newTarget.forget();
-}
-
-already_AddRefed<PathBuilder>
-DrawTargetD2D::CreatePathBuilder(FillRule aFillRule) const
-{
-  RefPtr<ID2D1PathGeometry> path;
-  HRESULT hr = factory()->CreatePathGeometry(getter_AddRefs(path));
-
-  if (FAILED(hr)) {
-    gfxWarning() << "Failed to create Direct2D Path Geometry. Code: " << hexa(hr);
-    return nullptr;
-  }
-
-  RefPtr<ID2D1GeometrySink> sink;
-  hr = path->Open(getter_AddRefs(sink));
-  if (FAILED(hr)) {
-    gfxWarning() << "Failed to access Direct2D Path Geometry. Code: " << hexa(hr);
-    return nullptr;
-  }
-
-  if (aFillRule == FillRule::FILL_WINDING) {
-    sink->SetFillMode(D2D1_FILL_MODE_WINDING);
-  }
-
-  return MakeAndAddRef<PathBuilderD2D>(sink, path, aFillRule, BackendType::DIRECT2D);
-}
-
-already_AddRefed<GradientStops>
-DrawTargetD2D::CreateGradientStops(GradientStop *rawStops, uint32_t aNumStops, ExtendMode aExtendMode) const
-{
-  D2D1_GRADIENT_STOP *stops = new D2D1_GRADIENT_STOP[aNumStops];
-
-  for (uint32_t i = 0; i < aNumStops; i++) {
-    stops[i].position = rawStops[i].offset;
-    stops[i].color = D2DColor(rawStops[i].color);
-  }
-
-  RefPtr<ID2D1GradientStopCollection> stopCollection;
-
-  HRESULT hr =
-    mRT->CreateGradientStopCollection(stops, aNumStops,
-                                      D2D1_GAMMA_2_2, D2DExtend(aExtendMode, Axis::BOTH),
-                                      getter_AddRefs(stopCollection));
-  delete [] stops;
-
-  if (FAILED(hr)) {
-    gfxWarning() << "Failed to create GradientStopCollection. Code: " << hexa(hr);
-    return nullptr;
-  }
-
-  return MakeAndAddRef<GradientStopsD2D>(stopCollection, Factory::GetDirect3D11Device());
-}
-
-already_AddRefed<FilterNode>
-DrawTargetD2D::CreateFilter(FilterType aType)
-{
-  RefPtr<ID2D1DeviceContext> dc;
-  HRESULT hr = mRT->QueryInterface((ID2D1DeviceContext**)getter_AddRefs(dc));
-
-  if (SUCCEEDED(hr)) {
-    return FilterNodeD2D1::Create(dc, aType);
-  }
-  return FilterNodeSoftware::Create(aType);
-}
-
-void*
-DrawTargetD2D::GetNativeSurface(NativeSurfaceType aType)
-{
-  if (aType != NativeSurfaceType::D3D10_TEXTURE) {
-    return nullptr;
-  }
-
-  return mTexture;
-}
-
-/*
- * Public functions
- */
-bool
-DrawTargetD2D::Init(const IntSize &aSize, SurfaceFormat aFormat)
-{
-  HRESULT hr;
-
-  mSize = aSize;
-  mFormat = aFormat;
-
-  if (!Factory::GetDirect3D10Device()) {
-    gfxCriticalError() << "Failed to Init Direct2D DrawTarget (No D3D10 Device set.)";
-    return false;
-  }
-  mDevice = Factory::GetDirect3D10Device();
-
-  CD3D10_TEXTURE2D_DESC desc(DXGIFormat(aFormat),
-                             mSize.width,
-                             mSize.height,
-                             1, 1);
-  desc.BindFlags = D3D10_BIND_RENDER_TARGET | D3D10_BIND_SHADER_RESOURCE;
-
-  hr = mDevice->CreateTexture2D(&desc, nullptr, getter_AddRefs(mTexture));
-
-  if (FAILED(hr)) {
-    gfxCriticalError(CriticalLog::DefaultOptions(Factory::ReasonableSurfaceSize(aSize))) << "Failed to init Direct2D DrawTarget. Size: " << mSize << " Code: " << hexa(hr);
-    return false;
-  }
-
-  if (!InitD2DRenderTarget()) {
-    return false;
-  }
-
-  mRT->Clear(D2D1::ColorF(0, 0));
-  return true;
-}
-
-bool
-DrawTargetD2D::Init(ID3D10Texture2D *aTexture, SurfaceFormat aFormat)
-{
-  HRESULT hr;
-
-  mTexture = aTexture;
-  mFormat = aFormat;
-
-  if (!mTexture) {
-    gfxCriticalError() << "No valid texture for Direct2D draw target initialization.";
-    return false;
-  }
-
-  RefPtr<ID3D10Device> device;
-  mTexture->GetDevice(getter_AddRefs(device));
-
-  hr = device->QueryInterface((ID3D10Device1**)getter_AddRefs(mDevice));
-
-  if (FAILED(hr)) {
-    gfxCriticalError() << "Failed to get D3D10 device from texture." << " format " << (int)aFormat;
-    return false;
-  }
-
-  D3D10_TEXTURE2D_DESC desc;
-  mTexture->GetDesc(&desc);
-  mSize.width = desc.Width;
-  mSize.height = desc.Height;
-
-  return InitD2DRenderTarget();
-}
-
-// {0D398B49-AE7B-416F-B26D-EA3C137D1CF7}
-static const GUID sPrivateDataD2D = 
-{ 0xd398b49, 0xae7b, 0x416f, { 0xb2, 0x6d, 0xea, 0x3c, 0x13, 0x7d, 0x1c, 0xf7 } };
-
-bool
-DrawTargetD2D::InitD3D10Data()
-{
-  HRESULT hr;
-  
-  UINT privateDataSize;
-  privateDataSize = sizeof(mPrivateData);
-  hr = mDevice->GetPrivateData(sPrivateDataD2D, &privateDataSize, &mPrivateData);
-
-  if (SUCCEEDED(hr)) {
-      return true;
-  }
-
-  mPrivateData = new PrivateD3D10DataD2D;
-
-  decltype(D3D10CreateEffectFromMemory)* createD3DEffect;
-  HMODULE d3dModule = LoadLibraryW(L"d3d10_1.dll");
-  createD3DEffect = (decltype(D3D10CreateEffectFromMemory)*)
-      GetProcAddress(d3dModule, "D3D10CreateEffectFromMemory");
-
-  hr = createD3DEffect((void*)d2deffect, sizeof(d2deffect), 0, mDevice, nullptr, getter_AddRefs(mPrivateData->mEffect));
-
-  if (FAILED(hr)) {
-    gfxWarning() << "Failed to initialize Direct2D required effects. Code: " << hexa(hr);
-    return false;
-  }
-
-  privateDataSize = sizeof(mPrivateData);
-  mDevice->SetPrivateData(sPrivateDataD2D, privateDataSize, &mPrivateData);
-
-  D3D10_INPUT_ELEMENT_DESC layout[] =
-  {
-    { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D10_INPUT_PER_VERTEX_DATA, 0 },
-  };
-  D3D10_PASS_DESC passDesc;
-  
-  mPrivateData->mEffect->GetTechniqueByName("SampleTexture")->GetPassByIndex(0)->GetDesc(&passDesc);
-
-  hr = mDevice->CreateInputLayout(layout,
-                                  sizeof(layout) / sizeof(D3D10_INPUT_ELEMENT_DESC),
-                                  passDesc.pIAInputSignature,
-                                  passDesc.IAInputSignatureSize,
-                                  getter_AddRefs(mPrivateData->mInputLayout));
-
-  if (FAILED(hr)) {
-    gfxWarning() << "Failed to initialize Direct2D required InputLayout. Code: " << hexa(hr);
-    return false;
-  }
-
-  D3D10_SUBRESOURCE_DATA data;
-  Vertex vertices[] = { {0.0, 0.0}, {1.0, 0.0}, {0.0, 1.0}, {1.0, 1.0} };
-  data.pSysMem = vertices;
-  CD3D10_BUFFER_DESC bufferDesc(sizeof(vertices), D3D10_BIND_VERTEX_BUFFER);
-
-  hr = mDevice->CreateBuffer(&bufferDesc, &data, getter_AddRefs(mPrivateData->mVB));
-
-  if (FAILED(hr)) {
-    gfxWarning() << "Failed to initialize Direct2D required VertexBuffer. Code: " << hexa(hr);
-    return false;
-  }
-
-  return true;
-}
-
-/*
- * Private helpers
- */
-uint32_t
-DrawTargetD2D::GetByteSize() const
-{
-  return mSize.width * mSize.height * BytesPerPixel(mFormat);
-}
-
-already_AddRefed<ID2D1Layer>
-DrawTargetD2D::GetCachedLayer()
-{
-  RefPtr<ID2D1Layer> layer;
-
-  if (mCurrentCachedLayer < 5) {
-    if (!mCachedLayers[mCurrentCachedLayer]) {
-      mRT->CreateLayer(getter_AddRefs(mCachedLayers[mCurrentCachedLayer]));
-      mVRAMUsageDT += GetByteSize();
-    }
-    layer = mCachedLayers[mCurrentCachedLayer];
-  } else {
-    mRT->CreateLayer(getter_AddRefs(layer));
-  }
-
-  mCurrentCachedLayer++;
-  return layer.forget();
-}
-
-void
-DrawTargetD2D::PopCachedLayer(ID2D1RenderTarget *aRT)
-{
-  aRT->PopLayer();
-  mCurrentCachedLayer--;
-}
-
-bool
-DrawTargetD2D::InitD2DRenderTarget()
-{
-  if (!factory()) {
-    gfxCriticalError() << "No valid D2D factory available.";
-    return false;
-  }
-
-  mRT = CreateRTForTexture(mTexture, mFormat);
-
-  if (!mRT) {
-    return false;
-  }
-
-  mRT->BeginDraw();
-
-  if (mFormat == SurfaceFormat::B8G8R8X8) {
-    mRT->SetTextAntialiasMode(D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE);
-  }
-
-  mVRAMUsageDT += GetByteSize();
-
-  return InitD3D10Data();
-}
-
-void
-DrawTargetD2D::PrepareForDrawing(ID2D1RenderTarget *aRT)
-{
-  if (!mClipsArePushed || aRT == mTempRT) {
-    if (mPushedClips.size()) {
-      // The transform of clips is relative to the world matrix, since we use the total
-      // transform for the clips, make the world matrix identity.
-      aRT->SetTransform(D2D1::IdentityMatrix());
-      if (aRT == mRT) {
-        mTransformDirty = true;
-        mClipsArePushed = true;
-      }
-      PushClipsToRT(aRT);
-    }
-  }
-  FlushTransformToRT();
-  MarkChanged();
-
-  if (aRT == mTempRT) {
-    mTempRT->SetTransform(D2DMatrix(mTransform));
-  }
-}
-
-void
-DrawTargetD2D::MarkChanged()
-{
-  if (mSnapshot) {
-    if (mSnapshot->hasOneRef()) {
-      // Just destroy it, since no-one else knows about it.
-      mSnapshot = nullptr;
-    } else {
-      mSnapshot->DrawTargetWillChange();
-      // The snapshot will no longer depend on this target.
-      MOZ_ASSERT(!mSnapshot);
-    }
-  }
-  if (mDependentTargets.size()) {
-    // Copy mDependentTargets since the Flush()es below will modify it.
-    TargetSet tmpTargets = mDependentTargets;
-    for (TargetSet::iterator iter = tmpTargets.begin();
-         iter != tmpTargets.end(); iter++) {
-      (*iter)->Flush();
-    }
-    // The Flush() should have broken all dependencies on this target.
-    MOZ_ASSERT(!mDependentTargets.size());
-  }
-}
-
-ID3D10BlendState*
-DrawTargetD2D::GetBlendStateForOperator(CompositionOp aOperator)
-{
-  size_t operatorIndex = static_cast<size_t>(aOperator);
-  if (mPrivateData->mBlendStates[operatorIndex]) {
-    return mPrivateData->mBlendStates[operatorIndex];
-  }
-
-  D3D10_BLEND_DESC desc;
-
-  memset(&desc, 0, sizeof(D3D10_BLEND_DESC));
-
-  desc.AlphaToCoverageEnable = FALSE;
-  desc.BlendEnable[0] = TRUE;
-  desc.RenderTargetWriteMask[0] = D3D10_COLOR_WRITE_ENABLE_ALL;
-  desc.BlendOp = desc.BlendOpAlpha = D3D10_BLEND_OP_ADD;
-
-  switch (aOperator) {
-  case CompositionOp::OP_ADD:
-    desc.SrcBlend = desc.SrcBlendAlpha = D3D10_BLEND_ONE;
-    desc.DestBlend = desc.DestBlendAlpha = D3D10_BLEND_ONE;
-    break;
-  case CompositionOp::OP_IN:
-    desc.SrcBlend = desc.SrcBlendAlpha = D3D10_BLEND_DEST_ALPHA;
-    desc.DestBlend = desc.DestBlendAlpha = D3D10_BLEND_ZERO;
-    break;
-  case CompositionOp::OP_OUT:
-    desc.SrcBlend = desc.SrcBlendAlpha = D3D10_BLEND_INV_DEST_ALPHA;
-    desc.DestBlend = desc.DestBlendAlpha = D3D10_BLEND_ZERO;
-    break;
-  case CompositionOp::OP_ATOP:
-    desc.SrcBlend = desc.SrcBlendAlpha = D3D10_BLEND_DEST_ALPHA;
-    desc.DestBlend = desc.DestBlendAlpha = D3D10_BLEND_INV_SRC_ALPHA;
-    break;
-  case CompositionOp::OP_DEST_IN:
-    desc.SrcBlend = desc.SrcBlendAlpha = D3D10_BLEND_ZERO;
-    desc.DestBlend = desc.DestBlendAlpha = D3D10_BLEND_SRC_ALPHA;
-    break;
-  case CompositionOp::OP_DEST_OUT:
-    desc.SrcBlend = desc.SrcBlendAlpha = D3D10_BLEND_ZERO;
-    desc.DestBlend = desc.DestBlendAlpha = D3D10_BLEND_INV_SRC_ALPHA;
-    break;
-  case CompositionOp::OP_DEST_ATOP:
-    desc.SrcBlend = desc.SrcBlendAlpha = D3D10_BLEND_INV_DEST_ALPHA;
-    desc.DestBlend = desc.DestBlendAlpha = D3D10_BLEND_SRC_ALPHA;
-    break;
-  case CompositionOp::OP_DEST_OVER:
-    desc.SrcBlend = desc.SrcBlendAlpha = D3D10_BLEND_INV_DEST_ALPHA;
-    desc.DestBlend = desc.DestBlendAlpha = D3D10_BLEND_ONE;
-    break;
-  case CompositionOp::OP_XOR:
-    desc.SrcBlend = desc.SrcBlendAlpha = D3D10_BLEND_INV_DEST_ALPHA;
-    desc.DestBlend = desc.DestBlendAlpha = D3D10_BLEND_INV_SRC_ALPHA;
-    break;
-  case CompositionOp::OP_SOURCE:
-    desc.SrcBlend = desc.SrcBlendAlpha = D3D10_BLEND_ONE;
-    desc.DestBlend = desc.DestBlendAlpha = D3D10_BLEND_ZERO;
-    break;
-  default:
-    desc.SrcBlend = desc.SrcBlendAlpha = D3D10_BLEND_ONE;
-    desc.DestBlend = desc.DestBlendAlpha = D3D10_BLEND_INV_SRC_ALPHA;
-  }
-  
-  mDevice->CreateBlendState(&desc, getter_AddRefs(mPrivateData->mBlendStates[operatorIndex]));
-
-  return mPrivateData->mBlendStates[operatorIndex];
-}
-
-/* This function prepares the temporary RT for drawing and returns it when a
- * drawing operation other than OVER is required.
- */
-ID2D1RenderTarget*
-DrawTargetD2D::GetRTForOperation(CompositionOp aOperator, const Pattern &aPattern)
-{
-  if (aOperator == CompositionOp::OP_OVER && IsPatternSupportedByD2D(aPattern)) {
-    return mRT;
-  }
-
-  PopAllClips();
-
-  if (aOperator > CompositionOp::OP_XOR) {
-    mRT->Flush();
-  }
-
-  if (mTempRT) {
-    mTempRT->Clear(D2D1::ColorF(0, 0));
-    return mTempRT;
-  }
-
-  EnsureViews();
-
-  if (!mRTView || !mSRView) {
-    gfxDebug() << *this << ": Failed to get required views. Defaulting to CompositionOp::OP_OVER.";
-    return mRT;
-  }
-
-  mTempRT = CreateRTForTexture(mTempTexture, SurfaceFormat::B8G8R8A8);
-
-  if (!mTempRT) {
-    return mRT;
-  }
-
-  mVRAMUsageDT += GetByteSize();
-
-  mTempRT->BeginDraw();
-
-  mTempRT->Clear(D2D1::ColorF(0, 0));
-
-  return mTempRT;
-}
-
-/* This function blends back the content of a drawing operation (drawn to an
- * empty surface with OVER, so the surface now contains the source operation
- * contents) to the rendertarget using the requested composition operation.
- * In order to respect clip for operations which are unbound by their mask,
- * the old content of the surface outside the clipped area may be blended back
- * to the surface.
- */
-void
-DrawTargetD2D::FinalizeRTForOperation(CompositionOp aOperator, const Pattern &aPattern, const Rect &aBounds)
-{
-  if (aOperator == CompositionOp::OP_OVER && IsPatternSupportedByD2D(aPattern)) {
-    return;
-  }
-
-  if (!mTempRT) {
-    return;
-  }
-
-  PopClipsFromRT(mTempRT);
-
-  mRT->Flush();
-  mTempRT->Flush();
-
-  AutoSaveRestoreClippedOut restoreClippedOut(this);
-
-  bool needsWriteBack =
-    !IsOperatorBoundByMask(aOperator) && mPushedClips.size();
-
-  if (needsWriteBack) {
-    restoreClippedOut.Save();
-  }
-
-  ID3D10RenderTargetView *rtViews = mRTView;
-  mDevice->OMSetRenderTargets(1, &rtViews, nullptr);
-
-  UINT stride = sizeof(Vertex);
-  UINT offset = 0;
-  ID3D10Buffer *buff = mPrivateData->mVB;
-
-  mDevice->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
-  mDevice->IASetVertexBuffers(0, 1, &buff, &stride, &offset);
-  mDevice->IASetInputLayout(mPrivateData->mInputLayout);
-
-  D3D10_VIEWPORT viewport;
-  viewport.MaxDepth = 1;
-  viewport.MinDepth = 0;
-  viewport.Height = mSize.height;
-  viewport.Width = mSize.width;
-  viewport.TopLeftX = 0;
-  viewport.TopLeftY = 0;
-
-  RefPtr<ID3D10Texture2D> tmpTexture;
-  RefPtr<ID3D10ShaderResourceView> mBckSRView;
-
-  mDevice->RSSetViewports(1, &viewport);
-  mPrivateData->mEffect->GetVariableByName("QuadDesc")->AsVector()->
-    SetFloatVector(ShaderConstantRectD3D10(-1.0f, 1.0f, 2.0f, -2.0f));
-
-  if (IsPatternSupportedByD2D(aPattern)) {
-    mPrivateData->mEffect->GetVariableByName("TexCoords")->AsVector()->
-      SetFloatVector(ShaderConstantRectD3D10(0, 0, 1.0f, 1.0f));
-    mPrivateData->mEffect->GetVariableByName("tex")->AsShaderResource()->SetResource(mSRView);
-
-    // Handle the case where we blend with the backdrop
-    if (aOperator > CompositionOp::OP_XOR) {
-      IntSize size = mSize;
-      SurfaceFormat format = mFormat;
-
-      CD3D10_TEXTURE2D_DESC desc(DXGIFormat(format), size.width, size.height, 1, 1);
-      desc.BindFlags = D3D10_BIND_RENDER_TARGET | D3D10_BIND_SHADER_RESOURCE;
-
-      HRESULT hr = mDevice->CreateTexture2D(&desc, nullptr, getter_AddRefs(tmpTexture));
-      if (FAILED(hr)) {
-        gfxWarning() << "Failed to create temporary texture to hold surface data.";
-        return;
-      }
-
-      mDevice->CopyResource(tmpTexture, mTexture);
-      if (FAILED(hr)) {
-        gfxWarning() << *this << "Failed to create shader resource view for temp texture. Code: " << hexa(hr);
-        return;
-      }
-
-      DrawTargetD2D::Flush();
-
-      hr = mDevice->CreateShaderResourceView(tmpTexture, nullptr, getter_AddRefs(mBckSRView));
-
-      if (FAILED(hr)) {
-        gfxWarning() << *this << "Failed to create shader resource view for temp texture. Code: " << hexa(hr);
-        return;
-      }
-
-      unsigned int compop = (unsigned int)aOperator - (unsigned int)CompositionOp::OP_XOR;
-      mPrivateData->mEffect->GetVariableByName("bcktex")->AsShaderResource()->SetResource(mBckSRView);
-      mPrivateData->mEffect->GetVariableByName("blendop")->AsScalar()->SetInt(compop);
-
-      if (aOperator > CompositionOp::OP_EXCLUSION)
-        mPrivateData->mEffect->GetTechniqueByName("SampleTextureForNonSeparableBlending")->
-          GetPassByIndex(0)->Apply(0);
-      else if (aOperator > CompositionOp::OP_COLOR_DODGE)
-        mPrivateData->mEffect->GetTechniqueByName("SampleTextureForSeparableBlending_2")->
-          GetPassByIndex(0)->Apply(0);
-      else
-        mPrivateData->mEffect->GetTechniqueByName("SampleTextureForSeparableBlending_1")->
-          GetPassByIndex(0)->Apply(0);
-    }
-    else {
-      mPrivateData->mEffect->GetTechniqueByName("SampleTexture")->GetPassByIndex(0)->Apply(0);
-    }
-
-  } else if (aPattern.GetType() == PatternType::RADIAL_GRADIENT) {
-    const RadialGradientPattern *pat = static_cast<const RadialGradientPattern*>(&aPattern);
-
-    if (pat->mCenter1 == pat->mCenter2 && pat->mRadius1 == pat->mRadius2) {
-      // Draw nothing!
-      return;
-    }
-
-    mPrivateData->mEffect->GetVariableByName("mask")->AsShaderResource()->SetResource(mSRView);
-
-    SetupEffectForRadialGradient(pat);
-  }
-
-  mDevice->OMSetBlendState(GetBlendStateForOperator(aOperator), nullptr, 0xffffffff);
-  
-  SetScissorToRect(nullptr);
-  mDevice->Draw(4, 0);
-}
-
-static D2D1_RECT_F
-IntersectRect(const D2D1_RECT_F& aRect1, const D2D1_RECT_F& aRect2)
-{
-  D2D1_RECT_F result;
-  result.left = max(aRect1.left, aRect2.left);
-  result.top = max(aRect1.top, aRect2.top);
-  result.right = min(aRect1.right, aRect2.right);
-  result.bottom = min(aRect1.bottom, aRect2.bottom);
-
-  result.right = max(result.right, result.left);
-  result.bottom = max(result.bottom, result.top);
-
-  return result;
-}
-
-bool
-DrawTargetD2D::GetDeviceSpaceClipRect(D2D1_RECT_F& aClipRect, bool& aIsPixelAligned)
-{
-  if (!mPushedClips.size()) {
-    return false;
-  }
-
-  std::vector<DrawTargetD2D::PushedClip>::iterator iter = mPushedClips.begin();
-  if (iter->mPath) {
-    return false;
-  }
-  aClipRect = iter->mBounds;
-  aIsPixelAligned = iter->mIsPixelAligned;
-
-  iter++;
-  for (;iter != mPushedClips.end(); iter++) {
-    if (iter->mPath) {
-      return false;
-    }
-    aClipRect = IntersectRect(aClipRect, iter->mBounds);
-    if (!iter->mIsPixelAligned) {
-      aIsPixelAligned = false;
-    }
-  }
-  return true;
-}
-
-already_AddRefed<ID2D1Geometry>
-DrawTargetD2D::GetClippedGeometry(IntRect *aClipBounds)
-{
-  if (mCurrentClippedGeometry) {
-    *aClipBounds = mCurrentClipBounds;
-    RefPtr<ID2D1Geometry> clippedGeometry(mCurrentClippedGeometry);
-    return clippedGeometry.forget();
-  }
-
-  mCurrentClipBounds = IntRect(IntPoint(0, 0), mSize);
-
-  // if pathGeom is null then pathRect represents the path.
-  RefPtr<ID2D1Geometry> pathGeom;
-  D2D1_RECT_F pathRect;
-  bool pathRectIsAxisAligned = false;
-  std::vector<DrawTargetD2D::PushedClip>::iterator iter = mPushedClips.begin();
-  
-  if (iter->mPath) {
-    pathGeom = GetTransformedGeometry(iter->mPath->GetGeometry(), iter->mTransform);
-  } else {
-    pathRect = iter->mBounds;
-    pathRectIsAxisAligned = iter->mIsPixelAligned;
-  }
-
-  iter++;
-  for (;iter != mPushedClips.end(); iter++) {
-    // Do nothing but add it to the current clip bounds.
-    if (!iter->mPath && iter->mIsPixelAligned) {
-      mCurrentClipBounds.IntersectRect(mCurrentClipBounds,
-        IntRect(int32_t(iter->mBounds.left), int32_t(iter->mBounds.top),
-                int32_t(iter->mBounds.right - iter->mBounds.left),
-                int32_t(iter->mBounds.bottom - iter->mBounds.top)));
-      continue;
-    }
-
-    if (!pathGeom) {
-      if (pathRectIsAxisAligned) {
-        mCurrentClipBounds.IntersectRect(mCurrentClipBounds,
-          IntRect(int32_t(pathRect.left), int32_t(pathRect.top),
-                  int32_t(pathRect.right - pathRect.left),
-                  int32_t(pathRect.bottom - pathRect.top)));
-      }
-      if (iter->mPath) {
-        // See if pathRect needs to go into the path geometry.
-        if (!pathRectIsAxisAligned) {
-          pathGeom = ConvertRectToGeometry(pathRect);
-        } else {
-          pathGeom = GetTransformedGeometry(iter->mPath->GetGeometry(), iter->mTransform);
-        }
-      } else {
-        pathRect = IntersectRect(pathRect, iter->mBounds);
-        pathRectIsAxisAligned = false;
-        continue;
-      }
-    }
-
-    RefPtr<ID2D1PathGeometry> newGeom;
-    factory()->CreatePathGeometry(getter_AddRefs(newGeom));
-
-    RefPtr<ID2D1GeometrySink> currentSink;
-    newGeom->Open(getter_AddRefs(currentSink));
-
-    if (iter->mPath) {
-      pathGeom->CombineWithGeometry(iter->mPath->GetGeometry(), D2D1_COMBINE_MODE_INTERSECT,
-                                    iter->mTransform, currentSink);
-    } else {
-      RefPtr<ID2D1Geometry> rectGeom = ConvertRectToGeometry(iter->mBounds);
-      pathGeom->CombineWithGeometry(rectGeom, D2D1_COMBINE_MODE_INTERSECT,
-                                    D2D1::IdentityMatrix(), currentSink);
-    }
-
-    currentSink->Close();
-
-    pathGeom = newGeom.forget();
-  }
-
-  // For now we need mCurrentClippedGeometry to always be non-nullptr. This
-  // method might seem a little strange but it is just fine, if pathGeom is
-  // nullptr pathRect will always still contain 1 clip unaccounted for
-  // regardless of mCurrentClipBounds.
-  if (!pathGeom) {
-    pathGeom = ConvertRectToGeometry(pathRect);
-  }
-  mCurrentClippedGeometry = pathGeom.forget();
-  *aClipBounds = mCurrentClipBounds;
-  RefPtr<ID2D1Geometry> clippedGeometry(mCurrentClippedGeometry);
-  return clippedGeometry.forget();
-}
-
-already_AddRefed<ID2D1RenderTarget>
-DrawTargetD2D::CreateRTForTexture(ID3D10Texture2D *aTexture, SurfaceFormat aFormat)
-{
-  HRESULT hr;
-
-  RefPtr<IDXGISurface> surface;
-  RefPtr<ID2D1RenderTarget> rt;
-
-  hr = aTexture->QueryInterface((IDXGISurface**)getter_AddRefs(surface));
-
-  if (FAILED(hr)) {
-    gfxCriticalError() << "Failed to QI texture to surface. Code: " << hexa(hr);
-    return nullptr;
-  }
-
-  D3D10_TEXTURE2D_DESC desc;
-  aTexture->GetDesc(&desc);
-
-  D2D1_ALPHA_MODE alphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED;
-
-  if (aFormat == SurfaceFormat::B8G8R8X8 && aTexture == mTexture) {
-    alphaMode = D2D1_ALPHA_MODE_IGNORE;
-  }
-
-  D2D1_RENDER_TARGET_PROPERTIES props =
-    D2D1::RenderTargetProperties(D2D1_RENDER_TARGET_TYPE_DEFAULT, D2D1::PixelFormat(desc.Format, alphaMode));
-  hr = factory()->CreateDxgiSurfaceRenderTarget(surface, props, getter_AddRefs(rt));
-
-  if (FAILED(hr)) {
-    gfxCriticalError() << "Failed to create D2D render target for texture. Code: "
-                       << hexa(hr) << " " << mSize << " Format: " << uint32_t(aFormat);
-    return nullptr;
-  }
-
-  return rt.forget();
-}
-
-void
-DrawTargetD2D::EnsureViews()
-{
-  if (mTempTexture && mSRView && mRTView) {
-    return;
-  }
-
-  HRESULT hr;
-
-  CD3D10_TEXTURE2D_DESC desc(DXGI_FORMAT_B8G8R8A8_UNORM,
-                             mSize.width,
-                             mSize.height,
-                             1, 1);
-  desc.BindFlags = D3D10_BIND_RENDER_TARGET | D3D10_BIND_SHADER_RESOURCE;
-
-  hr = mDevice->CreateTexture2D(&desc, nullptr, getter_AddRefs(mTempTexture));
-
-  if (FAILED(hr)) {
-    gfxWarning() << *this << "Failed to create temporary texture for rendertarget. Size: "
-      << mSize << " Code: " << hexa(hr);
-    return;
-  }
-
-  hr = mDevice->CreateShaderResourceView(mTempTexture, nullptr, getter_AddRefs(mSRView));
-
-  if (FAILED(hr)) {
-    gfxWarning() << *this << "Failed to create shader resource view for temp texture. Code: " << hexa(hr);
-    return;
-  }
-
-  hr = mDevice->CreateRenderTargetView(mTexture, nullptr, getter_AddRefs(mRTView));
-
-  if (FAILED(hr)) {
-    gfxWarning() << *this << "Failed to create rendertarget view for temp texture. Code: " << hexa(hr);
-  }
-}
-
-void
-DrawTargetD2D::PopAllClips()
-{
-  if (mClipsArePushed) {
-    PopClipsFromRT(mRT);
-  
-    mClipsArePushed = false;
-  }
-}
-
-void
-DrawTargetD2D::PushClipsToRT(ID2D1RenderTarget *aRT)
-{
-  for (std::vector<PushedClip>::iterator iter = mPushedClips.begin();
-        iter != mPushedClips.end(); iter++) {
-    if (iter->mLayer) {
-      PushD2DLayer(aRT, iter->mPath->mGeometry, iter->mLayer, iter->mTransform);
-    } else {
-      aRT->PushAxisAlignedClip(iter->mBounds, iter->mIsPixelAligned ? D2D1_ANTIALIAS_MODE_ALIASED : D2D1_ANTIALIAS_MODE_PER_PRIMITIVE);
-    }
-  }
-}
-
-void
-DrawTargetD2D::PopClipsFromRT(ID2D1RenderTarget *aRT)
-{
-  for (int i = mPushedClips.size() - 1; i >= 0; i--) {
-    if (mPushedClips[i].mLayer) {
-      aRT->PopLayer();
-    } else {
-      aRT->PopAxisAlignedClip();
-    }
-  }
-}
-
-void
-DrawTargetD2D::EnsureClipMaskTexture(IntRect *aBounds)
-{
-  if (mCurrentClipMaskTexture || mPushedClips.empty()) {
-    *aBounds = mCurrentClipBounds;
-    return;
-  }
-  
-  RefPtr<ID2D1Geometry> geometry = GetClippedGeometry(aBounds);
-
-  CD3D10_TEXTURE2D_DESC desc(DXGI_FORMAT_A8_UNORM,
-                             mSize.width,
-                             mSize.height,
-                             1, 1);
-  desc.BindFlags = D3D10_BIND_RENDER_TARGET | D3D10_BIND_SHADER_RESOURCE;
-
-  HRESULT hr = mDevice->CreateTexture2D(&desc, nullptr, getter_AddRefs(mCurrentClipMaskTexture));
-
-  if (FAILED(hr)) {
-    gfxWarning() << "Failed to create texture for ClipMask!";
-    return;
-  }
-
-  RefPtr<ID2D1RenderTarget> rt = CreateRTForTexture(mCurrentClipMaskTexture, SurfaceFormat::A8);
-
-  if (!rt) {
-    gfxWarning() << "Failed to create RT for ClipMask!";
-    return;
-  }
-  
-  RefPtr<ID2D1SolidColorBrush> brush;
-  rt->CreateSolidColorBrush(D2D1::ColorF(D2D1::ColorF::White), getter_AddRefs(brush));
-    
-  rt->BeginDraw();
-  rt->Clear(D2D1::ColorF(0, 0));
-  rt->FillGeometry(geometry, brush);
-  rt->EndDraw();
-}
-
-bool
-DrawTargetD2D::FillGlyphsManual(ScaledFontDWrite *aFont,
-                                const GlyphBuffer &aBuffer,
-                                const Color &aColor,
-                                IDWriteRenderingParams *aParams,
-                                const DrawOptions &aOptions)
-{
-  HRESULT hr;
-
-  RefPtr<IDWriteRenderingParams> params;
-
-  if (aParams) {
-    params = aParams;
-  } else {
-    mRT->GetTextRenderingParams(getter_AddRefs(params));
-  }
-
-  DWRITE_RENDERING_MODE renderMode = DWRITE_RENDERING_MODE_DEFAULT;
-  if (params) {
-    hr = aFont->mFontFace->GetRecommendedRenderingMode(
-      (FLOAT)aFont->GetSize(),
-      1.0f,
-      DWRITE_MEASURING_MODE_NATURAL,
-      params,
-      &renderMode);
-    if (FAILED(hr)) {
-      // this probably never happens, but let's play it safe
-      renderMode = DWRITE_RENDERING_MODE_DEFAULT;
-    }
-  }
-
-  // Deal with rendering modes CreateGlyphRunAnalysis doesn't accept.
-  switch (renderMode) {
-  case DWRITE_RENDERING_MODE_ALIASED:
-    // ClearType texture creation will fail in this mode, so bail out
-    return false;
-  case DWRITE_RENDERING_MODE_DEFAULT:
-    // As per DWRITE_RENDERING_MODE documentation, pick Natural for font
-    // sizes under 16 ppem
-    if (aFont->GetSize() < 16.0f) {
-      renderMode = DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL;
-    } else {
-      renderMode = DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL_SYMMETRIC;
-    }
-    break;
-  case DWRITE_RENDERING_MODE_OUTLINE:
-    renderMode = DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL_SYMMETRIC;
-    break;
-  default:
-    break;
-  }
-
-  DWRITE_MEASURING_MODE measureMode =
-    renderMode <= DWRITE_RENDERING_MODE_CLEARTYPE_GDI_CLASSIC ? DWRITE_MEASURING_MODE_GDI_CLASSIC :
-    renderMode == DWRITE_RENDERING_MODE_CLEARTYPE_GDI_NATURAL ? DWRITE_MEASURING_MODE_GDI_NATURAL :
-    DWRITE_MEASURING_MODE_NATURAL;
-
-  DWRITE_MATRIX mat = DWriteMatrixFromMatrix(mTransform);
-
-  AutoDWriteGlyphRun autoRun;
-  DWriteGlyphRunFromGlyphs(aBuffer, aFont, &autoRun);
-
-  RefPtr<IDWriteGlyphRunAnalysis> analysis;
-  hr = GetDWriteFactory()->CreateGlyphRunAnalysis(&autoRun, 1.0f, &mat,
-                                                  renderMode, measureMode, 0, 0, getter_AddRefs(analysis));
-
-  if (FAILED(hr)) {
-    return false;
-  }
-
-  RECT bounds;
-  hr = analysis->GetAlphaTextureBounds(DWRITE_TEXTURE_CLEARTYPE_3x1, &bounds);
-
-  if (bounds.bottom <= bounds.top || bounds.right <= bounds.left) {
-    // DWrite seems to do this sometimes. I'm not 100% sure why. See bug 758980.
-    gfxDebug() << "Empty alpha texture bounds! Falling back to regular drawing.";
-    return false;
-  }
-  IntRect rectBounds(bounds.left, bounds.top, bounds.right - bounds.left, bounds.bottom - bounds.top);
-  IntRect surfBounds(IntPoint(0, 0), mSize);
-
-  rectBounds.IntersectRect(rectBounds, surfBounds);
-
-  if (rectBounds.IsEmpty()) {
-    // Nothing to do.
-    return true;
-  }
-
-  RefPtr<ID3D10Texture2D> tex = CreateTextureForAnalysis(analysis, rectBounds);
-
-  if (!tex) {
-    return false;
-  }
-
-  RefPtr<ID3D10ShaderResourceView> srView;
-  hr = mDevice->CreateShaderResourceView(tex, nullptr, getter_AddRefs(srView));
-
-  if (FAILED(hr)) {
-    return false;
-  }
-
-  MarkChanged();
-
-  // Prepare our background texture for drawing.
-  PopAllClips();
-  mRT->Flush();
-
-  SetupStateForRendering();
-
-  ID3D10EffectTechnique *technique = mPrivateData->mEffect->GetTechniqueByName("SampleTextTexture");
-
-  mPrivateData->mEffect->GetVariableByName("QuadDesc")->AsVector()->
-    SetFloatVector(ShaderConstantRectD3D10(-1.0f + ((Float(rectBounds.x) / mSize.width) * 2.0f),
-                                           1.0f - (Float(rectBounds.y) / mSize.height * 2.0f),
-                                           (Float(rectBounds.width) / mSize.width) * 2.0f,
-                                           (-Float(rectBounds.height) / mSize.height) * 2.0f));
-  mPrivateData->mEffect->GetVariableByName("TexCoords")->AsVector()->
-    SetFloatVector(ShaderConstantRectD3D10(0, 0, 1.0f, 1.0f));
-  FLOAT color[4] = { aColor.r, aColor.g, aColor.b, aColor.a };
-  mPrivateData->mEffect->GetVariableByName("TextColor")->AsVector()->
-    SetFloatVector(color);
-  
-  mPrivateData->mEffect->GetVariableByName("tex")->AsShaderResource()->SetResource(srView);
-
-  bool isMasking = false;
-
-  IntRect clipBoundsStorage;
-  IntRect *clipBounds = nullptr;
-
-  if (!mPushedClips.empty()) {
-    clipBounds = &clipBoundsStorage;
-    RefPtr<ID2D1Geometry> geom = GetClippedGeometry(clipBounds);
-
-    RefPtr<ID2D1RectangleGeometry> rectGeom;
-    factory()->CreateRectangleGeometry(D2D1::RectF(Float(rectBounds.x),
-                                                   Float(rectBounds.y),
-                                                   Float(rectBounds.width + rectBounds.x),
-                                                   Float(rectBounds.height + rectBounds.y)),
-                                       getter_AddRefs(rectGeom));
-
-    D2D1_GEOMETRY_RELATION relation;
-    if (FAILED(geom->CompareWithGeometry(rectGeom, D2D1::IdentityMatrix(), &relation)) ||
-        relation != D2D1_GEOMETRY_RELATION_CONTAINS ) {
-      isMasking = true;
-    }        
-  }
-  
-  if (isMasking) {
-    clipBounds = &clipBoundsStorage;
-    EnsureClipMaskTexture(clipBounds);
-
-    RefPtr<ID3D10ShaderResourceView> srViewMask;
-    hr = mDevice->CreateShaderResourceView(mCurrentClipMaskTexture, nullptr, getter_AddRefs(srViewMask));
-
-    if (FAILED(hr)) {
-      return false;
-    }
-
-    mPrivateData->mEffect->GetVariableByName("mask")->AsShaderResource()->SetResource(srViewMask);
-
-    mPrivateData->mEffect->GetVariableByName("MaskTexCoords")->AsVector()->
-      SetFloatVector(ShaderConstantRectD3D10(Float(rectBounds.x) / mSize.width, Float(rectBounds.y) / mSize.height,
-                                             Float(rectBounds.width) / mSize.width, Float(rectBounds.height) / mSize.height));
-
-    technique->GetPassByIndex(1)->Apply(0);
-  } else {
-    technique->GetPassByIndex(0)->Apply(0);
-  }  
-
-  RefPtr<ID3D10RenderTargetView> rtView;
-  ID3D10RenderTargetView *rtViews;
-  mDevice->CreateRenderTargetView(mTexture, nullptr, getter_AddRefs(rtView));
-
-  rtViews = rtView;
-  mDevice->OMSetRenderTargets(1, &rtViews, nullptr);
-  SetScissorToRect(clipBounds);
-  mDevice->Draw(4, 0);
-  return true;
-}
-
-already_AddRefed<ID2D1Brush>
-DrawTargetD2D::CreateBrushForPattern(const Pattern &aPattern, Float aAlpha)
-{
-  if (!IsPatternSupportedByD2D(aPattern)) {
-    RefPtr<ID2D1SolidColorBrush> colBrush;
-    mRT->CreateSolidColorBrush(D2D1::ColorF(1.0f, 1.0f, 1.0f, 1.0f), getter_AddRefs(colBrush));
-    return colBrush.forget();
-  }
-
-  if (aPattern.GetType() == PatternType::COLOR) {
-    RefPtr<ID2D1SolidColorBrush> colBrush;
-    Color color = static_cast<const ColorPattern*>(&aPattern)->mColor;
-    mRT->CreateSolidColorBrush(D2D1::ColorF(color.r, color.g,
-                                            color.b, color.a),
-                               D2D1::BrushProperties(aAlpha),
-                               getter_AddRefs(colBrush));
-    return colBrush.forget();
-  }
-  if (aPattern.GetType() == PatternType::LINEAR_GRADIENT) {
-    RefPtr<ID2D1LinearGradientBrush> gradBrush;
-    const LinearGradientPattern *pat =
-      static_cast<const LinearGradientPattern*>(&aPattern);
-
-    GradientStopsD2D *stops = static_cast<GradientStopsD2D*>(pat->mStops.get());
-
-    if (!stops) {
-      gfxDebug() << "No stops specified for gradient pattern.";
-      return nullptr;
-    }
-
-    if (pat->mBegin == pat->mEnd) {
-      RefPtr<ID2D1SolidColorBrush> colBrush;
-      uint32_t stopCount = stops->mStopCollection->GetGradientStopCount();
-      vector<D2D1_GRADIENT_STOP> d2dStops(stopCount);
-      stops->mStopCollection->GetGradientStops(&d2dStops.front(), stopCount);
-      mRT->CreateSolidColorBrush(d2dStops.back().color,
-                                 D2D1::BrushProperties(aAlpha),
-                                 getter_AddRefs(colBrush));
-      return colBrush.forget();
-    }
-
-    mRT->CreateLinearGradientBrush(D2D1::LinearGradientBrushProperties(D2DPoint(pat->mBegin),
-                                                                       D2DPoint(pat->mEnd)),
-                                   D2D1::BrushProperties(aAlpha, D2DMatrix(pat->mMatrix)),
-                                   stops->mStopCollection,
-                                   getter_AddRefs(gradBrush));
-    return gradBrush.forget();
-  }
-  if (aPattern.GetType() == PatternType::RADIAL_GRADIENT) {
-    RefPtr<ID2D1RadialGradientBrush> gradBrush;
-    const RadialGradientPattern *pat =
-      static_cast<const RadialGradientPattern*>(&aPattern);
-
-    GradientStopsD2D *stops = static_cast<GradientStopsD2D*>(pat->mStops.get());
-
-    if (!stops) {
-      gfxDebug() << "No stops specified for gradient pattern.";
-      return nullptr;
-    }
-
-    // This will not be a complex radial gradient brush.
-    mRT->CreateRadialGradientBrush(
-      D2D1::RadialGradientBrushProperties(D2DPoint(pat->mCenter2),
-                                          D2DPoint(pat->mCenter1 - pat->mCenter2),
-                                          pat->mRadius2, pat->mRadius2),
-      D2D1::BrushProperties(aAlpha, D2DMatrix(pat->mMatrix)),
-      stops->mStopCollection,
-      getter_AddRefs(gradBrush));
-
-    return gradBrush.forget();
-  }
-  if (aPattern.GetType() == PatternType::SURFACE) {
-    RefPtr<ID2D1BitmapBrush> bmBrush;
-    const SurfacePattern *pat =
-      static_cast<const SurfacePattern*>(&aPattern);
-
-    if (!pat->mSurface) {
-      gfxDebug() << "No source surface specified for surface pattern";
-      return nullptr;
-    }
-
-    RefPtr<ID2D1Bitmap> bitmap;
-
-    Matrix mat = pat->mMatrix;
-
-    RefPtr<SourceSurface> source = pat->mSurface;
-
-    if (!pat->mSamplingRect.IsEmpty() &&
-        (source->GetType() == SurfaceType::D2D1_BITMAP ||
-         source->GetType() == SurfaceType::D2D1_DRAWTARGET)) {
-      IntRect samplingRect = pat->mSamplingRect;
-
-      RefPtr<DrawTargetD2D> dt = new DrawTargetD2D();
-      if (!dt->Init(samplingRect.Size(),
-                    source->GetFormat())) {
-        // FIXME: Uncomment assertion, bug 1068195
-        // MOZ_ASSERT(false, "Invalid sampling rect size!");
-        return nullptr;
-      }
-
-      dt->CopySurface(source, samplingRect, IntPoint());
-      source = dt->Snapshot();
-
-      mat.PreTranslate(samplingRect.x, samplingRect.y);
-    }
-    
-    switch (source->GetType()) {
-    case SurfaceType::D2D1_BITMAP:
-      {
-        SourceSurfaceD2D *surf = static_cast<SourceSurfaceD2D*>(source.get());
-
-        bitmap = surf->mBitmap;
-
-        if (!bitmap) {
-          return nullptr;
-        }
-      }
-      break;
-    case SurfaceType::D2D1_DRAWTARGET:
-      {
-        SourceSurfaceD2DTarget *surf =
-          static_cast<SourceSurfaceD2DTarget*>(source.get());
-        bitmap = surf->GetBitmap(mRT);
-        AddDependencyOnSource(surf);
-      }
-      break;
-    default:
-      {
-        RefPtr<DataSourceSurface> dataSurf = source->GetDataSurface();
-        if (!dataSurf) {
-          gfxWarning() << "Invalid surface type.";
-          return nullptr;
-        }
-
-        IntRect sourceRect = pat->mSamplingRect;
-        if (sourceRect.IsEmpty()) {
-          sourceRect = IntRect(0, 0, source->GetSize().width, source->GetSize().height);
-        }
-
-        bitmap = CreatePartialBitmapForSurface(dataSurf, mTransform, mSize, pat->mExtendMode, mat, mRT, &sourceRect);
-        if (!bitmap) {
-          RefPtr<ID2D1SolidColorBrush> colBrush;
-          mRT->CreateSolidColorBrush(D2D1::ColorF(0, 0), getter_AddRefs(colBrush));
-          return colBrush.forget();
-        }
-      }
-      break;
-    }
-
-    D2D1_EXTEND_MODE xRepeat = D2DExtend(pat->mExtendMode, Axis::X_AXIS);
-    D2D1_EXTEND_MODE yRepeat = D2DExtend(pat->mExtendMode, Axis::Y_AXIS);
-    HRESULT hr = mRT->CreateBitmapBrush(bitmap,
-                           D2D1::BitmapBrushProperties(xRepeat,
-                                                       yRepeat,
-                                                       D2DFilter(pat->mFilter)),
-                           D2D1::BrushProperties(aAlpha, D2DMatrix(mat)),
-                           getter_AddRefs(bmBrush));
-    if (FAILED(hr)) {
-      gfxCriticalError() << "[D2D] 1CreateBitmapBrush failure: " << hexa(hr);
-      return nullptr;
-    }
-    return bmBrush.forget();
-  }
-
-  gfxWarning() << "Invalid pattern type detected.";
-  return nullptr;
-}
-
-already_AddRefed<ID3D10Texture2D>
-DrawTargetD2D::CreateGradientTexture(const GradientStopsD2D *aStops)
-{
-  CD3D10_TEXTURE2D_DESC desc(DXGI_FORMAT_B8G8R8A8_UNORM, 4096, 1, 1, 1);
-
-  std::vector<D2D1_GRADIENT_STOP> rawStops;
-  rawStops.resize(aStops->mStopCollection->GetGradientStopCount());
-  aStops->mStopCollection->GetGradientStops(&rawStops.front(), rawStops.size());
-
-  std::vector<unsigned char> textureData;
-  textureData.resize(4096 * 4);
-  unsigned char *texData = &textureData.front();
-
-  float prevColorPos = 0;
-  float nextColorPos = 1.0f;
-  D2D1_COLOR_F prevColor = rawStops[0].color;
-  D2D1_COLOR_F nextColor = prevColor;
-
-  if (rawStops.size() >= 2) {
-    nextColor = rawStops[1].color;
-    nextColorPos = rawStops[1].position;
-  }
-
-  uint32_t stopPosition = 2;
-
-  // Not the most optimized way but this will do for now.
-  for (int i = 0; i < 4096; i++) {
-    // The 4095 seems a little counter intuitive, but we want the gradient
-    // color at offset 0 at the first pixel, and at offset 1.0f at the last
-    // pixel.
-    float pos = float(i) / 4095;
-
-    while (pos > nextColorPos) {
-      prevColor = nextColor;
-      prevColorPos = nextColorPos;
-      if (rawStops.size() > stopPosition) {
-        nextColor = rawStops[stopPosition].color;
-        nextColorPos = rawStops[stopPosition++].position;
-      } else {
-        nextColorPos = 1.0f;
-      }
-    }
-
-    float interp;
-    
-    if (nextColorPos != prevColorPos) {
-      interp = (pos - prevColorPos) / (nextColorPos - prevColorPos);
-    } else {
-      interp = 0;
-    }
-
-    Color newColor(prevColor.r + (nextColor.r - prevColor.r) * interp,
-                    prevColor.g + (nextColor.g - prevColor.g) * interp,
-                    prevColor.b + (nextColor.b - prevColor.b) * interp,
-                    prevColor.a + (nextColor.a - prevColor.a) * interp);
-
-    texData[i * 4] = (char)(255.0f * newColor.b);
-    texData[i * 4 + 1] = (char)(255.0f * newColor.g);
-    texData[i * 4 + 2] = (char)(255.0f * newColor.r);
-    texData[i * 4 + 3] = (char)(255.0f * newColor.a);
-  }
-
-  D3D10_SUBRESOURCE_DATA data;
-  data.pSysMem = &textureData.front();
-  data.SysMemPitch = 4096 * 4;
-
-  RefPtr<ID3D10Texture2D> tex;
-  mDevice->CreateTexture2D(&desc, &data, getter_AddRefs(tex));
-
-  return tex.forget();
-}
-
-already_AddRefed<ID3D10Texture2D>
-DrawTargetD2D::CreateTextureForAnalysis(IDWriteGlyphRunAnalysis *aAnalysis, const IntRect &aBounds)
-{
-  HRESULT hr;
-
-  uint32_t bufferSize = aBounds.width * aBounds.height * 3;
-
-  RECT bounds;
-  bounds.left = aBounds.x;
-  bounds.top = aBounds.y;
-  bounds.right = aBounds.x + aBounds.width;
-  bounds.bottom = aBounds.y + aBounds.height;
-
-  // Add one byte so we can safely read a 32-bit int when copying the last
-  // 3 bytes.
-  BYTE *texture = new BYTE[bufferSize + 1];
-  hr = aAnalysis->CreateAlphaTexture(DWRITE_TEXTURE_CLEARTYPE_3x1, &bounds, texture, bufferSize);
-
-  if (FAILED(hr)) {
-    delete [] texture;
-    return nullptr;
-  }
-
-  int alignedBufferSize = aBounds.width * aBounds.height * 4;
-
-  // Create a one-off immutable texture from system memory.
-  BYTE *alignedTextureData = new BYTE[alignedBufferSize];
-  for (int y = 0; y < aBounds.height; y++) {
-    for (int x = 0; x < aBounds.width; x++) {
-      // Copy 3 Bpp source to 4 Bpp destination memory used for
-      // texture creation. D3D10 has no 3 Bpp texture format we can
-      // use.
-      //
-      // Since we don't care what ends up in the alpha pixel of the
-      // destination, therefor we can simply copy a normal 32 bit
-      // integer each time, filling the alpha pixel of the destination
-      // with the first subpixel of the next pixel from the source.
-      *((int*)(alignedTextureData + (y * aBounds.width + x) * 4)) =
-        *((int*)(texture + (y * aBounds.width + x) * 3));
-    }
-  }
-
-  D3D10_SUBRESOURCE_DATA data;
-  
-  CD3D10_TEXTURE2D_DESC desc(DXGI_FORMAT_B8G8R8A8_UNORM,
-                             aBounds.width, aBounds.height,
-                             1, 1);
-  desc.Usage = D3D10_USAGE_IMMUTABLE;
-
-  data.SysMemPitch = aBounds.width * 4;
-  data.pSysMem = alignedTextureData;
-
-  RefPtr<ID3D10Texture2D> tex;
-  hr = mDevice->CreateTexture2D(&desc, &data, getter_AddRefs(tex));
-	
-  delete [] alignedTextureData;
-  delete [] texture;
-
-  if (FAILED(hr)) {
-    return nullptr;
-  }
-
-  return tex.forget();
-}
-
-void
-DrawTargetD2D::SetupEffectForRadialGradient(const RadialGradientPattern *aPattern)
-{
-  mPrivateData->mEffect->GetTechniqueByName("SampleRadialGradient")->GetPassByIndex(0)->Apply(0);
-  mPrivateData->mEffect->GetVariableByName("MaskTexCoords")->AsVector()->
-    SetFloatVector(ShaderConstantRectD3D10(0, 0, 1.0f, 1.0f));
-
-  float dimensions[] = { float(mSize.width), float(mSize.height), 0, 0 };
-  mPrivateData->mEffect->GetVariableByName("dimensions")->AsVector()->
-    SetFloatVector(dimensions);
-
-  const GradientStopsD2D *stops =
-    static_cast<const GradientStopsD2D*>(aPattern->mStops.get());
-
-  RefPtr<ID3D10Texture2D> tex = CreateGradientTexture(stops);
-
-  RefPtr<ID3D10ShaderResourceView> srView;
-  mDevice->CreateShaderResourceView(tex, nullptr, getter_AddRefs(srView));
-
-  mPrivateData->mEffect->GetVariableByName("tex")->AsShaderResource()->SetResource(srView);
-
-  Point dc = aPattern->mCenter2 - aPattern->mCenter1;
-  float dr = aPattern->mRadius2 - aPattern->mRadius1;
-
-  float diffv[] = { dc.x, dc.y, dr, 0 };
-  mPrivateData->mEffect->GetVariableByName("diff")->AsVector()->
-    SetFloatVector(diffv);
-
-  float center1[] = { aPattern->mCenter1.x, aPattern->mCenter1.y, dr, 0 };
-  mPrivateData->mEffect->GetVariableByName("center1")->AsVector()->
-    SetFloatVector(center1);
-
-  mPrivateData->mEffect->GetVariableByName("radius1")->AsScalar()->
-    SetFloat(aPattern->mRadius1);
-  mPrivateData->mEffect->GetVariableByName("sq_radius1")->AsScalar()->
-    SetFloat(pow(aPattern->mRadius1, 2));
-
-  Matrix invTransform = mTransform;
-
-  if (!invTransform.Invert()) {
-    // Bail if the matrix is singular.
-    return;
-  }
-  float matrix[] = { invTransform._11, invTransform._12, 0, 0,
-                      invTransform._21, invTransform._22, 0, 0,
-                      invTransform._31, invTransform._32, 1.0f, 0,
-                      0, 0, 0, 1.0f };
-
-  mPrivateData->mEffect->GetVariableByName("DeviceSpaceToUserSpace")->
-    AsMatrix()->SetMatrix(matrix);
-
-  float A = dc.x * dc.x + dc.y * dc.y - dr * dr;
-
-  uint32_t offset = 0;
-  switch (stops->mStopCollection->GetExtendMode()) {
-  case D2D1_EXTEND_MODE_WRAP:
-    offset = 1;
-    break;
-  case D2D1_EXTEND_MODE_MIRROR:
-    offset = 2;
-    break;
-  default:
-    gfxWarning() << "This shouldn't happen! Invalid extend mode for gradient stops.";
-  }
-
-  if (A == 0) {
-    mPrivateData->mEffect->GetTechniqueByName("SampleRadialGradient")->
-      GetPassByIndex(offset * 2 + 1)->Apply(0);
-  } else {
-    mPrivateData->mEffect->GetVariableByName("A")->AsScalar()->SetFloat(A);
-    mPrivateData->mEffect->GetTechniqueByName("SampleRadialGradient")->
-      GetPassByIndex(offset * 2)->Apply(0);
-  }
-}
-
-void
-DrawTargetD2D::SetupStateForRendering()
-{
-  UINT stride = sizeof(Vertex);
-  UINT offset = 0;
-  ID3D10Buffer *buff = mPrivateData->mVB;
-
-  mDevice->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
-  mDevice->IASetVertexBuffers(0, 1, &buff, &stride, &offset);
-  mDevice->IASetInputLayout(mPrivateData->mInputLayout);
-
-  D3D10_VIEWPORT viewport;
-  viewport.MaxDepth = 1;
-  viewport.MinDepth = 0;
-  viewport.Height = mSize.height;
-  viewport.Width = mSize.width;
-  viewport.TopLeftX = 0;
-  viewport.TopLeftY = 0;
-
-  mDevice->RSSetViewports(1, &viewport);
-}
-
-ID2D1Factory*
-DrawTargetD2D::factory()
-{
-  if (mFactory) {
-    return mFactory;
-  }
-
-  D2D1CreateFactoryFunc createD2DFactory;
-  HMODULE d2dModule = LoadLibraryW(L"d2d1.dll");
-  createD2DFactory = (D2D1CreateFactoryFunc)
-      GetProcAddress(d2dModule, "D2D1CreateFactory");
-
-  if (!createD2DFactory) {
-    gfxWarning() << "Failed to locate D2D1CreateFactory function.";
-    return nullptr;
-  }
-
-  D2D1_FACTORY_OPTIONS options;
-#ifdef _DEBUG
-  options.debugLevel = D2D1_DEBUG_LEVEL_WARNING;
-#else
-  options.debugLevel = D2D1_DEBUG_LEVEL_NONE;
-#endif
-  //options.debugLevel = D2D1_DEBUG_LEVEL_INFORMATION;
-
-  HRESULT hr = createD2DFactory(D2D1_FACTORY_TYPE_MULTI_THREADED,
-                                __uuidof(ID2D1Factory),
-                                &options,
-                                (void**)&mFactory);
-
-  if (FAILED(hr)) {
-    gfxWarning() << "Failed to create Direct2D factory.";
-  }
-
-  RefPtr<ID2D1Factory1> factoryD2D1;
-  hr = mFactory->QueryInterface((ID2D1Factory1**)getter_AddRefs(factoryD2D1));
-  if (SUCCEEDED(hr)) {
-    ExtendInputEffectD2D1::Register(factoryD2D1);
-  }
-
-  return mFactory;
-}
-
-void
-DrawTargetD2D::CleanupD2D()
-{
-  if (mFactory) {
-    RefPtr<ID2D1Factory1> factoryD2D1;
-    HRESULT hr = mFactory->QueryInterface((ID2D1Factory1**)getter_AddRefs(factoryD2D1));
-    if (SUCCEEDED(hr)) {
-      ExtendInputEffectD2D1::Unregister(factoryD2D1);
-    }
-
-    mFactory->Release();
-    mFactory = nullptr;
-  }
-}
-
-IDWriteFactory*
-DrawTargetD2D::GetDWriteFactory()
-{
-  if (mDWriteFactory) {
-    return mDWriteFactory;
-  }
-
-  decltype(DWriteCreateFactory)* createDWriteFactory;
-  HMODULE dwriteModule = LoadLibraryW(L"dwrite.dll");
-  createDWriteFactory = (decltype(DWriteCreateFactory)*)
-    GetProcAddress(dwriteModule, "DWriteCreateFactory");
-
-  if (!createDWriteFactory) {
-    gfxWarning() << "Failed to locate DWriteCreateFactory function.";
-    return nullptr;
-  }
-
-  HRESULT hr = createDWriteFactory(DWRITE_FACTORY_TYPE_SHARED, __uuidof(IDWriteFactory),
-                                   reinterpret_cast<IUnknown**>(&mDWriteFactory));
-
-  if (FAILED(hr)) {
-    gfxWarning() << "Failed to create DWrite Factory.";
-  }
-
-  return mDWriteFactory;
-}
-
-void
-DrawTargetD2D::SetScissorToRect(IntRect *aRect)
-{
-  D3D10_RECT rect;
-  if (aRect) {
-    rect.left = aRect->x;
-    rect.right = aRect->XMost();
-    rect.top = aRect->y;
-    rect.bottom = aRect->YMost();
-  } else {
-    rect.left = rect.top = INT32_MIN;
-    rect.right = rect.bottom = INT32_MAX;
-  }
-
-  mDevice->RSSetScissorRects(1, &rect);
-}
-
-void
-DrawTargetD2D::PushD2DLayer(ID2D1RenderTarget *aRT, ID2D1Geometry *aGeometry, ID2D1Layer *aLayer, const D2D1_MATRIX_3X2_F &aTransform)
-{
-  D2D1_LAYER_OPTIONS options = D2D1_LAYER_OPTIONS_NONE;
-  D2D1_LAYER_OPTIONS1 options1 =  D2D1_LAYER_OPTIONS1_NONE;
-
-  if (aRT->GetPixelFormat().alphaMode == D2D1_ALPHA_MODE_IGNORE) {
-    options = D2D1_LAYER_OPTIONS_INITIALIZE_FOR_CLEARTYPE;
-    options1 = D2D1_LAYER_OPTIONS1_IGNORE_ALPHA | D2D1_LAYER_OPTIONS1_INITIALIZE_FROM_BACKGROUND;
-  }
-
-	RefPtr<ID2D1DeviceContext> dc;
-	HRESULT hr = aRT->QueryInterface(IID_ID2D1DeviceContext, (void**)((ID2D1DeviceContext**)getter_AddRefs(dc)));
-
-	if (FAILED(hr)) {
-	    aRT->PushLayer(D2D1::LayerParameters(D2D1::InfiniteRect(), aGeometry,
-				                                   D2D1_ANTIALIAS_MODE_PER_PRIMITIVE, aTransform,
-				                                   1.0, nullptr, options),
-				             aLayer);
-	} else {
-	    dc->PushLayer(D2D1::LayerParameters1(D2D1::InfiniteRect(), aGeometry,
-				                                   D2D1_ANTIALIAS_MODE_PER_PRIMITIVE, aTransform,
-				                                   1.0, nullptr, options1),
-				            aLayer);
-	}
-}
-
-}
-}
deleted file mode 100644
--- a/gfx/2d/DrawTargetD2D.h
+++ /dev/null
@@ -1,290 +0,0 @@
-/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef MOZILLA_GFX_DRAWTARGETD2D_H_
-#define MOZILLA_GFX_DRAWTARGETD2D_H_
-
-#include "2D.h"
-#include "PathD2D.h"
-#include <d3d10_1.h>
-#include "HelpersD2D.h"
-
-#include <vector>
-#include <sstream>
-
-#include <unordered_set>
-
-struct IDWriteFactory;
-
-namespace mozilla {
-namespace gfx {
-
-class SourceSurfaceD2DTarget;
-class SourceSurfaceD2D;
-class GradientStopsD2D;
-class ScaledFontDWrite;
-
-const int32_t kLayerCacheSize = 5;
-
-struct PrivateD3D10DataD2D
-{
-  RefPtr<ID3D10Effect> mEffect;
-  RefPtr<ID3D10InputLayout> mInputLayout;
-  RefPtr<ID3D10Buffer> mVB;
-  RefPtr<ID3D10BlendState> mBlendStates[size_t(CompositionOp::OP_COUNT)];
-};
-
-class DrawTargetD2D : public DrawTarget
-{
-public:
-  MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(DrawTargetD2D, override)
-  DrawTargetD2D();
-  virtual ~DrawTargetD2D();
-
-  virtual DrawTargetType GetType() const override { return DrawTargetType::HARDWARE_RASTER; }
-  virtual BackendType GetBackendType() const override { return BackendType::DIRECT2D; }
-  virtual already_AddRefed<SourceSurface> Snapshot() override;
-  virtual IntSize GetSize() override { return mSize; }
-
-  virtual void Flush() override;
-  virtual void DrawSurface(SourceSurface *aSurface,
-                           const Rect &aDest,
-                           const Rect &aSource,
-                           const DrawSurfaceOptions &aSurfOptions = DrawSurfaceOptions(),
-                           const DrawOptions &aOptions = DrawOptions()) override;
-  virtual void DrawFilter(FilterNode *aNode,
-                          const Rect &aSourceRect,
-                          const Point &aDestPoint,
-                          const DrawOptions &aOptions = DrawOptions()) override;
-  virtual void DrawSurfaceWithShadow(SourceSurface *aSurface,
-                                     const Point &aDest,
-                                     const Color &aColor,
-                                     const Point &aOffset,
-                                     Float aSigma,
-                                     CompositionOp aOperator) override;
-  virtual void ClearRect(const Rect &aRect) override;
-  virtual void MaskSurface(const Pattern &aSource,
-                           SourceSurface *aMask,
-                           Point aOffset,
-                           const DrawOptions &aOptions = DrawOptions()) override;
-
-
-  virtual void CopySurface(SourceSurface *aSurface,
-                           const IntRect &aSourceRect,
-                           const IntPoint &aDestination) override;
-
-  virtual void FillRect(const Rect &aRect,
-                        const Pattern &aPattern,
-                        const DrawOptions &aOptions = DrawOptions()) override;
-  virtual void StrokeRect(const Rect &aRect,
-                          const Pattern &aPattern,
-                          const StrokeOptions &aStrokeOptions = StrokeOptions(),
-                          const DrawOptions &aOptions = DrawOptions()) override;
-  virtual void StrokeLine(const Point &aStart,
-                          const Point &aEnd,
-                          const Pattern &aPattern,
-                          const StrokeOptions &aStrokeOptions = StrokeOptions(),
-                          const DrawOptions &aOptions = DrawOptions()) override;
-  virtual void Stroke(const Path *aPath,
-                      const Pattern &aPattern,
-                      const StrokeOptions &aStrokeOptions = StrokeOptions(),
-                      const DrawOptions &aOptions = DrawOptions()) override;
-  virtual void Fill(const Path *aPath,
-                    const Pattern &aPattern,
-                    const DrawOptions &aOptions = DrawOptions()) override;
-  virtual void FillGlyphs(ScaledFont *aFont,
-                          const GlyphBuffer &aBuffer,
-                          const Pattern &aPattern,
-                          const DrawOptions &aOptions = DrawOptions(),
-                          const GlyphRenderingOptions *aRenderingOptions = nullptr) override;
-  virtual void Mask(const Pattern &aSource,
-                    const Pattern &aMask,
-                    const DrawOptions &aOptions = DrawOptions()) override;
-  virtual void PushClip(const Path *aPath) override;
-  virtual void PushClipRect(const Rect &aRect) override;
-  virtual void PopClip() override;
-
-  virtual already_AddRefed<SourceSurface> CreateSourceSurfaceFromData(unsigned char *aData,
-                                                            const IntSize &aSize,
-                                                            int32_t aStride,
-                                                            SurfaceFormat aFormat) const override;
-  virtual already_AddRefed<SourceSurface> OptimizeSourceSurface(SourceSurface *aSurface) const override;
-
-  virtual already_AddRefed<SourceSurface>
-    CreateSourceSurfaceFromNativeSurface(const NativeSurface &aSurface) const override;
-  
-  virtual already_AddRefed<DrawTarget>
-    CreateSimilarDrawTarget(const IntSize &aSize, SurfaceFormat aFormat) const override;
-
-  virtual already_AddRefed<PathBuilder> CreatePathBuilder(FillRule aFillRule = FillRule::FILL_WINDING) const override;
-
-  virtual already_AddRefed<GradientStops>
-    CreateGradientStops(GradientStop *aStops,
-                        uint32_t aNumStops,
-                        ExtendMode aExtendMode = ExtendMode::CLAMP) const override;
-
-  virtual already_AddRefed<FilterNode> CreateFilter(FilterType aType) override;
-
-  virtual bool SupportsRegionClipping() const override { return false; }
-
-  virtual void *GetNativeSurface(NativeSurfaceType aType) override;
-
-  bool Init(const IntSize &aSize, SurfaceFormat aFormat);
-  bool Init(ID3D10Texture2D *aTexture, SurfaceFormat aFormat);
-  bool InitD3D10Data();
-  uint32_t GetByteSize() const;
-  already_AddRefed<ID2D1Layer> GetCachedLayer();
-  void PopCachedLayer(ID2D1RenderTarget *aRT);
-
-  already_AddRefed<ID2D1Image> GetImageForSurface(SourceSurface *aSurface);
-
-  static ID2D1Factory *factory();
-  static void CleanupD2D();
-  static IDWriteFactory *GetDWriteFactory();
-  ID2D1RenderTarget *GetRT() { return mRT; }
-
-  static uint32_t GetMaxSurfaceSize() {
-    return D3D10_REQ_TEXTURE2D_U_OR_V_DIMENSION;
-  }
-
-  operator std::string() const {
-    std::stringstream stream;
-    stream << "DrawTargetD2D(" << this << ")";
-    return stream.str();
-  }
-
-  static uint64_t mVRAMUsageDT;
-  static uint64_t mVRAMUsageSS;
-
-private:
-  already_AddRefed<ID2D1Bitmap>
-  GetBitmapForSurface(SourceSurface *aSurface,
-                      Rect &aSource);
-  friend class AutoSaveRestoreClippedOut;
-  friend class SourceSurfaceD2DTarget;
-
-  typedef std::unordered_set<DrawTargetD2D*> TargetSet;
-
-  bool InitD2DRenderTarget();
-  void PrepareForDrawing(ID2D1RenderTarget *aRT);
-
-  // This function will mark the surface as changing, and make sure any
-  // copy-on-write snapshots are notified.
-  void MarkChanged();
-  void FlushTransformToRT() {
-    if (mTransformDirty) {
-      mRT->SetTransform(D2DMatrix(mTransform));
-      mTransformDirty = false;
-    }
-  }
-  void AddDependencyOnSource(SourceSurfaceD2DTarget* aSource);
-
-  ID3D10BlendState *GetBlendStateForOperator(CompositionOp aOperator);
-  ID2D1RenderTarget *GetRTForOperation(CompositionOp aOperator, const Pattern &aPattern);
-  void FinalizeRTForOperation(CompositionOp aOperator, const Pattern &aPattern, const Rect &aBounds);  void EnsureViews();
-  void PopAllClips();
-  void PushClipsToRT(ID2D1RenderTarget *aRT);
-  void PopClipsFromRT(ID2D1RenderTarget *aRT);
-
-  // This function ensures mCurrentClipMaskTexture contains a texture containing
-  // a mask corresponding with the current DrawTarget clip. See
-  // GetClippedGeometry for a description of aClipBounds.
-  void EnsureClipMaskTexture(IntRect *aClipBounds);
-
-  bool FillGlyphsManual(ScaledFontDWrite *aFont,
-                        const GlyphBuffer &aBuffer,
-                        const Color &aColor,
-                        IDWriteRenderingParams *aParams,
-                        const DrawOptions &aOptions = DrawOptions());
-
-  already_AddRefed<ID2D1RenderTarget> CreateRTForTexture(ID3D10Texture2D *aTexture, SurfaceFormat aFormat);
-
-  // This returns the clipped geometry, in addition it returns aClipBounds which
-  // represents the intersection of all pixel-aligned rectangular clips that
-  // are currently set. The returned clipped geometry must be clipped by these
-  // bounds to correctly reflect the total clip. This is in device space.
-  already_AddRefed<ID2D1Geometry> GetClippedGeometry(IntRect *aClipBounds);
-
-  bool GetDeviceSpaceClipRect(D2D1_RECT_F& aClipRect, bool& aIsPixelAligned);
-
-  already_AddRefed<ID2D1Brush> CreateBrushForPattern(const Pattern &aPattern, Float aAlpha = 1.0f);
-
-  already_AddRefed<ID3D10Texture2D> CreateGradientTexture(const GradientStopsD2D *aStops);
-  already_AddRefed<ID3D10Texture2D> CreateTextureForAnalysis(IDWriteGlyphRunAnalysis *aAnalysis, const IntRect &aBounds);
-
-  void SetupEffectForRadialGradient(const RadialGradientPattern *aPattern);
-  void SetupStateForRendering();
-
-  // Set the scissor rect to a certain IntRects, resets the scissor rect to
-  // surface bounds when nullptr is specified.
-  void SetScissorToRect(IntRect *aRect);
-
-  void PushD2DLayer(ID2D1RenderTarget *aRT, ID2D1Geometry *aGeometry, ID2D1Layer *aLayer, const D2D1_MATRIX_3X2_F &aTransform);
-
-  static const uint32_t test = 4;
-
-  IntSize mSize;
-
-  RefPtr<ID3D10Device1> mDevice;
-  RefPtr<ID3D10Texture2D> mTexture;
-  RefPtr<ID3D10Texture2D> mCurrentClipMaskTexture;
-  RefPtr<ID2D1Geometry> mCurrentClippedGeometry;
-  // This is only valid if mCurrentClippedGeometry is non-null. And will
-  // only be the intersection of all pixel-aligned retangular clips. This is in
-  // device space.
-  IntRect mCurrentClipBounds;
-  mutable RefPtr<ID2D1RenderTarget> mRT;
-
-  // We store this to prevent excessive SetTextRenderingParams calls.
-  RefPtr<IDWriteRenderingParams> mTextRenderingParams;
-
-  // Temporary texture and render target used for supporting alternative operators.
-  RefPtr<ID3D10Texture2D> mTempTexture;
-  RefPtr<ID3D10RenderTargetView> mRTView;
-  RefPtr<ID3D10ShaderResourceView> mSRView;
-  RefPtr<ID2D1RenderTarget> mTempRT;
-  RefPtr<ID3D10RenderTargetView> mTempRTView;
-
-  // List of pushed clips.
-  struct PushedClip
-  {
-    RefPtr<ID2D1Layer> mLayer;
-    D2D1_RECT_F mBounds;
-    union {
-      // If mPath is non-nullptr, the mTransform member will be used, otherwise
-      // the mIsPixelAligned member is valid.
-      D2D1_MATRIX_3X2_F mTransform;
-      bool mIsPixelAligned;
-    };
-    RefPtr<PathD2D> mPath;
-  };
-  std::vector<PushedClip> mPushedClips;
-
-  // We cache ID2D1Layer objects as it causes D2D to keep around textures that
-  // serve as the temporary surfaces for these operations. As texture creation
-  // is quite expensive this considerably improved performance.
-  // Careful here, RAII will not ensure destruction of the RefPtrs.
-  RefPtr<ID2D1Layer> mCachedLayers[kLayerCacheSize];
-  uint32_t mCurrentCachedLayer;
-  
-  // The latest snapshot of this surface. This needs to be told when this
-  // target is modified. We keep it alive as a cache.
-  RefPtr<SourceSurfaceD2DTarget> mSnapshot;
-  // A list of targets we need to flush when we're modified.
-  TargetSet mDependentTargets;
-  // A list of targets which have this object in their mDependentTargets set
-  TargetSet mDependingOnTargets;
-
-  // True of the current clip stack is pushed to the main RT.
-  bool mClipsArePushed;
-  PrivateD3D10DataD2D *mPrivateData;
-  static ID2D1Factory *mFactory;
-  static IDWriteFactory *mDWriteFactory;
-};
-
-}
-}
-
-#endif /* MOZILLA_GFX_DRAWTARGETD2D_H_ */
--- a/gfx/2d/DrawTargetD2D1.cpp
+++ b/gfx/2d/DrawTargetD2D1.cpp
@@ -1,33 +1,41 @@
 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include <initguid.h>
 #include "DrawTargetD2D1.h"
-#include "DrawTargetD2D.h"
 #include "FilterNodeSoftware.h"
 #include "GradientStopsD2D.h"
 #include "SourceSurfaceD2D1.h"
-#include "SourceSurfaceD2D.h"
 #include "RadialGradientEffectD2D1.h"
 
 #include "HelpersD2D.h"
 #include "FilterNodeD2D1.h"
+#include "ExtendInputEffectD2D1.h"
 #include "Tools.h"
 
 using namespace std;
 
+// decltype is not usable for overloaded functions.
+typedef HRESULT (WINAPI*D2D1CreateFactoryFunc)(
+    D2D1_FACTORY_TYPE factoryType,
+    REFIID iid,
+    CONST D2D1_FACTORY_OPTIONS *pFactoryOptions,
+    void **factory
+);
+
 namespace mozilla {
 namespace gfx {
 
 uint64_t DrawTargetD2D1::mVRAMUsageDT;
 uint64_t DrawTargetD2D1::mVRAMUsageSS;
+IDWriteFactory *DrawTargetD2D1::mDWriteFactory;
 ID2D1Factory1* DrawTargetD2D1::mFactory = nullptr;
 
 ID2D1Factory1 *D2DFactory1()
 {
   return DrawTargetD2D1::factory();
 }
 
 DrawTargetD2D1::DrawTargetD2D1()
@@ -599,17 +607,17 @@ DrawTargetD2D1::FillGlyphs(ScaledFont *a
         // the glyphs being drawn. In order not to get transparent pixels
         // copied up in our pushed layer stack.
         D2D1_RECT_F userRect;
         mDC->SetTransform(D2D1::IdentityMatrix());
         mDC->GetGlyphRunWorldBounds(D2D1::Point2F(), &autoRun,
                                     DWRITE_MEASURING_MODE_NATURAL, &userRect);
 
         RefPtr<ID2D1PathGeometry> path;
-        D2DFactory()->CreatePathGeometry(getter_AddRefs(path));
+        factory()->CreatePathGeometry(getter_AddRefs(path));
         RefPtr<ID2D1GeometrySink> sink;
         path->Open(getter_AddRefs(sink));
         AddRectToSink(sink, userRect);
         sink->Close();
 
         mDC->PushLayer(D2D1::LayerParameters1(D2D1::InfiniteRect(), path, D2D1_ANTIALIAS_MODE_ALIASED,
                                               D2DMatrix(mTransform), 1.0f, nullptr,
                                               D2D1_LAYER_OPTIONS1_INITIALIZE_FROM_BACKGROUND |
@@ -1055,37 +1063,89 @@ DrawTargetD2D1::GetByteSize() const
 
 ID2D1Factory1*
 DrawTargetD2D1::factory()
 {
   if (mFactory) {
     return mFactory;
   }
 
-  ID2D1Factory* d2dFactory = D2DFactory();
-  if (!d2dFactory) {
+  RefPtr<ID2D1Factory> factory;
+  D2D1CreateFactoryFunc createD2DFactory;
+  HMODULE d2dModule = LoadLibraryW(L"d2d1.dll");
+  createD2DFactory = (D2D1CreateFactoryFunc)
+      GetProcAddress(d2dModule, "D2D1CreateFactory");
+
+  if (!createD2DFactory) {
+    gfxWarning() << "Failed to locate D2D1CreateFactory function.";
+    return nullptr;
+  }
+
+  D2D1_FACTORY_OPTIONS options;
+#ifdef _DEBUG
+  options.debugLevel = D2D1_DEBUG_LEVEL_WARNING;
+#else
+  options.debugLevel = D2D1_DEBUG_LEVEL_NONE;
+#endif
+  //options.debugLevel = D2D1_DEBUG_LEVEL_INFORMATION;
+
+  HRESULT hr = createD2DFactory(D2D1_FACTORY_TYPE_MULTI_THREADED,
+                                __uuidof(ID2D1Factory),
+                                &options,
+                                getter_AddRefs(factory));
+
+  if (FAILED(hr) || !factory) {
+    gfxWarning() << "Failed to create Direct2D factory.";
     return nullptr;
   }
 
-  HRESULT hr = d2dFactory->QueryInterface((ID2D1Factory1**)&mFactory);
-
-  if (FAILED(hr)) {
+  hr = factory->QueryInterface((ID2D1Factory1**)&mFactory);
+  if (FAILED(hr) || !mFactory) {
     return nullptr;
   }
 
+  ExtendInputEffectD2D1::Register(mFactory);
   RadialGradientEffectD2D1::Register(mFactory);
 
   return mFactory;
 }
 
+IDWriteFactory*
+DrawTargetD2D1::GetDWriteFactory()
+{
+  if (mDWriteFactory) {
+    return mDWriteFactory;
+  }
+
+  decltype(DWriteCreateFactory)* createDWriteFactory;
+  HMODULE dwriteModule = LoadLibraryW(L"dwrite.dll");
+  createDWriteFactory = (decltype(DWriteCreateFactory)*)
+    GetProcAddress(dwriteModule, "DWriteCreateFactory");
+
+  if (!createDWriteFactory) {
+    gfxWarning() << "Failed to locate DWriteCreateFactory function.";
+    return nullptr;
+  }
+
+  HRESULT hr = createDWriteFactory(DWRITE_FACTORY_TYPE_SHARED, __uuidof(IDWriteFactory),
+                                   reinterpret_cast<IUnknown**>(&mDWriteFactory));
+
+  if (FAILED(hr)) {
+    gfxWarning() << "Failed to create DWrite Factory.";
+  }
+
+  return mDWriteFactory;
+}
+
 void
 DrawTargetD2D1::CleanupD2D()
 {
   if (mFactory) {
     RadialGradientEffectD2D1::Unregister(mFactory);
+    ExtendInputEffectD2D1::Unregister(mFactory);
     mFactory->Release();
     mFactory = nullptr;
   }
 }
 
 void
 DrawTargetD2D1::MarkChanged()
 {
--- a/gfx/2d/Factory.cpp
+++ b/gfx/2d/Factory.cpp
@@ -30,17 +30,16 @@
 #endif
 
 
 #ifdef XP_DARWIN
 #include "DrawTargetCG.h"
 #endif
 
 #ifdef WIN32
-#include "DrawTargetD2D.h"
 #include "DrawTargetD2D1.h"
 #include "ScaledFontDWrite.h"
 #include "NativeFontResourceDWrite.h"
 #include <d3d10_1.h>
 #include "HelpersD2D.h"
 #endif
 
 #include "DrawTargetDual.h"
@@ -156,17 +155,16 @@ HasCPUIDBit(unsigned int level, CPUIDReg
 namespace mozilla {
 namespace gfx {
 
 int32_t LoggingPrefs::sGfxLogLevel =
   PreferenceAccess::RegisterLivePref("gfx.logging.level", &sGfxLogLevel,
                                      LOG_DEFAULT);
 
 #ifdef WIN32
-ID3D10Device1 *Factory::mD3D10Device;
 ID3D11Device *Factory::mD3D11Device;
 ID2D1Device *Factory::mD2D1Device;
 #endif
 
 DrawEventRecorder *Factory::mRecorder;
 
 mozilla::gfx::Config* Factory::sConfig = nullptr;
 
@@ -310,25 +308,16 @@ Factory::CreateDrawTarget(BackendType aB
   if (!AllowedSurfaceSize(aSize)) {
     gfxCriticalError(LoggerOptionsBasedOnSize(aSize)) << "Failed to allocate a surface due to invalid size (CDT) " << aSize;
     return nullptr;
   }
 
   RefPtr<DrawTarget> retVal;
   switch (aBackend) {
 #ifdef WIN32
-  case BackendType::DIRECT2D:
-    {
-      RefPtr<DrawTargetD2D> newTarget;
-      newTarget = new DrawTargetD2D();
-      if (newTarget->Init(aSize, aFormat)) {
-        retVal = newTarget;
-      }
-      break;
-    }
   case BackendType::DIRECT2D1_1:
     {
       RefPtr<DrawTargetD2D1> newTarget;
       newTarget = new DrawTargetD2D1();
       if (newTarget->Init(aSize, aFormat)) {
         retVal = newTarget;
       }
       break;
@@ -494,18 +483,16 @@ Factory::GetMaxSurfaceSize(BackendType a
   case BackendType::COREGRAPHICS_ACCELERATED:
     return DrawTargetCG::GetMaxSurfaceSize();
 #endif
 #ifdef USE_SKIA
   case BackendType::SKIA:
     return DrawTargetSkia::GetMaxSurfaceSize();
 #endif
 #ifdef WIN32
-  case BackendType::DIRECT2D:
-    return DrawTargetD2D::GetMaxSurfaceSize();
   case BackendType::DIRECT2D1_1:
     return DrawTargetD2D1::GetMaxSurfaceSize();
 #endif
   default:
     return 0;
   }
 }
 
@@ -607,97 +594,16 @@ Factory::CreateDualDrawTarget(DrawTarget
   }
 
   return retVal.forget();
 }
 
 
 #ifdef WIN32
 already_AddRefed<DrawTarget>
-Factory::CreateDrawTargetForD3D10Texture(ID3D10Texture2D *aTexture, SurfaceFormat aFormat)
-{
-  MOZ_ASSERT(aTexture);
-
-  RefPtr<DrawTargetD2D> newTarget;
-
-  newTarget = new DrawTargetD2D();
-  if (newTarget->Init(aTexture, aFormat)) {
-    RefPtr<DrawTarget> retVal = newTarget;
-
-    if (mRecorder) {
-      retVal = new DrawTargetRecording(mRecorder, retVal, true);
-    }
-
-    return retVal.forget();
-  }
-
-  gfxWarning() << "Failed to create draw target for D3D10 texture.";
-
-  // Failed
-  return nullptr;
-}
-
-already_AddRefed<DrawTarget>
-Factory::CreateDualDrawTargetForD3D10Textures(ID3D10Texture2D *aTextureA,
-                                              ID3D10Texture2D *aTextureB,
-                                              SurfaceFormat aFormat)
-{
-  MOZ_ASSERT(aTextureA && aTextureB);
-  RefPtr<DrawTargetD2D> newTargetA;
-  RefPtr<DrawTargetD2D> newTargetB;
-
-  newTargetA = new DrawTargetD2D();
-  if (!newTargetA->Init(aTextureA, aFormat)) {
-    gfxWarning() << "Failed to create dual draw target for D3D10 texture.";
-    return nullptr;
-  }
-
-  newTargetB = new DrawTargetD2D();
-  if (!newTargetB->Init(aTextureB, aFormat)) {
-    gfxWarning() << "Failed to create new draw target for D3D10 texture.";
-    return nullptr;
-  }
-
-  RefPtr<DrawTarget> newTarget =
-    new DrawTargetDual(newTargetA, newTargetB);
-
-  RefPtr<DrawTarget> retVal = newTarget;
-
-  if (mRecorder) {
-    retVal = new DrawTargetRecording(mRecorder, retVal);
-  }
-
-  return retVal.forget();
-}
-
-void
-Factory::SetDirect3D10Device(ID3D10Device1 *aDevice)
-{
-  // do not throw on failure; return error codes and disconnect the device
-  // On Windows 8 error codes are the default, but on Windows 7 the
-  // default is to throw (or perhaps only with some drivers?)
-  if (aDevice) {
-    aDevice->SetExceptionMode(0);
-  }
-  mD3D10Device = aDevice;
-}
-
-ID3D10Device1*
-Factory::GetDirect3D10Device()
-{
-#ifdef DEBUG
-  if (mD3D10Device) {
-    UINT mode = mD3D10Device->GetExceptionMode();
-    MOZ_ASSERT(0 == mode);
-  }
-#endif
-  return mD3D10Device;
-}
-
-already_AddRefed<DrawTarget>
 Factory::CreateDrawTargetForD3D11Texture(ID3D11Texture2D *aTexture, SurfaceFormat aFormat)
 {
   MOZ_ASSERT(aTexture);
 
   RefPtr<DrawTargetD2D1> newTarget;
 
   newTarget = new DrawTargetD2D1();
   if (newTarget->Init(aTexture, aFormat)) {
@@ -762,34 +668,33 @@ already_AddRefed<GlyphRenderingOptions>
 Factory::CreateDWriteGlyphRenderingOptions(IDWriteRenderingParams *aParams)
 {
   return MakeAndAddRef<GlyphRenderingOptionsDWrite>(aParams);
 }
 
 uint64_t
 Factory::GetD2DVRAMUsageDrawTarget()
 {
-  return DrawTargetD2D::mVRAMUsageDT;
+  return DrawTargetD2D1::mVRAMUsageDT;
 }
 
 uint64_t
 Factory::GetD2DVRAMUsageSourceSurface()
 {
-  return DrawTargetD2D::mVRAMUsageSS;
+  return DrawTargetD2D1::mVRAMUsageSS;
 }
 
 void
 Factory::D2DCleanup()
 {
   if (mD2D1Device) {
     mD2D1Device->Release();
     mD2D1Device = nullptr;
   }
   DrawTargetD2D1::CleanupD2D();
-  DrawTargetD2D::CleanupD2D();
 }
 
 already_AddRefed<ScaledFont>
 Factory::CreateScaledFontForDWriteFont(IDWriteFont* aFont,
                                        IDWriteFontFamily* aFontFamily,
                                        IDWriteFontFace* aFontFace,
                                        float aSize)
 {
--- a/gfx/2d/FilterNodeD2D1.cpp
+++ b/gfx/2d/FilterNodeD2D1.cpp
@@ -3,19 +3,16 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "FilterNodeD2D1.h"
 
 #include "Logging.h"
 
 #include "SourceSurfaceD2D1.h"
-#include "SourceSurfaceD2D.h"
-#include "SourceSurfaceD2DTarget.h"
-#include "DrawTargetD2D.h"
 #include "DrawTargetD2D1.h"
 #include "ExtendInputEffectD2D1.h"
 
 namespace mozilla {
 namespace gfx {
 
 D2D1_COLORMATRIX_ALPHA_MODE D2DAlphaMode(uint32_t aMode)
 {
@@ -154,18 +151,16 @@ already_AddRefed<ID2D1Image> GetImageFor
 {
   if (aDT->IsTiledDrawTarget() || aDT->IsDualDrawTarget()) {
     gfxDevCrash(LogReason::FilterNodeD2D1Target) << "Incompatible draw target type! " << (int)aDT->IsTiledDrawTarget() << " " << (int)aDT->IsDualDrawTarget();
     return nullptr;
   }
   switch (aDT->GetBackendType()) {
     case BackendType::DIRECT2D1_1:
       return static_cast<DrawTargetD2D1*>(aDT)->GetImageForSurface(aSurface, ExtendMode::CLAMP);
-    case BackendType::DIRECT2D:
-      return static_cast<DrawTargetD2D*>(aDT)->GetImageForSurface(aSurface);
     default:
       gfxDevCrash(LogReason::FilterNodeD2D1Backend) << "Unknown draw target type! " << (int)aDT->GetBackendType();
       return nullptr;
   }
 }
 
 uint32_t ConvertValue(FilterType aType, uint32_t aAttribute, uint32_t aValue)
 {
--- a/gfx/2d/HelpersD2D.h
+++ b/gfx/2d/HelpersD2D.h
@@ -20,19 +20,18 @@
 #include "ScaledFontDWrite.h"
 
 #undef min
 #undef max
 
 namespace mozilla {
 namespace gfx {
 
-ID2D1Factory* D2DFactory();
-
 ID2D1Factory1* D2DFactory1();
+static ID2D1Factory* D2DFactory() { return D2DFactory1(); }
 
 static inline D2D1_POINT_2F D2DPoint(const Point &aPoint)
 {
   return D2D1::Point2F(aPoint.x, aPoint.y);
 }
 
 static inline D2D1_SIZE_U D2DIntSize(const IntSize &aSize)
 {
--- a/gfx/2d/Logging.h
+++ b/gfx/2d/Logging.h
@@ -91,18 +91,17 @@ public:
 /// show the warnings.
 ///
 /// gfxCriticalError is available in debug and release builds by default.
 /// It is only unavailable if gfx.logging.level is set to 0 (or less.)
 /// It outputs the message to stderr or equivalent, like gfxWarning.
 /// In the event of a crash, the crash report is annotated with first and
 /// the last few of these errors, under the key GraphicsCriticalError.
 /// The total number of errors stored in the crash report is controlled
-/// by preference gfx.logging.crash.length (default is six, so by default,
-/// the first as well as the last five would show up in the crash log.)
+/// by preference gfx.logging.crash.length.
 ///
 /// On platforms that support MOZ_LOGGING, the story is slightly more involved.
 /// In that case, unless gfx.logging.level is set to 4 or higher, the output
 /// is further controlled by the "gfx2d" logging module.  However, in the case
 /// where such module would disable the output, in all but gfxDebug cases,
 /// we will still send a printf.
 
 // The range is due to the values set in Histograms.json
--- a/gfx/2d/NativeFontResourceDWrite.cpp
+++ b/gfx/2d/NativeFontResourceDWrite.cpp
@@ -3,17 +3,17 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "NativeFontResourceDWrite.h"
 
 #include <unordered_map>
 
-#include "DrawTargetD2D.h"
+#include "DrawTargetD2D1.h"
 #include "Logging.h"
 #include "mozilla/RefPtr.h"
 
 namespace mozilla {
 namespace gfx {
 
 static Atomic<uint64_t> sNextFontFileKey;
 static std::unordered_map<uint64_t, IDWriteFontFileStream*> sFontFileStreams;
@@ -64,17 +64,17 @@ public:
     * loader, the key must be a uint64_t that has been generated by incrementing
     * sNextFontFileKey.
     * Also note that this is _not_ threadsafe.
     */
   static IDWriteFontFileLoader* Instance()
   {
     if (!mInstance) {
       mInstance = new DWriteFontFileLoader();
-      DrawTargetD2D::GetDWriteFactory()->
+      DrawTargetD2D1::GetDWriteFactory()->
           RegisterFontFileLoader(mInstance);
     }
     return mInstance;
   }
 
 private:
   static IDWriteFontFileLoader* mInstance;
 };
@@ -216,17 +216,17 @@ DWriteFontFileStream::ReleaseFileFragmen
 {
 }
 
 /* static */
 already_AddRefed<NativeFontResourceDWrite>
 NativeFontResourceDWrite::Create(uint8_t *aFontData, uint32_t aDataLength,
                                  bool aNeedsCairo)
 {
-  IDWriteFactory *factory = DrawTargetD2D::GetDWriteFactory();
+  IDWriteFactory *factory = DrawTargetD2D1::GetDWriteFactory();
   if (!factory) {
     gfxWarning() << "Failed to get DWrite Factory.";
     return nullptr;
   }
 
   uint64_t fontFileKey = sNextFontFileKey++;
   RefPtr<IDWriteFontFileStream> ffsRef =
     new DWriteFontFileStream(aFontData, aDataLength, fontFileKey);
--- a/gfx/2d/PathD2D.cpp
+++ b/gfx/2d/PathD2D.cpp
@@ -1,17 +1,17 @@
 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "PathD2D.h"
 #include "HelpersD2D.h"
 #include <math.h>
-#include "DrawTargetD2D.h"
+#include "DrawTargetD2D1.h"
 #include "Logging.h"
 
 namespace mozilla {
 namespace gfx {
 
 // This class exists as a wrapper for ID2D1SimplifiedGeometry sink, it allows
 // a geometry to be duplicated into a geometry sink, while removing the final
 // figure end and thus allowing a figure that was implicitly closed to be
@@ -346,17 +346,17 @@ PathD2D::CopyToBuilder(FillRule aFillRul
 {
   return TransformedCopyToBuilder(Matrix(), aFillRule);
 }
 
 already_AddRefed<PathBuilder>
 PathD2D::TransformedCopyToBuilder(const Matrix &aTransform, FillRule aFillRule) const
 {
   RefPtr<ID2D1PathGeometry> path;
-  HRESULT hr = DrawTargetD2D::factory()->CreatePathGeometry(getter_AddRefs(path));
+  HRESULT hr = DrawTargetD2D1::factory()->CreatePathGeometry(getter_AddRefs(path));
 
   if (FAILED(hr)) {
     gfxWarning() << "Failed to create PathGeometry. Code: " << hexa(hr);
     return nullptr;
   }
 
   RefPtr<ID2D1GeometrySink> sink;
   hr = path->Open(getter_AddRefs(sink));
--- a/gfx/2d/ScaledFontDWrite.cpp
+++ b/gfx/2d/ScaledFontDWrite.cpp
@@ -1,14 +1,14 @@
 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-#include "DrawTargetD2D.h"
+#include "DrawTargetD2D1.h"
 #include "ScaledFontDWrite.h"
 #include "PathD2D.h"
 
 #ifdef USE_SKIA
 #include "PathSkia.h"
 #include "skia/include/core/SkPaint.h"
 #include "skia/include/core/SkPath.h"
 #include "skia/include/ports/SkTypeface_win.h"
@@ -115,17 +115,17 @@ ScaledFontDWrite::GetPathForGlyphs(const
 
 
 #ifdef USE_SKIA
 SkTypeface*
 ScaledFontDWrite::GetSkTypeface()
 {
   MOZ_ASSERT(mFont);
   if (!mTypeface) {
-    IDWriteFactory *factory = DrawTargetD2D::GetDWriteFactory();
+    IDWriteFactory *factory = DrawTargetD2D1::GetDWriteFactory();
     mTypeface = SkCreateTypefaceFromDWriteFont(factory, mFontFace, mFont, mFontFamily);
   }
   return mTypeface;
 }
 #endif
 
 void
 ScaledFontDWrite::CopyGlyphsToBuilder(const GlyphBuffer &aBuffer, PathBuilder *aBuilder, BackendType aBackendType, const Matrix *aTransformHint)
deleted file mode 100644
--- a/gfx/2d/SourceSurfaceD2D.cpp
+++ /dev/null
@@ -1,317 +0,0 @@
-/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "SourceSurfaceD2D.h"
-#include "DrawTargetD2D.h"
-#include "Logging.h"
-#include "Tools.h"
-
-namespace mozilla {
-namespace gfx {
-
-SourceSurfaceD2D::SourceSurfaceD2D()
-{
-}
-
-SourceSurfaceD2D::~SourceSurfaceD2D()
-{
-  if (mBitmap) {
-    DrawTargetD2D::mVRAMUsageSS -= GetByteSize();
-  }
-}
-
-IntSize
-SourceSurfaceD2D::GetSize() const
-{
-  return mSize;
-}
-
-SurfaceFormat
-SourceSurfaceD2D::GetFormat() const
-{
-  return mFormat;
-}
-
-bool
-SourceSurfaceD2D::IsValid() const
-{
-  return mDevice == Factory::GetDirect3D10Device();
-}
-
-already_AddRefed<DataSourceSurface>
-SourceSurfaceD2D::GetDataSurface()
-{
-  RefPtr<DataSourceSurfaceD2D> result = new DataSourceSurfaceD2D(this);
-  if (result->IsValid()) {
-    return result.forget();
-  }
-  return nullptr;
-}
-
-bool
-SourceSurfaceD2D::InitFromData(unsigned char *aData,
-                               const IntSize &aSize,
-                               int32_t aStride,
-                               SurfaceFormat aFormat,
-                               ID2D1RenderTarget *aRT)
-{
-  HRESULT hr;
-
-  mFormat = aFormat;
-  mSize = aSize;
-
-  if ((uint32_t)aSize.width > aRT->GetMaximumBitmapSize() ||
-      (uint32_t)aSize.height > aRT->GetMaximumBitmapSize()) {
-    gfxDebug() << "Bitmap does not fit in texture.";
-    return false;
-  }
-
-  D2D1_BITMAP_PROPERTIES props = D2D1::BitmapProperties(D2DPixelFormat(aFormat));
-  hr = aRT->CreateBitmap(D2DIntSize(aSize), props, getter_AddRefs(mBitmap));
-
-  if (FAILED(hr)) {
-    gfxWarning() << "Failed to create D2D Bitmap for data. Code: " << hexa(hr);
-    return false;
-  }
-
-  hr = mBitmap->CopyFromMemory(nullptr, aData, aStride);
-
-  if (FAILED(hr)) {
-    gfxWarning() << "Failed to copy data to D2D bitmap. Code: " << hexa(hr);
-    return false;
-  }
-
-  DrawTargetD2D::mVRAMUsageSS += GetByteSize();
-  mDevice = Factory::GetDirect3D10Device();
-
-  return true;
-}
-
-bool
-SourceSurfaceD2D::InitFromTexture(ID3D10Texture2D *aTexture,
-                                  SurfaceFormat aFormat,
-                                  ID2D1RenderTarget *aRT)
-{
-  HRESULT hr;
-
-  RefPtr<IDXGISurface> surf;
-
-  hr = aTexture->QueryInterface((IDXGISurface**)&surf);
-
-  if (FAILED(hr)) {
-    gfxWarning() << "Failed to QI texture to surface. Code: " << hexa(hr);
-    return false;
-  }
-
-  D3D10_TEXTURE2D_DESC desc;
-  aTexture->GetDesc(&desc);
-
-  mSize = IntSize(desc.Width, desc.Height);
-  mFormat = aFormat;
-
-  D2D1_BITMAP_PROPERTIES props = D2D1::BitmapProperties(D2DPixelFormat(aFormat));
-  hr = aRT->CreateSharedBitmap(IID_IDXGISurface, surf, &props, getter_AddRefs(mBitmap));
-
-  if (FAILED(hr)) {
-    gfxWarning() << "Failed to create SharedBitmap. Code: " << hexa(hr);
-    return false;
-  }
-
-  aTexture->GetDevice(getter_AddRefs(mDevice));
-  DrawTargetD2D::mVRAMUsageSS += GetByteSize();
-
-  return true;
-}
-
-uint32_t
-SourceSurfaceD2D::GetByteSize() const
-{
-  return mSize.width * mSize.height * BytesPerPixel(mFormat);
-}
-
-DataSourceSurfaceD2D::DataSourceSurfaceD2D(SourceSurfaceD2D* aSourceSurface)
-  : mTexture(nullptr)
-  , mFormat(aSourceSurface->mFormat)
-  , mSize(aSourceSurface->mSize)
-  , mMapped(false)
-{
-  // We allocate ourselves a regular D3D surface (sourceTexture) and paint the
-  // D2D bitmap into it via a DXGI render target. Then we need to copy
-  // sourceTexture into a staging texture (mTexture), which we will lazily map
-  // to get the data.
-
-  CD3D10_TEXTURE2D_DESC desc(DXGIFormat(mFormat), mSize.width, mSize.height);
-  desc.MipLevels = 1;
-  desc.Usage = D3D10_USAGE_DEFAULT;
-  desc.BindFlags = D3D10_BIND_RENDER_TARGET | D3D10_BIND_SHADER_RESOURCE;
-  RefPtr<ID3D10Texture2D> sourceTexture;
-  HRESULT hr = aSourceSurface->mDevice->CreateTexture2D(&desc, nullptr,
-                                                        getter_AddRefs(sourceTexture));
-  if (FAILED(hr)) {
-    gfxWarning() << "Failed to create texture. Code: " << hexa(hr);
-    return;
-  }
-
-  RefPtr<IDXGISurface> dxgiSurface;
-  hr = sourceTexture->QueryInterface((IDXGISurface**)getter_AddRefs(dxgiSurface));
-  if (FAILED(hr)) {
-    gfxWarning() << "Failed to create DXGI surface. Code: " << hexa(hr);
-    return;
-  }
-
-  D2D1_RENDER_TARGET_PROPERTIES rtProps = D2D1::RenderTargetProperties(
-            D2D1_RENDER_TARGET_TYPE_DEFAULT,
-            D2D1::PixelFormat(DXGI_FORMAT_UNKNOWN, D2D1_ALPHA_MODE_PREMULTIPLIED));
-
-  RefPtr<ID2D1RenderTarget> renderTarget;
-  hr = DrawTargetD2D::factory()->CreateDxgiSurfaceRenderTarget(dxgiSurface,
-                                                               &rtProps,
-                                                               getter_AddRefs(renderTarget));
-  if (FAILED(hr)) {
-    gfxWarning() << "Failed to create render target. Code: " << hexa(hr);
-    return;
-  }
-
-  renderTarget->BeginDraw();
-  renderTarget->Clear(D2D1::ColorF(0, 0.0f));
-  if (aSourceSurface->GetFormat() != SurfaceFormat::A8) {
-    renderTarget->DrawBitmap(aSourceSurface->mBitmap,
-                             D2D1::RectF(0, 0,
-                             Float(mSize.width),
-                             Float(mSize.height)));
-  } else {
-    RefPtr<ID2D1SolidColorBrush> brush;
-    renderTarget->CreateSolidColorBrush(D2D1::ColorF(D2D1::ColorF::White), getter_AddRefs(brush));
-    renderTarget->SetAntialiasMode(D2D1_ANTIALIAS_MODE_ALIASED);
-    renderTarget->FillOpacityMask(aSourceSurface->mBitmap, brush, D2D1_OPACITY_MASK_CONTENT_GRAPHICS);
-  }
-  hr = renderTarget->EndDraw();
-  if (FAILED(hr)) {
-    gfxWarning() << "Failed to draw bitmap. Code: " << hexa(hr);
-    return;
-  }
-
-  desc.CPUAccessFlags = D3D10_CPU_ACCESS_READ | D3D10_CPU_ACCESS_WRITE;
-  desc.Usage = D3D10_USAGE_STAGING;
-  desc.BindFlags = 0;
-  hr = aSourceSurface->mDevice->CreateTexture2D(&desc, nullptr, getter_AddRefs(mTexture));
-  if (FAILED(hr)) {
-    gfxWarning() << "Failed to create staging texture. Code: " << hexa(hr);
-    mTexture = nullptr;
-    return;
-  }
-
-  aSourceSurface->mDevice->CopyResource(mTexture, sourceTexture);
-}
-
-DataSourceSurfaceD2D::~DataSourceSurfaceD2D()
-{
-  if (mMapped) {
-    mTexture->Unmap(0);
-  }
-}
-
-unsigned char*
-DataSourceSurfaceD2D::GetData()
-{
-  EnsureMappedTexture();
-  if (!mMapped) {
-    return nullptr;
-  }
-
-  return reinterpret_cast<unsigned char*>(mData.pData);
-}
-
-int32_t
-DataSourceSurfaceD2D::Stride()
-{
-  EnsureMappedTexture();
-  if (!mMapped) {
-    return 0;
-  }
-
-  return mData.RowPitch;
-}
-
-IntSize
-DataSourceSurfaceD2D::GetSize() const
-{
-  return mSize;
-}
-
-SurfaceFormat
-DataSourceSurfaceD2D::GetFormat() const
-{
-  return mFormat;
-}
-
-bool
-DataSourceSurfaceD2D::Map(MapType aMapType, MappedSurface *aMappedSurface)
-{
-  // DataSourceSurfaces used with the new Map API should not be used with GetData!!
-  MOZ_ASSERT(!mMapped);
-  MOZ_ASSERT(!mIsMapped);
-
-  if (!mTexture) {
-    return false;
-  }
-
-  D3D10_MAP mapType;
-
-  if (aMapType == MapType::READ) {
-    mapType = D3D10_MAP_READ;
-  } else if (aMapType == MapType::WRITE) {
-    mapType = D3D10_MAP_WRITE;
-  } else {
-    mapType = D3D10_MAP_READ_WRITE;
-  }
-
-  D3D10_MAPPED_TEXTURE2D map;
-
-  HRESULT hr = mTexture->Map(0, mapType, 0, &map);
-
-  if (FAILED(hr)) {
-    gfxWarning() << "Texture map failed with code: " << hexa(hr);
-    return false;
-  }
-
-  aMappedSurface->mData = (uint8_t*)map.pData;
-  aMappedSurface->mStride = map.RowPitch;
-  mIsMapped = !!aMappedSurface->mData;
-
-  return mIsMapped;
-}
-
-void
-DataSourceSurfaceD2D::Unmap()
-{
-  MOZ_ASSERT(mIsMapped);
-
-  mIsMapped = false;
-  mTexture->Unmap(0);
-}
-
-void
-DataSourceSurfaceD2D::EnsureMappedTexture()
-{
-  // Do not use GetData() after having used Map!
-  MOZ_ASSERT(!mIsMapped);
-
-  if (mMapped ||
-      !mTexture) {
-    return;
-  }
-
-  HRESULT hr = mTexture->Map(0, D3D10_MAP_READ, 0, &mData);
-  if (FAILED(hr)) {
-    gfxWarning() << "Failed to map texture. Code: " << hexa(hr);
-    mTexture = nullptr;
-  } else {
-    mMapped = true;
-  }
-}
-
-}
-}
deleted file mode 100644
--- a/gfx/2d/SourceSurfaceD2D.h
+++ /dev/null
@@ -1,90 +0,0 @@
-/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef MOZILLA_GFX_SOURCESURFACED2D_H_
-#define MOZILLA_GFX_SOURCESURFACED2D_H_
-
-#include "2D.h"
-#include "HelpersD2D.h"
-#include <vector>
-
-namespace mozilla {
-namespace gfx {
-
-class DataSourceSurfaceD2D;
-
-class SourceSurfaceD2D : public SourceSurface
-{
-public:
-  MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(SourceSurfaceD2D)
-  SourceSurfaceD2D();
-  ~SourceSurfaceD2D();
-
-  virtual SurfaceType GetType() const { return SurfaceType::D2D1_BITMAP; }
-  virtual IntSize GetSize() const;
-  virtual SurfaceFormat GetFormat() const;
-  virtual bool IsValid() const;
-
-  virtual already_AddRefed<DataSourceSurface> GetDataSurface();
-
-  ID2D1Bitmap *GetBitmap() { return mBitmap; }
-
-  bool InitFromData(unsigned char *aData,
-                    const IntSize &aSize,
-                    int32_t aStride,
-                    SurfaceFormat aFormat,
-                    ID2D1RenderTarget *aRT);
-  bool InitFromTexture(ID3D10Texture2D *aTexture,
-                       SurfaceFormat aFormat,
-                       ID2D1RenderTarget *aRT);
-private:
-  friend class DrawTargetD2D;
-  friend class DataSourceSurfaceD2D;
-
-  uint32_t GetByteSize() const;
-
-  RefPtr<ID2D1Bitmap> mBitmap;
-  // We need to keep this pointer here to check surface validity.
-  RefPtr<ID3D10Device> mDevice;
-  SurfaceFormat mFormat;
-  IntSize mSize;
-};
-
-
-class DataSourceSurfaceD2D : public DataSourceSurface
-{
-public:
-  MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(DataSourceSurfaceD2D)
-  DataSourceSurfaceD2D(SourceSurfaceD2D* aSourceSurface);
-  virtual ~DataSourceSurfaceD2D();
-
-  virtual unsigned char* GetData();
-  virtual int32_t Stride();
-  virtual IntSize GetSize() const;
-  virtual SurfaceFormat GetFormat() const;
-  virtual bool Map(MapType, MappedSurface *aMappedSurface);
-  virtual void Unmap();
-
-  bool IsValid()
-  {
-    return mTexture;
-  }
-
-private:
-  void EnsureMappedTexture();
-
-  RefPtr<ID3D10Texture2D> mTexture;
-
-  D3D10_MAPPED_TEXTURE2D mData;
-
-  SurfaceFormat mFormat;
-  IntSize mSize;
-  bool mMapped;
-};
-
-}
-}
-
-#endif /* MOZILLA_GFX_SOURCESURFACED2D_H_ */
deleted file mode 100644
--- a/gfx/2d/SourceSurfaceD2DTarget.cpp
+++ /dev/null
@@ -1,325 +0,0 @@
-/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "SourceSurfaceD2DTarget.h"
-#include "Logging.h"
-#include "DrawTargetD2D.h"
-#include "Tools.h"
-
-#include <algorithm>
-
-namespace mozilla {
-namespace gfx {
-
-SourceSurfaceD2DTarget::SourceSurfaceD2DTarget(DrawTargetD2D* aDrawTarget,
-                                               ID3D10Texture2D* aTexture,
-                                               SurfaceFormat aFormat)
-  : mDrawTarget(aDrawTarget)
-  , mTexture(aTexture)
-  , mFormat(aFormat)
-  , mOwnsCopy(false)
-{
-}
-
-SourceSurfaceD2DTarget::~SourceSurfaceD2DTarget()
-{
-  // We don't need to do anything special here to notify our mDrawTarget. It must
-  // already have cleared its mSnapshot field, otherwise this object would
-  // be kept alive.
-  if (mOwnsCopy) {
-    IntSize size = GetSize();
-
-    DrawTargetD2D::mVRAMUsageSS -= size.width * size.height * BytesPerPixel(mFormat);
-  }
-}
-
-IntSize
-SourceSurfaceD2DTarget::GetSize() const
-{
-  D3D10_TEXTURE2D_DESC desc;
-  mTexture->GetDesc(&desc);
-
-  return IntSize(desc.Width, desc.Height);
-}
-
-SurfaceFormat
-SourceSurfaceD2DTarget::GetFormat() const
-{
-  return mFormat;
-}
-
-already_AddRefed<DataSourceSurface>
-SourceSurfaceD2DTarget::GetDataSurface()
-{
-  RefPtr<DataSourceSurfaceD2DTarget> dataSurf =
-    new DataSourceSurfaceD2DTarget(mFormat);
-
-  D3D10_TEXTURE2D_DESC desc;
-  mTexture->GetDesc(&desc);
-
-  desc.CPUAccessFlags = D3D10_CPU_ACCESS_READ;
-  desc.Usage = D3D10_USAGE_STAGING;
-  desc.BindFlags = 0;
-  desc.MiscFlags = 0;
-
-  if (!Factory::GetDirect3D10Device()) {
-    gfxCriticalError() << "Invalid D3D10 device in D2D target surface (GDS)";
-    return nullptr;
-  }
-
-  HRESULT hr = Factory::GetDirect3D10Device()->CreateTexture2D(&desc, nullptr, getter_AddRefs(dataSurf->mTexture));
-
-  if (FAILED(hr)) {
-    gfxDebug() << "Failed to create staging texture for SourceSurface. Code: " << hexa(hr);
-    return nullptr;
-  }
-  Factory::GetDirect3D10Device()->CopyResource(dataSurf->mTexture, mTexture);
-
-  return dataSurf.forget();
-}
-
-void*
-SourceSurfaceD2DTarget::GetNativeSurface(NativeSurfaceType aType)
-{
-  if (aType == NativeSurfaceType::D3D10_TEXTURE) {
-    return static_cast<void*>(mTexture.get());
-  }
-  return nullptr;
-}
-
-ID3D10ShaderResourceView*
-SourceSurfaceD2DTarget::GetSRView()
-{
-  if (mSRView) {
-    return mSRView;
-  }
-
-  if (!Factory::GetDirect3D10Device()) {
-    gfxCriticalError() << "Invalid D3D10 device in D2D target surface (SRV)";
-    return nullptr;
-  }
-
-  HRESULT hr = Factory::GetDirect3D10Device()->CreateShaderResourceView(mTexture, nullptr, getter_AddRefs(mSRView));
-
-  if (FAILED(hr)) {
-    gfxWarning() << "Failed to create ShaderResourceView. Code: " << hexa(hr);
-  }
-
-  return mSRView;
-}
-
-void
-SourceSurfaceD2DTarget::DrawTargetWillChange()
-{
-  RefPtr<ID3D10Texture2D> oldTexture = mTexture;
-
-  D3D10_TEXTURE2D_DESC desc;
-  mTexture->GetDesc(&desc);
-
-  // Our original texture might implement the keyed mutex flag. We shouldn't
-  // need that here. We actually specifically don't want it since we don't lock
-  // our texture for usage!
-  desc.MiscFlags = 0;
-
-  // Get a copy of the surface data so the content at snapshot time was saved.
-  Factory::GetDirect3D10Device()->CreateTexture2D(&desc, nullptr, getter_AddRefs(mTexture));
-  Factory::GetDirect3D10Device()->CopyResource(mTexture, oldTexture);
-
-  mBitmap = nullptr;
-
-  DrawTargetD2D::mVRAMUsageSS += desc.Width * desc.Height * BytesPerPixel(mFormat);
-  mOwnsCopy = true;
-
-  // We now no longer depend on the source surface content remaining the same.
-  MarkIndependent();
-}
-
-ID2D1Bitmap*
-SourceSurfaceD2DTarget::GetBitmap(ID2D1RenderTarget *aRT)
-{
-  if (mBitmap) {
-    return mBitmap;
-  }
-
-  HRESULT hr;
-  D3D10_TEXTURE2D_DESC desc;
-  mTexture->GetDesc(&desc);
-
-  IntSize size(desc.Width, desc.Height);
-  
-  RefPtr<IDXGISurface> surf;
-  hr = mTexture->QueryInterface((IDXGISurface**)getter_AddRefs(surf));
-
-  if (FAILED(hr)) {
-    gfxWarning() << "Failed to query interface texture to DXGISurface. Code: " << hexa(hr);
-    return nullptr;
-  }
-
-  D2D1_BITMAP_PROPERTIES props = D2D1::BitmapProperties(D2DPixelFormat(mFormat));
-  hr = aRT->CreateSharedBitmap(IID_IDXGISurface, surf, &props, getter_AddRefs(mBitmap));
-
-  if (FAILED(hr)) {
-    // This seems to happen for SurfaceFormat::A8 sometimes...
-    hr = aRT->CreateBitmap(D2D1::SizeU(desc.Width, desc.Height),
-                           D2D1::BitmapProperties(D2DPixelFormat(mFormat)),
-                           getter_AddRefs(mBitmap));
-
-    if (FAILED(hr)) {
-      gfxWarning() << "Failed in CreateBitmap. Code: " << hexa(hr);
-      return nullptr;
-    }
-
-    RefPtr<ID2D1RenderTarget> rt;
-
-    if (mDrawTarget) {
-      rt = mDrawTarget->mRT;
-    }
-
-    if (!rt) {
-      // Okay, we already separated from our drawtarget. And we're an A8
-      // surface the only way we can get to a bitmap is by creating a
-      // a rendertarget and from there copying to a bitmap! Terrible!
-      RefPtr<IDXGISurface> surface;
-
-      hr = mTexture->QueryInterface((IDXGISurface**)getter_AddRefs(surface));
-
-      if (FAILED(hr)) {
-        gfxWarning() << "Failed to QI texture to surface.";
-        return nullptr;
-      }
-
-      D2D1_RENDER_TARGET_PROPERTIES props =
-        D2D1::RenderTargetProperties(D2D1_RENDER_TARGET_TYPE_DEFAULT, D2DPixelFormat(mFormat));
-      hr = DrawTargetD2D::factory()->CreateDxgiSurfaceRenderTarget(surface, props, getter_AddRefs(rt));
-
-      if (FAILED(hr)) {
-        gfxWarning() << "Failed to create D2D render target for texture.";
-        return nullptr;
-      }
-    }
-
-    mBitmap->CopyFromRenderTarget(nullptr, rt, nullptr);
-    return mBitmap;
-  }
-
-  return mBitmap;
-}
-
-void
-SourceSurfaceD2DTarget::MarkIndependent()
-{
-  if (mDrawTarget) {
-    MOZ_ASSERT(mDrawTarget->mSnapshot == this);
-    mDrawTarget->mSnapshot = nullptr;
-    mDrawTarget = nullptr;
-  }
-}
-
-DataSourceSurfaceD2DTarget::DataSourceSurfaceD2DTarget(SurfaceFormat aFormat)
-  : mFormat(aFormat)
-  , mMapped(false)
-{
-}
-
-DataSourceSurfaceD2DTarget::~DataSourceSurfaceD2DTarget()
-{
-  if (mMapped) {
-    mTexture->Unmap(0);
-  }
-}
-
-IntSize
-DataSourceSurfaceD2DTarget::GetSize() const
-{
-  D3D10_TEXTURE2D_DESC desc;
-  mTexture->GetDesc(&desc);
-
-  return IntSize(desc.Width, desc.Height);
-}
-
-SurfaceFormat
-DataSourceSurfaceD2DTarget::GetFormat() const
-{
-  return mFormat;
-}
-
-uint8_t*
-DataSourceSurfaceD2DTarget::GetData()
-{
-  EnsureMapped();
-
-  return (unsigned char*)mMap.pData;
-}
-
-int32_t
-DataSourceSurfaceD2DTarget::Stride()
-{
-  EnsureMapped();
-  return mMap.RowPitch;
-}
-
-bool
-DataSourceSurfaceD2DTarget::Map(MapType aMapType, MappedSurface *aMappedSurface)
-{
-  // DataSourceSurfaces used with the new Map API should not be used with GetData!!
-  MOZ_ASSERT(!mMapped);
-  MOZ_ASSERT(!mIsMapped);
-
-  if (!mTexture) {
-    return false;
-  }
-
-  D3D10_MAP mapType;
-
-  if (aMapType == MapType::READ) {
-    mapType = D3D10_MAP_READ;
-  } else if (aMapType == MapType::WRITE) {
-    mapType = D3D10_MAP_WRITE;
-  } else {
-    mapType = D3D10_MAP_READ_WRITE;
-  }
-
-  D3D10_MAPPED_TEXTURE2D map;
-
-  HRESULT hr = mTexture->Map(0, mapType, 0, &map);
-
-  if (FAILED(hr)) {
-    gfxWarning() << "Texture map failed with code: " << hexa(hr);
-    return false;
-  }
-
-  aMappedSurface->mData = (uint8_t*)map.pData;
-  aMappedSurface->mStride = map.RowPitch;
-  mIsMapped = !!aMappedSurface->mData;
-
-  return mIsMapped;
-}
-
-void
-DataSourceSurfaceD2DTarget::Unmap()
-{
-  MOZ_ASSERT(mIsMapped);
-
-  mIsMapped = false;
-  mTexture->Unmap(0);
-}
-
-void
-DataSourceSurfaceD2DTarget::EnsureMapped()
-{
-  // Do not use GetData() after having used Map!
-  MOZ_ASSERT(!mIsMapped);
-  if (!mMapped) {
-    HRESULT hr = mTexture->Map(0, D3D10_MAP_READ, 0, &mMap);
-    if (FAILED(hr)) {
-      gfxWarning() << "Failed to map texture to memory. Code: " << hexa(hr);
-      return;
-    }
-    mMapped = true;
-  }
-}
-
-}
-}
deleted file mode 100644
--- a/gfx/2d/SourceSurfaceD2DTarget.h
+++ /dev/null
@@ -1,90 +0,0 @@
-/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef MOZILLA_GFX_SOURCESURFACED2DTARGET_H_
-#define MOZILLA_GFX_SOURCESURFACED2DTARGET_H_
-
-#include "2D.h"
-#include "HelpersD2D.h"
-#include <vector>
-#include <d3d10_1.h>
-
-namespace mozilla {
-namespace gfx {
-
-class DrawTargetD2D;
-
-class SourceSurfaceD2DTarget : public SourceSurface
-{
-public:
-  MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(SourceSurfaceD2DTarget)
-  SourceSurfaceD2DTarget(DrawTargetD2D* aDrawTarget, ID3D10Texture2D* aTexture,
-                         SurfaceFormat aFormat);
-  ~SourceSurfaceD2DTarget();
-
-  virtual SurfaceType GetType() const { return SurfaceType::D2D1_DRAWTARGET; }
-  virtual IntSize GetSize() const;
-  virtual SurfaceFormat GetFormat() const;
-  virtual already_AddRefed<DataSourceSurface> GetDataSurface();
-  virtual void *GetNativeSurface(NativeSurfaceType aType);
-
-  DrawTargetD2D* GetDT() { return mDrawTarget; }
-  ID2D1Bitmap *GetBitmap(ID2D1RenderTarget *aRT);
-
-private:
-  friend class DrawTargetD2D;
-
-  ID3D10ShaderResourceView *GetSRView();
-
-  // This function is called by the draw target this texture belongs to when
-  // it is about to be changed. The texture will be required to make a copy
-  // of itself when this happens.
-  void DrawTargetWillChange();
-
-  // This will mark the surface as no longer depending on its drawtarget,
-  // this may happen on destruction or copying.
-  void MarkIndependent();
-
-  RefPtr<ID3D10ShaderResourceView> mSRView;
-  RefPtr<ID2D1Bitmap> mBitmap;
-  // Non-null if this is a "lazy copy" of the given draw target.
-  // Null if we've made a copy. The target is not kept alive, otherwise we'd
-  // have leaks since it might keep us alive. If the target is destroyed, it
-  // will notify us.
-  DrawTargetD2D* mDrawTarget;
-  mutable RefPtr<ID3D10Texture2D> mTexture;
-  SurfaceFormat mFormat;
-  bool mOwnsCopy;
-};
-
-class DataSourceSurfaceD2DTarget : public DataSourceSurface
-{
-public:
-  MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(DataSourceSurfaceD2DTarget)
-  DataSourceSurfaceD2DTarget(SurfaceFormat aFormat);
-  ~DataSourceSurfaceD2DTarget();
-
-  virtual SurfaceType GetType() const { return SurfaceType::DATA; }
-  virtual IntSize GetSize() const;
-  virtual SurfaceFormat GetFormat() const;
-  virtual uint8_t *GetData();
-  virtual int32_t Stride();
-  virtual bool Map(MapType, MappedSurface *aMappedSurface);
-  virtual void Unmap();
-
-private:
-  friend class SourceSurfaceD2DTarget;
-  void EnsureMapped();
-
-  mutable RefPtr<ID3D10Texture2D> mTexture;
-  SurfaceFormat mFormat;
-  D3D10_MAPPED_TEXTURE2D mMap;
-  bool mMapped;
-};
-
-}
-}
-
-#endif /* MOZILLA_GFX_SOURCESURFACED2DTARGET_H_ */
--- a/gfx/2d/Types.h
+++ b/gfx/2d/Types.h
@@ -118,17 +118,17 @@ enum class FilterType : int8_t {
 enum class DrawTargetType : int8_t {
   SOFTWARE_RASTER = 0,
   HARDWARE_RASTER,
   VECTOR
 };
 
 enum class BackendType : int8_t {
   NONE = 0,
-  DIRECT2D,
+  DIRECT2D, // Used for version independent D2D objects.
   COREGRAPHICS,
   COREGRAPHICS_ACCELERATED,
   CAIRO,
   SKIA,
   RECORDING,
   DIRECT2D1_1
 };
 
--- a/gfx/2d/moz.build
+++ b/gfx/2d/moz.build
@@ -61,30 +61,27 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('coc
     UNIFIED_SOURCES += [
         'DrawTargetCG.cpp',
         'PathCG.cpp',
         'ScaledFontMac.cpp',
         'SourceSurfaceCG.cpp',
     ]
 elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows':
     SOURCES += [
-        'DrawTargetD2D.cpp',
         'DrawTargetD2D1.cpp',
         'ExtendInputEffectD2D1.cpp',
         'FilterNodeD2D1.cpp',
         'JobScheduler_win32.cpp',
         'NativeFontResourceDWrite.cpp',
         'NativeFontResourceGDI.cpp',
         'PathD2D.cpp',
         'RadialGradientEffectD2D1.cpp',
         'ScaledFontDWrite.cpp',
         'ScaledFontWin.cpp',
-        'SourceSurfaceD2D.cpp',
         'SourceSurfaceD2D1.cpp',
-        'SourceSurfaceD2DTarget.cpp',
     ]
     DEFINES['WIN32'] = True
 
 if CONFIG['MOZ_WIDGET_TOOLKIT'] != 'windows':
     SOURCES += [
         'JobScheduler_posix.cpp',
     ]
 
--- a/gfx/gl/GLScreenBuffer.cpp
+++ b/gfx/gl/GLScreenBuffer.cpp
@@ -533,17 +533,17 @@ GLScreenBuffer::Attach(SharedSurface* su
 
 bool
 GLScreenBuffer::Swap(const gfx::IntSize& size)
 {
     RefPtr<SharedSurfaceTextureClient> newBack = mFactory->NewTexClient(size);
     if (!newBack)
         return false;
 
-    // In the case of DXGL interop, the new surface needs to be acquired before 
+    // In the case of DXGL interop, the new surface needs to be acquired before
     // it is attached so that the interop surface is locked, which populates
     // the GL renderbuffer. This results in the renderbuffer being ready and
     // attachment to framebuffer succeeds in Attach() call.
     newBack->Surf()->ProducerAcquire();
 
     if (!Attach(newBack->Surf(), size))
         return false;
     // Attach was successful.
@@ -823,20 +823,17 @@ DrawBuffer::Create(GLContext* const gl,
 
     CreateRenderbuffersForOffscreen(gl, formats, size, caps.antialias,
                                     pColorMSRB, pDepthRB, pStencilRB);
 
     GLuint fb = 0;
     gl->fGenFramebuffers(1, &fb);
     gl->AttachBuffersToFB(0, colorMSRB, depthRB, stencilRB, fb);
 
-    GLsizei samples = formats.samples;
-    if (!samples)
-        samples = 1;
-
+    const GLsizei samples = formats.samples;
     UniquePtr<DrawBuffer> ret( new DrawBuffer(gl, size, samples, fb, colorMSRB,
                                               depthRB, stencilRB) );
 
     GLenum err = localError.GetError();
     MOZ_ASSERT_IF(err != LOCAL_GL_NO_ERROR, err == LOCAL_GL_OUT_OF_MEMORY);
     if (err || !gl->IsFramebufferComplete(fb))
         return false;
 
--- a/gfx/gl/GLScreenBuffer.h
+++ b/gfx/gl/GLScreenBuffer.h
@@ -201,17 +201,17 @@ public:
     }
 
     GLuint ReadFB() const {
         return mRead->mFB;
     }
 
     GLsizei Samples() const {
         if (!mDraw)
-            return 1;
+            return 0;
 
         return mDraw->mSamples;
     }
 
     void DeletingFB(GLuint fb);
 
     const gfx::IntSize& Size() const {
         MOZ_ASSERT(mRead);
--- a/gfx/ipc/GraphicsMessages.ipdlh
+++ b/gfx/ipc/GraphicsMessages.ipdlh
@@ -14,15 +14,14 @@ struct DeviceInitData
 {
   bool useAcceleration;
 
   // Windows only.
   bool useD3D11;
   bool useD3D11WARP;
   bool useD3D11ImageBridge;
   bool d3d11TextureSharingWorks;
-  bool useD2D;
   bool useD2D1;
   DxgiAdapterDesc adapter;
 };
 
 } // namespace gfx
 } // namespace mozilla
--- a/gfx/layers/PersistentBufferProvider.h
+++ b/gfx/layers/PersistentBufferProvider.h
@@ -35,41 +35,48 @@ public:
 
   /**
    * Get a DrawTarget from the PersistentBufferProvider.
    *
    * \param aPersistedRect This indicates the area of the DrawTarget that needs
    *                       to have remained the same since the call to
    *                       ReturnAndUseDT.
    */
-  virtual gfx::DrawTarget* GetDT(const gfx::IntRect& aPersistedRect) = 0;
+  virtual already_AddRefed<gfx::DrawTarget> GetDT(const gfx::IntRect& aPersistedRect) = 0;
   /**
    * Return a DrawTarget to the PersistentBufferProvider and indicate the
    * contents of this DrawTarget is to be considered current by the
-   * BufferProvider
+   * BufferProvider. The caller should forget any references to the DrawTarget.
    */
-  virtual bool ReturnAndUseDT(gfx::DrawTarget* aDT) = 0;
+  virtual bool ReturnAndUseDT(already_AddRefed<gfx::DrawTarget> aDT) = 0;
 
   virtual already_AddRefed<gfx::SourceSurface> GetSnapshot() = 0;
 protected:
 };
 
 class PersistentBufferProviderBasic : public PersistentBufferProvider
 {
 public:
   MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(PersistentBufferProviderBasic)
 
   PersistentBufferProviderBasic(gfx::IntSize aSize, gfx::SurfaceFormat aFormat,
                                 gfx::BackendType aBackend);
   explicit PersistentBufferProviderBasic(gfx::DrawTarget* aTarget) : mDrawTarget(aTarget) {}
 
   bool IsValid() { return !!mDrawTarget; }
   virtual LayersBackend GetType() { return LayersBackend::LAYERS_BASIC; }
-  gfx::DrawTarget* GetDT(const gfx::IntRect& aPersistedRect) { return mDrawTarget; }
-  bool ReturnAndUseDT(gfx::DrawTarget* aDT) { MOZ_ASSERT(mDrawTarget == aDT); return true; }
+  already_AddRefed<gfx::DrawTarget> GetDT(const gfx::IntRect& aPersistedRect) {
+    RefPtr<gfx::DrawTarget> dt(mDrawTarget);
+    return dt.forget();
+  }
+  bool ReturnAndUseDT(already_AddRefed<gfx::DrawTarget> aDT) {
+    RefPtr<gfx::DrawTarget> dt(aDT);
+    MOZ_ASSERT(mDrawTarget == dt);
+    return true;
+  }
   virtual already_AddRefed<gfx::SourceSurface> GetSnapshot() { return mDrawTarget->Snapshot(); }
 private:
   RefPtr<gfx::DrawTarget> mDrawTarget;
 };
 
 } // namespace layers
 } // namespace mozilla
 
--- a/gfx/layers/apz/src/APZCTreeManager.cpp
+++ b/gfx/layers/apz/src/APZCTreeManager.cpp
@@ -1046,19 +1046,21 @@ APZCTreeManager::ProcessMouseEvent(Widge
 }
 
 nsEventStatus
 APZCTreeManager::ProcessWheelEvent(WidgetWheelEvent& aEvent,
                                    ScrollableLayerGuid* aOutTargetGuid,
                                    uint64_t* aOutInputBlockId)
 {
   ScrollWheelInput::ScrollMode scrollMode = ScrollWheelInput::SCROLLMODE_INSTANT;
-  if ((aEvent.deltaMode == nsIDOMWheelEvent::DOM_DELTA_LINE ||
-       aEvent.deltaMode == nsIDOMWheelEvent::DOM_DELTA_PAGE) &&
-      gfxPrefs::SmoothScrollEnabled() && gfxPrefs::WheelSmoothScrollEnabled())
+  if (gfxPrefs::SmoothScrollEnabled() &&
+      ((aEvent.deltaMode == nsIDOMWheelEvent::DOM_DELTA_LINE &&
+        gfxPrefs::WheelSmoothScrollEnabled()) ||
+       (aEvent.deltaMode == nsIDOMWheelEvent::DOM_DELTA_PAGE &&
+        gfxPrefs::PageSmoothScrollEnabled())))
   {
     scrollMode = ScrollWheelInput::SCROLLMODE_SMOOTH;
   }
 
   ScreenPoint origin(aEvent.refPoint.x, aEvent.refPoint.y);
   ScrollWheelInput input(aEvent.time, aEvent.timeStamp, 0,
                          scrollMode,
                          ScrollWheelInput::DeltaTypeForDeltaMode(aEvent.deltaMode),
--- a/gfx/layers/apz/src/AsyncPanZoomController.cpp
+++ b/gfx/layers/apz/src/AsyncPanZoomController.cpp
@@ -1787,18 +1787,17 @@ nsEventStatus AsyncPanZoomController::On
       ReentrantMonitorAutoEnter lock(mMonitor);
 
       if (mState != WHEEL_SCROLL) {
         CancelAnimation();
         SetState(WHEEL_SCROLL);
 
         nsPoint initialPosition = CSSPoint::ToAppUnits(mFrameMetrics.GetScrollOffset());
         StartAnimation(new WheelScrollAnimation(
-          *this,
-          initialPosition));
+          *this, initialPosition, aEvent.mDeltaType));
       }
 
       nsPoint deltaInAppUnits =
         CSSPoint::ToAppUnits(delta / mFrameMetrics.GetZoom());
       // Cast velocity from ParentLayerPoints/ms to CSSPoints/ms then convert to
       // appunits/second
       nsPoint velocity =
         CSSPoint::ToAppUnits(CSSPoint(mX.GetVelocity(), mY.GetVelocity())) * 1000.0f;
--- a/gfx/layers/apz/src/WheelScrollAnimation.cpp
+++ b/gfx/layers/apz/src/WheelScrollAnimation.cpp
@@ -8,20 +8,23 @@
 
 #include "AsyncPanZoomController.h"
 #include "gfxPrefs.h"
 #include "nsPoint.h"
 
 namespace mozilla {
 namespace layers {
 
-WheelScrollAnimation::WheelScrollAnimation(AsyncPanZoomController& aApzc, const nsPoint& aInitialPosition)
+WheelScrollAnimation::WheelScrollAnimation(AsyncPanZoomController& aApzc,
+                                           const nsPoint& aInitialPosition,
+                                           ScrollWheelInput::ScrollDeltaType aDeltaType)
   : AsyncScrollBase(aInitialPosition)
   , mApzc(aApzc)
   , mFinalDestination(aInitialPosition)
+  , mDeltaType(aDeltaType)
 {
 }
 
 void
 WheelScrollAnimation::Update(TimeStamp aTime, nsPoint aDelta, const nsSize& aCurrentVelocity)
 {
   InitPreferences(aTime);
 
@@ -81,18 +84,31 @@ WheelScrollAnimation::DoSample(FrameMetr
 
 void
 WheelScrollAnimation::InitPreferences(TimeStamp aTime)
 {
   if (!mIsFirstIteration) {
     return;
   }
 
-  mOriginMaxMS = clamped(gfxPrefs::WheelSmoothScrollMaxDurationMs(), 0, 10000);
-  mOriginMinMS = clamped(gfxPrefs::WheelSmoothScrollMinDurationMs(), 0, mOriginMaxMS);
+  switch (mDeltaType) {
+  case ScrollWheelInput::SCROLLDELTA_PAGE:
+    mOriginMaxMS = clamped(gfxPrefs::PageSmoothScrollMaxDurationMs(), 0, 10000);
+    mOriginMinMS = clamped(gfxPrefs::PageSmoothScrollMinDurationMs(), 0, mOriginMaxMS);
+    break;
+  case ScrollWheelInput::SCROLLDELTA_PIXEL:
+    mOriginMaxMS = clamped(gfxPrefs::PixelSmoothScrollMaxDurationMs(), 0, 10000);
+    mOriginMinMS = clamped(gfxPrefs::PixelSmoothScrollMinDurationMs(), 0, mOriginMaxMS);
+    break;
+  case ScrollWheelInput::SCROLLDELTA_LINE:
+  default:
+    mOriginMaxMS = clamped(gfxPrefs::WheelSmoothScrollMaxDurationMs(), 0, 10000);
+    mOriginMinMS = clamped(gfxPrefs::WheelSmoothScrollMinDurationMs(), 0, mOriginMaxMS);
+    break;
+  }
 
   // The pref is 100-based int percentage, while mIntervalRatio is 1-based ratio
   mIntervalRatio = ((double)gfxPrefs::SmoothScrollDurationToIntervalRatio()) / 100.0;
   mIntervalRatio = std::max(1.0, mIntervalRatio);
 
   InitializeHistory(aTime);
 }
 
--- a/gfx/layers/apz/src/WheelScrollAnimation.h
+++ b/gfx/layers/apz/src/WheelScrollAnimation.h
@@ -4,40 +4,44 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_layers_WheelScrollAnimation_h_
 #define mozilla_layers_WheelScrollAnimation_h_
 
 #include "AsyncPanZoomAnimation.h"
 #include "AsyncScrollBase.h"
+#include "InputData.h"
 
 namespace mozilla {
 namespace layers {
 
 class AsyncPanZoomController;
 
 class WheelScrollAnimation
   : public AsyncPanZoomAnimation,
     public AsyncScrollBase
 {
 public:
-  WheelScrollAnimation(AsyncPanZoomController& aApzc, const nsPoint& aInitialPosition);
+  WheelScrollAnimation(AsyncPanZoomController& aApzc,
+                       const nsPoint& aInitialPosition,
+                       ScrollWheelInput::ScrollDeltaType aDeltaType);
 
   bool DoSample(FrameMetrics& aFrameMetrics, const TimeDuration& aDelta) override;
   void Update(TimeStamp aTime, nsPoint aDelta, const nsSize& aCurrentVelocity);
 
   WheelScrollAnimation* AsWheelScrollAnimation() override {
     return this;
   }
 
 private:
   void InitPreferences(TimeStamp aTime);
 
 private:
   AsyncPanZoomController& mApzc;
   nsPoint mFinalDestination;
+  ScrollWheelInput::ScrollDeltaType mDeltaType;
 };
 
 } // namespace layers
 } // namespace mozilla
 
 #endif // mozilla_layers_WheelScrollAnimation_h_
--- a/gfx/layers/apz/test/reftest/reftest.list
+++ b/gfx/layers/apz/test/reftest/reftest.list
@@ -1,17 +1,17 @@
 # The following tests test the async positioning of the scrollbars.
 # Basic root-frame scrollbar with async scrolling
-chaos-mode skip-if(!asyncPan) fuzzy-if(Android,6,8) == async-scrollbar-1-v.html async-scrollbar-1-v-ref.html
-chaos-mode skip-if(!asyncPan) fuzzy-if(Android,6,8) == async-scrollbar-1-h.html async-scrollbar-1-h-ref.html
-chaos-mode skip-if(!asyncPan) fuzzy-if(Android,6,8) == async-scrollbar-1-vh.html async-scrollbar-1-vh-ref.html
-chaos-mode skip-if(!asyncPan) fuzzy-if(Android,6,8) == async-scrollbar-1-v-rtl.html async-scrollbar-1-v-rtl-ref.html
-chaos-mode skip-if(!asyncPan) fuzzy-if(Android,6,8) == async-scrollbar-1-h-rtl.html async-scrollbar-1-h-rtl-ref.html
-chaos-mode skip-if(!asyncPan) fuzzy-if(Android,6,8) == async-scrollbar-1-vh-rtl.html async-scrollbar-1-vh-rtl-ref.html
+skip-if(!asyncPan) fuzzy-if(Android,6,8) == async-scrollbar-1-v.html async-scrollbar-1-v-ref.html
+skip-if(!asyncPan) fuzzy-if(Android,6,8) == async-scrollbar-1-h.html async-scrollbar-1-h-ref.html
+skip-if(!asyncPan) fuzzy-if(Android,6,8) == async-scrollbar-1-vh.html async-scrollbar-1-vh-ref.html
+skip-if(!asyncPan) fuzzy-if(Android,6,8) == async-scrollbar-1-v-rtl.html async-scrollbar-1-v-rtl-ref.html
+skip-if(!asyncPan) fuzzy-if(Android,6,8) == async-scrollbar-1-h-rtl.html async-scrollbar-1-h-rtl-ref.html
+skip-if(!asyncPan) fuzzy-if(Android,6,8) == async-scrollbar-1-vh-rtl.html async-scrollbar-1-vh-rtl-ref.html
 
 # Different async zoom levels. Since the scrollthumb gets async-scaled in the
 # compositor, the border-radius ends of the scrollthumb are going to be a little
 # off, hence the fuzzy-if clauses.
-chaos-mode skip-if(!asyncZoom) fuzzy-if(B2G,98,82) == async-scrollbar-zoom-1.html async-scrollbar-zoom-1-ref.html
-chaos-mode skip-if(!asyncZoom) fuzzy-if(B2G,94,146) == async-scrollbar-zoom-2.html async-scrollbar-zoom-2-ref.html
+skip-if(!asyncZoom) fuzzy-if(B2G,98,82) == async-scrollbar-zoom-1.html async-scrollbar-zoom-1-ref.html
+skip-if(!asyncZoom) fuzzy-if(B2G,94,146) == async-scrollbar-zoom-2.html async-scrollbar-zoom-2-ref.html
 
 # Meta-viewport tag support
-chaos-mode skip-if(!asyncZoom) == initial-scale-1.html initial-scale-1-ref.html
+skip-if(!asyncZoom) == initial-scale-1.html initial-scale-1-ref.html
--- a/gfx/layers/client/ClientTiledPaintedLayer.cpp
+++ b/gfx/layers/client/ClientTiledPaintedLayer.cpp
@@ -23,16 +23,17 @@
 
 namespace mozilla {
 namespace layers {
 
 ClientTiledPaintedLayer::ClientTiledPaintedLayer(ClientLayerManager* const aManager,
                                                ClientLayerManager::PaintedLayerCreationHint aCreationHint)
   : PaintedLayer(aManager, static_cast<ClientLayer*>(this), aCreationHint)
   , mContentClient()
+  , mHaveSingleTiledContentClient(false)
 {
   MOZ_COUNT_CTOR(ClientTiledPaintedLayer);
   mPaintData.mLastScrollOffset = ParentLayerPoint(0, 0);
   mPaintData.mFirstPaint = true;
 }
 
 ClientTiledPaintedLayer::~ClientTiledPaintedLayer()
 {
@@ -406,28 +407,36 @@ ClientTiledPaintedLayer::EndPaint()
 void
 ClientTiledPaintedLayer::RenderLayer()
 {
   LayerManager::DrawPaintedLayerCallback callback =
     ClientManager()->GetPaintedLayerCallback();
   void *data = ClientManager()->GetPaintedLayerCallbackData();
 
   IntSize layerSize = mVisibleRegion.ToUnknownRegion().GetBounds().Size();
-  if (mContentClient && !mContentClient->SupportsLayerSize(layerSize, ClientManager())) {
+  IntSize tileSize(gfxPlatform::GetPlatform()->GetTileWidth(),
+                   gfxPlatform::GetPlatform()->GetTileHeight());
+
+  bool wantSingleTiledContentClient =
+      (mCreationHint == LayerManager::NONE || layerSize <= tileSize) &&
+      SingleTiledContentClient::ClientSupportsLayerSize(layerSize, ClientManager()) &&
+      gfxPrefs::LayersSingleTileEnabled();
+
+  if (mContentClient && mHaveSingleTiledContentClient && !wantSingleTiledContentClient) {
     mContentClient = nullptr;
     mValidRegion.SetEmpty();
   }
 
   if (!mContentClient) {
-    if (mCreationHint == LayerManager::NONE &&
-        SingleTiledContentClient::ClientSupportsLayerSize(layerSize, ClientManager()) &&
-        gfxPrefs::LayersSingleTileEnabled()) {
+    if (wantSingleTiledContentClient) {
       mContentClient = new SingleTiledContentClient(this, ClientManager());
+      mHaveSingleTiledContentClient = true;
     } else {
       mContentClient = new MultiTiledContentClient(this, ClientManager());
+      mHaveSingleTiledContentClient = false;
     }
 
     mContentClient->Connect();
     ClientManager()->AsShadowForwarder()->Attach(mContentClient, this);
     MOZ_ASSERT(mContentClient->GetForwarder());
   }
 
   if (mContentClient->GetTiledBuffer()->HasFormatChanged()) {
--- a/gfx/layers/client/ClientTiledPaintedLayer.h
+++ b/gfx/layers/client/ClientTiledPaintedLayer.h
@@ -128,16 +128,19 @@ private:
 
   /**
    * This causes the paint to be marked as finished, and updates any data
    * necessary to persist until the next paint.
    */
   void EndPaint();
 
   RefPtr<TiledContentClient> mContentClient;
+  // Flag to indicate if mContentClient is a SingleTiledContentClient. This is
+  // only valid when mContentClient is non-null.
+  bool mHaveSingleTiledContentClient;
   nsIntRegion mLowPrecisionValidRegion;
   BasicTiledLayerPaintData mPaintData;
 };
 
 } // namespace layers
 } // namespace mozilla
 
 #endif
--- a/gfx/layers/client/ContentClient.cpp
+++ b/gfx/layers/client/ContentClient.cpp
@@ -68,17 +68,17 @@ ContentClient::CreateContentClient(Compo
       backend != LayersBackend::LAYERS_BASIC) {
     return nullptr;
   }
 
   bool useDoubleBuffering = false;
 
 #ifdef XP_WIN
   if (backend == LayersBackend::LAYERS_D3D11) {
-    useDoubleBuffering = !!gfxWindowsPlatform::GetPlatform()->GetD3D10Device();
+    useDoubleBuffering = gfxWindowsPlatform::GetPlatform()->GetRenderMode() == gfxWindowsPlatform::RENDER_DIRECT2D;
   } else
 #endif
 #ifdef MOZ_WIDGET_GTK
   // We can't use double buffering when using image content with
   // Xrender support on Linux, as ContentHostDoubleBuffered is not
   // suited for direct uploads to the server.
   if (!gfxPlatformGtk::GetPlatform()->UseImageOffscreenSurfaces() ||
       !gfxPlatformGtk::GetPlatform()->UseXRender())
--- a/gfx/layers/client/SingleTiledContentClient.cpp
+++ b/gfx/layers/client/SingleTiledContentClient.cpp
@@ -41,22 +41,16 @@ SingleTiledContentClient::UpdatedBuffer(
 
 /* static */ bool
 SingleTiledContentClient::ClientSupportsLayerSize(const gfx::IntSize& aSize, ClientLayerManager* aManager)
 {
   int32_t maxTextureSize = aManager->GetMaxTextureSize();
   return aSize.width <= maxTextureSize && aSize.height <= maxTextureSize;
 }
 
-bool
-SingleTiledContentClient::SupportsLayerSize(const gfx::IntSize& aSize, ClientLayerManager* aManager) const
-{
-  return ClientSupportsLayerSize(aSize, aManager);
-}
-
 ClientSingleTiledLayerBuffer::ClientSingleTiledLayerBuffer(ClientTiledPaintedLayer* aPaintedLayer,
                                                            CompositableClient* aCompositableClient,
                                                            ClientLayerManager* aManager)
   : ClientTiledLayerBuffer(aPaintedLayer, aCompositableClient)
   , mManager(aManager)
   , mFormat(gfx::SurfaceFormat::UNKNOWN)
 {
 }
--- a/gfx/layers/client/SingleTiledContentClient.h
+++ b/gfx/layers/client/SingleTiledContentClient.h
@@ -122,18 +122,16 @@ public:
 
   virtual void ClearCachedResources() override;
 
   virtual void UpdatedBuffer(TiledBufferType aType) override;
 
   virtual ClientTiledLayerBuffer* GetTiledBuffer() override { return mTiledBuffer; }
   virtual ClientTiledLayerBuffer* GetLowPrecisionTiledBuffer() override { return nullptr; }
 
-  virtual bool SupportsLayerSize(const gfx::IntSize& aSize, ClientLayerManager* aManager) const override;
-
 private:
   RefPtr<ClientSingleTiledLayerBuffer> mTiledBuffer;
 };
 
 }
 }
 
 #endif
--- a/gfx/layers/client/TiledContentClient.h
+++ b/gfx/layers/client/TiledContentClient.h
@@ -623,19 +623,16 @@ public:
   virtual ClientTiledLayerBuffer* GetLowPrecisionTiledBuffer() = 0;
 
   enum TiledBufferType {
     TILED_BUFFER,
     LOW_PRECISION_TILED_BUFFER
   };
   virtual void UpdatedBuffer(TiledBufferType aType) = 0;
 
-  virtual bool SupportsLayerSize(const gfx::IntSize& aSize, ClientLayerManager* aManager) const
-  { return true; }
-
 private:
   const char* mName;
 };
 
 /**
  * An implementation of TiledContentClient that supports
  * multiple tiles and a low precision buffer.
  */
--- a/gfx/layers/d3d11/TextureD3D11.cpp
+++ b/gfx/layers/d3d11/TextureD3D11.cpp
@@ -248,41 +248,16 @@ D3D11TextureData::~D3D11TextureData()
   if (mDrawTarget) {
     Lock(OpenMode::OPEN_NONE, nullptr);
     mDrawTarget = nullptr;
     Unlock();
   }
 #endif
 }
 
-D3D10TextureData::D3D10TextureData(ID3D10Texture2D* aTexture,
-                 gfx::IntSize aSize, gfx::SurfaceFormat aFormat,
-                 bool aNeedsClear, bool aNeedsClearWhite,
-                 bool aIsForOutOfBandContent)
-: DXGITextureData(aSize, aFormat, aNeedsClear, aNeedsClearWhite, aIsForOutOfBandContent)
-, mTexture(aTexture)
-{
-  MOZ_ASSERT(aTexture);
-  mHasSynchronization = HasKeyedMutex(aTexture);
-}
-
-D3D10TextureData::~D3D10TextureData()
-{
-#ifdef DEBUG
-  // An Azure DrawTarget needs to be locked when it gets nullptr'ed as this is
-  // when it calls EndDraw. This EndDraw should not execute anything so it
-  // shouldn't -really- need the lock but the debug layer chokes on this.
-  if (mDrawTarget) {
-    Lock(OpenMode::OPEN_NONE, nullptr);
-    mDrawTarget = nullptr;
-    Unlock();
-  }
-#endif
-}
-
 bool
 D3D11TextureData::Lock(OpenMode aMode, FenceHandle*)
 {
   if (!LockD3DTexture(mTexture.get())) {
     return false;
   }
 
   if (NS_IsMainThread() && !mIsForOutOfBandContent) {
@@ -291,33 +266,16 @@ D3D11TextureData::Lock(OpenMode aMode, F
       return false;
     }
   }
 
   return true;
 }
 
 bool
-D3D10TextureData::Lock(OpenMode aMode, FenceHandle*)
-{
-  if (!LockD3DTexture(mTexture.get())) {
-    return false;
-  }
-
-  if (NS_IsMainThread() && !mIsForOutOfBandContent) {
-    if (!PrepareDrawTargetInLock(aMode)) {
-      Unlock();
-      return false;
-    }
-  }
-
-  return true;
-}
-
-bool
 DXGITextureData::PrepareDrawTargetInLock(OpenMode aMode)
 {
   // Make sure that successful write-lock means we will have a DrawTarget to
   // write into.
   if (!mDrawTarget && (aMode & OpenMode::OPEN_WRITE || mNeedsClear || mNeedsClearWhite)) {
     mDrawTarget = BorrowDrawTarget();
     if (!mDrawTarget) {
       return false;
@@ -338,47 +296,28 @@ DXGITextureData::PrepareDrawTargetInLock
 
 void
 D3D11TextureData::Unlock()
 {
   UnlockD3DTexture(mTexture.get());
 }
 
 void
-D3D10TextureData::Unlock()
-{
-  UnlockD3DTexture(mTexture.get());
-}
-
-void
 D3D11TextureData::SyncWithObject(SyncObject* aSyncObject)
 {
   if (!aSyncObject || !NS_IsMainThread() || mIsForOutOfBandContent) {
     // When off the main thread we sync using a keyed mutex per texture.
     return;
   }
 
   MOZ_ASSERT(aSyncObject->GetSyncType() == SyncObject::SyncType::D3D11);
   SyncObjectD3D11* sync = static_cast<SyncObjectD3D11*>(aSyncObject);
   sync->RegisterTexture(mTexture);
 }
 
-void
-D3D10TextureData::SyncWithObject(SyncObject* aSyncObject)
-{
-  if (!aSyncObject || !NS_IsMainThread()) {
-    // When off the main thread we sync using a keyed mutex per texture.
-    return;
-  }
-
-  MOZ_ASSERT(aSyncObject->GetSyncType() == SyncObject::SyncType::D3D11);
-  SyncObjectD3D11* sync = static_cast<SyncObjectD3D11*>(aSyncObject);
-  sync->RegisterTexture(mTexture);
-}
-
 bool
 DXGITextureData::Serialize(SurfaceDescriptor& aOutDescriptor)
 {
   RefPtr<IDXGIResource> resource;
   GetDXGIResource((IDXGIResource**)getter_AddRefs(resource));
   if (!resource) {
     return false;
   }
@@ -388,65 +327,25 @@ DXGITextureData::Serialize(SurfaceDescri
     LOGD3D11("Error getting shared handle for texture.");
     return false;
   }
 
   aOutDescriptor = SurfaceDescriptorD3D10((WindowsHandle)sharedHandle, mFormat, mSize);
   return true;
 }
 
-bool
-D3D10TextureData::ReadBack(TextureReadbackSink* aReadbackSinc)
-{
-  if (NS_IsMainThread() && aReadbackSinc && mTexture) {
-    ID3D10Device* device = gfxWindowsPlatform::GetPlatform()->GetD3D10Device();
-
-    D3D10_TEXTURE2D_DESC desc;
-    mTexture->GetDesc(&desc);
-    desc.BindFlags = 0;
-    desc.Usage = D3D10_USAGE_STAGING;
-    desc.CPUAccessFlags = D3D10_CPU_ACCESS_READ;
-    desc.MiscFlags = 0;
-
-    RefPtr<ID3D10Texture2D> tex;
-    HRESULT hr = device->CreateTexture2D(&desc, nullptr, getter_AddRefs(tex));
-
-    if (SUCCEEDED(hr)) {
-      device->CopyResource(tex, mTexture);
-      gfxWindowsPlatform::GetPlatform()->GetReadbackManager()->PostTask(tex, aReadbackSinc);
-    } else {
-      gfxCriticalError(CriticalLog::DefaultOptions(Factory::ReasonableSurfaceSize(mSize))) << "[D3D11] CreateTexture2D failure " << mSize << " Code: " << gfx::hexa(hr);
-      aReadbackSinc->ProcessReadback(nullptr);
-    }
-  }
-
-  return true;
-}
-
 DXGITextureData*
 DXGITextureData::Create(IntSize aSize, SurfaceFormat aFormat, TextureAllocationFlags aFlags)
 {
   if (aFormat == SurfaceFormat::A8) {
     // Currently we don't support A8 surfaces. Fallback.
     return nullptr;
   }
 
-  gfxWindowsPlatform* windowsPlatform = gfxWindowsPlatform::GetPlatform();
-  // When we're not on the main thread we're not going to be using Direct2D
-  // to access the contents of this texture client so we will always use D3D11.
-  bool useD3D11 =
-    windowsPlatform->GetContentBackendFor(LayersBackend::LAYERS_D3D11) == BackendType::DIRECT2D1_1 ||
-    !NS_IsMainThread() ||
-    (aFlags & ALLOC_FOR_OUT_OF_BAND_CONTENT);
-
-  if (useD3D11) {
-    return D3D11TextureData::Create(aSize, aFormat, aFlags);
-  } else {
-    return D3D10TextureData::Create(aSize, aFormat, aFlags);
-  }
+  return D3D11TextureData::Create(aSize, aFormat, aFlags);
 }
 
 DXGITextureData*
 D3D11TextureData::Create(IntSize aSize, SurfaceFormat aFormat, TextureAllocationFlags aFlags,
                          ID3D11Device* aDevice)
 {
   RefPtr<ID3D11Texture2D> texture11;
   ID3D11Device* d3d11device = aDevice ? aDevice
@@ -502,69 +401,22 @@ CreateD3D11TextureClientWithDevice(IntSi
 TextureData*
 D3D11TextureData::CreateSimilar(ISurfaceAllocator* aAllocator,
                                 TextureFlags aFlags,
                                 TextureAllocationFlags aAllocFlags) const
 {
   return D3D11TextureData::Create(mSize, mFormat, aAllocFlags);
 }
 
-DXGITextureData*
-D3D10TextureData::Create(IntSize aSize, SurfaceFormat aFormat, TextureAllocationFlags aFlags)
-{
-  RefPtr<ID3D10Texture2D> texture10;
-  ID3D10Device* device = gfxWindowsPlatform::GetPlatform()->GetD3D10Device();
-
-  CD3D10_TEXTURE2D_DESC newDesc(DXGI_FORMAT_B8G8R8A8_UNORM,
-    aSize.width, aSize.height, 1, 1,
-    D3D10_BIND_RENDER_TARGET | D3D10_BIND_SHADER_RESOURCE);
-
-  newDesc.MiscFlags = D3D10_RESOURCE_MISC_SHARED;
-
-  HRESULT hr = device->CreateTexture2D(&newDesc, nullptr, getter_AddRefs(texture10));
-  if (FAILED(hr)) {
-    gfxCriticalError(CriticalLog::DefaultOptions(Factory::ReasonableSurfaceSize(aSize)))
-      << "[D3D10] 2 CreateTexture2D failure " << aSize << " Code: " << gfx::hexa(hr);
-    return nullptr;
-  }
-  texture10->SetPrivateDataInterface(sD3D11TextureUsage,
-                                     new TextureMemoryMeasurer(newDesc.Width * newDesc.Height * 4));
-
-  return new D3D10TextureData(texture10, aSize, aFormat,
-                              aFlags & ALLOC_CLEAR_BUFFER,
-                              aFlags & ALLOC_CLEAR_BUFFER_WHITE,
-                              false /* aIsForOutOfBandContent */);
-}
-
-void
-D3D10TextureData::Deallocate(ISurfaceAllocator* aAllocator)
-{
-  mTexture = nullptr;
-}
-
-TextureData*
-D3D10TextureData::CreateSimilar(ISurfaceAllocator* aAllocator,
-                                TextureFlags aFlags,
-                                TextureAllocationFlags aAllocFlags) const
-{
-  return D3D10TextureData::Create(mSize, mFormat, aAllocFlags);
-}
-
 void
 D3D11TextureData::GetDXGIResource(IDXGIResource** aOutResource)
 {
   mTexture->QueryInterface(aOutResource);
 }
 
-void
-D3D10TextureData::GetDXGIResource(IDXGIResource** aOutResource)
-{
-  mTexture->QueryInterface(aOutResource);
-}
-
 DXGIYCbCrTextureData*
 DXGIYCbCrTextureData::Create(ISurfaceAllocator* aAllocator,
                              TextureFlags aFlags,
                              IUnknown* aTextureY,
                              IUnknown* aTextureCb,
                              IUnknown* aTextureCr,
                              HANDLE aHandleY,
                              HANDLE aHandleCb,
@@ -703,33 +555,16 @@ D3D11TextureData::BorrowDrawTarget()
       gfxCriticalNote << "Could not borrow DrawTarget (D3D11) " << (int)mFormat;
     }
   }
 
   RefPtr<DrawTarget> result = mDrawTarget;
   return result.forget();
 }
 
-already_AddRefed<DrawTarget>
-D3D10TextureData::BorrowDrawTarget()
-{
-  MOZ_ASSERT(NS_IsMainThread());
-
-  if (!mDrawTarget && mTexture) {
-    // This may return a null DrawTarget
-    mDrawTarget = Factory::CreateDrawTargetForD3D10Texture(mTexture, mFormat);
-    if (!mDrawTarget) {
-      gfxCriticalNote << "Could not borrow DrawTarget (D3D10) " << (int)mFormat;
-    }
-  }
-
-  RefPtr<DrawTarget> result = mDrawTarget;
-  return result.forget();
-}
-
 bool
 D3D11TextureData::UpdateFromSurface(gfx::SourceSurface* aSurface)
 {
   RefPtr<DataSourceSurface> srcSurf = aSurface->GetDataSurface();
 
   if (!srcSurf) {
     gfxCriticalError() << "Failed to GetDataSurface in UpdateFromSurface (D3D11).";
     return false;
@@ -753,49 +588,16 @@ D3D11TextureData::UpdateFromSurface(gfx:
   box.right = aSurface->GetSize().width;
   box.bottom = aSurface->GetSize().height;
   ctx->UpdateSubresource(mTexture, 0, &box, sourceMap.mData, sourceMap.mStride, 0);
   srcSurf->Unmap();
 
   return true;
 }
 
-bool
-D3D10TextureData::UpdateFromSurface(gfx::SourceSurface* aSurface)
-{
-  RefPtr<DataSourceSurface> srcSurf = aSurface->GetDataSurface();
-
-  if (!srcSurf) {
-    gfxCriticalError() << "Failed to GetDataSurface in UpdateFromSurface (D3D10).";
-    return false;
-  }
-
-  DataSourceSurface::MappedSurface sourceMap;
-  if (!srcSurf->Map(DataSourceSurface::READ, &sourceMap)) {
-    gfxCriticalError() << "Failed to map source surface for UpdateFromSurface (D3D10).";
-    return false;
-  }
-
-  RefPtr<ID3D10Device> device;
-  mTexture->GetDevice(getter_AddRefs(device));
-
-  D3D10_BOX box;
-  box.front = 0;
-  box.back = 1;
-  box.top = box.left = 0;
-  box.right = aSurface->GetSize().width;
-  box.bottom = aSurface->GetSize().height;
-
-  device->UpdateSubresource(mTexture, 0, &box, sourceMap.mData, sourceMap.mStride, 0);
-
-  srcSurf->Unmap();
-
-  return true;
-}
-
 DXGITextureHostD3D11::DXGITextureHostD3D11(TextureFlags aFlags,
                                            const SurfaceDescriptorD3D10& aDescriptor)
   : TextureHost(aFlags)
   , mSize(aDescriptor.size())
   , mHandle(aDescriptor.handle())
   , mFormat(aDescriptor.format())
   , mIsLocked(false)
 {
@@ -1223,56 +1025,20 @@ SyncObjectD3D11::SyncObjectD3D11(SyncHan
 
 void
 SyncObjectD3D11::RegisterTexture(ID3D11Texture2D* aTexture)
 {
   mD3D11SyncedTextures.push_back(aTexture);
 }
 
 void
-SyncObjectD3D11::RegisterTexture(ID3D10Texture2D* aTexture)
-{
-  mD3D10SyncedTextures.push_back(aTexture);
-}
-
-void
 SyncObjectD3D11::FinalizeFrame()
 {
   HRESULT hr;
 
-  if (!mD3D10Texture && mD3D10SyncedTextures.size()) {
-    ID3D10Device* device = gfxWindowsPlatform::GetPlatform()->GetD3D10Device();
-    if (!device) {
-      return;
-    }
-
-    hr = device->OpenSharedResource(mHandle, __uuidof(ID3D10Texture2D), (void**)(ID3D10Texture2D**)getter_AddRefs(mD3D10Texture));
-
-    if (FAILED(hr) || !mD3D10Texture) {
-      gfxCriticalError() << "Failed to D3D10 OpenSharedResource for frame finalization: " << hexa(hr);
-
-      if (gfxWindowsPlatform::GetPlatform()->DidRenderingDeviceReset()) {
-        return;
-      }
-
-      gfxDevCrash(LogReason::D3D10FinalizeFrame) << "Without device reset: " << hexa(hr);
-    }
-
-    // test QI
-    RefPtr<IDXGIKeyedMutex> mutex;
-    hr = mD3D10Texture->QueryInterface((IDXGIKeyedMutex**)getter_AddRefs(mutex));
-
-    if (FAILED(hr) || !mutex) {
-      // Leave both the critical error and MOZ_CRASH for now; the critical error lets
-      // us "save" the hr value.  We will probably eventuall replace this with gfxDevCrash.
-      gfxCriticalError() << "Failed to get KeyedMutex (1): " << hexa(hr);
-      MOZ_CRASH("GFX: Cannot get D3D10 KeyedMutex");
-    }
-  }
-
   if (!mD3D11Texture && mD3D11SyncedTextures.size()) {
     ID3D11Device* device = gfxWindowsPlatform::GetPlatform()->GetD3D11ContentDevice();
 
     hr = device->OpenSharedResource(mHandle, __uuidof(ID3D11Texture2D), (void**)(ID3D11Texture2D**)getter_AddRefs(mD3D11Texture));
 
     if (FAILED(hr) || !mD3D11Texture) {
       gfxCriticalError() << "Failed to D3D11 OpenSharedResource for frame finalization: " << hexa(hr);
 
@@ -1290,47 +1056,16 @@ SyncObjectD3D11::FinalizeFrame()
     if (FAILED(hr) || !mutex) {
       // Leave both the critical error and MOZ_CRASH for now; the critical error lets
       // us "save" the hr value.  We will probably eventuall replace this with gfxDevCrash.
       gfxCriticalError() << "Failed to get KeyedMutex (2): " << hexa(hr);
       MOZ_CRASH("GFX: Cannot get D3D11 KeyedMutex");
     }
   }
 
-  if (mD3D10SyncedTextures.size()) {
-    RefPtr<IDXGIKeyedMutex> mutex;
-    hr = mD3D10Texture->QueryInterface((IDXGIKeyedMutex**)getter_AddRefs(mutex));
-    hr = mutex->AcquireSync(0, 20000);
-
-    if (hr == WAIT_TIMEOUT) {
-      if (gfxWindowsPlatform::GetPlatform()->DidRenderingDeviceReset()) {
-        gfxWarning() << "AcquireSync timed out because of device reset.";
-        return;
-      }
-      gfxDevCrash(LogReason::D3D10SyncLock) << "Timeout on the D3D10 sync lock";
-    }
-
-    D3D10_BOX box;
-    box.front = box.top = box.left = 0;
-    box.back = box.bottom = box.right = 1;
-
-    ID3D10Device* device = gfxWindowsPlatform::GetPlatform()->GetD3D10Device();
-    if (!device) {
-      return;
-    }
-
-    for (auto iter = mD3D10SyncedTextures.begin(); iter != mD3D10SyncedTextures.end(); iter++) {
-      device->CopySubresourceRegion(mD3D10Texture, 0, 0, 0, 0, *iter, 0, &box);
-    }
-
-    mutex->ReleaseSync(0);
-
-    mD3D10SyncedTextures.clear();
-  }
-
   if (mD3D11SyncedTextures.size()) {
     RefPtr<IDXGIKeyedMutex> mutex;
     hr = mD3D11Texture->QueryInterface((IDXGIKeyedMutex**)getter_AddRefs(mutex));
     hr = mutex->AcquireSync(0, 20000);
 
     if (hr == WAIT_TIMEOUT) {
       if (gfxWindowsPlatform::GetPlatform()->DidRenderingDeviceReset()) {
         gfxWarning() << "AcquireSync timed out because of device reset.";
--- a/gfx/layers/d3d11/TextureD3D11.h
+++ b/gfx/layers/d3d11/TextureD3D11.h
@@ -104,55 +104,16 @@ protected:
 };
 
 already_AddRefed<TextureClient>
 CreateD3D11extureClientWithDevice(gfx::IntSize aSize, gfx::SurfaceFormat aFormat,
                                   TextureFlags aTextureFlags, TextureAllocationFlags aAllocFlags,
                                   ID3D11Device* aDevice,
                                   ISurfaceAllocator* aAllocator);
 
-
-class D3D10TextureData : public DXGITextureData
-{
-public:
-  static DXGITextureData*
-  Create(gfx::IntSize aSize, gfx::SurfaceFormat aFormat, TextureAllocationFlags aFlags);
-
-  virtual bool Lock(OpenMode aMode, FenceHandle*) override;
-
-  virtual void Unlock() override;
-
-  virtual bool UpdateFromSurface(gfx::SourceSurface* aSurface) override;
-
-  virtual already_AddRefed<gfx::DrawTarget> BorrowDrawTarget() override;
-
-  virtual TextureData*
-  CreateSimilar(ISurfaceAllocator* aAllocator,
-                TextureFlags aFlags,
-                TextureAllocationFlags aAllocFlags) const override;
-
-  // TODO - merge this with the FenceHandle API!
-  virtual void SyncWithObject(SyncObject* aSync) override;
-
-  virtual bool ReadBack(TextureReadbackSink* aReadbackSinc) override;
-
-  virtual void Deallocate(ISurfaceAllocator* aAllocator) override;
-
-  ~D3D10TextureData();
-protected:
-  D3D10TextureData(ID3D10Texture2D* aTexture,
-                   gfx::IntSize aSize, gfx::SurfaceFormat aFormat,
-                   bool aNeedsClear, bool aNeedsClearWhite,
-                   bool aIsForOutOfBandContent);
-
-  virtual void GetDXGIResource(IDXGIResource** aOutResource) override;
-
-  RefPtr<ID3D10Texture2D> mTexture;
-};
-
 class DXGIYCbCrTextureData : public TextureData
 {
 public:
   static DXGIYCbCrTextureData*
   Create(ISurfaceAllocator* aAllocator,
          TextureFlags aFlags,
          IUnknown* aTextureY,
          IUnknown* aTextureCb,
@@ -426,22 +387,19 @@ class SyncObjectD3D11 : public SyncObjec
 {
 public:
   SyncObjectD3D11(SyncHandle aSyncHandle);
   virtual void FinalizeFrame();
 
   virtual SyncType GetSyncType() { return SyncType::D3D11; }
 
   void RegisterTexture(ID3D11Texture2D* aTexture);
-  void RegisterTexture(ID3D10Texture2D* aTexture);
 
 private:
   RefPtr<ID3D11Texture2D> mD3D11Texture;
-  RefPtr<ID3D10Texture2D> mD3D10Texture;
-  std::vector<ID3D10Texture2D*> mD3D10SyncedTextures;
   std::vector<ID3D11Texture2D*> mD3D11SyncedTextures;
   SyncHandle mHandle;
 };
 
 inline uint32_t GetMaxTextureSizeForFeatureLevel(D3D_FEATURE_LEVEL aFeatureLevel)
 {
   int32_t maxTextureSize;
   switch (aFeatureLevel) {
--- a/gfx/src/nsDeviceContext.cpp
+++ b/gfx/src/nsDeviceContext.cpp
@@ -717,8 +717,23 @@ nsDeviceContext::SetFullZoom(float aScal
 void
 nsDeviceContext::UpdateAppUnitsForFullZoom()
 {
     mAppUnitsPerDevPixel =
         std::max(1, NSToIntRound(float(mAppUnitsPerDevPixelAtUnitFullZoom) / mFullZoom));
     // adjust mFullZoom to reflect appunit rounding
     mFullZoom = float(mAppUnitsPerDevPixelAtUnitFullZoom) / mAppUnitsPerDevPixel;
 }
+
+DesktopToLayoutDeviceScale
+nsDeviceContext::GetDesktopToDeviceScale()
+{
+    nsCOMPtr<nsIScreen> screen;
+    FindScreen(getter_AddRefs(screen));
+
+    if (screen) {
+        double scale;
+        screen->GetContentsScaleFactor(&scale);
+        return DesktopToLayoutDeviceScale(scale);
+    }
+
+    return DesktopToLayoutDeviceScale(1.0);
+}
--- a/gfx/src/nsDeviceContext.h
+++ b/gfx/src/nsDeviceContext.h
@@ -246,16 +246,18 @@ public:
      */
     float GetFullZoom() const { return mFullZoom; }
 
     /**
      * True if this device context was created for printing.
      */
     bool IsPrinterSurface();
 
+    mozilla::DesktopToLayoutDeviceScale GetDesktopToDeviceScale();
+
 private:
     // Private destructor, to discourage deletion outside of Release():
     ~nsDeviceContext();
 
     void SetDPI();
     void ComputeClientRectUsingScreen(nsRect *outRect);
     void ComputeFullAreaUsingScreen(nsRect *outRect);
     void FindScreen(nsIScreen **outScreen);
--- a/gfx/src/nsRegion.cpp
+++ b/gfx/src/nsRegion.cpp
@@ -733,23 +733,34 @@ nsIntRegion nsRegion::ScaleToNearestPixe
     result.Or(result, deviceRect);
   }
   return result;
 }
 
 nsIntRegion nsRegion::ScaleToOutsidePixels (float aScaleX, float aScaleY,
                                             nscoord aAppUnitsPerPixel) const
 {
-  nsIntRegion result;
-  for (auto iter = RectIter(); !iter.Done(); iter.Next()) {
-    mozilla::gfx::IntRect deviceRect =
-      iter.Get().ScaleToOutsidePixels(aScaleX, aScaleY, aAppUnitsPerPixel);
-    result.Or(result, deviceRect);
+  // make a copy of the region so that we can mutate it inplace
+  nsRegion region = *this;
+  int n;
+  pixman_box32_t *boxes = pixman_region32_rectangles(&region.mImpl, &n);
+  boxes = pixman_region32_rectangles(&region.mImpl, &n);
+  for (int i=0; i<n; i++) {
+    nsRect rect = BoxToRect(boxes[i]);
+    mozilla::gfx::IntRect irect = rect.ScaleToOutsidePixels(aScaleX, aScaleY, aAppUnitsPerPixel);
+    boxes[i] = RectToBox(irect);
   }
-  return result;
+
+  nsIntRegion iRegion;
+  // clear out the initial pixman_region so that we can replace it below
+  pixman_region32_fini(&iRegion.mImpl.mImpl);
+  // This will union all of the rectangles and runs in about O(n lg(n))
+  pixman_region32_init_rects(&iRegion.mImpl.mImpl, boxes, n);
+
+  return iRegion;
 }
 
 nsIntRegion nsRegion::ScaleToInsidePixels (float aScaleX, float aScaleY,
                                            nscoord aAppUnitsPerPixel) const
 {
   /* When scaling a rect, walk forward through the rect list up until the y value is greater
    * than the current rect's YMost() value.
    *
--- a/gfx/thebes/gfxBlur.cpp
+++ b/gfx/thebes/gfxBlur.cpp
@@ -589,17 +589,17 @@ RepeatOrStretchSurface(DrawTarget& aDT, 
                        const Rect& aDest, const Rect& aSrc, Rect& aSkipRect)
 {
   if (aSkipRect.Contains(aDest)) {
     return;
   }
 
   if ((!aDT.GetTransform().IsRectilinear() &&
        aDT.GetBackendType() != BackendType::CAIRO) ||
-      (aDT.GetBackendType() == BackendType::DIRECT2D)) {
+      (aDT.GetBackendType() == BackendType::DIRECT2D1_1)) {
     // Use stretching if possible, since it leads to less seams when the
     // destination is transformed. However, don't do this if we're using cairo,
     // because if cairo is using pixman it won't render anything for large
     // stretch factors because pixman's internal fixed point precision is not
     // high enough to handle those scale factors.
     // Calling FillRect on a D2D backend with a repeating pattern is much slower
     // than DrawSurface, so special case the D2D backend here.
     aDT.DrawSurface(aSurface, aDest, aSrc);
--- a/gfx/thebes/gfxPlatform.cpp
+++ b/gfx/thebes/gfxPlatform.cpp
@@ -267,17 +267,17 @@ CrashStatsLogForwarder::UpdateStringsVec
   }
   return true;
 }
 
 void CrashStatsLogForwarder::UpdateCrashReport()
 {
   std::stringstream message;
   for(LoggingRecord::iterator it = mBuffer.begin(); it != mBuffer.end(); ++it) {
-    message << "|[" << Get<0>(*it) << "]" << Get<1>(*it) << " (t=" << Get<2>(*it) << ")";
+    message << "|[" << Get<0>(*it) << "]" << Get<1>(*it) << " (t=" << Get<2>(*it) << ") ";
   }
 
 #ifdef MOZ_CRASHREPORTER
   nsCString reportString(message.str().c_str());
   nsresult annotated = CrashReporter::AnnotateCrashReport(mCrashCriticalKey, reportString);
 #else
   nsresult annotated = NS_ERROR_NOT_IMPLEMENTED;
 #endif
--- a/gfx/thebes/gfxPrefs.h
+++ b/gfx/thebes/gfxPrefs.h
@@ -207,16 +207,26 @@ private:
                 SmoothScrollCurrentVelocityWeighting, float, 0.25);
   DECL_GFX_PREF(Live, "general.smoothScroll.durationToIntervalRatio",
                 SmoothScrollDurationToIntervalRatio, int32_t, 200);
   DECL_GFX_PREF(Live, "general.smoothScroll.mouseWheel",       WheelSmoothScrollEnabled, bool, true);
   DECL_GFX_PREF(Live, "general.smoothScroll.mouseWheel.durationMaxMS",
                 WheelSmoothScrollMaxDurationMs, int32_t, 400);
   DECL_GFX_PREF(Live, "general.smoothScroll.mouseWheel.durationMinMS",
                 WheelSmoothScrollMinDurationMs, int32_t, 200);
+  DECL_GFX_PREF(Live, "general.smoothScroll.pages",            PageSmoothScrollEnabled, bool, true);
+  DECL_GFX_PREF(Live, "general.smoothScroll.pages.durationMaxMS",
+                PageSmoothScrollMaxDurationMs, int32_t, 150);
+  DECL_GFX_PREF(Live, "general.smoothScroll.pages.durationMinMS",
+                PageSmoothScrollMinDurationMs, int32_t, 150);
+  DECL_GFX_PREF(Live, "general.smoothScroll.pixels",           PixelSmoothScrollEnabled, bool, true);
+  DECL_GFX_PREF(Live, "general.smoothScroll.pixels.durationMaxMS",
+                PixelSmoothScrollMaxDurationMs, int32_t, 150);
+  DECL_GFX_PREF(Live, "general.smoothScroll.pixels.durationMinMS",
+                PixelSmoothScrollMinDurationMs, int32_t, 150);
   DECL_GFX_PREF(Live, "general.smoothScroll.stopDecelerationWeighting",
                 SmoothScrollStopDecelerationWeighting, float, 0.4f);
 
   DECL_GFX_PREF(Once, "gfx.android.rgb16.force",               AndroidRGB16Force, bool, false);
 #if defined(ANDROID)
   DECL_GFX_PREF(Once, "gfx.apitrace.enabled",                  UseApitrace, bool, false);
 #endif
 #if defined(RELEASE_BUILD)
@@ -237,26 +247,24 @@ private:
 
   DECL_GFX_PREF(Live, "gfx.color_management.enablev4",         CMSEnableV4, bool, false);
   DECL_GFX_PREF(Live, "gfx.color_management.mode",             CMSMode, int32_t,-1);
   // The zero default here should match QCMS_INTENT_DEFAULT from qcms.h
   DECL_GFX_PREF(Live, "gfx.color_management.rendering_intent", CMSRenderingIntent, int32_t, 0);
 
   DECL_GFX_PREF(Once, "gfx.direct2d.disabled",                 Direct2DDisabled, bool, false);
   DECL_GFX_PREF(Once, "gfx.direct2d.force-enabled",            Direct2DForceEnabled, bool, false);
-  DECL_GFX_PREF(Live, "gfx.direct2d.use1_1",                   Direct2DUse1_1, bool, false);
-  DECL_GFX_PREF(Live, "gfx.direct2d.allow1_0",                 Direct2DAllow1_0, bool, false);
   DECL_GFX_PREF(Live, "gfx.draw-color-bars",                   CompositorDrawColorBars, bool, false);
   DECL_GFX_PREF(Once, "gfx.e10s.hide-plugins-for-scroll",      HidePluginsForScroll, bool, true);
   DECL_GFX_PREF(Once, "gfx.font_rendering.directwrite.force-enabled", DirectWriteFontRenderingForceEnabled, bool, false);
   DECL_GFX_PREF(Live, "gfx.gralloc.fence-with-readpixels",     GrallocFenceWithReadPixels, bool, false);
   DECL_GFX_PREF(Live, "gfx.layerscope.enabled",                LayerScopeEnabled, bool, false);
   DECL_GFX_PREF(Live, "gfx.layerscope.port",                   LayerScopePort, int32_t, 23456);
   // Note that        "gfx.logging.level" is defined in Logging.h
-  DECL_GFX_PREF(Once, "gfx.logging.crash.length",              GfxLoggingCrashLength, uint32_t, 6);
+  DECL_GFX_PREF(Once, "gfx.logging.crash.length",              GfxLoggingCrashLength, uint32_t, 16);
   // The maximums here are quite conservative, we can tighten them if problems show up.
   DECL_GFX_PREF(Once, "gfx.max-alloc-size",                    MaxAllocSize, int32_t, (int32_t)500000000);
   DECL_GFX_PREF(Once, "gfx.max-texture-size",                  MaxTextureSize, int32_t, (int32_t)32767);
   DECL_GFX_PREF(Live, "gfx.partialpresent.force",              PartialPresent, int32_t, 0);
   DECL_GFX_PREF(Live, "gfx.perf-warnings.enabled",             PerfWarnings, bool, false);
   DECL_GFX_PREF(Live, "gfx.SurfaceTexture.detach.enabled",     SurfaceTextureDetachEnabled, bool, true);
   DECL_GFX_PREF(Live, "gfx.testing.device-reset",              DeviceResetForTesting, int32_t, 0);
   DECL_GFX_PREF(Live, "gfx.testing.device-fail",               DeviceFailForTesting, bool, false);
--- a/gfx/thebes/gfxUtils.cpp
+++ b/gfx/thebes/gfxUtils.cpp
@@ -417,18 +417,17 @@ CreateSamplingRestrictedDrawable(gfxDraw
                                  gfxContext* aContext,
                                  const ImageRegion& aRegion,
                                  const SurfaceFormat aFormat)
 {
     PROFILER_LABEL("gfxUtils", "CreateSamplingRestricedDrawable",
       js::ProfileEntry::Category::GRAPHICS);
 
     DrawTarget* destDrawTarget = aContext->GetDrawTarget();
-    if ((destDrawTarget->GetBackendType() == BackendType::DIRECT2D1_1) ||
-        (destDrawTarget->GetBackendType() == BackendType::DIRECT2D)) {
+    if (destDrawTarget->GetBackendType() == BackendType::DIRECT2D1_1) {
       return nullptr;
     }
 
     gfxRect clipExtents = aContext->GetClipExtents();
 
     // Inflate by one pixel because bilinear filtering will sample at most
     // one pixel beyond the computed image pixel coordinate.
     clipExtents.Inflate(1.0);
--- a/gfx/thebes/gfxWindowsPlatform.cpp
+++ b/gfx/thebes/gfxWindowsPlatform.cpp
@@ -38,37 +38,33 @@
 #include "gfxGDIFont.h"
 
 #include "mozilla/layers/CompositorParent.h"   // for CompositorParent::IsInCompositorThread
 #include "DeviceManagerD3D9.h"
 #include "mozilla/layers/ReadbackManagerD3D11.h"
 
 #include "WinUtils.h"
 
-#ifdef CAIRO_HAS_DWRITE_FONT
 #include "gfxDWriteFontList.h"
 #include "gfxDWriteFonts.h"
 #include "gfxDWriteCommon.h"
 #include <dwrite.h>
-#endif
 
 #include "gfxTextRun.h"
 #include "gfxUserFontSet.h"
 #include "nsWindowsHelpers.h"
 #include "gfx2DGlue.h"
 
 #include <string>
 
-#ifdef CAIRO_HAS_D2D_SURFACE
 #include <d3d10_1.h>
 
 #include "mozilla/gfx/2D.h"
 
 #include "nsMemory.h"
-#endif
 
 #include <d3d11.h>
 
 #include "nsIMemoryReporter.h"
 #include <winternl.h>
 #include "d3dkmtQueryStatistics.h"
 
 #include "SurfaceCache.h"
@@ -109,24 +105,21 @@ DCFromDrawTarget::DCFromDrawTarget(DrawT
   if (!mDC) {
     // Get the whole screen DC:
     mDC = GetDC(nullptr);
     SetGraphicsMode(mDC, GM_ADVANCED);
     mNeedsRelease = true;
   }
 }
 
-#ifdef CAIRO_HAS_D2D_SURFACE
-
 static const char *kFeatureLevelPref =
   "gfx.direct3d.last_used_feature_level_idx";
 static const int kSupportedFeatureLevels[] =
   { D3D10_FEATURE_LEVEL_10_1, D3D10_FEATURE_LEVEL_10_0 };
 
-#endif
 
 class GfxD2DVramReporter final : public nsIMemoryReporter
 {
     ~GfxD2DVramReporter() {}
 
 public:
     NS_DECL_ISUPPORTS
 
@@ -161,26 +154,26 @@ NS_IMPL_ISUPPORTS(GfxD2DVramReporter, ns
 #define GFX_CLEARTYPE_PARAMS_CONTRAST  "gfx.font_rendering.cleartype_params.enhanced_contrast"
 #define GFX_CLEARTYPE_PARAMS_LEVEL     "gfx.font_rendering.cleartype_params.cleartype_level"
 #define GFX_CLEARTYPE_PARAMS_STRUCTURE "gfx.font_rendering.cleartype_params.pixel_structure"
 #define GFX_CLEARTYPE_PARAMS_MODE      "gfx.font_rendering.cleartype_params.rendering_mode"
 
 class GPUAdapterReporter final : public nsIMemoryReporter
 {
     // Callers must Release the DXGIAdapter after use or risk mem-leak
-    static bool GetDXGIAdapter(IDXGIAdapter **DXGIAdapter)
+    static bool GetDXGIAdapter(IDXGIAdapter **aDXGIAdapter)
     {
-        ID3D10Device1 *D2D10Device;
-        IDXGIDevice *DXGIDevice;
+        ID3D11Device *d3d11Device;
+        IDXGIDevice *dxgiDevice;
         bool result = false;
 
-        if ((D2D10Device = mozilla::gfx::Factory::GetDirect3D10Device())) {
-            if (D2D10Device->QueryInterface(__uuidof(IDXGIDevice), (void **)&DXGIDevice) == S_OK) {
-                result = (DXGIDevice->GetAdapter(DXGIAdapter) == S_OK);
-                DXGIDevice->Release();
+        if ((d3d11Device = mozilla::gfx::Factory::GetDirect3D11Device())) {
+            if (d3d11Device->QueryInterface(__uuidof(IDXGIDevice), (void **)&dxgiDevice) == S_OK) {
+                result = (dxgiDevice->GetAdapter(aDXGIAdapter) == S_OK);
+                dxgiDevice->Release();
             }
         }
 
         return result;
     }
 
     ~GPUAdapterReporter() {}
 
@@ -371,17 +364,16 @@ GetParentDevicePrefs()
 gfxWindowsPlatform::gfxWindowsPlatform()
   : mRenderMode(RENDER_GDI)
   , mIsWARP(false)
   , mHasDeviceReset(false)
   , mHasFakeDeviceReset(false)
   , mCompositorD3D11TextureSharingWorks(false)
   , mAcceleration(FeatureStatus::Unused)
   , mD3D11Status(FeatureStatus::Unused)
-  , mD2DStatus(FeatureStatus::Unused)
   , mD2D1Status(FeatureStatus::Unused)
 {
     mUseClearTypeForDownloadableFonts = UNINITIALIZED_VALUE;
     mUseClearTypeAlways = UNINITIALIZED_VALUE;
 
     /* 
      * Initialize COM 
      */ 
@@ -406,17 +398,16 @@ gfxWindowsPlatform::gfxWindowsPlatform()
     RegisterStrongMemoryReporter(new D3D11TextureReporter());
     RegisterStrongMemoryReporter(new D3D9TextureReporter());
     RegisterStrongMemoryReporter(new D3D9SharedTextureReporter());
 }
 
 gfxWindowsPlatform::~gfxWindowsPlatform()
 {
     mDeviceManager = nullptr;
-    mD3D10Device = nullptr;
     mD3D11Device = nullptr;
     mD3D11ContentDevice = nullptr;
     mD3D11ImageBridgeDevice = nullptr;
 
     mozilla::gfx::Factory::D2DCleanup();
 
     mAdapter = nullptr;
 
@@ -484,19 +475,17 @@ gfxWindowsPlatform::HandleDeviceReset()
       }
     }
   } else {
     Telemetry::Accumulate(Telemetry::DEVICE_RESET_REASON, uint32_t(resetReason));
   }
 
   // Remove devices and adapters.
   ResetD3D11Devices();
-  mD3D10Device = nullptr;
   mAdapter = nullptr;
-  Factory::SetDirect3D10Device(nullptr);
 
   // Reset local state. Note: we leave feature status variables as-is. They
   // will be recomputed by InitializeDevices().
   mHasDeviceReset = false;
   mHasFakeDeviceReset = false;
   mCompositorD3D11TextureSharingWorks = false;
   mDeviceResetReason = DeviceResetReason::OK;
 
@@ -514,27 +503,21 @@ gfxWindowsPlatform::HandleDeviceReset()
 static const BackendType SOFTWARE_BACKEND = BackendType::CAIRO;
 
 void
 gfxWindowsPlatform::UpdateBackendPrefs()
 {
   uint32_t canvasMask = BackendTypeBit(SOFTWARE_BACKEND);
   uint32_t contentMask = BackendTypeBit(SOFTWARE_BACKEND);
   BackendType defaultBackend = SOFTWARE_BACKEND;
-  if (GetD2DStatus() == FeatureStatus::Available) {
+  if (GetD2D1Status() == FeatureStatus::Available) {
     mRenderMode = RENDER_DIRECT2D;
-    canvasMask |= BackendTypeBit(BackendType::DIRECT2D);
-    contentMask |= BackendTypeBit(BackendType::DIRECT2D);
-    if (GetD2D1Status() == FeatureStatus::Available) {
-      contentMask |= BackendTypeBit(BackendType::DIRECT2D1_1);
-      canvasMask |= BackendTypeBit(BackendType::DIRECT2D1_1);
-      defaultBackend = BackendType::DIRECT2D1_1;
-    } else {
-      defaultBackend = BackendType::DIRECT2D;
-    }
+    contentMask |= BackendTypeBit(BackendType::DIRECT2D1_1);
+    canvasMask |= BackendTypeBit(BackendType::DIRECT2D1_1);
+    defaultBackend = BackendType::DIRECT2D1_1;
   } else {
     mRenderMode = RENDER_GDI;
     canvasMask |= BackendTypeBit(BackendType::SKIA);
   }
   contentMask |= BackendTypeBit(BackendType::SKIA);
   InitBackendPrefs(canvasMask, defaultBackend, contentMask, defaultBackend);
 }
 
@@ -566,153 +549,35 @@ gfxWindowsPlatform::GetContentBackendFor
   if (aLayers == LayersBackend::LAYERS_D3D11) {
     return gfxPlatform::GetDefaultContentBackend();
   }
 
   // If we're not accelerated with D3D11, never use D2D.
   return SOFTWARE_BACKEND;
 }
 
-#ifdef CAIRO_HAS_D2D_SURFACE
-HRESULT
-gfxWindowsPlatform::CreateDevice(RefPtr<IDXGIAdapter1> &adapter1,
-                                 int featureLevelIndex)
-{
-  nsModuleHandle d3d10module(LoadLibrarySystem32(L"d3d10_1.dll"));
-  if (!d3d10module)
-    return E_FAIL;
-  decltype(D3D10CreateDevice1)* createD3DDevice =
-    (decltype(D3D10CreateDevice1)*) GetProcAddress(d3d10module, "D3D10CreateDevice1");
-  if (!createD3DDevice)
-    return E_FAIL;
-
-  ID3D10Device1* device = nullptr;
-  HRESULT hr =
-    createD3DDevice(adapter1, D3D10_DRIVER_TYPE_HARDWARE, nullptr,
-#ifdef DEBUG
-                    // This isn't set because of bug 1078411
-                    // D3D10_CREATE_DEVICE_DEBUG |
-#endif
-                    D3D10_CREATE_DEVICE_BGRA_SUPPORT |
-                    D3D10_CREATE_DEVICE_PREVENT_INTERNAL_THREADING_OPTIMIZATIONS,
-                    static_cast<D3D10_FEATURE_LEVEL1>(kSupportedFeatureLevels[featureLevelIndex]),
-                    D3D10_1_SDK_VERSION, &device);
-
-  // If we fail here, the DirectX version or video card probably
-  // changed.  We previously could use 10.1 but now we can't
-  // anymore.  Revert back to doing a 10.0 check first before
-  // the 10.1 check.
-  if (device) {
-    mD3D10Device = device;
-
-    // Leak the module while the D3D 10 device is being used.
-    d3d10module.disown();
-
-    // Setup a pref for future launch optimizaitons when in main process.
-    if (XRE_IsParentProcess()) {
-      Preferences::SetInt(kFeatureLevelPref, featureLevelIndex);
-    }
-  }
-
-  return device ? S_OK : hr;
-}
-#endif
-
-void
-gfxWindowsPlatform::VerifyD2DDevice(bool aAttemptForce)
-{
-  if ((!Factory::SupportsD2D1() || !gfxPrefs::Direct2DUse1_1()) && !gfxPrefs::Direct2DAllow1_0()) {
-    return;
-  }
-
-#ifdef CAIRO_HAS_D2D_SURFACE
-    if (mD3D10Device) {
-        if (SUCCEEDED(mD3D10Device->GetDeviceRemovedReason())) {
-            return;
-        }
-        mD3D10Device = nullptr;
-
-        // Surface cache needs to be invalidated since it may contain vector
-        // images rendered with our old, broken D2D device.
-        SurfaceCache::DiscardAll();
-    }
-
-    mozilla::ScopedGfxFeatureReporter reporter("D2D", aAttemptForce);
-
-    int supportedFeatureLevelsCount = ArrayLength(kSupportedFeatureLevels);
-
-    RefPtr<IDXGIAdapter1> adapter1 = GetDXGIAdapter();
-
-    if (!adapter1) {
-      // Unable to create adapter, abort acceleration.
-      return;
-    }
-
-    // It takes a lot of time (5-10% of startup time or ~100ms) to do both
-    // a createD3DDevice on D3D10_FEATURE_LEVEL_10_0.  We therefore store
-    // the last used feature level to go direct to that.
-    int featureLevelIndex = Preferences::GetInt(kFeatureLevelPref, 0);
-    if (featureLevelIndex >= supportedFeatureLevelsCount || featureLevelIndex < 0)
-      featureLevelIndex = 0;
-
-    // Start with the last used feature level, and move to lower DX versions
-    // until we find one that works.
-    HRESULT hr = E_FAIL;
-    for (int i = featureLevelIndex; i < supportedFeatureLevelsCount; i++) {
-      hr = CreateDevice(adapter1, i);
-      // If it succeeded we found the first available feature level
-      if (SUCCEEDED(hr))
-        break;
-    }
-
-    // If we succeeded in creating a device, try for a newer device
-    // that we haven't tried yet.
-    if (SUCCEEDED(hr)) {
-      for (int i = featureLevelIndex - 1; i >= 0; i--) {
-        hr = CreateDevice(adapter1, i);
-        // If it failed then we don't have new hardware
-        if (FAILED(hr)) {
-          break;
-        }
-      }
-    }
-
-    if (mD3D10Device) {
-        reporter.SetSuccessful();
-        mozilla::gfx::Factory::SetDirect3D10Device(mD3D10Device);
-    }
-
-    ScopedGfxFeatureReporter reporter1_1("D2D1.1V");
-
-    if (Factory::SupportsD2D1()) {
-      reporter1_1.SetSuccessful();
-    }
-#endif
-}
-
 gfxPlatformFontList*
 gfxWindowsPlatform::CreatePlatformFontList()
 {
     gfxPlatformFontList *pfl;
 
-#ifdef CAIRO_HAS_DWRITE_FONT
     // bug 630201 - older pre-RTM versions of Direct2D/DirectWrite cause odd
     // crashers so blacklist them altogether
     if (IsNotWin7PreRTM() && GetDWriteFactory()) {
         pfl = new gfxDWriteFontList();
         if (NS_SUCCEEDED(pfl->InitFontList())) {
             return pfl;
         }
         // DWrite font initialization failed! Don't know why this would happen,
         // but apparently it can - see bug 594865.
         // So we're going to fall back to GDI fonts & rendering.
         gfxPlatformFontList::Shutdown();
         DisableD2D();
     }
-#endif
+
     pfl = new gfxGDIFontList();
 
     if (NS_SUCCEEDED(pfl->InitFontList())) {
         return pfl;
     }
 
     gfxPlatformFontList::Shutdown();
     return nullptr;
@@ -722,20 +587,18 @@ gfxWindowsPlatform::CreatePlatformFontLi
 // be used when, after initially chosing to use Direct2D, we encounter a
 // scenario we can't support.
 //
 // This is called during gfxPlatform::Init() so at this point there should be no
 // DrawTargetD2D/1 instances.
 void
 gfxWindowsPlatform::DisableD2D()
 {
-  mD2DStatus = FeatureStatus::Failed;
   mD2D1Status = FeatureStatus::Failed;
   Factory::SetDirect3D11Device(nullptr);
-  Factory::SetDirect3D10Device(nullptr);
   UpdateBackendPrefs();
 }
 
 already_AddRefed<gfxASurface>
 gfxWindowsPlatform::CreateOffscreenSurface(const IntSize& aSize,
                                            gfxImageFormat aFormat)
 {
     RefPtr<gfxASurface> surf = nullptr;
@@ -1173,22 +1036,16 @@ gfxWindowsPlatform::DidRenderingDeviceRe
     }
   }
   if (mD3D11ContentDevice) {
     HRESULT hr = mD3D11ContentDevice->GetDeviceRemovedReason();
     if (IsDeviceReset(hr, aResetReason)) {
       return true;
     }
   }
-  if (GetD3D10Device()) {
-    HRESULT hr = GetD3D10Device()->GetDeviceRemovedReason();
-    if (IsDeviceReset(hr, aResetReason)) {
-      return true;
-    }
-  }
   if (XRE_IsParentProcess() && gfxPrefs::DeviceResetForTesting()) {
     TestDeviceReset((DeviceResetReason)gfxPrefs::DeviceResetForTesting());
     if (aResetReason) {
       *aResetReason = mDeviceResetReason;
     }
     gfxPrefs::SetDeviceResetForTesting(0);
     return true;
   }
@@ -1442,17 +1299,16 @@ gfxWindowsPlatform::FontsPrefsChanged(co
 }
 
 #define ENHANCED_CONTRAST_REGISTRY_KEY \
     HKEY_CURRENT_USER, "Software\\Microsoft\\Avalon.Graphics\\DISPLAY1\\EnhancedContrastLevel"
 
 void
 gfxWindowsPlatform::SetupClearTypeParams()
 {
-#if CAIRO_HAS_DWRITE_FONT
     if (GetDWriteFactory()) {
         // any missing prefs will default to invalid (-1) and be ignored;
         // out-of-range values will also be ignored
         FLOAT gamma = -1.0;
         FLOAT contrast = -1.0;
         FLOAT level = -1.0;
         int geometry = -1;
         int mode = -1;
@@ -1550,17 +1406,16 @@ gfxWindowsPlatform::SetupClearTypeParams
         GetDWriteFactory()->CreateCustomRenderingParams(gamma, contrast, level,
             dwriteGeometry, renderMode,
             getter_AddRefs(mRenderingParams[TEXT_RENDERING_NORMAL]));
 
         GetDWriteFactory()->CreateCustomRenderingParams(gamma, contrast, level,
             dwriteGeometry, DWRITE_RENDERING_MODE_CLEARTYPE_GDI_CLASSIC,
             getter_AddRefs(mRenderingParams[TEXT_RENDERING_GDI_CLASSIC]));
     }
-#endif
 }
 
 void
 gfxWindowsPlatform::OnDeviceManagerDestroy(DeviceManagerD3D9* aDeviceManager)
 {
   if (aDeviceManager == mDeviceManager) {
     mDeviceManager = nullptr;
   }
@@ -2412,17 +2267,17 @@ gfxWindowsPlatform::InitializeDevices()
   // Initialize Direct2D.
   if (mD3D11Status == FeatureStatus::Available) {
     InitializeD2D();
   }
 
   // Usually we want D2D in order to use DWrite, but if the users have it
   // forced, we'll let them have it, as unsupported configuration.
   if (gfxPrefs::DirectWriteFontRenderingForceEnabled() &&
-      IsFeatureStatusFailure(mD2DStatus) &&
+      IsFeatureStatusFailure(mD2D1Status) &&
       !mDWriteFactory) {
     gfxCriticalNote << "Attempting DWrite without D2D support";
     InitDWriteSupport();
   }
 }
 
 FeatureStatus
 gfxWindowsPlatform::CheckAccelerationSupport()
@@ -2578,27 +2433,21 @@ IsD2DBlacklisted()
   }
   return false;
 }
 
 // Check whether we can support Direct2D. Although some of these checks will
 // not change after a TDR (like the OS version), we could find a driver change
 // that runs us into the blacklist.
 FeatureStatus
-gfxWindowsPlatform::CheckD2DSupport()
+gfxWindowsPlatform::CheckD2D1Support()
 {
-  // Don't revive D2D support after a failure.
-  if (IsFeatureStatusFailure(mD2DStatus)) {
-    return mD2DStatus;
-  }
-
-  if (XRE_IsContentProcess()) {
-    return GetParentDevicePrefs().useD2D()
-           ? FeatureStatus::Available
-           : FeatureStatus::Blocked;
+  // Don't revive D2D1 support after a failure.
+  if (IsFeatureStatusFailure(mD2D1Status)) {
+    return mD2D1Status;
   }
 
   if (!gfxPrefs::Direct2DForceEnabled() && IsD2DBlacklisted()) {
     return FeatureStatus::Blacklisted;
   }
 
   // Do not ever try to use D2D if it's explicitly disabled.
   if (gfxPrefs::Direct2DDisabled()) {
@@ -2612,92 +2461,62 @@ gfxWindowsPlatform::CheckD2DSupport()
     return FeatureStatus::Unavailable;
   }
 
   // Normally we don't use D2D content drawing when using WARP. However if
   // WARP is force-enabled, we will let Direct2D use WARP as well.
   if (mIsWARP && !gfxPrefs::LayersD3D11ForceWARP()) {
     return FeatureStatus::Blocked;
   }
+
+  if (!Factory::SupportsD2D1()) {
+    return FeatureStatus::Unavailable;
+  }
+
+  if (XRE_IsContentProcess()) {
+    return GetParentDevicePrefs().useD2D1()
+           ? FeatureStatus::Available
+           : FeatureStatus::Blocked;
+  }
+
   return FeatureStatus::Available;
 }
 
 void
 gfxWindowsPlatform::InitializeD2D()
 {
-  mD2DStatus = CheckD2DSupport();
-  if (IsFeatureStatusFailure(mD2DStatus)) {
+  ScopedGfxFeatureReporter d2d1_1("D2D1.1");
+
+  mD2D1Status = CheckD2D1Support();
+  if (IsFeatureStatusFailure(mD2D1Status)) {
     return;
   }
 
   if (!mCompositorD3D11TextureSharingWorks) {
-    mD2DStatus = FeatureStatus::Failed;
+    mD2D1Status = FeatureStatus::Failed;
     return;
   }
 
   // Using Direct2D depends on DWrite support.
   if (!mDWriteFactory && !InitDWriteSupport()) {
-    mD2DStatus = FeatureStatus::Failed;
-    return;
-  }
-
-  // Initialize D2D 1.1.
-  InitializeD2D1();
-
-  // Initialize D2D 1.0.
-  VerifyD2DDevice(gfxPrefs::Direct2DForceEnabled());
-  if (!mD3D10Device) {
-    mDWriteFactory = nullptr;
-    mD2DStatus = FeatureStatus::Failed;
-    return;
-  }
-
-  mD2DStatus = FeatureStatus::Available;
-}
-
-FeatureStatus
-gfxWindowsPlatform::CheckD2D1Support()
-{
-  // Don't revive D2D1 support after a failure.
-  if (IsFeatureStatusFailure(mD2D1Status)) {
-    return mD2D1Status;
-  }
-  if (!Factory::SupportsD2D1()) {
-    return FeatureStatus::Unavailable;
-  }
-  if (XRE_IsContentProcess()) {
-    return GetParentDevicePrefs().useD2D1()
-           ? FeatureStatus::Available
-           : FeatureStatus::Blocked;
-  }
-  if (!gfxPrefs::Direct2DUse1_1()) {
-    return FeatureStatus::Disabled;
-  }
-  return FeatureStatus::Available;
-}
-
-void
-gfxWindowsPlatform::InitializeD2D1()
-{
-  ScopedGfxFeatureReporter d2d1_1("D2D1.1");
-
-  mD2D1Status = CheckD2D1Support();
-  if (IsFeatureStatusFailure(mD2D1Status)) {
+    mD2D1Status = FeatureStatus::Failed;
     return;
   }
 
   if (!mD3D11ContentDevice) {
     mD2D1Status = FeatureStatus::Failed;
     return;
   }
 
   mD2D1Status = FeatureStatus::Available;
   Factory::SetDirect3D11Device(mD3D11ContentDevice);
 
   d2d1_1.SetSuccessful();
+
+  mD2D1Status = FeatureStatus::Available;
 }
 
 bool
 gfxWindowsPlatform::CreateD3D11DecoderDeviceHelper(
   IDXGIAdapter1* aAdapter, RefPtr<ID3D11Device>& aDevice, HRESULT& aResOut)
 {
   MOZ_SEH_TRY{
     aResOut =
@@ -3047,25 +2866,16 @@ gfxWindowsPlatform::GetD3D11Status() con
 {
   if (mAcceleration != FeatureStatus::Available) {
     return mAcceleration;
   }
   return mD3D11Status;
 }
 
 FeatureStatus
-gfxWindowsPlatform::GetD2DStatus() const
-{
-  if (GetD3D11Status() != FeatureStatus::Available) {
-    return FeatureStatus::Unavailable;
-  }
-  return mD2DStatus;
-}
-
-FeatureStatus
 gfxWindowsPlatform::GetD2D1Status() const
 {
   if (GetD3D11Status() != FeatureStatus::Available) {
     re