Bug 1101130: Make Direct2D 1.1 clean up its resources on shutdown. r=jrmuizel
authorBas Schouten <bschouten@mozilla.com>
Thu, 20 Nov 2014 00:16:48 +0000
changeset 216566 c3fbfee4a06b70215e764f1bc73a61430caf67bd
parent 216565 e46da4d0299d557964d01276c5efb2b37fc2f596
child 216567 8681a64218039f4bc6ea8113c522a6c2acee209e
push idunknown
push userunknown
push dateunknown
reviewersjrmuizel
bugs1101130
milestone36.0a1
Bug 1101130: Make Direct2D 1.1 clean up its resources on shutdown. r=jrmuizel
gfx/2d/DrawTargetD2D1.cpp
gfx/2d/Factory.cpp
gfx/2d/RadialGradientEffectD2D1.cpp
gfx/2d/RadialGradientEffectD2D1.h
--- a/gfx/2d/DrawTargetD2D1.cpp
+++ b/gfx/2d/DrawTargetD2D1.cpp
@@ -846,16 +846,26 @@ DrawTargetD2D1::factory()
   }
 
   RadialGradientEffectD2D1::Register(mFactory);
 
   return mFactory;
 }
 
 void
+DrawTargetD2D1::CleanupD2D()
+{
+  if (mFactory) {
+    RadialGradientEffectD2D1::Unregister(mFactory);
+    mFactory->Release();
+    mFactory = nullptr;
+  }
+}
+
+void
 DrawTargetD2D1::MarkChanged()
 {
   if (mSnapshot) {
     if (mSnapshot->hasOneRef()) {
       // Just destroy it, since no-one else knows about it.
       mSnapshot = nullptr;
     } else {
       mSnapshot->DrawTargetWillChange();
--- a/gfx/2d/Factory.cpp
+++ b/gfx/2d/Factory.cpp
@@ -604,16 +604,21 @@ Factory::CreateDrawTargetForD3D11Texture
   return nullptr;
 }
 
 void
 Factory::SetDirect3D11Device(ID3D11Device *aDevice)
 {
   mD3D11Device = aDevice;
 
+  if (mD2D1Device) {
+    mD2D1Device->Release();
+    mD2D1Device = nullptr;
+  }
+
   RefPtr<ID2D1Factory1> factory = D2DFactory1();
 
   RefPtr<IDXGIDevice> device;
   aDevice->QueryInterface((IDXGIDevice**)byRef(device));
   factory->CreateDevice(device, &mD2D1Device);
 }
 
 ID3D11Device*
@@ -651,17 +656,22 @@ uint64_t
 Factory::GetD2DVRAMUsageSourceSurface()
 {
   return DrawTargetD2D::mVRAMUsageSS;
 }
 
 void
 Factory::D2DCleanup()
 {
+  if (mD2D1Device) {
+    mD2D1Device->Release();
+    mD2D1Device = nullptr;
+  }
   DrawTargetD2D::CleanupD2D();
+  DrawTargetD2D1::CleanupD2D();
 }
 
 #endif // XP_WIN
 
 #ifdef USE_SKIA_GPU
 TemporaryRef<DrawTarget>
 Factory::CreateDrawTargetSkiaWithGrContext(GrContext* aGrContext,
                                            const IntSize &aSize,
--- a/gfx/2d/RadialGradientEffectD2D1.cpp
+++ b/gfx/2d/RadialGradientEffectD2D1.cpp
@@ -279,16 +279,22 @@ RadialGradientEffectD2D1::Register(ID2D1
   HRESULT hr = aFactory->RegisterEffectFromString(CLSID_RadialGradientEffect, kXmlDescription, bindings, ARRAYSIZE(bindings), CreateEffect);
 
   if (FAILED(hr)) {
     gfxWarning() << "Failed to register radial gradient effect.";
   }
   return hr;
 }
 
+void
+RadialGradientEffectD2D1::Unregister(ID2D1Factory1 *aFactory)
+{
+  aFactory->UnregisterEffect(CLSID_RadialGradientEffect);
+}
+
 HRESULT __stdcall
 RadialGradientEffectD2D1::CreateEffect(IUnknown **aEffectImpl)
 {
   *aEffectImpl = static_cast<ID2D1EffectImpl*>(new RadialGradientEffectD2D1());
   (*aEffectImpl)->AddRef();
 
   return S_OK;
 }
--- a/gfx/2d/RadialGradientEffectD2D1.h
+++ b/gfx/2d/RadialGradientEffectD2D1.h
@@ -67,16 +67,17 @@ public:
 
   // ID2D1TransformNode
   IFACEMETHODIMP_(UINT32) GetInputCount() const { return 1; }
 
   // ID2D1DrawTransform
   IFACEMETHODIMP SetDrawInfo(ID2D1DrawInfo *pDrawInfo);
 
   static HRESULT Register(ID2D1Factory1* aFactory);
+  static void Unregister(ID2D1Factory1* aFactory);
   static HRESULT __stdcall CreateEffect(IUnknown** aEffectImpl);
 
   HRESULT SetStopCollection(IUnknown *aStopCollection);
   IUnknown *GetStopCollection() const { return mStopCollection; }
 
 private:
   TemporaryRef<ID2D1ResourceTexture> CreateGradientTexture();