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 487626 3f011c8298138864c9545307ef907bd4125c52ef
parent 486741 16effd5b21ab03629feca04b5b83911bb757394c
child 487627 976a252acb46e36d4d75da85b05805d2c1d2668d
child 487628 4ec8e6b7efa1d0149f60d846a38c260ecd097522
child 487774 7840efc78391216bd87f93d533602e692a818c02
child 487779 a6607b0ffa3e0d73e8a471a2de33da9846786d15
child 487781 7eaf2c9c1d23fc91d99c7359538acc0ed9ee4a30
push id46276
push userbmo:jharris@mozilla.com
push dateTue, 21 Feb 2017 22:02:54 +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/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,
--- a/gfx/thebes/gfxPrefs.h
+++ b/gfx/thebes/gfxPrefs.h
@@ -495,17 +495,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);