Bug 1101130: Make Direct2D 1.1 clean up its resources on shutdown. r=jrmuizel
--- 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();