Bug 1281259 - Port DXVA to gfxConfig draft
authoreyim <eyim@mozilla.com>
Thu, 14 Jul 2016 10:21:06 -0400
changeset 390001 2afc395d430c0d233a6247812c385af85620b83d
parent 390000 ee1973d27f13e5adc7d41a8917c097266ec907b7
child 525914 3e098888b05942bdb7591792a27c676b505e8522
push id23579
push userbmo:eyim@mozilla.com
push dateWed, 20 Jul 2016 14:55:12 +0000
bugs1281259
milestone50.0a1
Bug 1281259 - Port DXVA to gfxConfig MozReview-Commit-ID: 7Yp3ynxZoFE
dom/media/mediasource/MediaSource.cpp
dom/media/platforms/apple/AppleDecoderModule.cpp
dom/media/platforms/wmf/WMFDecoderModule.cpp
gfx/config/gfxFeature.h
gfx/thebes/gfxPlatform.cpp
gfx/thebes/gfxPlatform.h
gfx/thebes/gfxWindowsPlatform.cpp
gfx/thebes/gfxWindowsPlatform.h
--- a/dom/media/mediasource/MediaSource.cpp
+++ b/dom/media/mediasource/MediaSource.cpp
@@ -26,16 +26,17 @@
 #include "nsIScriptObjectPrincipal.h"
 #include "nsPIDOMWindow.h"
 #include "nsString.h"
 #include "nsThreadUtils.h"
 #include "mozilla/Logging.h"
 #include "nsServiceManagerUtils.h"
 #include "gfxPlatform.h"
 #include "mozilla/Snprintf.h"
+#include "gfxConfig.h"
 
 #ifdef MOZ_WIDGET_ANDROID
 #include "AndroidBridge.h"
 #endif
 
 struct JSContext;
 class JSObject;
 
