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"
20 # include "mozilla/WindowsVersion.h"
21 # include "mozilla/gfx/DeviceManagerDx.h"
22 # include "mozilla/gfx/DisplayConfigWindows.h"
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();
41 StaticPrefs::gfx_webrender_max_partial_present_rects_AtStartup() > 0;
42 EmplaceUserPref(StaticPrefs::GetPrefName_gfx_webrender_program_binary_disk(),
45 StaticPrefs::gfx_webrender_use_optimized_shaders_AtStartup();
47 mWrForceAngle
= StaticPrefs::gfx_webrender_force_angle_AtStartup();
48 mWrForceAngleNoGPUProcess
= StaticPrefs::
49 gfx_webrender_enabled_no_gpu_process_with_angle_win_AtStartup();
51 Preferences::GetBool("gfx.webrender.dcomp-win.enabled", false);
54 mWrEnvForceEnabled
= gfxPlatform::WebRenderEnvvarEnabled();
57 DeviceManagerDx::Get()->CheckHardwareStretchingSupport(mHwStretchingSupport
);
58 mScaledResolution
= HasScaledResolution();
59 mIsWin10OrLater
= IsWin10OrLater();
60 mWrCompositorDCompRequired
= true;
62 ++mHwStretchingSupport
.mBoth
;
66 mDisableHwCompositingNoWr
= true;
72 #ifdef EARLY_BETA_OR_EARLIER
73 mIsEarlyBetaOrEarlier
= true;
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
);
93 mFeatureD3D11HwAngle
= &gfxConfig::GetFeature(Feature::D3D11_HW_ANGLE
);
94 mFeatureD3D11Compositing
= &gfxConfig::GetFeature(Feature::D3D11_COMPOSITING
);
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
);
112 if (!NS_SUCCEEDED(mGfxInfo
->GetFeatureStatus(aFeature
, blockId
, &status
))) {
113 aFeatureState
->Disable(FeatureStatus::BlockedNoGfxInfo
, "gfxInfo is broken",
114 "FEATURE_FAILURE_NO_GFX_INFO"_ns
);
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();
132 if (NS_FAILED(mGfxInfo
->GetFeatureStatus(nsIGfxInfo::FEATURE_WEBRENDER
,
133 failureId
, &status
))) {
134 mFeatureWrQualified
->Disable(FeatureStatus::BlockedNoGfxInfo
,
136 "FEATURE_FAILURE_WR_NO_GFX_INFO"_ns
);
141 case nsIGfxInfo::FEATURE_ALLOW_ALWAYS
:
142 case nsIGfxInfo::FEATURE_ALLOW_QUALIFIED
:
144 case nsIGfxInfo::FEATURE_DENIED
:
145 mFeatureWrQualified
->Disable(FeatureStatus::Denied
, "Not on allowlist",
149 mFeatureWrQualified
->Disable(FeatureStatus::Blocklisted
,
150 "No qualified hardware", failureId
);
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
);
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
);
231 mFeatureWr
->ForceDisable(FeatureStatus::UnavailableInSafeMode
,
232 "Safe-mode is enabled",
233 "FEATURE_FAILURE_SAFE_MODE"_ns
);
236 mFeatureWrAngle
->EnableByDefault();
237 if (mFeatureD3D11HwAngle
) {
239 if (!mFeatureD3D11HwAngle
->IsEnabled()) {
240 mFeatureWrAngle
->ForceDisable(FeatureStatus::UnavailableNoAngle
,
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
);
255 mFeatureWrAngle
->Disable(FeatureStatus::Disabled
, "ANGLE is not forced",
256 "FEATURE_FAILURE_ANGLE_NOT_FORCED"_ns
);
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
,
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.",
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
);
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") {
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
,
344 mFeatureWrShaderCache
->SetDefaultFromPref(
345 StaticPrefs::GetPrefName_gfx_webrender_program_binary_disk(), true,
346 StaticPrefs::GetPrefDefault_gfx_webrender_program_binary_disk(),
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
);
371 } // namespace mozilla