Bug 1352016 - P1. Add method to check if NV12 rendering is usable. r?mattwoodrow draft
authorJean-Yves Avenard <jyavenard@mozilla.com>
Sun, 10 Sep 2017 17:51:35 +0200
changeset 663095 f253bff4b59d8d08e9c952d2b0c350dc404794f9
parent 662980 b0e945eed81db8bf076daf64e381c514f70144f0
child 663096 92e4fa648f0cd850e81f3800541baf06f1a75de3
child 663994 c4998cac20e8805eaf075a19069d343436c1ff42
push id79318
push userbmo:jyavenard@mozilla.com
push dateTue, 12 Sep 2017 16:35:45 +0000
reviewersmattwoodrow
bugs1352016
milestone57.0a1
Bug 1352016 - P1. Add method to check if NV12 rendering is usable. r?mattwoodrow It will allow to blacklist all NVidia Tesla and AMD UVD3 GPU. MozReview-Commit-ID: LaJqyIj0Yau
dom/media/platforms/wmf/DXVA2Manager.cpp
dom/media/platforms/wmf/DXVA2Manager.h
--- a/dom/media/platforms/wmf/DXVA2Manager.cpp
+++ b/dom/media/platforms/wmf/DXVA2Manager.cpp
@@ -3,16 +3,17 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include <d3d11.h>
 #include "DXVA2Manager.h"
 #include "D3D9SurfaceImage.h"
 #include "DriverCrashGuard.h"
+#include "GfxDriverInfo.h"
 #include "ImageContainer.h"
 #include "MFTDecoder.h"
 #include "MediaTelemetryConstants.h"
 #include "gfxCrashReporterUtils.h"
 #include "gfxPrefs.h"
 #include "gfxWindowsPlatform.h"
 #include "mfapi.h"
 #include "mozilla/Telemetry.h"
@@ -69,16 +70,49 @@ static const DWORD sAMDPreUVD4[] = {
   0x6850, 0x6858, 0x6859, 0x6760, 0x6761, 0x6762, 0x6763, 0x6764, 0x6765, 0x6766, 0x6767, 0x6768, 0x6770,
   0x6771, 0x6772, 0x6778, 0x6779, 0x677b, 0x6700, 0x6701, 0x6702, 0x6703, 0x6704, 0x6705, 0x6706, 0x6707,
   0x6708, 0x6709, 0x6718, 0x6719, 0x671c, 0x671d, 0x671f, 0x9900, 0x9901, 0x9903, 0x9904, 0x9905, 0x9906,
   0x9907, 0x9908, 0x9909, 0x990a, 0x990b, 0x990c, 0x990d, 0x990e, 0x990f, 0x9910, 0x9913, 0x9917, 0x9918,
   0x9919, 0x9990, 0x9991, 0x9992, 0x9993, 0x9994, 0x9995, 0x9996, 0x9997, 0x9998, 0x9999, 0x999a, 0x999b,
   0x999c, 0x999d, 0x99a0, 0x99a2, 0x99a4
 };
 
