Bug 1120128 - Implement blacklist for DXVA and blacklist AMD Radeon HD 5800. r=Bas
☠☠ backed out by ef01cebd1e07 ☠ ☠
authorMatt Woodrow <mwoodrow@mozilla.com>
Mon, 26 Jan 2015 13:34:28 +1300
changeset 226146 774ff21aecb3cc882d2fd53317fc1f4aa5d7109a
parent 226145 53f5af7b9bf0c3ef628cbff92e8a6d052f89d1bc
child 226147 5df638c467f85c763a8d72507c39680561d6efd3
push id54769
push usermwoodrow@mozilla.com
push dateWed, 28 Jan 2015 01:23:26 +0000
treeherdermozilla-inbound@774ff21aecb3 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersBas
bugs1120128
milestone38.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 1120128 - Implement blacklist for DXVA and blacklist AMD Radeon HD 5800. r=Bas
dom/media/fmp4/wmf/WMFVideoMFTManager.cpp
dom/media/mediasource/moz.build
dom/media/wmf/WMFReader.cpp
gfx/thebes/gfxPlatform.cpp
gfx/thebes/gfxPlatform.h
media/libstagefright/binding/BufferStream.cpp
media/libstagefright/binding/include/mp4_demuxer/BufferStream.h
widget/GfxDriverInfo.cpp
widget/GfxDriverInfo.h
widget/GfxInfoBase.cpp
widget/nsIGfxInfo.idl
widget/windows/GfxInfo.cpp
--- a/dom/media/fmp4/wmf/WMFVideoMFTManager.cpp
+++ b/dom/media/fmp4/wmf/WMFVideoMFTManager.cpp
@@ -149,17 +149,18 @@ WMFVideoMFTManager::InitializeDXVA()
   // to a halt, and makes playback performance *worse*.
   if (!mDXVAEnabled ||
       (mLayersBackend != LayersBackend::LAYERS_D3D9 &&
        mLayersBackend != LayersBackend::LAYERS_D3D10 &&
        mLayersBackend != LayersBackend::LAYERS_D3D11)) {
     return false;
   }
 
-  if (gfxWindowsPlatform::GetPlatform()->IsWARP()) {
+  if (gfxWindowsPlatform::GetPlatform()->IsWARP() ||
+      !gfxPlatform::CanUseDXVA()) {
     return false;
   }
 
   // The DXVA manager must be created on the main thread.
   nsRefPtr<CreateDXVAManagerEvent> event(new CreateDXVAManagerEvent());
   NS_DispatchToMainThread(event, NS_DISPATCH_SYNC);
   mDXVA2Manager = event->mDXVA2Manager;
 
--- a/dom/media/mediasource/moz.build
+++ b/dom/media/mediasource/moz.build
@@ -4,16 +4,17 @@
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 MOCHITEST_MANIFESTS += ['test/mochitest.ini']
 
 EXPORTS += [
     'AsyncEventRunner.h',
     'MediaSourceDecoder.h',
     'MediaSourceReader.h',
+    'ResourceQueue.h',
 ]
 
 EXPORTS.mozilla.dom += [
     'MediaSource.h',
     'SourceBuffer.h',
     'SourceBufferList.h',
 ]
 
--- a/dom/media/wmf/WMFReader.cpp
+++ b/dom/media/wmf/WMFReader.cpp
@@ -106,17 +106,18 @@ WMFReader::InitializeDXVA()
 
   LayersBackend backend = layerManager->GetCompositorBackendType();
   if (backend != LayersBackend::LAYERS_D3D9 &&
       backend != LayersBackend::LAYERS_D3D10 &&
       backend != LayersBackend::LAYERS_D3D11) {
     return false;
   }
 
-  if (gfxWindowsPlatform::GetPlatform()->IsWARP()) {
+  if (gfxWindowsPlatform::GetPlatform()->IsWARP() ||
+      !gfxPlatform::CanUseDXVA()) {
     return false;
   }
 
   mDXVA2Manager = DXVA2Manager::Create();
 
   return mDXVA2Manager != nullptr;
 }
 
--- a/gfx/thebes/gfxPlatform.cpp
+++ b/gfx/thebes/gfxPlatform.cpp
@@ -2159,16 +2159,17 @@ gfxPlatform::OptimalFormatForContent(gfx
  * There are a number of layers acceleration (or layers in general) preferences
  * that should be consistent for the lifetime of the application (bug 840967).
  * As such, we will evaluate them all as soon as one of them is evaluated
  * and remember the values.  Changing these preferences during the run will
  * not have any effect until we restart.
  */
 static bool sLayersSupportsD3D9 = false;
 static bool sLayersSupportsD3D11 = false;
+static bool sLayersSupportsDXVA = false;
 static bool sBufferRotationCheckPref = true;
 static bool sPrefBrowserTabsRemoteAutostart = false;
 
 static bool sLayersAccelerationPrefsInitialized = false;
 
 void
 InitLayersAccelerationPrefs()
 {
@@ -2200,16 +2201,21 @@ InitLayersAccelerationPrefs()
           if (status == nsIGfxInfo::FEATURE_STATUS_OK) {
             sLayersSupportsD3D11 = true;
           }
         }
         if (!gfxPrefs::LayersD3D11DisableWARP()) {
           // Always support D3D11 when WARP is allowed.
           sLayersSupportsD3D11 = true;
         }
+        if (NS_SUCCEEDED(gfxInfo->GetFeatureStatus(nsIGfxInfo::FEATURE_DXVA, &status))) {
+          if (status == nsIGfxInfo::FEATURE_STATUS_OK) {
+            sLayersSupportsDXVA = true;
+          }
+        }
       }
     }
 #endif
 
     sLayersAccelerationPrefsInitialized = true;
   }
 }
 