@@ -76,17 +77,17 @@ static const char* const gMediaSourceTyp
 // 2. If H264 hardware acceleration is not available.
 // 3. The CPU is considered to be fast enough
 static bool
 IsWebMForced(DecoderDoctorDiagnostics* aDiagnostics)
 {
   bool mp4supported =
     DecoderTraits::IsMP4TypeAndEnabled(NS_LITERAL_CSTRING("video/mp4"),
                                        aDiagnostics);
-  bool hwsupported = gfxPlatform::GetPlatform()->CanUseHardwareVideoDecoding();
+  bool hwsupported = gfx::gfxConfig::IsEnabled(gfx::Feature::HW_VIDEO_DECODING);
   return !mp4supported || !hwsupported || VP9Benchmark::IsVP9DecodeFast();
 }
 
 static nsresult
 IsTypeSupported(const nsAString& aType, DecoderDoctorDiagnostics* aDiagnostics)
 {
   if (aType.IsEmpty()) {
     return NS_ERROR_DOM_TYPE_ERR;
--- a/dom/media/platforms/apple/AppleDecoderModule.cpp
+++ b/dom/media/platforms/apple/AppleDecoderModule.cpp
@@ -8,16 +8,17 @@
 #include "AppleCMLinker.h"
 #include "AppleDecoderModule.h"
 #include "AppleVTDecoder.h"
 #include "AppleVTLinker.h"
 #include "MacIOSurfaceImage.h"
 #include "MediaPrefs.h"
 #include "mozilla/DebugOnly.h"
 #include "mozilla/Logging.h"
+#include "gfxConfig.h"
 
 namespace mozilla {
 
 bool AppleDecoderModule::sInitialized = false;
 bool AppleDecoderModule::sIsCoreMediaAvailable = false;
 bool AppleDecoderModule::sIsVTAvailable = false;
 bool AppleDecoderModule::sIsVTHWAvailable = false;
 bool AppleDecoderModule::sCanUseHardwareVideoDecoder = true;
@@ -47,18 +48,17 @@ AppleDecoderModule::Init()
   // dlopen VideoToolbox.framework if it's available.
   // We must link both CM and VideoToolbox framework to allow for proper
   // paired Link/Unlink calls
   bool haveVideoToolbox = loaded && AppleVTLinker::Link();
   sIsVTAvailable = sIsCoreMediaAvailable && haveVideoToolbox;
 
   sIsVTHWAvailable = AppleVTLinker::skPropEnableHWAccel != nullptr;
 
-  sCanUseHardwareVideoDecoder = loaded &&
-    gfxPlatform::GetPlatform()->CanUseHardwareVideoDecoding();
+  sCanUseHardwareVideoDecoder = loaded && gfxConfig::IsEnabled(gfx::Feature::HW_VIDEO_DECODING);
 
   sInitialized = true;
 }
 
 nsresult
 AppleDecoderModule::Startup()
 {
   if (!sInitialized || !sIsVTAvailable) {
--- a/dom/media/platforms/wmf/WMFDecoderModule.cpp
+++ b/dom/media/platforms/wmf/WMFDecoderModule.cpp
@@ -20,16 +20,17 @@
 #include "nsWindowsHelpers.h"
 #include "GfxDriverInfo.h"
 #include "gfxWindowsPlatform.h"
 #include "MediaInfo.h"
 #include "MediaPrefs.h"
 #include "prsystem.h"
 #include "mozilla/Maybe.h"
 #include "mozilla/StaticMutex.h"
+#include "gfxConfig.h"
 
 namespace mozilla {
 
 static Atomic<bool> sDXVAEnabled(false);
 
 WMFDecoderModule::WMFDecoderModule()
   : mWMFInitialized(false)
 {
@@ -42,17 +43,17 @@ WMFDecoderModule::~WMFDecoderModule()
     NS_ASSERTION(SUCCEEDED(hr), "MFShutdown failed");
   }
 }
 
 /* static */
 void
 WMFDecoderModule::Init()
 {
-  sDXVAEnabled = gfxPlatform::GetPlatform()->CanUseHardwareVideoDecoding();
+  sDXVAEnabled = gfx::gfxConfig::IsEnabled(gfx::Feature::HW_VIDEO_DECODING);
 }
 
 /* static */
 int
 WMFDecoderModule::GetNumDecoderThreads()
 {
   int32_t numCores = PR_GetNumberOfProcessors();
 
--- a/gfx/config/gfxFeature.h
+++ b/gfx/config/gfxFeature.h
@@ -17,18 +17,19 @@ namespace gfx {
 
 #define GFX_FEATURE_MAP(_)                                                        \
   /* Name,                        Type,         Description */                    \
   _(HW_COMPOSITING,               Feature,      "Compositing")                    \
   _(D3D11_COMPOSITING,            Feature,      "Direct3D11 Compositing")         \
   _(D3D9_COMPOSITING,             Feature,      "Direct3D9 Compositing")          \
   _(OPENGL_COMPOSITING,           Feature,      "OpenGL Compositing")             \
   _(DIRECT2D,                     Feature,      "Direct2D")                       \
-  _(D3D11_HW_ANGLE,               Feature,      "Direct3D11 hardware ANGLE")               \
+  _(D3D11_HW_ANGLE,               Feature,      "Direct3D11 hardware ANGLE")      \
   _(GPU_PROCESS,                  Feature,      "GPU Process")                    \
+  _(HW_VIDEO_DECODING,            Feature,      "Hardware Video Decoding")        \
   /* Add new entries above this comment */
 
 enum class Feature : uint32_t {
 #define MAKE_ENUM(name, type, desc) name,
   GFX_FEATURE_MAP(MAKE_ENUM)
 #undef MAKE_ENUM
   NumValues
 };
--- a/gfx/thebes/gfxPlatform.cpp
+++ b/gfx/thebes/gfxPlatform.cpp
@@ -991,16 +991,31 @@ struct DependentSourceSurfaceUserData
   RefPtr<gfxASurface> mSurface;
 };
 
 void SourceSurfaceDestroyed(void *aData)
 {
   delete static_cast<DependentSourceSurfaceUserData*>(aData);
 }
 
+/**
+ * Used to update (enable or disable) hw video decode feature based on pref
+ * Dummy parameters are used to work with existing RegisterCallback func
+ */
+static void
+UpdateHWDecBasedOnPref(const char* aPref, void* aClosure)
+{
+  FeatureState& hwVideoDecFeature = gfxConfig::GetFeature(Feature::HW_VIDEO_DECODING);
+
+  if (!Preferences::GetBool("media.hardware-video-decoding.failed", false))
+  {
+    hwVideoDecFeature.UserDisable("Hardware video decoding disabled by user preference.", NS_LITERAL_CSTRING("FEATURE_FAILURE_HW_VIDEO_DEC_DISABLED_BY_PREF"));
+  }
+}
+
 void
 gfxPlatform::ClearSourceSurfaceForSurface(gfxASurface *aSurface)
 {
   aSurface->SetData(&kSourceSurface, nullptr, nullptr);
 }
 
 /* static */ already_AddRefed<SourceSurface>
 gfxPlatform::GetSourceSurfaceForSurface(DrawTarget *aTarget, gfxASurface *aSurface)
@@ -2069,18 +2084,16 @@ 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 mozilla::Atomic<bool> sLayersSupportsHardwareVideoDecoding(false);
-static bool sLayersHardwareVideoDecodingFailed = false;
 static bool sBufferRotationCheckPref = true;
 static bool sPrefBrowserTabsRemoteAutostart = false;
 
 static mozilla::Atomic<bool> sLayersAccelerationPrefsInitialized(false);
 
 void
 gfxPlatform::InitAcceleration()
 {
@@ -2096,32 +2109,47 @@ gfxPlatform::InitAcceleration()
   // explicit.
   MOZ_ASSERT(NS_IsMainThread(), "can only initialize prefs on the main thread");
 
   gfxPrefs::GetSingleton();
   sPrefBrowserTabsRemoteAutostart = BrowserTabsRemoteAutostart();
 
   nsCOMPtr<nsIGfxInfo> gfxInfo = services::GetGfxInfo();
   nsCString discardFailureId;
-  int32_t status;
+
+  FeatureState& hwVideoDecFeature = gfxConfig::GetFeature(Feature::HW_VIDEO_DECODING);
 
-  if (Preferences::GetBool("media.hardware-video-decoding.enabled", false) &&
+  // feature prefs on
+  if (Preferences::GetBool("media.hardware-video-decoding.enabled", false)
 #ifdef XP_WIN
-    Preferences::GetBool("media.windows-media-foundation.use-dxva", true) &&
+    && Preferences::GetBool("media.windows-media-foundation.use-dxva", true)
 #endif
-      NS_SUCCEEDED(gfxInfo->GetFeatureStatus(nsIGfxInfo::FEATURE_HARDWARE_VIDEO_DECODING,
-                                               discardFailureId, &status))) {
-      if (status == nsIGfxInfo::FEATURE_STATUS_OK || gfxPrefs::HardwareVideoDecodingForceEnabled()) {
-         sLayersSupportsHardwareVideoDecoding = true;
-    }
+  ) {
+    hwVideoDecFeature.EnableByDefault();
+  }
+  // not forced on and prefs not set
+  else {
+    hwVideoDecFeature.DisableByDefault(FeatureStatus::Disabled, "HW video decode pref not set.", NS_LITERAL_CSTRING("FEATURE_FAILURE_HW_VIDEO_DEC_DISABLED"));
   }
 
-  Preferences::AddBoolVarCache(&sLayersHardwareVideoDecodingFailed,
-                               "media.hardware-video-decoding.failed",
-                               false);
+  // force enabled feature
+  if (gfxPrefs::HardwareVideoDecodingForceEnabled()) {
+    hwVideoDecFeature.UserForceEnable("User force-enabled video decoding.");
+  }
+
+  gPlatform->InitHWVideoDecodingConfig(hwVideoDecFeature);
+
+  //blocklist
+  nsCString message;
+  nsCString failureId;
+  if (!IsGfxInfoStatusOkay(nsIGfxInfo::FEATURE_HARDWARE_VIDEO_DECODING, &message, failureId)) {
+    hwVideoDecFeature.Disable(FeatureStatus::Blacklisted, message.get(), failureId);
+  }
+
+  Preferences::RegisterCallback(UpdateHWDecBasedOnPref, "media.hardware-video-decoding.failed", NULL, Preferences::ExactMatch);
 
   if (XRE_IsParentProcess()) {
     if (gfxPrefs::GPUProcessDevEnabled()) {
       // We want to hide this from about:support, so only set a default if the
       // pref is known to be true.
       gfxConfig::SetDefaultFromPref(
         Feature::GPU_PROCESS,
         gfxPrefs::GetGPUProcessDevEnabledPrefName(),
@@ -2171,25 +2199,16 @@ gfxPlatform::InitCompositorAccelerationP
   // Safe mode trumps everything.
   if (InSafeMode()) {
     feature.ForceDisable(FeatureStatus::Blocked, "Acceleration blocked by safe-mode",
                          NS_LITERAL_CSTRING("FEATURE_FAILURE_COMP_SAFEMODE"));
   }
 }
 
 bool
-gfxPlatform::CanUseHardwareVideoDecoding()
-{
-  // this function is called from the compositor thread, so it is not
-  // safe to init the prefs etc. from here.
-  MOZ_ASSERT(sLayersAccelerationPrefsInitialized);
-  return sLayersSupportsHardwareVideoDecoding && !sLayersHardwareVideoDecodingFailed;
-}
-
-bool
 gfxPlatform::AccelerateLayersByDefault()
 {
 #if defined(MOZ_GL_PROVIDER) || defined(MOZ_WIDGET_UIKIT)
   return true;
 #else
   return false;
 #endif
 }
@@ -2492,9 +2511,9 @@ gfxPlatform::IsGfxInfoStatusOkay(int32_t
       status != nsIGfxInfo::FEATURE_STATUS_OK)
   {
     aOutMessage->AssignLiteral("#BLOCKLIST_");
     aOutMessage->AppendASCII(aFailureId.get());
     return false;
   }
 
   return true;
-}
+}
\ No newline at end of file
--- a/gfx/thebes/gfxPlatform.h
+++ b/gfx/thebes/gfxPlatform.h
@@ -47,16 +47,17 @@ class SkiaGLGlue;
 namespace gfx {
 class DrawTarget;
 class SourceSurface;
 class DataSourceSurface;
 class ScaledFont;
 class DrawEventRecorder;
 class VsyncSource;
 class DeviceInitData;
+class FeatureState;
 
 inline uint32_t
 BackendTypeBit(BackendType b)
 {
   return 1 << uint8_t(b);
 }
 
 } // namespace gfx
@@ -168,16 +169,18 @@ public:
      * Shut down Thebes.
      * Init() arranges for this to be called at an appropriate time.
      */
     static void Shutdown();
 
     static void InitLayersIPC();
     static void ShutdownLayersIPC();
 
+    virtual void InitHWVideoDecodingConfig(mozilla::gfx::FeatureState& hwVideoDecFeature){};
+
     /**
      * Initialize ScrollMetadata statics. Does not depend on gfxPlatform.
      */
     static void InitNullMetadata();
 
     /**
      * Create an offscreen surface of the given dimensions
      * and image format.
@@ -447,18 +450,16 @@ public:
         // platform-specific override, by default do nothing
     }
 
     // Are we in safe mode?
     static bool InSafeMode();
 
     static bool OffMainThreadCompositingEnabled();
 
-    virtual bool CanUseHardwareVideoDecoding();
-
     // Returns a prioritized list of all available compositor backends.
     void GetCompositorBackends(bool useAcceleration, nsTArray<mozilla::layers::LayersBackend>& aBackends);
 
     /**
      * Is it possible to use buffer rotation.  Note that these
      * check the preference, but also allow for the override to
      * disable it using DisableBufferRotation.
      */
--- a/gfx/thebes/gfxWindowsPlatform.cpp
+++ b/gfx/thebes/gfxWindowsPlatform.cpp
@@ -397,25 +397,16 @@ gfxWindowsPlatform::InitAcceleration()
 
   InitializeConfig();
   InitializeDevices();
   UpdateANGLEConfig();
   UpdateRenderMode();
 }
 
 bool
-gfxWindowsPlatform::CanUseHardwareVideoDecoding()
-{
-  if (!gfxPrefs::LayersPreferD3D9() && !mCompositorD3D11TextureSharingWorks) {
-    return false;
-  }
-  return !IsWARP() && gfxPlatform::CanUseHardwareVideoDecoding();
-}
-
-bool
 gfxWindowsPlatform::InitDWriteSupport()
 {
   MOZ_ASSERT(!mDWriteFactory && IsVistaOrLater());
 
   mozilla::ScopedGfxFeatureReporter reporter("DWrite");
   decltype(DWriteCreateFactory)* createDWriteFactory = (decltype(DWriteCreateFactory)*)
       GetProcAddress(LoadLibraryW(L"dwrite.dll"), "DWriteCreateFactory");
   if (!createDWriteFactory) {
@@ -1927,16 +1918,27 @@ InitializeANGLEConfig()
   if (!gfxPlatform::IsGfxInfoStatusOkay(nsIGfxInfo::FEATURE_DIRECT3D_11_ANGLE, &message,
                            failureId)) {
     d3d11ANGLE.Disable(FeatureStatus::Blacklisted, message.get(), failureId);
   }
 
 }
 
 void
+gfxWindowsPlatform::InitHWVideoDecoodingConfig(FeatureState& hwVideoDecFeature)
+{
+    if (!gfxPrefs::LayersPreferD3D9() && !CompositorD3D11TextureSharingWorks()) {
+      hwVideoDecFeature.UserDisable("D3d9 not used, and d3d11 texture sharing not working", NS_LITERAL_CSTRING("FEATURE_FAILURE_HW_VIDEO_DEC_D3D_NOT_WORKING"));
+    }
+    else if (!IsWARP()) {
+      hwVideoDecFeature.UserDisable("WARP is disabled.", NS_LITERAL_CSTRING("FEATURE_FAILURE_HW_VIDEO_DEC_NO_WARP"));
+    }
+}
+
+void
 gfxWindowsPlatform::InitializeConfig()
 {
   if (!XRE_IsParentProcess()) {
     // Child processes init their configuration via UpdateDeviceInitData().
     return;
   }
 
   InitializeD3D9Config();
--- a/gfx/thebes/gfxWindowsPlatform.h
+++ b/gfx/thebes/gfxWindowsPlatform.h
@@ -155,29 +155,32 @@ public:
      * Verifies a D2D device is present and working, will attempt to create one
      * it is non-functional or non-existant.
      *
      * \param aAttemptForce Attempt to force D2D cairo device creation by using
      * cairo device creation routines.
      */
     void VerifyD2DDevice(bool aAttemptForce);
 
+    /**
+     * Check to see that hw video decoding can be enabled, if not disable the feature
+     */
+    void InitHWVideoDecoodingConfig(mozilla::gfx::FeatureState& hwVideoDecFeature);
+
     virtual void GetCommonFallbackFonts(uint32_t aCh, uint32_t aNextCh,
                                         Script aRunScript,
                                         nsTArray<const char*>& aFontList) override;
 
     gfxFontGroup*
     CreateFontGroup(const mozilla::FontFamilyList& aFontFamilyList,
                     const gfxFontStyle *aStyle,
                     gfxTextPerfMetrics* aTextPerf,
                     gfxUserFontSet *aUserFontSet,
                     gfxFloat aDevToCssSize) override;
 
-    virtual bool CanUseHardwareVideoDecoding() override;
-
     /**
      * Check whether format is supported on a platform or not (if unclear, returns true)
      */
     virtual bool IsFontFormatSupported(nsIURI *aFontURI, uint32_t aFormatFlags) override;
 
     virtual void CompositorUpdated() override;
 
     bool DidRenderingDeviceReset(DeviceResetReason* aResetReason = nullptr) override;