Bug 1338011 - Adds an intermediate fallback when the GPU process crashes r?dvander draft
authorJay Harris <jharris@mozilla.com>
Thu, 16 Feb 2017 12:23:09 +1300
changeset 485528 6ec4f5c2c15066d7f22648d68e2b4cae6084bafd
parent 484996 e783bdf2cb500b1b23aadc3957c59264b3d2c6e7
child 485529 60e079709974817f0321668d67b87e59b4d64707
push id45755
push userbmo:jharris@mozilla.com
push dateThu, 16 Feb 2017 20:42:24 +0000
reviewersdvander
bugs1338011
milestone54.0a1
Bug 1338011 - Adds an intermediate fallback when the GPU process crashes r?dvander MozReview-Commit-ID: 9x1ckaWagcE
dom/media/platforms/wmf/WMFDecoderModule.cpp
gfx/ipc/GPUProcessManager.cpp
gfx/ipc/GPUProcessManager.h
gfx/thebes/gfxPlatform.cpp
gfx/thebes/gfxPlatform.h
gfx/thebes/gfxPrefs.h
--- a/dom/media/platforms/wmf/WMFDecoderModule.cpp
+++ b/dom/media/platforms/wmf/WMFDecoderModule.cpp
@@ -23,16 +23,17 @@
 #include "mozilla/gfx/gfxVars.h"
 #include "nsAutoPtr.h"
 #include "nsComponentManagerUtils.h"
 #include "nsIGfxInfo.h"
 #include "nsIWindowsRegKey.h"
 #include "nsServiceManagerUtils.h"
 #include "nsWindowsHelpers.h"
 #include "prsystem.h"
+#include "nsIXULRuntime.h"
 
 namespace mozilla {
 
 static Atomic<bool> sDXVAEnabled(false);
 
 WMFDecoderModule::~WMFDecoderModule()
 {
   if (mWMFInitialized) {
@@ -40,17 +41,30 @@ WMFDecoderModule::~WMFDecoderModule()
     NS_ASSERTION(SUCCEEDED(hr), "MFShutdown failed");
   }
 }
 
 /* static */
 void
 WMFDecoderModule::Init()
 {
-  sDXVAEnabled = gfx::gfxVars::CanUseHardwareVideoDecoding();
+  if (XRE_IsContentProcess()) {
+    // If we're in the content process and the UseGPUDecoder pref is set, it
+    // means that we've given up on the GPU process (it's been crashing) so we
+    // should disable DXVA
+    sDXVAEnabled = !MediaPrefs::PDMUseGPUDecoder();
+  } else if (XRE_IsGPUProcess()) {
+    // Always allow DXVA in the GPU process.
+    sDXVAEnabled = true;
+  } else {
+    // Only allow DXVA in the UI process if we aren't in e10s Firefox
+    sDXVAEnabled = !mozilla::BrowserTabsRemoteAutostart();
+  }
+
+  sDXVAEnabled = sDXVAEnabled && gfx::gfxVars::CanUseHardwareVideoDecoding();
 }
 
 /* static */
 int
 WMFDecoderModule::GetNumDecoderThreads()
 {
   int32_t numCores = PR_GetNumberOfProcessors();
 
--- a/gfx/ipc/GPUProcessManager.cpp
+++ b/gfx/ipc/GPUProcessManager.cpp
@@ -374,16 +374,18 @@ GPUProcessManager::OnProcessUnexpectedSh
 
   DestroyProcess();
 
   if (mNumProcessAttempts > uint32_t(gfxPrefs::GPUProcessMaxRestarts())) {
     char disableMessage[64];
     SprintfLiteral(disableMessage, "GPU process disabled after %d attempts",
                    mNumProcessAttempts);
     DisableGPUProcess(disableMessage);
+  } else if (mNumProcessAttempts > uint32_t(gfxPrefs::GPUProcessMaxRestartsWithDecoder())) {
+    mDecodeVideoOnGpuProcess = false;
   }
 
   HandleProcessLost();
 }
 
 void
 GPUProcessManager::HandleProcessLost()
 {
@@ -789,17 +791,19 @@ GPUProcessManager::CreateContentVRManage
   *aOutEndpoint = Move(childPipe);
   return true;
 }
 
 void
 GPUProcessManager::CreateContentVideoDecoderManager(base::ProcessId aOtherProcess,
                                                     ipc::Endpoint<dom::PVideoDecoderManagerChild>* aOutEndpoint)
 {
-  if (!mGPUChild || !MediaPrefs::PDMUseGPUDecoder()) {
+  if (!mGPUChild ||
+      !MediaPrefs::PDMUseGPUDecoder() ||
+      !mDecodeVideoOnGpuProcess) {
     return;
   }
 
   ipc::Endpoint<dom::PVideoDecoderManagerParent> parentPipe;
   ipc::Endpoint<dom::PVideoDecoderManagerChild> childPipe;
 
   nsresult rv = dom::PVideoDecoderManager::CreateEndpoints(
     mGPUChild->OtherPid(),
--- a/gfx/ipc/GPUProcessManager.h
+++ b/gfx/ipc/GPUProcessManager.h
@@ -220,16 +220,18 @@ private:
   protected:
     ~Observer() {}
 
     GPUProcessManager* mManager;
   };
   friend class Observer;
 
 private:
+  bool mDecodeVideoOnGpuProcess = true;
+
   RefPtr<Observer> mObserver;
   ipc::TaskFactory<GPUProcessManager> mTaskFactory;
   RefPtr<VsyncIOThreadHolder> mVsyncIOThread;
   uint64_t mNextLayerTreeId;
   uint64_t mNextResetSequenceNo;
   uint32_t mNumProcessAttempts;
 
   nsTArray<RefPtr<RemoteCompositorSession>> mRemoteSessions;
--- a/gfx/thebes/gfxPlatform.cpp
+++ b/gfx/thebes/gfxPlatform.cpp
@@ -2194,18 +2194,18 @@ gfxPlatform::InitAcceleration()
 
   if (Preferences::GetBool("media.hardware-video-decoding.enabled", false) &&
 #ifdef XP_WIN
     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;
-    }
+        sLayersSupportsHardwareVideoDecoding = true;
+      }
   }
 
   sLayersAccelerationPrefsInitialized = true;
 
   if (XRE_IsParentProcess()) {
     Preferences::RegisterCallbackAndCall(VideoDecodingFailedChangedCallback,
                                          "media.hardware-video-decoding.failed",
                                          nullptr,
@@ -2334,16 +2334,20 @@ gfxPlatform::InitWebRenderConfig()
     "Build doesn't include WebRender",
     NS_LITERAL_CSTRING("FEATURE_FAILURE_NO_WEBRENDER"));
 #endif
 
   // gfxFeature is not usable in the GPU process, so we use gfxVars to transmit this feature
   gfxVars::SetUseWebRender(gfxConfig::IsEnabled(Feature::WEBRENDER));
 }
 
+bool gfxPlatform::HardwareVideoDecodingBlacklisted() {
+  return sLayersSupportsHardwareVideoDecoding;
+}
+
 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;
 }