@@ -2227,16 +2233,25 @@ gfxPlatform::CanUseDirect3D11()
 {
   // this function is called from the compositor thread, so it is not
   // safe to init the prefs etc. from here.
   MOZ_ASSERT(sLayersAccelerationPrefsInitialized);
   return sLayersSupportsD3D11;
 }
 
 bool
+gfxPlatform::CanUseDXVA()
+{
+  // this function is called from the compositor thread, so it is not
+  // safe to init the prefs etc. from here.
+  MOZ_ASSERT(sLayersAccelerationPrefsInitialized);
+  return sLayersSupportsDXVA;
+}
+
+bool
 gfxPlatform::BufferRotationEnabled()
 {
   MutexAutoLock autoLock(*gGfxPlatformPrefsLock);
 
   return sBufferRotationCheckPref && gfxPrefs::BufferRotationEnabled();
 }
 
 void
--- a/gfx/thebes/gfxPlatform.h
+++ b/gfx/thebes/gfxPlatform.h
@@ -476,16 +476,17 @@ public:
     {
         // platform-specific override, by default do nothing
     }
 
     static bool OffMainThreadCompositingEnabled();
 
     static bool CanUseDirect3D9();
     static bool CanUseDirect3D11();
+    static bool CanUseDXVA();
 
     /**
      * Is it possible to use buffer rotation.  Note that these
      * check the preference, but also allow for the override to
      * disable it using DisableBufferRotation.
      */
     static bool BufferRotationEnabled();
     static void DisableBufferRotation();