+// List of NVidia Telsa GPU known to have broken NV12 rendering.
+static const DWORD sNVIDIABrokenNV12[] = {
+  0x0191, 0x0193, 0x0194, 0x0197, 0x019d, 0x019e, // G80
+  0x0400, 0x0401, 0x0402, 0x0403, 0x0404, 0x0405, 0x0406, 0x0407, 0x0408, 0x0409, // G84
+  0x040a, 0x040b, 0x040c, 0x040d, 0x040e, 0x040f,
+  0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427, 0x0428, 0x0429, // G86
+  0x042a, 0x042b, 0x042c, 0x042d, 0x042e, 0x042f,
+  0x0410, 0x0600, 0x0601, 0x0602, 0x0603, 0x0604, 0x0605, 0x0606, 0x0607, 0x0608, // G92
+  0x0609, 0x060a, 0x060b, 0x060c, 0x060f, 0x0610, 0x0611, 0x0612, 0x0613, 0x0614,
+  0x0615, 0x0617, 0x0618, 0x0619, 0x061a, 0x061b, 0x061c, 0x061d, 0x061e, 0x061f, // G94
+  0x0621, 0x0622, 0x0623, 0x0625, 0x0626, 0x0627, 0x0628, 0x062a, 0x062b, 0x062c,
+  0x062d, 0x062e, 0x0631, 0x0635, 0x0637, 0x0638, 0x063a,
+  0x0640, 0x0641, 0x0643, 0x0644, 0x0645, 0x0646, 0x0647, 0x0648, 0x0649, 0x064a, // G96
+  0x064b, 0x064c, 0x0651, 0x0652, 0x0653, 0x0654, 0x0655, 0x0656, 0x0658, 0x0659,
+  0x065a, 0x065b, 0x065c, 0x065f,
+  0x06e0, 0x06e1, 0x06e2, 0x06e3, 0x06e4, 0x06e6, 0x06e7, 0x06e8, 0x06e9, 0x06ea, // G98
+  0x06eb, 0x06ec, 0x06ef, 0x06f1, 0x06f8, 0x06f9, 0x06fa, 0x06fb, 0x06fd, 0x06ff,
+  0x05e0, 0x05e1, 0x05e2, 0x05e3, 0x05e6, 0x05e7, 0x05e9, 0x05ea, 0x05eb, 0x05ed, // G200
+  0x05ee, 0x05ef,
+  0x0840, 0x0844, 0x0845, 0x0846, 0x0847, 0x0848, 0x0849, 0x084a, 0x084b, 0x084c, // MCP77
+  0x084d, 0x084f,
+  0x0860, 0x0861, 0x0862, 0x0863, 0x0864, 0x0865, 0x0866, 0x0867, 0x0868, 0x0869, // MCP79
+  0x086a, 0x086c, 0x086d, 0x086e, 0x086f, 0x0870, 0x0871, 0x0872, 0x0873, 0x0874,
+  0x0876, 0x087a, 0x087d, 0x087e, 0x087f,
+  0x0ca0, 0x0ca2, 0x0ca3, 0x0ca2, 0x0ca4, 0x0ca5, 0x0ca7, 0x0ca9, 0x0cac, 0x0caf, // GT215
+  0x0cb0, 0x0cb1, 0x0cbc,
+  0x0a20, 0x0a22, 0x0a23, 0x0a26, 0x0a27, 0x0a28, 0x0a29, 0x0a2a, 0x0a2b, 0x0a2c, // GT216
+  0x0a2d, 0x0a32, 0x0a34, 0x0a35, 0x0a38, 0x0a3c,
+  0x0a60, 0x0a62, 0x0a63, 0x0a64, 0x0a65, 0x0a66, 0x0a67, 0x0a68, 0x0a69, 0x0a6a, // GT218
+  0x0a6c, 0x0a6e, 0x0a6f, 0x0a70, 0x0a71, 0x0a72, 0x0a73, 0x0a74, 0x0a75, 0x0a76,
+  0x0a78, 0x0a7a, 0x0a7c, 0x10c0, 0x10c3, 0x10c5, 0x10d8
+};
+
 // The size we use for our synchronization surface.
 // 16x16 is the size recommended by Microsoft (in the D3D9ExDXGISharedSurf sample) that works
 // best to avoid driver bugs.
 static const uint32_t kSyncSurfaceSize = 16;
 
 namespace mozilla {
 
 using layers::Image;
@@ -1263,9 +1297,40 @@ DXVA2Manager::IsUnsupportedResolution(co
   // AMD cards with UVD3 or earlier perform poorly trying to decode 1080p60 in
   // hardware, so use software instead. Pick 45 as an arbitrary upper bound for
   // the framerate we can handle.
   return mIsAMDPreUVD4 &&
          (aWidth >= 1920 || aHeight >= 1088) &&
          aFramerate > 45;
 }
 
+/* static */ bool
+DXVA2Manager::IsNV12Supported(uint32_t aVendorID,
+                              uint32_t aDeviceID,
+                              const nsAString& aDriverVersionString)
+{
+  if (aVendorID == 0x1022) {
+    // AMD
+    // Block old cards regardless of driver version.
+    for (const auto& model : sAMDPreUVD4) {
+      if (aDeviceID == model) {
+        return false;
+      }
+    }
+    // AMD driver earlier than 21.19.411.0 have bugs in their handling of NV12
+    // surfaces.
+    uint64_t driverVersion;
+    if (widget::ParseDriverVersion(aDriverVersionString, &driverVersion) &&
+        driverVersion < widget::V(21, 19, 411, 0)) {
+      return false;
+    }
+  } else if (aVendorID == 0x10DE) {
+    // NVidia
+    for (const auto& model : sNVIDIABrokenNV12) {
+      if (aDeviceID == model) {
+        return false;
+      }
+    }
+  }
+  return true;
+}
+
 } // namespace mozilla
--- a/dom/media/platforms/wmf/DXVA2Manager.h
+++ b/dom/media/platforms/wmf/DXVA2Manager.h
@@ -66,16 +66,20 @@ public:
   virtual bool SupportsConfig(IMFMediaType* aType, float aFramerate) = 0;
 
   // When we want to decode with DXVA2 directly instead of using it by MFT, we
   // need to take responsibility for creating a decoder and handle the related
   // decoding operations by ourself.
   virtual bool CreateDXVA2Decoder(const VideoInfo& aVideoInfo,
                                   nsACString& aFailureReason) = 0;
 
+  static bool IsNV12Supported(uint32_t aVendorID,
+                              uint32_t aDeviceID,
+                              const nsAString& aDriverVersionString);
+
 protected:
   Mutex mLock;
   DXVA2Manager();
 
   bool IsUnsupportedResolution(const uint32_t& aWidth,
                                const uint32_t& aHeight,
                                const float& aFramerate) const;