Bug 1046550 - Part 2: Allow creating D2D 1.1 DrawTargets for D3D11 textures. r=bas
authorMatt Woodrow <mwoodrow@mozilla.com>
Sun, 14 Sep 2014 23:51:27 +0200
changeset 205249 20e97c8496e46d042b65c423fa2bb577cd6703e2
parent 205248 418e2846120f79ba40cf5871d107682b8e20b176
child 205250 7b9201731195c5391405de8d9f52b370a34a4ba0
push id1
push userroot
push dateMon, 20 Oct 2014 17:29:22 +0000
reviewersbas
bugs1046550
milestone35.0a1
Bug 1046550 - Part 2: Allow creating D2D 1.1 DrawTargets for D3D11 textures. r=bas
gfx/2d/2D.h
gfx/2d/DrawTargetD2D1.cpp
gfx/2d/DrawTargetD2D1.h
gfx/2d/Factory.cpp
--- a/gfx/2d/2D.h
+++ b/gfx/2d/2D.h
@@ -32,16 +32,17 @@
 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;
 
 class GrContext;
 struct GrGLInterface;
 
 struct CGContext;
@@ -1185,16 +1186,18 @@ public:
   static TemporaryRef<DrawTarget>
     CreateDualDrawTargetForD3D10Textures(ID3D10Texture2D *aTextureA,
                                          ID3D10Texture2D *aTextureB,
                                          SurfaceFormat aFormat);
 
   static void SetDirect3D10Device(ID3D10Device1 *aDevice);
   static ID3D10Device1 *GetDirect3D10Device();
 #ifdef USE_D2D1_1
+  static TemporaryRef<DrawTarget> CreateDrawTargetForD3D11Texture(ID3D11Texture2D *aTexture, SurfaceFormat aFormat);
+
   static void SetDirect3D11Device(ID3D11Device *aDevice);
   static ID3D11Device *GetDirect3D11Device();
   static ID2D1Device *GetD2D1Device();
   static bool SupportsD2D1();
 #endif
 
   static TemporaryRef<GlyphRenderingOptions>
     CreateDWriteGlyphRenderingOptions(IDWriteRenderingParams *aParams);
