Bug 1352016 - P1. Add method to check if NV12 rendering is usable. r=mattwoodrow
authorJean-Yves Avenard <jyavenard@mozilla.com>
Sun, 10 Sep 2017 17:51:35 +0200
changeset 430090 369f2167e1277fee6f5c48d37c2044b351597e7b
parent 430089 1682167a89460705853970f382905370a03e74c5
child 430091 2bd972867854e5f0359ce5387816323f9eeb670b
push id7761
push userjlund@mozilla.com
push dateFri, 15 Sep 2017 00:19:52 +0000
treeherdermozilla-beta@c38455951db4 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmattwoodrow
bugs1352016
milestone57.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
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;