--- a/media/libstagefright/binding/BufferStream.cpp
+++ b/media/libstagefright/binding/BufferStream.cpp
@@ -7,59 +7,90 @@
 #include <algorithm>
 
 using namespace mozilla;
 
 namespace mp4_demuxer {
 
 BufferStream::BufferStream()
   : mStartOffset(0)
+  , mLogicalLength(0)
+  , mStartIndex(0)
 {
 }
 
 /*virtual*/ bool
 BufferStream::ReadAt(int64_t aOffset, void* aData, size_t aLength,
                      size_t* aBytesRead)
 {
-  if (aOffset < mStartOffset || aOffset > mStartOffset + mData.Length()) {
+  if (aOffset < (mStartOffset + mStartIndex) ||
+      mData.IsEmpty() ||
+      aOffset > mStartOffset + mData.LastElement()->Length()) {
     return false;
   }
   *aBytesRead =
     std::min(aLength, size_t(mStartOffset + mData.Length() - aOffset));
   memcpy(aData, &mData[aOffset - mStartOffset], *aBytesRead);
+
+  aOffset -= mStartOffset;
+  size_t index = mStartIndex;
+  *aBytesRead = 0;
+
+  uint8_t* dest = (uint8_t*)aData;
+
+  for (uint32_t i = 0; i < mData.Length() && aLength; i++) {
+    ResourceItem* item = mData[i];
+    if (aOffset >= index && aOffset < item->Length()) {
+      size_t count = std::min(item->Length() - aOffset, (uint64_t)aLength);
+      *aBytesRead += count;
+      memcpy(dest, &item->mData[aOffset], count);
+      dest += count;
+      aLength -= count;
+    }
+    aOffset -= item->Length();
+    index = 0;
+  }
   return true;
 }
 
 /*virtual*/ bool
 BufferStream::CachedReadAt(int64_t aOffset, void* aData, size_t aLength,
                            size_t* aBytesRead)
 {
   return ReadAt(aOffset, aData, aLength, aBytesRead);
 }
 
 /*virtual*/ bool
 BufferStream::Length(int64_t* aLength)
 {
-  *aLength = mStartOffset + mData.Length();
+  *aLength = mLogicalLength;
   return true;
 }
 
 /* virtual */ void
 BufferStream::DiscardBefore(int64_t aOffset)
 {
-  if (aOffset > mStartOffset) {
-    mData.RemoveElementsAt(0, aOffset - mStartOffset);
-    mStartOffset = aOffset;
+  while (!mData.IsEmpty() &&
+         mStartOffset + mData[0]->mData.Length() <= aOffset) {
+    mStartOffset += mData[0]->mData.Length();
+    mData.RemoveElementAt(0);
   }
+  mStartIndex = aOffset - mStartOffset;
 }
 
 void
 BufferStream::AppendBytes(const uint8_t* aData, size_t aLength)
 {
-  mData.AppendElements(aData, aLength);
+  mData.AppendElement(new ResourceItem(aData, aLength));
+}
+
+void
+BufferStream::AppendData(ResourceItem* aItem)
+{
+  mData.AppendElement(aItem);
 }
 
 MediaByteRange
 BufferStream::GetByteRange()
 {
-  return MediaByteRange(mStartOffset, mStartOffset + mData.Length());
+  return MediaByteRange(mStartOffset + mStartIndex, mLogicalLength);
 }
 }
--- a/media/libstagefright/binding/include/mp4_demuxer/BufferStream.h
+++ b/media/libstagefright/binding/include/mp4_demuxer/BufferStream.h
@@ -2,38 +2,41 @@
  * 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/. */
 
 #ifndef BUFFER_STREAM_H_
 #define BUFFER_STREAM_H_
 
 #include "mp4_demuxer/mp4_demuxer.h"
 #include "nsTArray.h"
+#include "ResourceQueue.h"
 
 namespace mp4_demuxer {
 
 class BufferStream : public Stream
 {
 public:
   /* BufferStream does not take ownership of aData nor does it make a copy.
    * Therefore BufferStream shouldn't get used after aData is destroyed.
    */
   BufferStream();
 
-  virtual bool ReadAt(int64_t aOffset, void* aData, size_t aLength,
-                      size_t* aBytesRead) MOZ_OVERRIDE;
-  virtual bool CachedReadAt(int64_t aOffset, void* aData, size_t aLength,
-                            size_t* aBytesRead) MOZ_OVERRIDE;
-  virtual bool Length(int64_t* aLength) MOZ_OVERRIDE;
+  bool ReadAt(int64_t aOffset, void* aData, size_t aLength,
+              size_t* aBytesRead);
+  bool CachedReadAt(int64_t aOffset, void* aData, size_t aLength,
+                    size_t* aBytesRead);
+  bool Length(int64_t* aLength);
 
-  virtual void DiscardBefore(int64_t aOffset) MOZ_OVERRIDE;
+  void DiscardBefore(int64_t aOffset);
 
   void AppendBytes(const uint8_t* aData, size_t aLength);
+  void AppendData(mozilla::ResourceItem* aItem);
 
   mozilla::MediaByteRange GetByteRange();
 
-private:
   int64_t mStartOffset;
-  nsTArray<uint8_t> mData;
+  int64_t mLogicalLength;
+  int64_t mStartIndex;
+  nsTArray<nsRefPtr<mozilla::ResourceItem>> mData;
 };
 }
 
 #endif
--- a/widget/GfxDriverInfo.cpp
+++ b/widget/GfxDriverInfo.cpp
@@ -209,16 +209,19 @@ const GfxDeviceFamily* GfxDriverInfo::Ge
       APPEND_DEVICE(0x7291);
       break;
     case Geforce7300GT:
       APPEND_DEVICE(0x0393);
       break;
     case Nvidia310M:
       APPEND_DEVICE(0x0A70);
       break;
+    case AMDRadeonHD5800:
+      APPEND_DEVICE(0x6899);
+      break;
     // This should never happen, but we get a warning if we don't handle this.
     case DeviceFamilyMax:
       NS_WARNING("Invalid DeviceFamily id");
       break;
   }
 
   return deviceFamily;
 }
