Bug 1684170 - Decouple WebRender and Software WebRender gfxConfig features. r=jrmuizel

Lack of support of (hardware) WebRender should not block Software
WebRender support. This can happen when ANGLE isn't supported, for
example.

Differential Revision: https://phabricator.services.mozilla.com/D100445
This commit is contained in:
Andrew Osmond 2021-01-14 19:59:10 +00:00
parent 869d44f53c
commit 9168cac006
5 changed files with 76 additions and 59 deletions

View File

@ -266,7 +266,11 @@ void gfxConfigManager::ConfigureWebRender() {
// Prior to bug 1523788, the `prefEnabled` check was only done on Nightly,
// so as to prevent random users from easily enabling WebRender on
// unqualified hardware in beta/release.
if (mWrEnvForceEnabled) {
if (mWrSoftwareForceEnabled) {
MOZ_ASSERT(mFeatureWrSoftware->IsEnabled());
mFeatureWr->UserDisable("User force-enabled software WR",
"FEATURE_FAILURE_USER_FORCE_ENABLED_SW_WR"_ns);
} else if (mWrEnvForceEnabled) {
mFeatureWr->UserForceEnable("Force enabled by envvar");
} else if (mWrForceEnabled) {
mFeatureWr->UserForceEnable("Force enabled by pref");
@ -282,21 +286,12 @@ void gfxConfigManager::ConfigureWebRender() {
if (!mFeatureWrQualified->IsEnabled()) {
// No qualified hardware. If we haven't allowed software fallback,
// then we need to disable WR.
if (!mFeatureWrSoftware->IsEnabled()) {
mFeatureWr->Disable(FeatureStatus::Disabled, "Not qualified",
"FEATURE_FAILURE_NOT_QUALIFIED"_ns);
}
} else {
// Otherwise we have qualified hardware, so we can disable the software
// feature. Note that this doesn't override the force-enabled state set by
// the pref, so the pref will still enable software.
mFeatureWrSoftware->Disable(FeatureStatus::Disabled,
"Overriden by qualified hardware",
"FEATURE_FAILURE_OVERRIDEN"_ns);
mFeatureWr->Disable(FeatureStatus::Disabled, "Not qualified",
"FEATURE_FAILURE_NOT_QUALIFIED"_ns);
}
// HW_COMPOSITING being disabled implies interfacing with the GPU might break
if (!mFeatureHwCompositing->IsEnabled() && !mFeatureWrSoftware->IsEnabled()) {
if (!mFeatureHwCompositing->IsEnabled()) {
mFeatureWr->ForceDisable(FeatureStatus::UnavailableNoHwCompositing,
"Hardware compositing is disabled",
"FEATURE_FAILURE_WEBRENDER_NEED_HWCOMP"_ns);
@ -306,6 +301,9 @@ void gfxConfigManager::ConfigureWebRender() {
mFeatureWr->ForceDisable(FeatureStatus::UnavailableInSafeMode,
"Safe-mode is enabled",
"FEATURE_FAILURE_SAFE_MODE"_ns);
mFeatureWrSoftware->ForceDisable(FeatureStatus::UnavailableInSafeMode,
"Safe-mode is enabled",
"FEATURE_FAILURE_SAFE_MODE"_ns);
}
if (mXRenderEnabled) {
@ -313,6 +311,9 @@ void gfxConfigManager::ConfigureWebRender() {
// default. If the user opts into it don't enable webrender.
mFeatureWr->ForceDisable(FeatureStatus::Blocked, "XRender is enabled",
"FEATURE_FAILURE_XRENDER"_ns);
mFeatureWrSoftware->ForceDisable(FeatureStatus::Blocked,
"XRender is enabled",
"FEATURE_FAILURE_XRENDER"_ns);
}
mFeatureWrAngle->EnableByDefault();
@ -328,7 +329,7 @@ void gfxConfigManager::ConfigureWebRender() {
mFeatureWrAngle->ForceDisable(
FeatureStatus::UnavailableNoGpuProcess, "GPU Process is disabled",
"FEATURE_FAILURE_GPU_PROCESS_DISABLED"_ns);
} else if (!mFeatureWr->IsEnabled()) {
} else if (!mFeatureWr->IsEnabled() && !mFeatureWrSoftware->IsEnabled()) {
mFeatureWrAngle->ForceDisable(FeatureStatus::Unavailable,
"WebRender disabled",
"FEATURE_FAILURE_WR_DISABLED"_ns);
@ -399,7 +400,7 @@ void gfxConfigManager::ConfigureWebRender() {
// Initialize WebRender partial present config.
// Partial present is used only when WebRender compositor is not used.
if (mWrPartialPresent) {
if (mFeatureWr->IsEnabled()) {
if (mFeatureWr->IsEnabled() || mFeatureWrSoftware->IsEnabled()) {
mFeatureWrPartial->EnableByDefault();
}
}

View File

@ -455,33 +455,30 @@ bool GPUProcessManager::DisableWebRenderConfig(wr::WebRenderError aError,
}
// Disable WebRender
if (aError == wr::WebRenderError::INITIALIZE) {
gfx::gfxConfig::GetFeature(gfx::Feature::WEBRENDER)
.ForceDisable(gfx::FeatureStatus::Unavailable,
"WebRender initialization failed", aMsg);
gfxPlatform::DisableWebRender(gfx::FeatureStatus::Unavailable,
"WebRender initialization failed", aMsg);
} else if (aError == wr::WebRenderError::MAKE_CURRENT) {
gfx::gfxConfig::GetFeature(gfx::Feature::WEBRENDER)
.ForceDisable(gfx::FeatureStatus::Unavailable,
"Failed to make render context current",
"FEATURE_FAILURE_WEBRENDER_MAKE_CURRENT"_ns);
gfxPlatform::DisableWebRender(gfx::FeatureStatus::Unavailable,
"Failed to make render context current",
"FEATURE_FAILURE_WEBRENDER_MAKE_CURRENT"_ns);
} else if (aError == wr::WebRenderError::RENDER) {
gfx::gfxConfig::GetFeature(gfx::Feature::WEBRENDER)
.ForceDisable(gfx::FeatureStatus::Unavailable,
"Failed to render WebRender",
"FEATURE_FAILURE_WEBRENDER_RENDER"_ns);
gfxPlatform::DisableWebRender(gfx::FeatureStatus::Unavailable,
"Failed to render WebRender",
"FEATURE_FAILURE_WEBRENDER_RENDER"_ns);
} else if (aError == wr::WebRenderError::NEW_SURFACE) {
gfx::gfxConfig::GetFeature(gfx::Feature::WEBRENDER)
.ForceDisable(gfx::FeatureStatus::Unavailable,
"Failed to create new surface",
"FEATURE_FAILURE_WEBRENDER_NEW_SURFACE"_ns);
gfxPlatform::DisableWebRender(gfx::FeatureStatus::Unavailable,
"Failed to create new surface",
"FEATURE_FAILURE_WEBRENDER_NEW_SURFACE"_ns);
} else if (aError == wr::WebRenderError::EXCESSIVE_RESETS) {
gfx::gfxConfig::GetFeature(gfx::Feature::WEBRENDER)
.ForceDisable(gfx::FeatureStatus::Unavailable,
"Device resets exceeded threshold",
"FEATURE_FAILURE_WEBRENDER_EXCESSIVE_RESETS"_ns);
gfxPlatform::DisableWebRender(
gfx::FeatureStatus::Unavailable, "Device resets exceeded threshold",
"FEATURE_FAILURE_WEBRENDER_EXCESSIVE_RESETS"_ns);
} else {
MOZ_ASSERT_UNREACHABLE("Invalid value");
gfxPlatform::DisableWebRender(gfx::FeatureStatus::Unavailable,
"Unhandled failure reason",
"FEATURE_FAILURE_WEBRENDER_UNHANDLED"_ns);
}
gfx::gfxVars::SetUseWebRender(false);
gfx::gfxVars::SetUseWebRenderDCompVideoOverlayWin(false);
#if defined(MOZ_WIDGET_ANDROID)

View File

@ -419,6 +419,7 @@ TEST_F(GfxConfigManager, WebRenderDisabledWithAllowSoftwareGPUProcess) {
TEST_F(GfxConfigManager, WebRenderSafeMode) {
mSafeMode = true;
mMockGfxInfo->mStatusWrSoftware = nsIGfxInfo::FEATURE_ALLOW_ALWAYS;
ConfigureWebRender();
EXPECT_TRUE(mFeatures.mWrQualified.IsEnabled());
@ -725,6 +726,7 @@ TEST_F(GfxConfigManager, WebRenderNvidiaLowMixedRefreshRateNotNightly) {
TEST_F(GfxConfigManager, WebRenderWhenXRenderEnabled) {
mXRenderEnabled = true;
mMockGfxInfo->mStatusWrSoftware = nsIGfxInfo::FEATURE_ALLOW_ALWAYS;
ConfigureWebRender();
EXPECT_TRUE(mFeatures.mWrQualified.IsEnabled());
@ -742,8 +744,7 @@ TEST_F(GfxConfigManager, WebRenderWhenXRenderEnabled) {
TEST_F(GfxConfigManager, WebRenderSofwareAndQualified) {
// Enabling software in gfxInfo gives the same results
// as the default configuration, since qualified hardware
// takes precedence and we won't enable the software
// feature.
// takes precedence, but we still enable the software feature.
mMockGfxInfo->mStatusWrSoftware = nsIGfxInfo::FEATURE_ALLOW_ALWAYS;
ConfigureWebRender();
@ -756,7 +757,7 @@ TEST_F(GfxConfigManager, WebRenderSofwareAndQualified) {
EXPECT_TRUE(mFeatures.mHwCompositing.IsEnabled());
EXPECT_TRUE(mFeatures.mGPUProcess.IsEnabled());
EXPECT_TRUE(mFeatures.mD3D11HwAngle.IsEnabled());
EXPECT_FALSE(mFeatures.mWrSoftware.IsEnabled());
EXPECT_TRUE(mFeatures.mWrSoftware.IsEnabled());
}
TEST_F(GfxConfigManager, WebRenderSofwareAndNotQualified) {
@ -767,10 +768,10 @@ TEST_F(GfxConfigManager, WebRenderSofwareAndNotQualified) {
ConfigureWebRender();
EXPECT_FALSE(mFeatures.mWrQualified.IsEnabled());
EXPECT_TRUE(mFeatures.mWr.IsEnabled());
EXPECT_TRUE(mFeatures.mWrCompositor.IsEnabled());
EXPECT_FALSE(mFeatures.mWr.IsEnabled());
EXPECT_FALSE(mFeatures.mWrCompositor.IsEnabled());
EXPECT_TRUE(mFeatures.mWrAngle.IsEnabled());
EXPECT_TRUE(mFeatures.mWrDComp.IsEnabled());
EXPECT_FALSE(mFeatures.mWrDComp.IsEnabled());
EXPECT_TRUE(mFeatures.mWrPartial.IsEnabled());
EXPECT_TRUE(mFeatures.mHwCompositing.IsEnabled());
EXPECT_TRUE(mFeatures.mGPUProcess.IsEnabled());
@ -836,9 +837,9 @@ TEST_F(GfxConfigManager, WebRenderForceSoftwareForceDisabledEnvvar) {
EXPECT_TRUE(mFeatures.mWrQualified.IsEnabled());
EXPECT_FALSE(mFeatures.mWr.IsEnabled());
EXPECT_FALSE(mFeatures.mWrCompositor.IsEnabled());
EXPECT_FALSE(mFeatures.mWrAngle.IsEnabled());
EXPECT_TRUE(mFeatures.mWrAngle.IsEnabled());
EXPECT_FALSE(mFeatures.mWrDComp.IsEnabled());
EXPECT_FALSE(mFeatures.mWrPartial.IsEnabled());
EXPECT_TRUE(mFeatures.mWrPartial.IsEnabled());
EXPECT_TRUE(mFeatures.mHwCompositing.IsEnabled());
EXPECT_TRUE(mFeatures.mGPUProcess.IsEnabled());
EXPECT_TRUE(mFeatures.mD3D11HwAngle.IsEnabled());
@ -905,10 +906,10 @@ TEST_F(GfxConfigManager, WebRenderForceSoftwareForceEnabledEnvvar) {
ConfigureWebRender();
EXPECT_FALSE(mFeatures.mWrQualified.IsEnabled());
EXPECT_TRUE(mFeatures.mWr.IsEnabled());
EXPECT_TRUE(mFeatures.mWrCompositor.IsEnabled());
EXPECT_FALSE(mFeatures.mWr.IsEnabled());
EXPECT_FALSE(mFeatures.mWrCompositor.IsEnabled());
EXPECT_TRUE(mFeatures.mWrAngle.IsEnabled());
EXPECT_TRUE(mFeatures.mWrDComp.IsEnabled());
EXPECT_FALSE(mFeatures.mWrDComp.IsEnabled());
EXPECT_TRUE(mFeatures.mWrPartial.IsEnabled());
EXPECT_TRUE(mFeatures.mHwCompositing.IsEnabled());
EXPECT_TRUE(mFeatures.mGPUProcess.IsEnabled());

View File

@ -2703,29 +2703,29 @@ void gfxPlatform::InitWebRenderConfig() {
manager.Init();
manager.ConfigureWebRender();
bool hasHardware = gfxConfig::IsEnabled(Feature::WEBRENDER);
bool hasSoftware = gfxConfig::IsEnabled(Feature::WEBRENDER_SOFTWARE);
bool hasWebRender = hasHardware || hasSoftware;
#ifdef XP_WIN
if (gfxConfig::IsEnabled(Feature::WEBRENDER_ANGLE)) {
gfxVars::SetUseWebRenderANGLE(gfxConfig::IsEnabled(Feature::WEBRENDER));
gfxVars::SetUseWebRenderANGLE(hasWebRender);
}
#endif
if (Preferences::GetBool("gfx.webrender.program-binary-disk", false)) {
gfxVars::SetUseWebRenderProgramBinaryDisk(
gfxConfig::IsEnabled(Feature::WEBRENDER));
gfxVars::SetUseWebRenderProgramBinaryDisk(hasWebRender);
}
if (StaticPrefs::gfx_webrender_use_optimized_shaders_AtStartup()) {
gfxVars::SetUseWebRenderOptimizedShaders(
gfxConfig::IsEnabled(Feature::WEBRENDER));
gfxVars::SetUseWebRenderOptimizedShaders(hasWebRender);
}
gfxVars::SetUseSoftwareWebRender(
gfxConfig::IsEnabled(Feature::WEBRENDER) &&
gfxConfig::IsEnabled(Feature::WEBRENDER_SOFTWARE));
gfxVars::SetUseSoftwareWebRender(!hasHardware && hasSoftware);
// gfxFeature is not usable in the GPU process, so we use gfxVars to transmit
// this feature
if (gfxConfig::IsEnabled(Feature::WEBRENDER)) {
if (hasWebRender) {
gfxVars::SetUseWebRender(true);
reporter.SetSuccessful();
@ -3350,13 +3350,26 @@ void gfxPlatform::NotifyCompositorCreated(LayersBackend aBackend) {
}
/* static */
void gfxPlatform::NotifyGPUProcessDisabled() {
void gfxPlatform::DisableWebRender(FeatureStatus aStatus, const char* aMessage,
const nsACString& aFailureId) {
if (gfxConfig::IsEnabled(Feature::WEBRENDER)) {
gfxConfig::GetFeature(Feature::WEBRENDER)
.ForceDisable(FeatureStatus::Unavailable, "GPU Process is disabled",
"FEATURE_FAILURE_GPU_PROCESS_DISABLED"_ns);
gfxVars::SetUseWebRender(false);
.ForceDisable(aStatus, aMessage, aFailureId);
}
// TODO(aosmond): When WebRender Software replaces Basic, we must not disable
// it because of GPU process crashes, etc.
if (gfxConfig::IsEnabled(Feature::WEBRENDER_SOFTWARE)) {
gfxConfig::GetFeature(Feature::WEBRENDER_SOFTWARE)
.ForceDisable(aStatus, aMessage, aFailureId);
}
gfxVars::SetUseWebRender(false);
gfxVars::SetUseSoftwareWebRender(false);
}
/* static */
void gfxPlatform::NotifyGPUProcessDisabled() {
DisableWebRender(FeatureStatus::Unavailable, "GPU Process is disabled",
"FEATURE_FAILURE_GPU_PROCESS_DISABLED"_ns);
gfxVars::SetRemoteCanvasEnabled(false);
}

View File

@ -13,6 +13,7 @@
#include "nsCOMPtr.h"
#include "nsUnicodeScriptCodes.h"
#include "gfxTelemetry.h"
#include "gfxTypes.h"
#include "gfxSkipChars.h"
@ -790,6 +791,10 @@ class gfxPlatform : public mozilla::layers::MemoryPressureListener {
static const char* WebRenderResourcePathOverride();
static void DisableWebRender(mozilla::gfx::FeatureStatus aStatus,
const char* aMessage,
const nsACString& aFailureId);
void NotifyFrameStats(nsTArray<mozilla::layers::FrameStats>&& aFrameStats);
virtual void OnMemoryPressure(