--- a/gfx/2d/DrawTargetD2D1.cpp
+++ b/gfx/2d/DrawTargetD2D1.cpp
@@ -589,16 +589,62 @@ DrawTargetD2D1::CreateGradientStops(Grad
 
 TemporaryRef<FilterNode>
 DrawTargetD2D1::CreateFilter(FilterType aType)
 {
   return FilterNodeD2D1::Create(this, mDC, aType);
 }
 
 bool
+DrawTargetD2D1::Init(ID3D11Texture2D* aTexture, SurfaceFormat aFormat)
+{
+  HRESULT hr;
+
+  hr = Factory::GetD2D1Device()->CreateDeviceContext(D2D1_DEVICE_CONTEXT_OPTIONS_ENABLE_MULTITHREADED_OPTIMIZATIONS, byRef(mDC));
+
+  if (FAILED(hr)) {
+    gfxWarning() << *this << ": Error " << hr << " failed to initialize new DeviceContext.";
+    return false;
+  }
+
+  RefPtr<IDXGISurface> dxgiSurface;
+  aTexture->QueryInterface(__uuidof(IDXGISurface),
+                           (void**)((IDXGISurface**)byRef(dxgiSurface)));
+  if (!dxgiSurface) {
+    return false;
+  }
+
+  D2D1_BITMAP_PROPERTIES1 props;
+  props.dpiX = 96;
+  props.dpiY = 96;
+  props.pixelFormat = D2DPixelFormat(aFormat);
+  props.colorContext = nullptr;
+  props.bitmapOptions = D2D1_BITMAP_OPTIONS_TARGET;
+  mDC->CreateBitmapFromDxgiSurface(dxgiSurface, props, (ID2D1Bitmap1**)byRef(mBitmap));
+
+  if (FAILED(hr)) {
+    gfxWarning() << *this << ": Error " << hr << " failed to create new CommandList.";
+    return false;
+  }
+
+  mFormat = aFormat;
+  D3D11_TEXTURE2D_DESC desc;
+  aTexture->GetDesc(&desc);
+  mSize.width = desc.Width;
+  mSize.height = desc.Height;
+
+  mDC->CreateBitmap(D2DIntSize(mSize), nullptr, 0, props, (ID2D1Bitmap1**)byRef(mTempBitmap));
+
+  mDC->SetTarget(mBitmap);
+
+  mDC->BeginDraw();
+  return true;
+}
+
+bool
 DrawTargetD2D1::Init(const IntSize &aSize, SurfaceFormat aFormat)
 {
   HRESULT hr;
   
   hr = Factory::GetD2D1Device()->CreateDeviceContext(D2D1_DEVICE_CONTEXT_OPTIONS_ENABLE_MULTITHREADED_OPTIMIZATIONS, byRef(mDC));
 
   if (FAILED(hr)) {
     gfxWarning() << *this << ": Error " << hr << " failed to initialize new DeviceContext.";
--- a/gfx/2d/DrawTargetD2D1.h
+++ b/gfx/2d/DrawTargetD2D1.h
@@ -120,16 +120,17 @@ public:
                         uint32_t aNumStops,
                         ExtendMode aExtendMode = ExtendMode::CLAMP) const;
 
   virtual TemporaryRef<FilterNode> CreateFilter(FilterType aType);
 
   virtual void *GetNativeSurface(NativeSurfaceType aType) { return nullptr; }
 
   bool Init(const IntSize &aSize, SurfaceFormat aFormat);
+  bool Init(ID3D11Texture2D* aTexture, SurfaceFormat aFormat);
   uint32_t GetByteSize() const;
 
   TemporaryRef<ID2D1Image> GetImageForSurface(SourceSurface *aSurface, Matrix &aSourceTransform,
                                               ExtendMode aExtendMode);
 
   TemporaryRef<ID2D1Image> GetImageForSurface(SourceSurface *aSurface, ExtendMode aExtendMode) {
     Matrix mat;
     return GetImageForSurface(aSurface, mat, aExtendMode);
--- a/gfx/2d/Factory.cpp
+++ b/gfx/2d/Factory.cpp
@@ -543,25 +543,48 @@ Factory::SetDirect3D10Device(ID3D10Devic
   // On Windows 8 error codes are the default, but on Windows 7 the
   // default is to throw (or perhaps only with some drivers?)
   aDevice->SetExceptionMode(0);
   mD3D10Device = aDevice;
 }
 
 ID3D10Device1*
 Factory::GetDirect3D10Device()
+
 {
 #ifdef DEBUG
   UINT mode = mD3D10Device->GetExceptionMode();
   MOZ_ASSERT(0 == mode);
 #endif
   return mD3D10Device;
 }
 
 #ifdef USE_D2D1_1
+TemporaryRef<DrawTarget>
+Factory::CreateDrawTargetForD3D11Texture(ID3D11Texture2D *aTexture, SurfaceFormat aFormat)
+{
+  RefPtr<DrawTargetD2D1> newTarget;
+
+  newTarget = new DrawTargetD2D1();
+  if (newTarget->Init(aTexture, aFormat)) {
+    RefPtr<DrawTarget> retVal = newTarget;
+
+    if (mRecorder) {
+      retVal = new DrawTargetRecording(mRecorder, retVal, true);
+    }
+
+    return retVal;
+  }
+
+  gfxWarning() << "Failed to create draw target for D3D10 texture.";
+
+  // Failed
+  return nullptr;
+}
+
 void
 Factory::SetDirect3D11Device(ID3D11Device *aDevice)
 {
   mD3D11Device = aDevice;
 
   RefPtr<ID2D1Factory1> factory = D2DFactory1();
 
   RefPtr<IDXGIDevice> device;