Bug 1271491: [WMF] P6. Check that D3D didn't crash earlier. r?cpearce draft
authorJean-Yves Avenard <jyavenard@mozilla.com>
Wed, 11 May 2016 12:26:34 +1000
changeset 365637 0a8ae9f6592dc0dca94753cf5749a83084886312
parent 365636 ce56e5a6a900b65fd46bc56be5a8594c031d2da6
child 365638 25eb7d4919953d28059045b0aa96c038891075ac
push id17802
push userbmo:jyavenard@mozilla.com
push dateWed, 11 May 2016 06:07:08 +0000
reviewerscpearce
bugs1271491
milestone49.0a1
Bug 1271491: [WMF] P6. Check that D3D didn't crash earlier. r?cpearce Currently, the test launch a synchronous dispatch to the main thread. It may be acceptable to simply use an asynchronous check instead, using the cached result. MozReview-Commit-ID: 4CclrCdo9py
dom/media/platforms/wmf/DXVA2Manager.cpp
--- a/dom/media/platforms/wmf/DXVA2Manager.cpp
+++ b/dom/media/platforms/wmf/DXVA2Manager.cpp
@@ -8,16 +8,17 @@
 #include <d3d11.h>
 #include "nsThreadUtils.h"
 #include "ImageContainer.h"
 #include "gfxWindowsPlatform.h"
 #include "D3D9SurfaceImage.h"
 #include "mozilla/layers/D3D11ShareHandleImage.h"
 #include "mozilla/layers/ImageBridgeChild.h"
 #include "mozilla/StaticMutex.h"
+#include "mozilla/SyncRunnable.h"
 #include "mozilla/Telemetry.h"
 #include "MediaTelemetryConstants.h"
 #include "mfapi.h"
 #include "MediaPrefs.h"
 #include "MFTDecoder.h"
 #include "DriverCrashGuard.h"
 #include "nsPrintfCString.h"
 
@@ -78,16 +79,19 @@ namespace mozilla {
 
 using layers::Image;
 using layers::ImageContainer;
 using layers::D3D9SurfaceImage;
 using layers::D3D9RecycleAllocator;
 using layers::D3D11ShareHandleImage;
 using layers::D3D11RecycleAllocator;
 
+static Atomic<bool> sD3D9CrashGuardResult(false);
+static Atomic<bool> sD3D11CrashGuardResult(false);
+
 class D3D9DXVA2Manager : public DXVA2Manager
 {
 public:
   D3D9DXVA2Manager();
   virtual ~D3D9DXVA2Manager();
 
   HRESULT Init(nsACString& aFailureReason);
 
@@ -98,16 +102,32 @@ public:
   HRESULT CopyToImage(IMFSample* aVideoSample,
                       const nsIntRect& aRegion,
                       ImageContainer* aContainer,
                       Image** aOutImage) override;
 
   bool SupportsConfig(IMFMediaType* aType, float aFramerate) override;
 
 private:
+  static void UpdateCrashGuardResult()
+  {
+    if (!NS_IsMainThread()) {
+      nsCOMPtr<nsIThread> mainThread = do_GetMainThread();
+      nsCOMPtr<nsIRunnable> runnable =
+        NS_NewRunnableFunction([]() { UpdateCrashGuardResult(); });
+      // We must not dispatch to a taskqueue, as tail dispatching may cause
+      // a deadlock.
+      SyncRunnable::DispatchToThread(mainThread, runnable);
+      return;
+    }
+    gfx::D3D9VideoCrashGuard crashGuard;
+    if (crashGuard.Crashed()) {
+      sD3D9CrashGuardResult = true;
+    }
+  }
   RefPtr<IDirect3D9Ex> mD3D9;
   RefPtr<IDirect3DDevice9Ex> mDevice;
   RefPtr<IDirect3DDeviceManager9> mDeviceManager;
   RefPtr<D3D9RecycleAllocator> mTextureClientAllocator;
   RefPtr<IDirectXVideoDecoderService> mDecoderService;
   RefPtr<IDirect3DSurface9> mSyncSurface;
   GUID mDecoderGUID;
   UINT32 mResetToken;
@@ -249,18 +269,18 @@ D3D9DXVA2Manager::GetDXVADeviceManager()
 {
   MutexAutoLock lock(mLock);
   return mDeviceManager;
 }
 
 HRESULT
 D3D9DXVA2Manager::Init(nsACString& aFailureReason)
 {
-  gfx::D3D9VideoCrashGuard crashGuard;
-  if (crashGuard.Crashed()) {
+  UpdateCrashGuardResult();
+  if (sD3D9CrashGuardResult) {
     NS_WARNING("DXVA2D3D9 crash detected");
     aFailureReason.AssignLiteral("DXVA2D3D9 crashes detected in the past");
     return E_FAIL;
   }
 
   // Create D3D9Ex.
   HMODULE d3d9lib = LoadLibraryW(L"d3d9.dll");
   NS_ENSURE_TRUE(d3d9lib, E_FAIL);
@@ -512,16 +532,32 @@ public:
 
   bool SupportsConfig(IMFMediaType* aType, float aFramerate) override;
 
 private:
   HRESULT CreateFormatConverter();
 
   HRESULT CreateOutputSample(RefPtr<IMFSample>& aSample,
                              ID3D11Texture2D* aTexture);
+  static void UpdateCrashGuardResult()
+  {
+    if (!NS_IsMainThread()) {
+      nsCOMPtr<nsIThread> mainThread = do_GetMainThread();
+      nsCOMPtr<nsIRunnable> runnable =
+        NS_NewRunnableFunction([]() { UpdateCrashGuardResult(); });
+      // We must not dispatch to a taskqueue, as tail dispatching may cause
+      // a deadlock.
+      SyncRunnable::DispatchToThread(mainThread, runnable);
+      return;
+    }
+    gfx::D3D11VideoCrashGuard crashGuard;
+    if (crashGuard.Crashed()) {
+      sD3D11CrashGuardResult = true;
+    }
+  }
 
   RefPtr<ID3D11Device> mDevice;
   RefPtr<ID3D11DeviceContext> mContext;
   RefPtr<IMFDXGIDeviceManager> mDXGIDeviceManager;
   RefPtr<MFTDecoder> mTransform;
   RefPtr<D3D11RecycleAllocator> mTextureClientAllocator;
   RefPtr<ID3D11Texture2D> mSyncSurface;
   GUID mDecoderGUID;
@@ -596,18 +632,18 @@ D3D11DXVA2Manager::GetDXVADeviceManager(
   return mDXGIDeviceManager;
 }
 
 HRESULT
 D3D11DXVA2Manager::Init(nsACString& aFailureReason)
 {
   HRESULT hr;
 
-  gfx::D3D11VideoCrashGuard crashGuard;
-  if (crashGuard.Crashed()) {
+  UpdateCrashGuardResult();
+  if (sD3D11CrashGuardResult) {
     NS_WARNING("DXVA2D3D11 crash detected");
     aFailureReason.AssignLiteral("DXVA2D3D11 crashes detected in the past");
     return E_FAIL;
   }
 
   mDevice = gfxWindowsPlatform::GetPlatform()->CreateD3D11DecoderDevice();
   if (!mDevice) {
     aFailureReason.AssignLiteral("Failed to create D3D11 device for decoder");