Bug 1785744 [wpt PR 35504] - Recalc style for elements where :toggle() pseudo-class...
[gecko.git] / gfx / config / gfxConfigManager.cpp
blob55628c9638aeb0add94b147eca4a8ff9b116913b
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/. */
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"
19 #ifdef XP_WIN
20 # include "mozilla/WindowsVersion.h"
21 # include "mozilla/gfx/DeviceManagerDx.h"
22 # include "mozilla/gfx/DisplayConfigWindows.h"
23 #endif
25 namespace mozilla {
26 namespace gfx {
28 void gfxConfigManager::Init() {
29 MOZ_ASSERT(XRE_IsParentProcess());
31 EmplaceUserPref("gfx.webrender.compositor", mWrCompositorEnabled);
32 mWrForceEnabled = gfxPlatform::WebRenderPrefEnabled();
33 mWrSoftwareForceEnabled = StaticPrefs::gfx_webrender_software_AtStartup();
34 mWrCompositorForceEnabled =
35 StaticPrefs::gfx_webrender_compositor_force_enabled_AtStartup();
36 mGPUProcessAllowSoftware =
37 StaticPrefs::layers_gpu_process_allow_software_AtStartup();
38 mWrForcePartialPresent =
39 StaticPrefs::gfx_webrender_force_partial_present_AtStartup();
40 mWrPartialPresent =
41 StaticPrefs::gfx_webrender_max_partial_present_rects_AtStartup() > 0;
42 EmplaceUserPref(StaticPrefs::GetPrefName_gfx_webrender_program_binary_disk(),
43 mWrShaderCache);
44 mWrOptimizedShaders =
45 StaticPrefs::gfx_webrender_use_optimized_shaders_AtStartup();
46 #ifdef XP_WIN
47 mWrForceAngle = StaticPrefs::gfx_webrender_force_angle_AtStartup();
48 mWrForceAngleNoGPUProcess = StaticPrefs::
49 gfx_webrender_enabled_no_gpu_process_with_angle_win_AtStartup();
50 mWrDCompWinEnabled =
51 Preferences::GetBool("gfx.webrender.dcomp-win.enabled", false);
52 #endif
54 mWrEnvForceEnabled = gfxPlatform::WebRenderEnvvarEnabled();
56 #ifdef XP_WIN
57 DeviceManagerDx::Get()->CheckHardwareStretchingSupport(mHwStretchingSupport);
58 mScaledResolution = HasScaledResolution();
59 mIsWin10OrLater = IsWin10OrLater();
60 mWrCompositorDCompRequired = true;
61 #else
62 ++mHwStretchingSupport.mBoth;
63 #endif
65 #ifdef MOZ_WIDGET_GTK
66 mDisableHwCompositingNoWr = true;
67 #endif
69 #ifdef NIGHTLY_BUILD
70 mIsNightly = true;
71 #endif
72 #ifdef EARLY_BETA_OR_EARLIER
73 mIsEarlyBetaOrEarlier = true;
74 #endif
75 mSafeMode = gfxPlatform::InSafeMode();
77 mGfxInfo = components::GfxInfo::Service();
79 mFeatureWr = &gfxConfig::GetFeature(Feature::WEBRENDER);
80 mFeatureWrQualified = &gfxConfig::GetFeature(Feature::WEBRENDER_QUALIFIED);
81 mFeatureWrCompositor = &gfxConfig::GetFeature(Feature::WEBRENDER_COMPOSITOR);
82 mFeatureWrAngle = &gfxConfig::GetFeature(Feature::WEBRENDER_ANGLE);
83 mFeatureWrDComp = &gfxConfig::GetFeature(Feature::WEBRENDER_DCOMP_PRESENT);
84 mFeatureWrPartial = &gfxConfig::GetFeature(Feature::WEBRENDER_PARTIAL);
85 mFeatureWrShaderCache =
86 &gfxConfig::GetFeature(Feature::WEBRENDER_SHADER_CACHE);
87 mFeatureWrOptimizedShaders =
88 &gfxConfig::GetFeature(Feature::WEBRENDER_OPTIMIZED_SHADERS);
89 mFeatureWrSoftware = &gfxConfig::GetFeature(Feature::WEBRENDER_SOFTWARE);
91 mFeatureHwCompositing = &gfxConfig::GetFeature(Feature::HW_COMPOSITING);
92 #ifdef XP_WIN
93 mFeatureD3D11HwAngle = &gfxConfig::GetFeature(Feature::D3D11_HW_ANGLE);
94 mFeatureD3D11Compositing = &gfxConfig::GetFeature(Feature::D3D11_COMPOSITING);
95 #endif
96 mFeatureGPUProcess = &gfxConfig::GetFeature(Feature::GPU_PROCESS);
99 void gfxConfigManager::EmplaceUserPref(const char* aPrefName,
100 Maybe<bool>& aValue) {
101 if (Preferences::HasUserValue(aPrefName)) {
102 aValue.emplace(Preferences::GetBool(aPrefName, false));
106 void gfxConfigManager::ConfigureFromBlocklist(long aFeature,
107 FeatureState* aFeatureState) {
108 MOZ_ASSERT(aFeatureState);
110 nsCString blockId;
111 int32_t status;
112 if (!NS_SUCCEEDED(mGfxInfo->GetFeatureStatus(aFeature, blockId, &status))) {
113 aFeatureState->Disable(FeatureStatus::BlockedNoGfxInfo, "gfxInfo is broken",
114 "FEATURE_FAILURE_NO_GFX_INFO"_ns);
116 } else {
117 if (status != nsIGfxInfo::FEATURE_STATUS_OK) {
118 aFeatureState->Disable(FeatureStatus::Blocklisted,
119 "Blocklisted by gfxInfo", blockId);
124 void gfxConfigManager::ConfigureWebRenderQualified() {
125 MOZ_ASSERT(mFeatureWrQualified);
126 MOZ_ASSERT(mFeatureWrCompositor);
128 mFeatureWrQualified->EnableByDefault();
130 nsCString failureId;
131 int32_t status;
132 if (NS_FAILED(mGfxInfo->GetFeatureStatus(nsIGfxInfo::FEATURE_WEBRENDER,
133 failureId, &status))) {
134 mFeatureWrQualified->Disable(FeatureStatus::BlockedNoGfxInfo,
135 "gfxInfo is broken",
136 "FEATURE_FAILURE_WR_NO_GFX_INFO"_ns);
137 return;
140 switch (status) {
141 case nsIGfxInfo::FEATURE_ALLOW_ALWAYS:
142 case nsIGfxInfo::FEATURE_ALLOW_QUALIFIED:
143 break;
144 case nsIGfxInfo::FEATURE_DENIED:
145 mFeatureWrQualified->Disable(FeatureStatus::Denied, "Not on allowlist",
146 failureId);
147 break;
148 default:
149 mFeatureWrQualified->Disable(FeatureStatus::Blocklisted,
150 "No qualified hardware", failureId);
151 break;
152 case nsIGfxInfo::FEATURE_STATUS_OK:
153 MOZ_ASSERT_UNREACHABLE("We should still be rolling out WebRender!");
154 mFeatureWrQualified->Disable(FeatureStatus::Blocked,
155 "Not controlled by rollout", failureId);
156 break;
160 void gfxConfigManager::ConfigureWebRender() {
161 MOZ_ASSERT(XRE_IsParentProcess());
162 MOZ_ASSERT(mFeatureWr);
163 MOZ_ASSERT(mFeatureWrQualified);
164 MOZ_ASSERT(mFeatureWrCompositor);
165 MOZ_ASSERT(mFeatureWrAngle);
166 MOZ_ASSERT(mFeatureWrDComp);
167 MOZ_ASSERT(mFeatureWrPartial);
168 MOZ_ASSERT(mFeatureWrShaderCache);
169 MOZ_ASSERT(mFeatureWrOptimizedShaders);
170 MOZ_ASSERT(mFeatureWrSoftware);
171 MOZ_ASSERT(mFeatureHwCompositing);
172 MOZ_ASSERT(mFeatureGPUProcess);
174 // Initialize WebRender native compositor usage
175 mFeatureWrCompositor->SetDefaultFromPref("gfx.webrender.compositor", true,
176 false, mWrCompositorEnabled);
178 if (mWrCompositorForceEnabled) {
179 mFeatureWrCompositor->UserForceEnable("Force enabled by pref");
182 ConfigureFromBlocklist(nsIGfxInfo::FEATURE_WEBRENDER_COMPOSITOR,
183 mFeatureWrCompositor);
185 // Disable native compositor when hardware stretching is not supported. It is
186 // for avoiding a problem like Bug 1618370.
187 // XXX Is there a better check for Bug 1618370?
188 if (!mHwStretchingSupport.IsFullySupported() && mScaledResolution) {
189 nsPrintfCString failureId(
190 "FEATURE_FAILURE_NO_HARDWARE_STRETCHING_B%uW%uF%uN%uE%u",
191 mHwStretchingSupport.mBoth, mHwStretchingSupport.mWindowOnly,
192 mHwStretchingSupport.mFullScreenOnly, mHwStretchingSupport.mNone,
193 mHwStretchingSupport.mError);
194 mFeatureWrCompositor->Disable(FeatureStatus::Unavailable,
195 "No hardware stretching support", failureId);
198 mFeatureWr->EnableByDefault();
199 mFeatureWrSoftware->EnableByDefault();
200 ConfigureWebRenderQualified();
202 // envvar works everywhere; note that we need this for testing in CI.
203 // Prior to bug 1523788, the `prefEnabled` check was only done on Nightly,
204 // so as to prevent random users from easily enabling WebRender on
205 // unqualified hardware in beta/release.
206 if (mWrSoftwareForceEnabled) {
207 MOZ_ASSERT(mFeatureWrSoftware->IsEnabled());
208 mFeatureWr->UserDisable("User force-enabled software WR",
209 "FEATURE_FAILURE_USER_FORCE_ENABLED_SW_WR"_ns);
210 } else if (mWrEnvForceEnabled) {
211 mFeatureWr->UserForceEnable("Force enabled by envvar");
212 } else if (mWrForceEnabled) {
213 mFeatureWr->UserForceEnable("Force enabled by pref");
216 if (!mFeatureWrQualified->IsEnabled()) {
217 // No qualified hardware. If we haven't allowed software fallback,
218 // then we need to disable WR.
219 mFeatureWr->Disable(FeatureStatus::Disabled, "Not qualified",
220 "FEATURE_FAILURE_NOT_QUALIFIED"_ns);
223 // HW_COMPOSITING being disabled implies interfacing with the GPU might break
224 if (!mFeatureHwCompositing->IsEnabled()) {
225 mFeatureWr->ForceDisable(FeatureStatus::UnavailableNoHwCompositing,
226 "Hardware compositing is disabled",
227 "FEATURE_FAILURE_WEBRENDER_NEED_HWCOMP"_ns);
230 if (mSafeMode) {
231 mFeatureWr->ForceDisable(FeatureStatus::UnavailableInSafeMode,
232 "Safe-mode is enabled",
233 "FEATURE_FAILURE_SAFE_MODE"_ns);
236 mFeatureWrAngle->EnableByDefault();
237 if (mFeatureD3D11HwAngle) {
238 if (mWrForceAngle) {
239 if (!mFeatureD3D11HwAngle->IsEnabled()) {
240 mFeatureWrAngle->ForceDisable(FeatureStatus::UnavailableNoAngle,
241 "ANGLE is disabled",
242 mFeatureD3D11HwAngle->GetFailureId());
243 } else if (!mFeatureGPUProcess->IsEnabled() &&
244 !mWrForceAngleNoGPUProcess) {
245 // WebRender with ANGLE relies on the GPU process when on Windows
246 mFeatureWrAngle->ForceDisable(
247 FeatureStatus::UnavailableNoGpuProcess, "GPU Process is disabled",
248 "FEATURE_FAILURE_GPU_PROCESS_DISABLED"_ns);
249 } else if (!mFeatureWr->IsEnabled() && !mFeatureWrSoftware->IsEnabled()) {
250 mFeatureWrAngle->ForceDisable(FeatureStatus::Unavailable,
251 "WebRender disabled",
252 "FEATURE_FAILURE_WR_DISABLED"_ns);
254 } else {
255 mFeatureWrAngle->Disable(FeatureStatus::Disabled, "ANGLE is not forced",
256 "FEATURE_FAILURE_ANGLE_NOT_FORCED"_ns);
258 } else {
259 mFeatureWrAngle->Disable(FeatureStatus::Unavailable, "OS not supported",
260 "FEATURE_FAILURE_OS_NOT_SUPPORTED"_ns);
263 if (mWrForceAngle && mFeatureWr->IsEnabled() &&
264 !mFeatureWrAngle->IsEnabled()) {
265 // Ensure we disable WebRender if ANGLE is unavailable and it is required.
266 mFeatureWr->ForceDisable(FeatureStatus::UnavailableNoAngle,
267 "ANGLE is disabled",
268 mFeatureWrAngle->GetFailureId());
271 if (!mFeatureWr->IsEnabled() && mDisableHwCompositingNoWr) {
272 if (mFeatureHwCompositing->IsEnabled()) {
273 // Hardware compositing should be disabled by default if we aren't using
274 // WebRender. We had to check if it is enabled at all, because it may
275 // already have been forced disabled (e.g. safe mode, headless). It may
276 // still be forced on by the user, and if so, this should have no effect.
277 mFeatureHwCompositing->Disable(FeatureStatus::Blocked,
278 "Acceleration blocked by platform", ""_ns);
281 if (!mFeatureHwCompositing->IsEnabled() &&
282 mFeatureGPUProcess->IsEnabled() && !mGPUProcessAllowSoftware) {
283 // We have neither WebRender nor OpenGL, we don't allow the GPU process
284 // for basic compositor, and it wasn't disabled already.
285 mFeatureGPUProcess->Disable(FeatureStatus::Unavailable,
286 "Hardware compositing is unavailable.",
287 ""_ns);
291 mFeatureWrDComp->EnableByDefault();
292 if (!mWrDCompWinEnabled) {
293 mFeatureWrDComp->UserDisable("User disabled via pref",
294 "FEATURE_FAILURE_DCOMP_PREF_DISABLED"_ns);
297 if (!mIsWin10OrLater) {
298 // XXX relax win version to windows 8.
299 mFeatureWrDComp->Disable(FeatureStatus::Unavailable,
300 "Requires Windows 10 or later",
301 "FEATURE_FAILURE_DCOMP_NOT_WIN10"_ns);
304 if (!mIsNightly) {
305 // Disable DirectComposition for NVIDIA users with high/mixed refresh rate
306 // monitors due to rendering artifacts.
307 nsAutoString adapterVendorID;
308 mGfxInfo->GetAdapterVendorID(adapterVendorID);
309 if (adapterVendorID == u"0x10de") {
310 bool mixed = false;
311 int32_t maxRefreshRate = mGfxInfo->GetMaxRefreshRate(&mixed);
312 if (maxRefreshRate > 60 && mixed) {
313 mFeatureWrDComp->Disable(FeatureStatus::Blocked,
314 "Monitor refresh rate too high/mixed",
315 "NVIDIA_REFRESH_RATE_MIXED"_ns);
320 mFeatureWrDComp->MaybeSetFailed(
321 mFeatureWr->IsEnabled(), FeatureStatus::Unavailable, "Requires WebRender",
322 "FEATURE_FAILURE_DCOMP_NOT_WR"_ns);
323 mFeatureWrDComp->MaybeSetFailed(mFeatureWrAngle->IsEnabled(),
324 FeatureStatus::Unavailable, "Requires ANGLE",
325 "FEATURE_FAILURE_DCOMP_NOT_ANGLE"_ns);
327 if (!mFeatureWrDComp->IsEnabled() && mWrCompositorDCompRequired) {
328 mFeatureWrCompositor->ForceDisable(FeatureStatus::Unavailable,
329 "No DirectComposition usage",
330 mFeatureWrDComp->GetFailureId());
333 // Initialize WebRender partial present config.
334 // Partial present is used only when WebRender compositor is not used.
335 mFeatureWrPartial->SetDefault(mWrPartialPresent, FeatureStatus::Disabled,
336 "User disabled via pref");
337 if (mWrForcePartialPresent) {
338 mFeatureWrPartial->UserForceEnable("Force enabled by pref");
341 ConfigureFromBlocklist(nsIGfxInfo::FEATURE_WEBRENDER_PARTIAL_PRESENT,
342 mFeatureWrPartial);
344 mFeatureWrShaderCache->SetDefaultFromPref(
345 StaticPrefs::GetPrefName_gfx_webrender_program_binary_disk(), true,
346 StaticPrefs::GetPrefDefault_gfx_webrender_program_binary_disk(),
347 mWrShaderCache);
348 ConfigureFromBlocklist(nsIGfxInfo::FEATURE_WEBRENDER_SHADER_CACHE,
349 mFeatureWrShaderCache);
350 if (!mFeatureWr->IsEnabled()) {
351 mFeatureWrShaderCache->ForceDisable(FeatureStatus::Unavailable,
352 "WebRender disabled",
353 "FEATURE_FAILURE_WR_DISABLED"_ns);
356 mFeatureWrOptimizedShaders->EnableByDefault();
357 if (!mWrOptimizedShaders) {
358 mFeatureWrOptimizedShaders->UserDisable("User disabled via pref",
359 "FEATURE_FAILURE_PREF_DISABLED"_ns);
361 ConfigureFromBlocklist(nsIGfxInfo::FEATURE_WEBRENDER_OPTIMIZED_SHADERS,
362 mFeatureWrOptimizedShaders);
363 if (!mFeatureWr->IsEnabled()) {
364 mFeatureWrOptimizedShaders->ForceDisable(FeatureStatus::Unavailable,
365 "WebRender disabled",
366 "FEATURE_FAILURE_WR_DISABLED"_ns);
370 } // namespace gfx
371 } // namespace mozilla