--- a/widget/GfxDriverInfo.h
+++ b/widget/GfxDriverInfo.h
@@ -68,16 +68,17 @@ enum DeviceFamily {
   IntelGMAX3000,
   IntelGMAX4500HD,
   IntelHD3000,
   IntelMobileHDGraphics,
   NvidiaBlockD3D9Layers,
   RadeonX1000,
   Geforce7300GT,
   Nvidia310M,
+  AMDRadeonHD5800,
   DeviceFamilyMax
 };
 
 enum DeviceVendor {
   VendorAll,
   VendorIntel,
   VendorNVIDIA,
   VendorAMD,
--- a/widget/GfxInfoBase.cpp
+++ b/widget/GfxInfoBase.cpp
@@ -118,16 +118,19 @@ GetPrefNameForFeature(int32_t aFeature)
       name = BLACKLIST_PREF_BRANCH "layers.direct3d10";
       break;
     case nsIGfxInfo::FEATURE_DIRECT3D_10_1_LAYERS:
       name = BLACKLIST_PREF_BRANCH "layers.direct3d10-1";
       break;
     case nsIGfxInfo::FEATURE_DIRECT3D_11_LAYERS:
       name = BLACKLIST_PREF_BRANCH "layers.direct3d11";
       break;
+    case nsIGfxInfo::FEATURE_DXVA:
+      name = BLACKLIST_PREF_BRANCH "dxva";
+      break;
     case nsIGfxInfo::FEATURE_OPENGL_LAYERS:
       name = BLACKLIST_PREF_BRANCH "layers.opengl";
       break;
     case nsIGfxInfo::FEATURE_WEBGL_OPENGL:
       name = BLACKLIST_PREF_BRANCH "webgl.opengl";
       break;
     case nsIGfxInfo::FEATURE_WEBGL_ANGLE:
       name = BLACKLIST_PREF_BRANCH "webgl.angle";
@@ -282,16 +285,18 @@ BlacklistFeatureToGfxFeature(const nsASt
   else if (aFeature.EqualsLiteral("DIRECT3D_9_LAYERS"))
     return nsIGfxInfo::FEATURE_DIRECT3D_9_LAYERS;
   else if (aFeature.EqualsLiteral("DIRECT3D_10_LAYERS"))
     return nsIGfxInfo::FEATURE_DIRECT3D_10_LAYERS;
   else if (aFeature.EqualsLiteral("DIRECT3D_10_1_LAYERS"))
     return nsIGfxInfo::FEATURE_DIRECT3D_10_1_LAYERS;
   else if (aFeature.EqualsLiteral("DIRECT3D_11_LAYERS"))
     return nsIGfxInfo::FEATURE_DIRECT3D_11_LAYERS;
+  else if (aFeature.EqualsLiteral("DXVA"))
+    return nsIGfxInfo::FEATURE_DXVA;
   else if (aFeature.EqualsLiteral("OPENGL_LAYERS"))
     return nsIGfxInfo::FEATURE_OPENGL_LAYERS;
   else if (aFeature.EqualsLiteral("WEBGL_OPENGL"))
     return nsIGfxInfo::FEATURE_WEBGL_OPENGL;
   else if (aFeature.EqualsLiteral("WEBGL_ANGLE"))
     return nsIGfxInfo::FEATURE_WEBGL_ANGLE;
   else if (aFeature.EqualsLiteral("WEBGL_MSAA"))
     return nsIGfxInfo::FEATURE_WEBGL_MSAA;
@@ -837,16 +842,17 @@ void
 GfxInfoBase::EvaluateDownloadedBlacklist(nsTArray<GfxDriverInfo>& aDriverInfo)
 {
   int32_t features[] = {
     nsIGfxInfo::FEATURE_DIRECT2D,
     nsIGfxInfo::FEATURE_DIRECT3D_9_LAYERS,
     nsIGfxInfo::FEATURE_DIRECT3D_10_LAYERS,
     nsIGfxInfo::FEATURE_DIRECT3D_10_1_LAYERS,
     nsIGfxInfo::FEATURE_DIRECT3D_11_LAYERS,
+    nsIGfxInfo::FEATURE_DXVA,
     nsIGfxInfo::FEATURE_OPENGL_LAYERS,
     nsIGfxInfo::FEATURE_WEBGL_OPENGL,
     nsIGfxInfo::FEATURE_WEBGL_ANGLE,
     nsIGfxInfo::FEATURE_WEBGL_MSAA,
     nsIGfxInfo::FEATURE_STAGEFRIGHT,
     0
   };
 
--- a/widget/nsIGfxInfo.idl
+++ b/widget/nsIGfxInfo.idl
@@ -82,16 +82,18 @@ interface nsIGfxInfo : nsISupports
   /* Whether WebGL antialiasing is supported. */
   const long FEATURE_WEBGL_MSAA = 8;
   /* Whether Stagefright is supported */
   const long FEATURE_STAGEFRIGHT = 9;
   /* Whether Webrtc Hardware acceleration is supported */
   const long FEATURE_WEBRTC_HW_ACCELERATION = 10;
   /* Whether Direct3D 11 is supported for layers. */
   const long FEATURE_DIRECT3D_11_LAYERS = 11;
+  /* Whether DXVA is supported for video decoding. */
+  const long FEATURE_DXVA = 12;
 
   /*
    * A set of return values from GetFeatureStatus
    */
 
   /* The driver is save to the best of our knowledge */
   const long FEATURE_STATUS_OK = 1;
   /* We don't know the status of the feature yet. The analysis probably hasn't finished yet. */
--- a/widget/windows/GfxInfo.cpp
+++ b/widget/windows/GfxInfo.cpp
@@ -1029,16 +1029,21 @@ GfxInfo::GetGfxDriverInfo()
       GfxDriverInfo::allFeatures, nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION,
       DRIVER_LESS_THAN, V(6,2,0,0), "< 6.2.0.0" );
 
     /* Bug 1008759: Optimus (NVidia) crash.  Disable D2D on NV 310M. */
     APPEND_TO_DRIVER_BLOCKLIST2(DRIVER_OS_ALL,
       (nsAString&)GfxDriverInfo::GetDeviceVendor(VendorNVIDIA), (GfxDeviceFamily*)GfxDriverInfo::GetDeviceFamily(Nvidia310M),
       nsIGfxInfo::FEATURE_DIRECT2D, nsIGfxInfo::FEATURE_BLOCKED_DEVICE,
       DRIVER_LESS_THAN, GfxDriverInfo::allDriverVersions);
+
+    APPEND_TO_DRIVER_BLOCKLIST2(DRIVER_OS_ALL,
+      (nsAString&)GfxDriverInfo::GetDeviceVendor(VendorATI), (GfxDeviceFamily*)GfxDriverInfo::GetDeviceFamily(AMDRadeonHD5800),
+      nsIGfxInfo::FEATURE_DXVA, nsIGfxInfo::FEATURE_BLOCKED_DEVICE,
+      DRIVER_LESS_THAN, GfxDriverInfo::allDriverVersions);
   }
   return *mDriverInfo;
 }
 
 nsresult
 GfxInfo::GetFeatureStatusImpl(int32_t aFeature,
                               int32_t *aStatus, 
                               nsAString & aSuggestedDriverVersion,