Bug 1153123 - Don't upload in the ImageBridge thread if A8 texture sharing is broken. r=Bas, a=lizzard
authorMatt Woodrow <mwoodrow@mozilla.com>
Wed, 13 May 2015 23:42:32 +1200
changeset 266200 d744ad902c75
parent 266199 a7f385942c76
child 266201 561e0bdf9614
push id4785
push userryanvm@gmail.com
push date2015-06-08 13:34 +0000
treeherdermozilla-beta@a2c9c4c49319 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersBas, lizzard
bugs1153123
milestone39.0
Bug 1153123 - Don't upload in the ImageBridge thread if A8 texture sharing is broken. r=Bas, a=lizzard
gfx/layers/IMFYCbCrImage.cpp
gfx/thebes/gfxWindowsPlatform.cpp
gfx/thebes/gfxWindowsPlatform.h
--- a/gfx/layers/IMFYCbCrImage.cpp
+++ b/gfx/layers/IMFYCbCrImage.cpp
@@ -198,19 +198,19 @@ IMFYCbCrImage::GetD3D9TextureClient(Comp
   mTextureClient = texClient;
 
   return mTextureClient;
 }
 
 TextureClient*
 IMFYCbCrImage::GetTextureClient(CompositableClient* aClient)
 {
-  ID3D11Device* device = gfxWindowsPlatform::GetPlatform()->GetD3D11MediaDevice();
+  ID3D11Device* device = gfxWindowsPlatform::GetPlatform()->GetD3D11ImageBridgeDevice();
   if (!device ||
-    aClient->GetForwarder()->GetCompositorBackendType() != LayersBackend::LAYERS_D3D11) {
+      aClient->GetForwarder()->GetCompositorBackendType() != LayersBackend::LAYERS_D3D11) {
 
     IDirect3DDevice9* d3d9device = gfxWindowsPlatform::GetPlatform()->GetD3D9Device();
     if (d3d9device && aClient->GetForwarder()->GetCompositorBackendType() == LayersBackend::LAYERS_D3D9) {
       return GetD3D9TextureClient(aClient);
     }
     return nullptr;
   }
 
--- a/gfx/thebes/gfxWindowsPlatform.cpp
+++ b/gfx/thebes/gfxWindowsPlatform.cpp
@@ -407,17 +407,16 @@ public:
   }
 };
 
 NS_IMPL_ISUPPORTS(D3D9SharedTextureReporter, nsIMemoryReporter)
 
 gfxWindowsPlatform::gfxWindowsPlatform()
   : mD3D11DeviceInitialized(false)
   , mIsWARP(false)
