Backed out changeset 8e13ba75bccf (bug 1247775)
authorCarsten "Tomcat" Book <cbook@mozilla.com>
Fri, 12 Feb 2016 08:49:28 +0100
changeset 284094 2705df1debefec258a389e23915acc6c3dbdefc8
parent 284093 ea6f3bbe55c18d58faf4629dd673345b21028705
child 284095 013a55b91737a3f4e7938cac336854b65243fbb6
push id29995
push usercbook@mozilla.com
push dateFri, 12 Feb 2016 14:16:12 +0000
treeherdermozilla-central@218d16a9ddcc [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs1247775
milestone47.0a1
backs out8e13ba75bccf16690be1fdcfb12d1ac4c36948a9
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Backed out changeset 8e13ba75bccf (bug 1247775)
gfx/2d/2D.h
gfx/2d/DrawTargetD2D.cpp
gfx/2d/DrawTargetD2D.h
gfx/2d/DrawTargetD2D1.cpp
gfx/2d/Factory.cpp
gfx/2d/FilterNodeD2D1.cpp
gfx/2d/HelpersD2D.h
gfx/2d/NativeFontResourceDWrite.cpp
gfx/2d/PathD2D.cpp
gfx/2d/ScaledFontDWrite.cpp
gfx/2d/SourceSurfaceD2D.cpp
gfx/2d/SourceSurfaceD2D.h
gfx/2d/SourceSurfaceD2DTarget.cpp
gfx/2d/SourceSurfaceD2DTarget.h
gfx/2d/Types.h
gfx/2d/moz.build
--- a/gfx/2d/2D.h
+++ b/gfx/2d/2D.h
@@ -31,16 +31,18 @@
 #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;
 
@@ -1357,16 +1359,24 @@ 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>
@@ -1379,16 +1389,17 @@ 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
new file mode 100644
--- /dev/null
+++ b/gfx/2d/DrawTargetD2D.cpp
@@ -0,0 +1,2831 @@
+/* -*- 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);
+	}
+}
+
+}
+}
new file mode 100644
--- /dev/null
+++ b/gfx/2d/DrawTargetD2D.h
@@ -0,0 +1,290 @@
+/* -*- 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,41 +1,33 @@
 /* -*- 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()
@@ -607,17 +599,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;
-        factory()->CreatePathGeometry(getter_AddRefs(path));
+        D2DFactory()->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 |
@@ -1063,89 +1055,37 @@ DrawTargetD2D1::GetByteSize() const
 
 ID2D1Factory1*
 DrawTargetD2D1::factory()
 {
   if (mFactory) {
     return mFactory;
   }
 
-  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.";
+  ID2D1Factory* d2dFactory = D2DFactory();
+  if (!d2dFactory) {
     return nullptr;
   }
 
-  hr = factory->QueryInterface((ID2D1Factory1**)&mFactory);
-  if (FAILED(hr) || !mFactory) {
+  HRESULT hr = d2dFactory->QueryInterface((ID2D1Factory1**)&mFactory);
+
+  if (FAILED(hr)) {
     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,16 +30,17 @@
 #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"
@@ -155,16 +156,17 @@ 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;
 
@@ -308,16 +310,25 @@ 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;
@@ -483,16 +494,18 @@ 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;
   }
 }
 
@@ -594,16 +607,97 @@ 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)) {
@@ -668,33 +762,34 @@ already_AddRefed<GlyphRenderingOptions>
 Factory::CreateDWriteGlyphRenderingOptions(IDWriteRenderingParams *aParams)
 {
   return MakeAndAddRef<GlyphRenderingOptionsDWrite>(aParams);
 }
 
 uint64_t
 Factory::GetD2DVRAMUsageDrawTarget()
 {
-  return DrawTargetD2D1::mVRAMUsageDT;
+  return DrawTargetD2D::mVRAMUsageDT;
 }
 
 uint64_t
 Factory::GetD2DVRAMUsageSourceSurface()
 {
-  return DrawTargetD2D1::mVRAMUsageSS;
+  return DrawTargetD2D::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,16 +3,19 @@
  * 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)
 {
@@ -151,16 +154,18 @@ 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,18 +20,19 @@
 #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/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 "DrawTargetD2D1.h"
+#include "DrawTargetD2D.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();
-      DrawTargetD2D1::GetDWriteFactory()->
+      DrawTargetD2D::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 = DrawTargetD2D1::GetDWriteFactory();
+  IDWriteFactory *factory = DrawTargetD2D::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 "DrawTargetD2D1.h"
+#include "DrawTargetD2D.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 = DrawTargetD2D1::factory()->CreatePathGeometry(getter_AddRefs(path));
+  HRESULT hr = DrawTargetD2D::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 "DrawTargetD2D1.h"
+#include "DrawTargetD2D.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 = DrawTargetD2D1::GetDWriteFactory();
+    IDWriteFactory *factory = DrawTargetD2D::GetDWriteFactory();
     mTypeface = SkCreateTypefaceFromDWriteFont(factory, mFontFace, mFont, mFontFamily);
   }
   return mTypeface;
 }
 #endif
 
 void
 ScaledFontDWrite::CopyGlyphsToBuilder(const GlyphBuffer &aBuffer, PathBuilder *aBuilder, BackendType aBackendType, const Matrix *aTransformHint)
new file mode 100644
--- /dev/null
+++ b/gfx/2d/SourceSurfaceD2D.cpp
@@ -0,0 +1,317 @@
+/* -*- 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;
+  }
+}
+
+}
+}
new file mode 100644
--- /dev/null
+++ b/gfx/2d/SourceSurfaceD2D.h
@@ -0,0 +1,90 @@
+/* -*- 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_ */
new file mode 100644
--- /dev/null
+++ b/gfx/2d/SourceSurfaceD2DTarget.cpp
@@ -0,0 +1,325 @@
+/* -*- 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;
+  }
+}
+
+}
+}
new file mode 100644
--- /dev/null
+++ b/gfx/2d/SourceSurfaceD2DTarget.h
@@ -0,0 +1,90 @@
+/* -*- 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, // Used for version independent D2D objects.
+  DIRECT2D,
   COREGRAPHICS,
   COREGRAPHICS_ACCELERATED,
   CAIRO,
   SKIA,
   RECORDING,
   DIRECT2D1_1
 };
 
--- a/gfx/2d/moz.build
+++ b/gfx/2d/moz.build
@@ -61,27 +61,30 @@ 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',
     ]