Bug 1271491: [WMF] P7. 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 instead.
MozReview-Commit-ID: 4CclrCdo9py
--- 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");