Bug 1254400 - Handle device reset for d3d9. r=dvander
authorMorris Tseng <mtseng@mozilla.com>
Tue, 29 Mar 2016 09:26:29 +0800
changeset 290776 f75d2232611e65b453f280e02dfd5ca76a1e6477
parent 290775 5f7d9726c2ffb569007e416ca940df658a7b8500
child 290777 2626d857b9851ac400e8c727f15b0dea126c286c
push id19656
push usergwagner@mozilla.com
push dateMon, 04 Apr 2016 13:43:23 +0000
treeherderb2g-inbound@e99061fde28a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdvander
bugs1254400
milestone48.0a1
Bug 1254400 - Handle device reset for d3d9. r=dvander
gfx/layers/d3d9/CompositorD3D9.cpp
gfx/layers/d3d9/TextureD3D9.cpp
gfx/layers/d3d9/TextureD3D9.h
gfx/thebes/gfxWindowsPlatform.cpp
gfx/thebes/gfxWindowsPlatform.h
--- a/gfx/layers/d3d9/CompositorD3D9.cpp
+++ b/gfx/layers/d3d9/CompositorD3D9.cpp
@@ -665,17 +665,19 @@ CompositorD3D9::Ready()
 }
 
 void
 CompositorD3D9::FailedToResetDevice() {
   mFailedResetAttempts += 1;
   // 10 is a totally arbitrary number that we may want to increase or decrease
   // depending on how things behave in the wild.
   if (mFailedResetAttempts > 10) {
-    MOZ_CRASH("GFX: Unable to get a working D3D9 Compositor");
+    mFailedResetAttempts = 0;
+    gfxWindowsPlatform::GetPlatform()->D3D9DeviceReset();
+    gfxWarning() << "[D3D9] Unable to get a working D3D9 Compositor";
   }
 }
 
 void
 CompositorD3D9::BeginFrame(const nsIntRegion& aInvalidRegion,
                            const Rect *aClipRectIn,
                            const Rect& aRenderBounds,
                            bool aOpaque,
--- a/gfx/layers/d3d9/TextureD3D9.cpp
+++ b/gfx/layers/d3d9/TextureD3D9.cpp
@@ -899,17 +899,17 @@ TextureHostD3D9::UpdatedInternal(const n
                                                nullptr, mFlags);
     if (mFlags & TextureFlags::COMPONENT_ALPHA) {
       // Update the full region the first time for component alpha textures.
       regionToUpdate = nullptr;
     }
   }
 
   if (!mTextureSource->UpdateFromTexture(mTexture, regionToUpdate)) {
-    gfxCriticalError() << "[D3D9] DataTextureSourceD3D9::UpdateFromTexture failed";
+    gfxWarning() << "[D3D9] DataTextureSourceD3D9::UpdateFromTexture failed";
   }
 }
 
 IDirect3DDevice9*
 TextureHostD3D9::GetDevice()
 {
   if (mFlags & TextureFlags::INVALID_COMPOSITOR) {
     return nullptr;
--- a/gfx/layers/d3d9/TextureD3D9.h
+++ b/gfx/layers/d3d9/TextureD3D9.h
@@ -78,17 +78,17 @@ protected:
     _D3DFORMAT aFormat);
 
   gfx::IntSize mSize;
 
   // Linked list of all objects holding d3d9 textures.
   TextureSourceD3D9* mPreviousHost;
   TextureSourceD3D9* mNextHost;
   // The device manager that created our textures.
-  DeviceManagerD3D9* mCreatingDeviceManager;
+  RefPtr<DeviceManagerD3D9> mCreatingDeviceManager;
 
   StereoMode mStereoMode;
   RefPtr<IDirect3DTexture9> mTexture;
 };
 
 /**
  * A TextureSource that implements the DataTextureSource interface.
  * it can be used without a TextureHost and is able to upload texture data
--- a/gfx/thebes/gfxWindowsPlatform.cpp
+++ b/gfx/thebes/gfxWindowsPlatform.cpp
@@ -372,16 +372,17 @@ gfxWindowsPlatform::gfxWindowsPlatform()
   , mDeviceLock("gfxWindowsPlatform.mDeviceLock")
   , mIsWARP(false)
   , mHasDeviceReset(false)
   , mHasFakeDeviceReset(false)
   , mCompositorD3D11TextureSharingWorks(false)
   , mAcceleration(FeatureStatus::Unused)
   , mD3D11Status(FeatureStatus::Unused)
   , mD2D1Status(FeatureStatus::Unused)
+  , mHasD3D9DeviceReset(false)
 {
     mUseClearTypeForDownloadableFonts = UNINITIALIZED_VALUE;
     mUseClearTypeAlways = UNINITIALIZED_VALUE;
 
     /* 
      * Initialize COM 
      */ 
     CoInitialize(nullptr); 
