Bug 1338011 - Adds an intermediate fallback when the GPU process crashes r?dvander draft
authorJay Harris <jharris@mozilla.com>
Fri, 10 Feb 2017 16:17:20 +1300
changeset 483185 2a324961439818f1931463a89ebc624315280d27
parent 479958 e677ba018b22558fef1d07b74d416fd3a28a5dc3
child 545589 06f6213c82124d0ce8a1ec801d5edaa59595c5df
push id45256
push userbmo:jharris@mozilla.com
push dateMon, 13 Feb 2017 23:55:00 +0000
reviewersdvander
bugs1338011
milestone54.0a1
Bug 1338011 - Adds an intermediate fallback when the GPU process crashes r?dvander MozReview-Commit-ID: 3cu7DlUnYGV
dom/media/platforms/wmf/WMFDecoderModule.cpp
gfx/config/gfxFeature.h
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
@@ -45,17 +45,29 @@ WMFDecoderModule::~WMFDecoderModule()
     NS_ASSERTION(SUCCEEDED(hr), "MFShutdown failed");
   }
 }
 
 /* static */
 void
 WMFDecoderModule::Init()
 {
-  sDXVAEnabled = gfx::gfxVars::CanUseHardwareVideoDecoding();
+  if (XRE_IsContentProcess()) {
+    // Only allow content processes to use DXVA if we're not attempting
+    // to do decoding in the GPU process.
+    sDXVAEnabled = !MediaPrefs::PDMUseGPUDecoder();
+  } else if (XRE_IsGPUProcess()) {
+    // Always allow DXVA in the GPU process.
+    sDXVAEnabled = true;
+  } else {
+    // Never allow DXVA in the UI process.
+    sDXVAEnabled = false;
+  }
+
+  sDXVAEnabled = sDXVAEnabled && gfx::gfxVars::CanUseHardwareVideoDecoding();
 }
 
 /* static */
 int
 WMFDecoderModule::GetNumDecoderThreads()
 {
   int32_t numCores = PR_GetNumberOfProcessors();
 
--- a/gfx/config/gfxFeature.h
+++ b/gfx/config/gfxFeature.h
@@ -20,16 +20,17 @@ namespace gfx {
   _(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")      \
   _(DIRECT_DRAW,                  Feature,      "DirectDraw")                     \
   _(GPU_PROCESS,                  Feature,      "GPU Process")                    \
+  _(GPU_VIDEO_DECODING,           Feature,      "GPU 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/ipc/GPUProcessManager.cpp
+++ b/gfx/ipc/GPUProcessManager.cpp
@@ -154,16 +154,27 @@ GPUProcessManager::DisableGPUProcess(con
   gfxConfig::SetFailed(Feature::GPU_PROCESS, FeatureStatus::Failed, aMessage);
   gfxCriticalNote << aMessage;
 
   DestroyProcess();
   ShutdownVsyncIOThread();
 }
 
 void
+GPUProcessManager::DisableVideoDecodingOnGPUProcess(const char* aMessage)
+{
+  if (!gfxConfig::IsEnabled(Feature::GPU_VIDEO_DECODING)) {
+    return;
+  }
+
+  gfxConfig::SetFailed(Feature::GPU_VIDEO_DECODING, FeatureStatus::Failed, aMessage);
+  gfxCriticalNote << aMessage;
+}
+
+void
 GPUProcessManager::EnsureGPUReady()
 {
   if (mProcess && !mProcess->IsConnected()) {
     if (!mProcess->WaitForLaunch()) {
       // If this fails, we should have fired OnProcessLaunchComplete and
       // removed the process.
       MOZ_ASSERT(!mProcess && !mGPUChild);
       return;
@@ -364,16 +375,23 @@ GPUProcessManager::OnProcessDeviceReset(
 
 void
 GPUProcessManager::OnProcessUnexpectedShutdown(GPUProcessHost* aHost)
 {
   MOZ_ASSERT(mProcess && mProcess == aHost);
 
   DestroyProcess();
 
+  if (mNumProcessAttempts > uint32_t(gfxPrefs::GPUProcessMaxRestartsWithDecoder())) {
+    char disableMessage[64];
+    SprintfLiteral(disableMessage, "VideoDecoding on GPU process disabled after %d attempts",
+                   mNumProcessAttempts);
+    DisableVideoDecodingOnGPUProcess(disableMessage);
+  }
+
   if (mNumProcessAttempts > uint32_t(gfxPrefs::GPUProcessMaxRestarts())) {
     char disableMessage[64];
     SprintfLiteral(disableMessage, "GPU process disabled after %d attempts",
                    mNumProcessAttempts);
     DisableGPUProcess(disableMessage);
   }
 
   HandleProcessLost();
@@ -784,17 +802,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()
+      || !gfxConfig::IsEnabled(Feature::GPU_VIDEO_DECODING)) {
     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
@@ -182,16 +182,20 @@ private:
   void UnregisterSession(RemoteCompositorSession* aSession);
 
 private:
   GPUProcessManager();
 
   // Permanently disable the GPU process and record a message why.
   void DisableGPUProcess(const char* aMessage);
 
+  // Permanently disable Video Decoding on the GPU process and record a reason
+  // why.
+  void DisableVideoDecodingOnGPUProcess(const char* aMessage);
+
   // Shutdown the GPU process.
   void CleanShutdown();
   void DestroyProcess();
 
   void HandleProcessLost();
 
   void EnsureVsyncIOThread();
   void ShutdownVsyncIOThread();
--- a/gfx/thebes/gfxPlatform.cpp
+++ b/gfx/thebes/gfxPlatform.cpp
@@ -2214,16 +2214,17 @@ gfxPlatform::InitGPUProcessPrefs()
 {
   // We want to hide this from about:support, so only set a default if the
   // pref is known to be true.
   if (!gfxPrefs::GPUProcessEnabled() && !gfxPrefs::GPUProcessForceEnabled()) {
     return;
   }
 
   FeatureState& gpuProc = gfxConfig::GetFeature(Feature::GPU_PROCESS);
+  FeatureState& gpuVideoDecode = gfxConfig::GetFeature(Feature::GPU_VIDEO_DECODING);
 
   // We require E10S - otherwise, there is very little benefit to the GPU
   // process, since the UI process must still use acceleration for
   // performance.
   if (!BrowserTabsRemoteAutostart()) {
     gpuProc.DisableByDefault(
       FeatureStatus::Unavailable,
       "Multi-process mode is not enabled",
@@ -2234,28 +2235,40 @@ gfxPlatform::InitGPUProcessPrefs()
       true,
       gfxPrefs::GetGPUProcessEnabledPrefDefault());
   }
 
   if (gfxPrefs::GPUProcessForceEnabled()) {
     gpuProc.UserForceEnable("User force-enabled via pref");
   }
 
+  gpuVideoDecode.InitOrUpdate(gpuProc.IsEnabled(), gpuProc.GetValue(), "Setting from GPU Process feature");
+
   if (InSafeMode()) {
     gpuProc.ForceDisable(
       FeatureStatus::Blocked,
       "Safe-mode is enabled",
       NS_LITERAL_CSTRING("FEATURE_FAILURE_SAFE_MODE"));
+
+    gpuVideoDecode.ForceDisable(
+      FeatureStatus::Blocked,
+      "Safe-mode is enabled",
+      NS_LITERAL_CSTRING("FEATURE_FAILURE_SAFE_MODE"));
     return;
   }
   if (gfxPrefs::LayerScopeEnabled()) {
     gpuProc.ForceDisable(
       FeatureStatus::Blocked,
       "LayerScope does not work in the GPU process",
       NS_LITERAL_CSTRING("FEATURE_FAILURE_LAYERSCOPE"));
+
+    gpuVideoDecode.ForceDisable(
+      FeatureStatus::Blocked,
+      "LayerScope does not work in the GPU process",
+      NS_LITERAL_CSTRING("FEATURE_FAILURE_LAYERSCOPE"));
     return;
   }
 }
 
 void
 gfxPlatform::InitCompositorAccelerationPrefs()
 {
   const char *acceleratedEnv = PR_GetEnv("MOZ_ACCELERATED");
--- a/gfx/thebes/gfxPrefs.h
+++ b/gfx/thebes/gfxPrefs.h
@@ -491,17 +491,18 @@ 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);
+  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);