gfxConfigManager.cpp (13472B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */ 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #include "mozilla/gfx/gfxConfigManager.h" 8 #include "mozilla/gfx/gfxVars.h" 9 #include "mozilla/Preferences.h" 10 #include "mozilla/Components.h" 11 #include "mozilla/StaticPrefs_gfx.h" 12 #include "mozilla/StaticPrefs_layers.h" 13 #include "gfxConfig.h" 14 #include "gfxPlatform.h" 15 #include "nsIGfxInfo.h" 16 #include "nsPrintfCString.h" 17 #include "nsXULAppAPI.h" 18 19 #ifdef XP_WIN 20 # include "mozilla/gfx/DeviceManagerDx.h" 21 # include "mozilla/gfx/DisplayConfigWindows.h" 22 #endif 23 24 namespace mozilla { 25 namespace gfx { 26 27 void gfxConfigManager::Init() { 28 MOZ_ASSERT(XRE_IsParentProcess()); 29 30 EmplaceUserPref("gfx.webrender.compositor", mWrCompositorEnabled); 31 mWrForceEnabled = gfxPlatform::WebRenderPrefEnabled(); 32 mWrSoftwareForceEnabled = StaticPrefs::gfx_webrender_software_AtStartup(); 33 mWrCompositorForceEnabled = 34 #ifdef MOZ_WAYLAND 35 StaticPrefs::gfx_wayland_hdr_AtStartup() || 36 StaticPrefs::gfx_wayland_hdr_force_enabled_AtStartup() || 37 #endif 38 StaticPrefs::gfx_webrender_compositor_force_enabled_AtStartup(); 39 mWrForcePartialPresent = 40 StaticPrefs::gfx_webrender_force_partial_present_AtStartup(); 41 mWrPartialPresent = 42 StaticPrefs::gfx_webrender_max_partial_present_rects_AtStartup() > 0; 43 EmplaceUserPref(StaticPrefs::GetPrefName_gfx_webrender_program_binary_disk(), 44 mWrShaderCache); 45 mWrOptimizedShaders = 46 StaticPrefs::gfx_webrender_use_optimized_shaders_AtStartup(); 47 mWrScissoredCacheClearsEnabled = 48 StaticPrefs::gfx_webrender_scissored_cache_clears_enabled_AtStartup(); 49 mWrScissoredCacheClearsForceEnabled = StaticPrefs:: 50 gfx_webrender_scissored_cache_clears_force_enabled_AtStartup(); 51 #ifdef XP_WIN 52 mWrForceAngle = StaticPrefs::gfx_webrender_force_angle_AtStartup(); 53 mWrForceAngleNoGPUProcess = StaticPrefs:: 54 gfx_webrender_enabled_no_gpu_process_with_angle_win_AtStartup(); 55 mWrDCompWinEnabled = 56 Preferences::GetBool("gfx.webrender.dcomp-win.enabled", false); 57 #endif 58 59 mWrEnvForceEnabled = gfxPlatform::WebRenderEnvvarEnabled(); 60 61 #ifdef XP_WIN 62 DeviceManagerDx::Get()->CheckHardwareStretchingSupport(mHwStretchingSupport); 63 mScaledResolution = HasScaledResolution(); 64 mWrCompositorDCompRequired = true; 65 #else 66 ++mHwStretchingSupport.mBoth; 67 #endif 68 69 #ifdef MOZ_WIDGET_GTK 70 mDisableHwCompositingNoWr = true; 71 #endif 72 73 #ifdef NIGHTLY_BUILD 74 mIsNightly = true; 75 #endif 76 #ifdef EARLY_BETA_OR_EARLIER 77 mIsEarlyBetaOrEarlier = true; 78 #endif 79 mSafeMode = gfxPlatform::InSafeMode(); 80 81 mGfxInfo = components::GfxInfo::Service(); 82 83 mFeatureWr = &gfxConfig::GetFeature(Feature::WEBRENDER); 84 mFeatureWrCompositor = &gfxConfig::GetFeature(Feature::WEBRENDER_COMPOSITOR); 85 mFeatureWrAngle = &gfxConfig::GetFeature(Feature::WEBRENDER_ANGLE); 86 mFeatureWrDComp = &gfxConfig::GetFeature(Feature::WEBRENDER_DCOMP_PRESENT); 87 mFeatureWrPartial = &gfxConfig::GetFeature(Feature::WEBRENDER_PARTIAL); 88 mFeatureWrShaderCache = 89 &gfxConfig::GetFeature(Feature::WEBRENDER_SHADER_CACHE); 90 mFeatureWrOptimizedShaders = 91 &gfxConfig::GetFeature(Feature::WEBRENDER_OPTIMIZED_SHADERS); 92 mFeatureWrScissoredCacheClears = 93 &gfxConfig::GetFeature(Feature::WEBRENDER_SCISSORED_CACHE_CLEARS); 94 95 mFeatureHwCompositing = &gfxConfig::GetFeature(Feature::HW_COMPOSITING); 96 #ifdef XP_WIN 97 mFeatureD3D11HwAngle = &gfxConfig::GetFeature(Feature::D3D11_HW_ANGLE); 98 mFeatureD3D11Compositing = &gfxConfig::GetFeature(Feature::D3D11_COMPOSITING); 99 #endif 100 mFeatureGPUProcess = &gfxConfig::GetFeature(Feature::GPU_PROCESS); 101 mFeatureGLNorm16Textures = 102 &gfxConfig::GetFeature(Feature::GL_NORM16_TEXTURES); 103 } 104 105 void gfxConfigManager::EmplaceUserPref(const char* aPrefName, 106 Maybe<bool>& aValue) { 107 if (Preferences::HasUserValue(aPrefName)) { 108 aValue.emplace(Preferences::GetBool(aPrefName, false)); 109 } 110 } 111 112 void gfxConfigManager::ConfigureFromBlocklist(long aFeature, 113 FeatureState* aFeatureState) { 114 MOZ_ASSERT(aFeatureState); 115 116 nsCString blockId; 117 int32_t status; 118 if (!NS_SUCCEEDED(mGfxInfo->GetFeatureStatus(aFeature, blockId, &status))) { 119 aFeatureState->Disable(FeatureStatus::BlockedNoGfxInfo, "gfxInfo is broken", 120 "FEATURE_FAILURE_NO_GFX_INFO"_ns); 121 return; 122 } 123 124 switch (status) { 125 case nsIGfxInfo::FEATURE_STATUS_OK: 126 case nsIGfxInfo::FEATURE_ALLOW_ALWAYS: 127 break; 128 case nsIGfxInfo::FEATURE_ALLOW_QUALIFIED: 129 MOZ_ASSERT_UNREACHABLE("Allowing only qualified, but needs experiment?"); 130 break; 131 case nsIGfxInfo::FEATURE_DENIED: 132 aFeatureState->Disable(FeatureStatus::Denied, "Not on allowlist", 133 blockId); 134 break; 135 default: 136 aFeatureState->Disable(FeatureStatus::Blocklisted, 137 "Blocklisted by gfxInfo", blockId); 138 break; 139 } 140 } 141 142 void gfxConfigManager::ConfigureWebRender() { 143 MOZ_ASSERT(XRE_IsParentProcess()); 144 MOZ_ASSERT(mFeatureWr); 145 MOZ_ASSERT(mFeatureWrCompositor); 146 MOZ_ASSERT(mFeatureWrAngle); 147 MOZ_ASSERT(mFeatureWrDComp); 148 MOZ_ASSERT(mFeatureWrPartial); 149 MOZ_ASSERT(mFeatureWrShaderCache); 150 MOZ_ASSERT(mFeatureWrOptimizedShaders); 151 MOZ_ASSERT(mFeatureWrScissoredCacheClears); 152 MOZ_ASSERT(mFeatureHwCompositing); 153 MOZ_ASSERT(mFeatureGPUProcess); 154 MOZ_ASSERT(mFeatureGLNorm16Textures); 155 156 // Initialize WebRender native compositor usage 157 mFeatureWrCompositor->SetDefaultFromPref("gfx.webrender.compositor", true, 158 false, mWrCompositorEnabled); 159 160 if (mWrCompositorForceEnabled) { 161 mFeatureWrCompositor->UserForceEnable("Force enabled by pref"); 162 } 163 164 ConfigureFromBlocklist(nsIGfxInfo::FEATURE_WEBRENDER_COMPOSITOR, 165 mFeatureWrCompositor); 166 167 // Disable native compositor when hardware stretching is not supported. It is 168 // for avoiding a problem like Bug 1618370. 169 // XXX Is there a better check for Bug 1618370? 170 if (!mHwStretchingSupport.IsFullySupported() && mScaledResolution) { 171 nsPrintfCString failureId( 172 "FEATURE_FAILURE_NO_HARDWARE_STRETCHING_B%uW%uF%uN%uE%u", 173 mHwStretchingSupport.mBoth, mHwStretchingSupport.mWindowOnly, 174 mHwStretchingSupport.mFullScreenOnly, mHwStretchingSupport.mNone, 175 mHwStretchingSupport.mError); 176 mFeatureWrCompositor->Disable(FeatureStatus::Unavailable, 177 "No hardware stretching support", failureId); 178 } 179 180 mFeatureWr->EnableByDefault(); 181 182 // envvar works everywhere; note that we need this for testing in CI. 183 // Prior to bug 1523788, the `prefEnabled` check was only done on Nightly, 184 // so as to prevent random users from easily enabling WebRender on 185 // unqualified hardware in beta/release. 186 if (mWrSoftwareForceEnabled) { 187 mFeatureWr->UserDisable("User force-enabled software WR", 188 "FEATURE_FAILURE_USER_FORCE_ENABLED_SW_WR"_ns); 189 } else if (mWrEnvForceEnabled) { 190 mFeatureWr->UserForceEnable("Force enabled by envvar"); 191 } else if (mWrForceEnabled) { 192 mFeatureWr->UserForceEnable("Force enabled by pref"); 193 } 194 195 ConfigureFromBlocklist(nsIGfxInfo::FEATURE_WEBRENDER, mFeatureWr); 196 197 // HW_COMPOSITING being disabled implies interfacing with the GPU might break 198 if (!mFeatureHwCompositing->IsEnabled()) { 199 mFeatureWr->ForceDisable(FeatureStatus::UnavailableNoHwCompositing, 200 "Hardware compositing is disabled", 201 "FEATURE_FAILURE_WEBRENDER_NEED_HWCOMP"_ns); 202 } 203 204 if (mSafeMode) { 205 mFeatureWr->ForceDisable(FeatureStatus::UnavailableInSafeMode, 206 "Safe-mode is enabled", 207 "FEATURE_FAILURE_SAFE_MODE"_ns); 208 } 209 210 mFeatureWrAngle->EnableByDefault(); 211 if (mFeatureD3D11HwAngle) { 212 if (mWrForceAngle) { 213 if (!mFeatureD3D11HwAngle->IsEnabled()) { 214 mFeatureWrAngle->ForceDisable(FeatureStatus::UnavailableNoAngle, 215 "ANGLE is disabled", 216 mFeatureD3D11HwAngle->GetFailureId()); 217 } else if (!mFeatureGPUProcess->IsEnabled() && 218 !mWrForceAngleNoGPUProcess) { 219 // WebRender with ANGLE relies on the GPU process when on Windows 220 mFeatureWrAngle->ForceDisable( 221 FeatureStatus::UnavailableNoGpuProcess, "GPU Process is disabled", 222 "FEATURE_FAILURE_GPU_PROCESS_DISABLED"_ns); 223 } 224 } else { 225 mFeatureWrAngle->Disable(FeatureStatus::Disabled, "ANGLE is not forced", 226 "FEATURE_FAILURE_ANGLE_NOT_FORCED"_ns); 227 } 228 } else { 229 mFeatureWrAngle->Disable(FeatureStatus::Unavailable, "OS not supported", 230 "FEATURE_FAILURE_OS_NOT_SUPPORTED"_ns); 231 } 232 233 if (mWrForceAngle && mFeatureWr->IsEnabled() && 234 !mFeatureWrAngle->IsEnabled()) { 235 // Ensure we disable WebRender if ANGLE is unavailable and it is required. 236 mFeatureWr->ForceDisable(FeatureStatus::UnavailableNoAngle, 237 "ANGLE is disabled", 238 mFeatureWrAngle->GetFailureId()); 239 } 240 241 if (!mFeatureWr->IsEnabled() && mDisableHwCompositingNoWr) { 242 if (mFeatureHwCompositing->IsEnabled()) { 243 // Hardware compositing should be disabled by default if we aren't using 244 // WebRender. We had to check if it is enabled at all, because it may 245 // already have been forced disabled (e.g. safe mode, headless). It may 246 // still be forced on by the user, and if so, this should have no effect. 247 mFeatureHwCompositing->Disable(FeatureStatus::Blocked, 248 "Acceleration blocked by platform", ""_ns); 249 } 250 } 251 252 mFeatureWrDComp->EnableByDefault(); 253 254 if (!mWrDCompWinEnabled) { 255 mFeatureWrDComp->UserDisable("User disabled via pref", 256 "FEATURE_FAILURE_DCOMP_PREF_DISABLED"_ns); 257 } 258 259 ConfigureFromBlocklist(nsIGfxInfo::FEATURE_WEBRENDER_DCOMP, mFeatureWrDComp); 260 261 if (!mFeatureGPUProcess->IsEnabled()) { 262 mFeatureWrDComp->Disable(FeatureStatus::Unavailable, "Requires GPU process", 263 "FEATURE_FAILURE_NO_GPU_PROCESS"_ns); 264 } 265 266 mFeatureWrDComp->MaybeSetFailed( 267 mFeatureWr->IsEnabled(), FeatureStatus::Unavailable, "Requires WebRender", 268 "FEATURE_FAILURE_DCOMP_NOT_WR"_ns); 269 mFeatureWrDComp->MaybeSetFailed(mFeatureWrAngle->IsEnabled(), 270 FeatureStatus::Unavailable, "Requires ANGLE", 271 "FEATURE_FAILURE_DCOMP_NOT_ANGLE"_ns); 272 273 if (!mFeatureWrDComp->IsEnabled() && mWrCompositorDCompRequired) { 274 mFeatureWrCompositor->ForceDisable(FeatureStatus::Unavailable, 275 "No DirectComposition usage", 276 mFeatureWrDComp->GetFailureId()); 277 } 278 279 // Initialize WebRender partial present config. 280 // Partial present is used only when WebRender compositor is not used. 281 mFeatureWrPartial->SetDefault(mWrPartialPresent, FeatureStatus::Disabled, 282 "User disabled via pref"); 283 if (mWrForcePartialPresent) { 284 mFeatureWrPartial->UserForceEnable("Force enabled by pref"); 285 } 286 287 ConfigureFromBlocklist(nsIGfxInfo::FEATURE_WEBRENDER_PARTIAL_PRESENT, 288 mFeatureWrPartial); 289 290 mFeatureWrShaderCache->SetDefaultFromPref( 291 StaticPrefs::GetPrefName_gfx_webrender_program_binary_disk(), true, 292 StaticPrefs::GetPrefDefault_gfx_webrender_program_binary_disk(), 293 mWrShaderCache); 294 ConfigureFromBlocklist(nsIGfxInfo::FEATURE_WEBRENDER_SHADER_CACHE, 295 mFeatureWrShaderCache); 296 if (!mFeatureWr->IsEnabled()) { 297 mFeatureWrShaderCache->ForceDisable(FeatureStatus::Unavailable, 298 "WebRender disabled", 299 "FEATURE_FAILURE_WR_DISABLED"_ns); 300 } 301 302 mFeatureWrOptimizedShaders->EnableByDefault(); 303 if (!mWrOptimizedShaders) { 304 mFeatureWrOptimizedShaders->UserDisable("User disabled via pref", 305 "FEATURE_FAILURE_PREF_DISABLED"_ns); 306 } 307 ConfigureFromBlocklist(nsIGfxInfo::FEATURE_WEBRENDER_OPTIMIZED_SHADERS, 308 mFeatureWrOptimizedShaders); 309 if (!mFeatureWr->IsEnabled()) { 310 mFeatureWrOptimizedShaders->ForceDisable(FeatureStatus::Unavailable, 311 "WebRender disabled", 312 "FEATURE_FAILURE_WR_DISABLED"_ns); 313 } 314 315 mFeatureWrScissoredCacheClears->SetDefault(mWrScissoredCacheClearsEnabled, 316 FeatureStatus::Disabled, 317 "User disabled via pref"); 318 if (mWrScissoredCacheClearsForceEnabled) { 319 mFeatureWrScissoredCacheClears->UserForceEnable("Force enabled by pref"); 320 } 321 ConfigureFromBlocklist(nsIGfxInfo::FEATURE_WEBRENDER_SCISSORED_CACHE_CLEARS, 322 mFeatureWrScissoredCacheClears); 323 324 mFeatureGLNorm16Textures->EnableByDefault(); 325 ConfigureFromBlocklist(nsIGfxInfo::FEATURE_GL_NORM16_TEXTURES, 326 mFeatureGLNorm16Textures); 327 } 328 329 } // namespace gfx 330 } // namespace mozilla