@@ -478,16 +479,17 @@ gfxWindowsPlatform::HandleDeviceReset()
   // Remove devices and adapters.
   ResetD3D11Devices();
   mAdapter = nullptr;
 
   // Reset local state. Note: we leave feature status variables as-is. They
   // will be recomputed by InitializeDevices().
   mHasDeviceReset = false;
   mHasFakeDeviceReset = false;
+  mHasD3D9DeviceReset = false;
   mCompositorD3D11TextureSharingWorks = false;
   mDeviceResetReason = DeviceResetReason::OK;
 
   imgLoader::Singleton()->ClearCache(true);
   imgLoader::Singleton()->ClearCache(false);
   gfxAlphaBoxBlur::ShutdownBlurCache();
 
   // Since we got a device reset, we must ask the parent process for an updated
@@ -991,16 +993,19 @@ gfxWindowsPlatform::DidRenderingDeviceRe
     }
   }
   if (mD3D11ContentDevice) {
     HRESULT hr = mD3D11ContentDevice->GetDeviceRemovedReason();
     if (IsDeviceReset(hr, aResetReason)) {
       return true;
     }
   }
+  if (mHasD3D9DeviceReset) {
+    return true;
+  }
   if (XRE_IsParentProcess() && gfxPrefs::DeviceResetForTesting()) {
     TestDeviceReset((DeviceResetReason)gfxPrefs::DeviceResetForTesting());
     if (aResetReason) {
       *aResetReason = mDeviceResetReason;
     }
     gfxPrefs::SetDeviceResetForTesting(0);
     return true;
   }
@@ -1387,16 +1392,21 @@ gfxWindowsPlatform::OnDeviceManagerDestr
 
 IDirect3DDevice9*
 gfxWindowsPlatform::GetD3D9Device()
 {
   DeviceManagerD3D9* manager = GetD3D9DeviceManager();
   return manager ? manager->device() : nullptr;
 }
 
+void
+gfxWindowsPlatform::D3D9DeviceReset() {
+  mHasD3D9DeviceReset = true;
+}
+
 DeviceManagerD3D9*
 gfxWindowsPlatform::GetD3D9DeviceManager()
 {
   // We should only create the d3d9 device on the compositor thread
   // or we don't have a compositor thread.
   if (!mDeviceManager &&
       (!gfxPlatform::UsesOffMainThreadCompositing() ||
        CompositorBridgeParent::IsInCompositorThread())) {
--- a/gfx/thebes/gfxWindowsPlatform.h
+++ b/gfx/thebes/gfxWindowsPlatform.h
@@ -207,16 +207,17 @@ public:
 
     bool GetD3D11Device(RefPtr<ID3D11Device>* aOutDevice);
     bool GetD3D11DeviceForCurrentThread(RefPtr<ID3D11Device>* aOutDevice);
     bool GetD3D11ImageBridgeDevice(RefPtr<ID3D11Device>* aOutDevice);
 
     void OnDeviceManagerDestroy(mozilla::layers::DeviceManagerD3D9* aDeviceManager);
     mozilla::layers::DeviceManagerD3D9* GetD3D9DeviceManager();
     IDirect3DDevice9* GetD3D9Device();
+    void D3D9DeviceReset();
     ID3D11Device *GetD3D11ContentDevice();
 
     // Create a D3D11 device to be used for DXVA decoding.
     already_AddRefed<ID3D11Device> CreateD3D11DecoderDevice();
     bool CreateD3D11DecoderDeviceHelper(
       IDXGIAdapter1* aAdapter, RefPtr<ID3D11Device>& aDevice,
       HRESULT& aResOut);
 
@@ -328,16 +329,17 @@ private:
     RefPtr<ID3D11Device> mD3D11Device;
     RefPtr<ID3D11Device> mD3D11ContentDevice;
     RefPtr<ID3D11Device> mD3D11ImageBridgeDevice;
     RefPtr<mozilla::layers::DeviceManagerD3D9> mDeviceManager;
     bool mIsWARP;
     bool mHasDeviceReset;
     bool mHasFakeDeviceReset;
     bool mCompositorD3D11TextureSharingWorks;
+    mozilla::Atomic<bool> mHasD3D9DeviceReset;
     DeviceResetReason mDeviceResetReason;
 
     RefPtr<mozilla::layers::ReadbackManagerD3D11> mD3D11ReadbackManager;
 
     // These should not be accessed directly. Use the Get[Feature]Status
     // accessors instead.
     mozilla::gfx::FeatureStatus mAcceleration;
     mozilla::gfx::FeatureStatus mD3D11Status;