-  , mCanInitMediaDevice(false)
 {
     mUseClearTypeForDownloadableFonts = UNINITIALIZED_VALUE;
     mUseClearTypeAlways = UNINITIALIZED_VALUE;
 
     mUsingGDIFonts = false;
 
     /* 
      * Initialize COM 
@@ -1591,65 +1590,25 @@ gfxWindowsPlatform::GetD3D11ContentDevic
   }
 
   InitD3D11Devices();
 
   return mD3D11ContentDevice;
 }
 
 ID3D11Device*
-gfxWindowsPlatform::GetD3D11MediaDevice()
+gfxWindowsPlatform::GetD3D11ImageBridgeDevice()
 {
-  if (mD3D11MediaDevice) {
-    return mD3D11MediaDevice;
-  }
-
-  if (!mCanInitMediaDevice) {
-    return nullptr;
+  if (mD3D11DeviceInitialized) {
+    return mD3D11ImageBridgeDevice;
   }
 
-  mCanInitMediaDevice = false;
-
-  nsModuleHandle d3d11Module(LoadLibrarySystem32(L"d3d11.dll"));
-  decltype(D3D11CreateDevice)* d3d11CreateDevice = (decltype(D3D11CreateDevice)*)
-    GetProcAddress(d3d11Module, "D3D11CreateDevice");
-  MOZ_ASSERT(d3d11CreateDevice);
-
-  nsTArray<D3D_FEATURE_LEVEL> featureLevels;
-  if (IsWin8OrLater()) {
-    featureLevels.AppendElement(D3D_FEATURE_LEVEL_11_1);
-  }
-  featureLevels.AppendElement(D3D_FEATURE_LEVEL_11_0);
-  featureLevels.AppendElement(D3D_FEATURE_LEVEL_10_1);
-  featureLevels.AppendElement(D3D_FEATURE_LEVEL_10_0);
-  featureLevels.AppendElement(D3D_FEATURE_LEVEL_9_3);
-
-  RefPtr<IDXGIAdapter1> adapter = GetDXGIAdapter();
-  MOZ_ASSERT(adapter);
+  InitD3D11Devices();
 
-  HRESULT hr = E_INVALIDARG;
-
-  MOZ_SEH_TRY{
-    hr = d3d11CreateDevice(adapter, D3D_DRIVER_TYPE_UNKNOWN, nullptr,
-                           D3D11_CREATE_DEVICE_BGRA_SUPPORT,
-                           featureLevels.Elements(), featureLevels.Length(),
-                           D3D11_SDK_VERSION, byRef(mD3D11MediaDevice), nullptr, nullptr);
-  } MOZ_SEH_EXCEPT(EXCEPTION_EXECUTE_HANDLER) {
-    mD3D11MediaDevice = nullptr;
-  }
-
-  d3d11Module.disown();
-
-  if (FAILED(hr)) {
-    return nullptr;
-  }
-
-  mD3D11MediaDevice->SetExceptionMode(0);
-
-  return mD3D11MediaDevice;
+  return mD3D11ImageBridgeDevice;
 }
 
 
 ReadbackManagerD3D11*
 gfxWindowsPlatform::GetReadbackManager()
 {
   if (!mD3D11ReadbackManager) {
     mD3D11ReadbackManager = new ReadbackManagerD3D11();
@@ -1767,29 +1726,21 @@ bool DoesD3D11DeviceWork(ID3D11Device *d
     }
   }
   result = true;
   return true;
 }
 
 // See bug 1083071. On some drivers, Direct3D 11 CreateShaderResourceView fails
 // with E_OUTOFMEMORY.
-bool DoesD3D11TextureSharingWork(ID3D11Device *device)
+bool DoesD3D11TextureSharingWorkInternal(ID3D11Device *device, DXGI_FORMAT format, UINT bindflags)
 {
-  static bool checked;
-  static bool result;
-
-  if (checked)
-      return result;
-  checked = true;
-
   if (gfxPrefs::Direct2DForceEnabled() ||
       gfxPrefs::LayersAccelerationForceEnabled())
   {
-    result = true;
     return true;
   }
 
   if (GetModuleHandleW(L"atidxx32.dll")) {
     nsCOMPtr<nsIGfxInfo> gfxInfo = do_GetService("@mozilla.org/gfx/info;1");
     if (gfxInfo) {
       nsString vendorID, vendorID2;
       gfxInfo->GetAdapterVendorID(vendorID);
@@ -1804,23 +1755,23 @@ bool DoesD3D11TextureSharingWork(ID3D11D
   }
 
   RefPtr<ID3D11Texture2D> texture;
   D3D11_TEXTURE2D_DESC desc;
   desc.Width = 32;
   desc.Height = 32;
   desc.MipLevels = 1;
   desc.ArraySize = 1;
-  desc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
+  desc.Format = format;
   desc.SampleDesc.Count = 1;
   desc.SampleDesc.Quality = 0;
   desc.Usage = D3D11_USAGE_DEFAULT;
   desc.CPUAccessFlags = 0;
   desc.MiscFlags = D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX;
-  desc.BindFlags = D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE;
+  desc.BindFlags = bindflags;
   if (FAILED(device->CreateTexture2D(&desc, NULL, byRef(texture)))) {
     return false;
   }
 
   HANDLE shareHandle;
   nsRefPtr<IDXGIResource> otherResource;
   if (FAILED(texture->QueryInterface(__uuidof(IDXGIResource),
                                      getter_AddRefs(otherResource))))
@@ -1851,20 +1802,32 @@ bool DoesD3D11TextureSharingWork(ID3D11D
   // This if(FAILED()) is the one that actually fails on systems affected by bug 1083071.
   if (FAILED(device->CreateShaderResourceView(sharedTexture, NULL, byRef(sharedView)))) {
 #if defined(MOZ_CRASHREPORTER)
     CrashReporter::AppendAppNotesToCrashReport(NS_LITERAL_CSTRING("CreateShaderResourceView failed\n"));
 #endif
     return false;
   }
 
-  result = true;
   return true;
 }
 
+bool DoesD3D11TextureSharingWork(ID3D11Device *device)
+{
+  static bool checked;
+  static bool result;
+
+  if (checked)
+    return result;
+  checked = true;
+
+  result = DoesD3D11TextureSharingWorkInternal(device, DXGI_FORMAT_B8G8R8A8_UNORM, D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE);
+  return result;
+}
+
 void
 gfxWindowsPlatform::InitD3D11Devices()
 {
   // This function attempts to initialize our D3D11 devices. If the hardware
   // is not blacklisted for D3D11 layers. This will first attempt to create a
   // hardware accelerated device. If this creation fails or the hardware is
   // blacklisted, then this function will abort if WARP is disabled, causing us
   // to fallback to D3D9 or Basic layers. If WARP is not disabled it will use
@@ -2032,17 +1995,37 @@ gfxWindowsPlatform::InitD3D11Devices()
     }
 
     mD3D11ContentDevice->SetExceptionMode(0);
 
     Factory::SetDirect3D11Device(mD3D11ContentDevice);
   }
 
   if (!useWARP) {
-    mCanInitMediaDevice = true;
+    hr = E_INVALIDARG;
+
+    MOZ_SEH_TRY{
+      hr = d3d11CreateDevice(adapter, D3D_DRIVER_TYPE_UNKNOWN, nullptr,
+                             D3D11_CREATE_DEVICE_BGRA_SUPPORT,
+                             featureLevels.Elements(), featureLevels.Length(),
+                             D3D11_SDK_VERSION, byRef(mD3D11ImageBridgeDevice), nullptr, nullptr);
+    } MOZ_SEH_EXCEPT(EXCEPTION_EXECUTE_HANDLER) {
+      mD3D11ImageBridgeDevice = nullptr;
+    }
+
+    if (FAILED(hr)) {
+      d3d11Module.disown();
+      return;
+    }
+
+    mD3D11ImageBridgeDevice->SetExceptionMode(0);
+
+    if (!DoesD3D11TextureSharingWorkInternal(mD3D11ImageBridgeDevice, DXGI_FORMAT_A8_UNORM, D3D11_BIND_SHADER_RESOURCE)) {
+      mD3D11ImageBridgeDevice = nullptr;
+    }
   }
 
   // We leak these everywhere and we need them our entire runtime anyway, let's
   // leak it here as well.
   d3d11Module.disown();
 }
 
 static bool
--- a/gfx/thebes/gfxWindowsPlatform.h
+++ b/gfx/thebes/gfxWindowsPlatform.h
@@ -241,17 +241,18 @@ public:
     mozilla::layers::DeviceManagerD3D9* GetD3D9DeviceManager();
     IDirect3DDevice9* GetD3D9Device();
 #ifdef CAIRO_HAS_D2D_SURFACE
     cairo_device_t *GetD2DDevice() { return mD2DDevice; }
     ID3D10Device1 *GetD3D10Device() { return mD2DDevice ? cairo_d2d_device_get_device(mD2DDevice) : nullptr; }
 #endif
     ID3D11Device *GetD3D11Device();
     ID3D11Device *GetD3D11ContentDevice();
-    ID3D11Device *GetD3D11MediaDevice();
+    // Device to be used on the ImageBridge thread
+    ID3D11Device *GetD3D11ImageBridgeDevice();
 
     mozilla::layers::ReadbackManagerD3D11* GetReadbackManager();
 
     static bool IsOptimus();
 
     bool IsWARP() { return mIsWARP; }
 
     bool SupportsApzWheelInput() override {
@@ -287,21 +288,20 @@ private:
 #endif
 #ifdef CAIRO_HAS_D2D_SURFACE
     cairo_device_t *mD2DDevice;
 #endif
     mozilla::RefPtr<IDXGIAdapter1> mAdapter;
     nsRefPtr<mozilla::layers::DeviceManagerD3D9> mDeviceManager;
     mozilla::RefPtr<ID3D11Device> mD3D11Device;
     mozilla::RefPtr<ID3D11Device> mD3D11ContentDevice;
-    mozilla::RefPtr<ID3D11Device> mD3D11MediaDevice;
+    mozilla::RefPtr<ID3D11Device> mD3D11ImageBridgeDevice;
     bool mD3D11DeviceInitialized;
     mozilla::RefPtr<mozilla::layers::ReadbackManagerD3D11> mD3D11ReadbackManager;
     bool mIsWARP;
-    bool mCanInitMediaDevice;
 
     virtual void GetPlatformCMSOutputProfile(void* &mem, size_t &size);
 };
 
 bool DoesD3D11TextureSharingWork(ID3D11Device *device);
 bool DoesD3D11DeviceWork(ID3D11Device *device);
 
 #endif /* GFX_WINDOWS_PLATFORM_H */