Bug 1348320: Use UpdateSubResource on crashy intel device/OS version combinations. r=jrmuizel draft
authorBas Schouten <bschouten@mozilla.com>
Mon, 01 May 2017 01:11:24 +0000
changeset 570804 fadec88a9586bc40e44d2f91aae5c9c5f8f59a5c
parent 570796 abd077c234e84eb69566a9000e81a4b17b164e6e
child 626573 95686e55841ceaf68fd142512cbb2c7d92a70703
push id56582
push userbschouten@mozilla.com
push dateMon, 01 May 2017 01:11:40 +0000
reviewersjrmuizel
bugs1348320
milestone55.0a1
Bug 1348320: Use UpdateSubResource on crashy intel device/OS version combinations. r=jrmuizel MozReview-Commit-ID: EdDn4qy1ajP
gfx/layers/d3d11/TextureD3D11.cpp
gfx/thebes/DeviceManagerDx.cpp
gfx/thebes/DeviceManagerDx.h
--- a/gfx/layers/d3d11/TextureD3D11.cpp
+++ b/gfx/layers/d3d11/TextureD3D11.cpp
@@ -423,39 +423,54 @@ D3D11TextureData::Create(IntSize aSize, 
   if (aSurface && newDesc.MiscFlags == D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX &&
       !DeviceManagerDx::Get()->CanInitializeKeyedMutexTextures()) {
     return nullptr;
   }
 
   D3D11_SUBRESOURCE_DATA uploadData;
   D3D11_SUBRESOURCE_DATA* uploadDataPtr = nullptr;
   RefPtr<DataSourceSurface> srcSurf;
+  DataSourceSurface::MappedSurface sourceMap;
+
   if (aSurface) {
     srcSurf = aSurface->GetDataSurface();
 
     if (!srcSurf) {
       gfxCriticalError() << "Failed to GetDataSurface in D3D11TextureData::Create";
       return nullptr;
     }
 
-    DataSourceSurface::MappedSurface sourceMap;
     if (!srcSurf->Map(DataSourceSurface::READ, &sourceMap)) {
       gfxCriticalError() << "Failed to map source surface for D3D11TextureData::Create";
       return nullptr;
     }
+  }
 
+  if (srcSurf && !DeviceManagerDx::Get()->HasCrashyInitData()) {
     uploadData.pSysMem = sourceMap.mData;
     uploadData.SysMemPitch = sourceMap.mStride;
     uploadData.SysMemSlicePitch = 0; // unused
 
     uploadDataPtr = &uploadData;
   }
 
   RefPtr<ID3D11Texture2D> texture11;
   HRESULT hr = device->CreateTexture2D(&newDesc, uploadDataPtr, getter_AddRefs(texture11));
+
+  if (srcSurf && DeviceManagerDx::Get()->HasCrashyInitData()) {
+    D3D11_BOX box;
+    box.front = box.top = box.left = 0;
+    box.back = 1;
+    box.right = aSize.width;
+    box.bottom = aSize.height;
+    RefPtr<ID3D11DeviceContext> ctx;
+    device->GetImmediateContext(getter_AddRefs(ctx));
+    ctx->UpdateSubresource(texture11, 0, &box, sourceMap.mData, sourceMap.mStride, 0);
+  }
+
   if (srcSurf) {
     srcSurf->Unmap();
   }
   if (FAILED(hr)) {
     gfxCriticalError(CriticalLog::DefaultOptions(Factory::ReasonableSurfaceSize(aSize)))
       << "[D3D11] 2 CreateTexture2D failure " << aSize << " Code: " << gfx::hexa(hr);
     return nullptr;
   }
--- a/gfx/thebes/DeviceManagerDx.cpp
+++ b/gfx/thebes/DeviceManagerDx.cpp
@@ -817,16 +817,27 @@ DeviceManagerDx::CanInitializeKeyedMutex
     return false;
   }
   // Disable this on all Intel devices because of crashes.
   // See bug 1292923.
   return (mDeviceStatus->adapter().VendorId != 0x8086 || gfxPrefs::Direct3D11AllowIntelMutex());
 }
 
 bool
+DeviceManagerDx::HasCrashyInitData()
+{
+  MutexAutoLock lock(mDeviceLock);
+  if (!mDeviceStatus) {
+    return false;
+  }
+
+  return (mDeviceStatus->adapter().VendorId == 0x8086 && !IsWin10OrLater());
+}
+
+bool
 DeviceManagerDx::CheckRemotePresentSupport()
 {
   MOZ_ASSERT(XRE_IsParentProcess());
 
   RefPtr<IDXGIAdapter1> adapter = GetDXGIAdapter();
   if (!adapter) {
     return false;
   }
--- a/gfx/thebes/DeviceManagerDx.h
+++ b/gfx/thebes/DeviceManagerDx.h
@@ -62,16 +62,20 @@ public:
 
   // Returns true if we can create a texture with
   // D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX and also
   // upload texture data during the CreateTexture2D
   // call. This crashes on some devices, so we might
   // need to avoid it.
   bool CanInitializeKeyedMutexTextures();
 
+  // Intel devices on older windows versions seem to occasionally have
+  // stability issues when supplying InitData to CreateTexture2D.
+  bool HasCrashyInitData();
+
   bool CreateCompositorDevices();
   void CreateContentDevices();
 
   void ImportDeviceInfo(const D3D11DeviceStatus& aDeviceStatus);
   void ExportDeviceInfo(D3D11DeviceStatus* aOut);
 
   void ResetDevices();
   void InitializeDirectDraw();