--- a/gfx/thebes/gfxPlatform.h
+++ b/gfx/thebes/gfxPlatform.h
@@ -293,16 +293,21 @@ public:
       return mContentBackend;
     }
 
     /// Return the software backend to use by default.
     mozilla::gfx::BackendType GetSoftwareBackend() {
         return mSoftwareBackend;
     }
 
+    /**
+    * Indicates whether or not hardware video decoding has been blacklisted.
+    */
+    virtual bool HardwareVideoDecodingBlacklisted();
+
     // Return the best content backend available that is compatible with the
     // given layers backend.
     virtual mozilla::gfx::BackendType GetContentBackendFor(mozilla::layers::LayersBackend aLayers) {
       return mContentBackend;
     }
 
     mozilla::gfx::BackendType GetPreferredCanvasBackend() {
       return mPreferredCanvasBackend;
--- a/gfx/thebes/gfxPrefs.h
+++ b/gfx/thebes/gfxPrefs.h
@@ -493,17 +493,19 @@ private:
   DECL_GFX_PREF(Live, "layers.effect.invert",                  LayersEffectInvert, bool, false);
   DECL_GFX_PREF(Once, "layers.enable-tiles",                   LayersTilesEnabled, bool, false);
   DECL_GFX_PREF(Live, "layers.flash-borders",                  FlashLayerBorders, bool, false);
   DECL_GFX_PREF(Once, "layers.force-shmem-tiles",              ForceShmemTiles, bool, false);
   DECL_GFX_PREF(Live, "layers.frame-counter",                  DrawFrameCounter, bool, false);
   DECL_GFX_PREF(Once, "layers.gpu-process.enabled",            GPUProcessEnabled, bool, false);
   DECL_GFX_PREF(Once, "layers.gpu-process.force-enabled",      GPUProcessForceEnabled, bool, false);
   DECL_GFX_PREF(Once, "layers.gpu-process.timeout_ms",         GPUProcessTimeoutMs, int32_t, 5000);
-  DECL_GFX_PREF(Live, "layers.gpu-process.max_restarts",       GPUProcessMaxRestarts, int32_t, 0);
+  DECL_GFX_PREF(Live, "layers.gpu-process.max_restarts",       GPUProcessMaxRestarts, int32_t, 1);
+  // Note: This pref will only be used if it is less than layers.gpu-process.max_restarts.
+  DECL_GFX_PREF(Live, "layers.gpu-process.max_restarts_with_decoder", GPUProcessMaxRestartsWithDecoder, int32_t, 0);
   DECL_GFX_PREF(Live, "layers.low-precision-buffer",           UseLowPrecisionBuffer, bool, false);
   DECL_GFX_PREF(Live, "layers.low-precision-opacity",          LowPrecisionOpacity, float, 1.0f);
   DECL_GFX_PREF(Live, "layers.low-precision-resolution",       LowPrecisionResolution, float, 0.25f);
   DECL_GFX_PREF(Live, "layers.max-active",                     MaxActiveLayers, int32_t, -1);
   DECL_GFX_PREF(Once, "layers.offmainthreadcomposition.force-disabled", LayersOffMainThreadCompositionForceDisabled, bool, false);
   DECL_GFX_PREF(Live, "layers.offmainthreadcomposition.frame-rate", LayersCompositionFrameRate, int32_t,-1);
   DECL_GFX_PREF(Live, "layers.orientation.sync.timeout",       OrientationSyncMillis, uint32_t, (uint32_t)0);
   DECL_GFX_PREF(Once, "layers.prefer-d3d9",                    LayersPreferD3D9, bool, false);