Bug 1338011 - Adds an intermediate fallback when the GPU process crashes r?dvander
MozReview-Commit-ID: 3cu7DlUnYGV
--- 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);