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();
46 mWrScissoredCacheClearsEnabled
=
47 StaticPrefs::gfx_webrender_scissored_cache_clears_enabled_AtStartup();
48 mWrScissoredCacheClearsForceEnabled
= StaticPrefs::
49 gfx_webrender_scissored_cache_clears_force_enabled_AtStartup();
51 mWrForceAngle
= StaticPrefs::gfx_webrender_force_angle_AtStartup();
52 mWrForceAngleNoGPUProcess
= StaticPrefs::
53 gfx_webrender_enabled_no_gpu_process_with_angle_win_AtStartup();
55 Preferences::GetBool("gfx.webrender.dcomp-win.enabled", false);
58 mWrEnvForceEnabled
= gfxPlatform::WebRenderEnvvarEnabled();
61 DeviceManagerDx::Get()->CheckHardwareStretchingSupport(mHwStretchingSupport
);
62 mScaledResolution
= HasScaledResolution();
63 mIsWin11OrLater
= IsWin11OrLater();
64 mWrCompositorDCompRequired
= true;
66 ++mHwStretchingSupport
.mBoth
;
70 mDisableHwCompositingNoWr
= true;
76 #ifdef EARLY_BETA_OR_EARLIER
77 mIsEarlyBetaOrEarlier
= true;
79 mSafeMode
= gfxPlatform::InSafeMode();
81 mGfxInfo
= components::GfxInfo::Service();
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
);
95 mFeatureHwCompositing
= &gfxConfig::GetFeature(Feature::HW_COMPOSITING
);
97 mFeatureD3D11HwAngle
= &gfxConfig::GetFeature(Feature::D3D11_HW_ANGLE
);
98 mFeatureD3D11Compositing
= &gfxConfig::GetFeature(Feature::D3D11_COMPOSITING
);
100 mFeatureGPUProcess
= &gfxConfig::GetFeature(Feature::GPU_PROCESS
);
103 void gfxConfigManager::EmplaceUserPref(const char* aPrefName
,
104 Maybe
<bool>& aValue
) {
105 if (Preferences::HasUserValue(aPrefName
)) {
106 aValue
.emplace(Preferences::GetBool(aPrefName
, false));
110 void gfxConfigManager::ConfigureFromBlocklist(long aFeature
,
111 FeatureState
* aFeatureState
) {
112 MOZ_ASSERT(aFeatureState
);
116 if (!NS_SUCCEEDED(mGfxInfo
->GetFeatureStatus(aFeature
, blockId
, &status
))) {
117 aFeatureState
->Disable(FeatureStatus::BlockedNoGfxInfo
, "gfxInfo is broken",
118 "FEATURE_FAILURE_NO_GFX_INFO"_ns
);
123 case nsIGfxInfo::FEATURE_STATUS_OK
:
124 case nsIGfxInfo::FEATURE_ALLOW_ALWAYS
:
126 case nsIGfxInfo::FEATURE_ALLOW_QUALIFIED
:
127 MOZ_ASSERT_UNREACHABLE("Allowing only qualified, but needs experiment?");
129 case nsIGfxInfo::FEATURE_DENIED
:
130 aFeatureState
->Disable(FeatureStatus::Denied
, "Not on allowlist",
134 aFeatureState
->Disable(FeatureStatus::Blocklisted
,
135 "Blocklisted by gfxInfo", blockId
);
140 void gfxConfigManager::ConfigureWebRender() {
141 MOZ_ASSERT(XRE_IsParentProcess());
142 MOZ_ASSERT(mFeatureWr
);
143 MOZ_ASSERT(mFeatureWrCompositor
);
144 MOZ_ASSERT(mFeatureWrAngle
);
145 MOZ_ASSERT(mFeatureWrDComp
);
146 MOZ_ASSERT(mFeatureWrPartial
);
147 MOZ_ASSERT(mFeatureWrShaderCache
);
148 MOZ_ASSERT(mFeatureWrOptimizedShaders
);
149 MOZ_ASSERT(mFeatureWrScissoredCacheClears
);
150 MOZ_ASSERT(mFeatureHwCompositing
);
151 MOZ_ASSERT(mFeatureGPUProcess
);
153 // Initialize WebRender native compositor usage
154 mFeatureWrCompositor
->SetDefaultFromPref("gfx.webrender.compositor", true,
155 false, mWrCompositorEnabled
);
157 if (mWrCompositorForceEnabled
) {
158 mFeatureWrCompositor
->UserForceEnable("Force enabled by pref");
161 ConfigureFromBlocklist(nsIGfxInfo::FEATURE_WEBRENDER_COMPOSITOR
,
162 mFeatureWrCompositor
);
164 // Disable native compositor when hardware stretching is not supported. It is
165 // for avoiding a problem like Bug 1618370.
166 // XXX Is there a better check for Bug 1618370?
167 if (!mHwStretchingSupport
.IsFullySupported() && mScaledResolution
) {
168 nsPrintfCString
failureId(
169 "FEATURE_FAILURE_NO_HARDWARE_STRETCHING_B%uW%uF%uN%uE%u",
170 mHwStretchingSupport
.mBoth
, mHwStretchingSupport
.mWindowOnly
,
171 mHwStretchingSupport
.mFullScreenOnly
, mHwStretchingSupport
.mNone
,
172 mHwStretchingSupport
.mError
);
173 mFeatureWrCompositor
->Disable(FeatureStatus::Unavailable
,
174 "No hardware stretching support", failureId
);
177 mFeatureWr
->EnableByDefault();
179 // envvar works everywhere; note that we need this for testing in CI.
180 // Prior to bug 1523788, the `prefEnabled` check was only done on Nightly,
181 // so as to prevent random users from easily enabling WebRender on
182 // unqualified hardware in beta/release.
183 if (mWrSoftwareForceEnabled
) {
184 mFeatureWr
->UserDisable("User force-enabled software WR",
185 "FEATURE_FAILURE_USER_FORCE_ENABLED_SW_WR"_ns
);
186 } else if (mWrEnvForceEnabled
) {
187 mFeatureWr
->UserForceEnable("Force enabled by envvar");
188 } else if (mWrForceEnabled
) {
189 mFeatureWr
->UserForceEnable("Force enabled by pref");
192 ConfigureFromBlocklist(nsIGfxInfo::FEATURE_WEBRENDER
, mFeatureWr
);
194 // HW_COMPOSITING being disabled implies interfacing with the GPU might break
195 if (!mFeatureHwCompositing
->IsEnabled()) {
196 mFeatureWr
->ForceDisable(FeatureStatus::UnavailableNoHwCompositing
,
197 "Hardware compositing is disabled",
198 "FEATURE_FAILURE_WEBRENDER_NEED_HWCOMP"_ns
);
202 mFeatureWr
->ForceDisable(FeatureStatus::UnavailableInSafeMode
,
203 "Safe-mode is enabled",
204 "FEATURE_FAILURE_SAFE_MODE"_ns
);
207 mFeatureWrAngle
->EnableByDefault();
208 if (mFeatureD3D11HwAngle
) {
210 if (!mFeatureD3D11HwAngle
->IsEnabled()) {
211 mFeatureWrAngle
->ForceDisable(FeatureStatus::UnavailableNoAngle
,
213 mFeatureD3D11HwAngle
->GetFailureId());
214 } else if (!mFeatureGPUProcess
->IsEnabled() &&
215 !mWrForceAngleNoGPUProcess
) {
216 // WebRender with ANGLE relies on the GPU process when on Windows
217 mFeatureWrAngle
->ForceDisable(
218 FeatureStatus::UnavailableNoGpuProcess
, "GPU Process is disabled",
219 "FEATURE_FAILURE_GPU_PROCESS_DISABLED"_ns
);
222 mFeatureWrAngle
->Disable(FeatureStatus::Disabled
, "ANGLE is not forced",
223 "FEATURE_FAILURE_ANGLE_NOT_FORCED"_ns
);
226 mFeatureWrAngle
->Disable(FeatureStatus::Unavailable
, "OS not supported",
227 "FEATURE_FAILURE_OS_NOT_SUPPORTED"_ns
);
230 if (mWrForceAngle
&& mFeatureWr
->IsEnabled() &&
231 !mFeatureWrAngle
->IsEnabled()) {
232 // Ensure we disable WebRender if ANGLE is unavailable and it is required.
233 mFeatureWr
->ForceDisable(FeatureStatus::UnavailableNoAngle
,
235 mFeatureWrAngle
->GetFailureId());
238 if (!mFeatureWr
->IsEnabled() && mDisableHwCompositingNoWr
) {
239 if (mFeatureHwCompositing
->IsEnabled()) {
240 // Hardware compositing should be disabled by default if we aren't using
241 // WebRender. We had to check if it is enabled at all, because it may
242 // already have been forced disabled (e.g. safe mode, headless). It may
243 // still be forced on by the user, and if so, this should have no effect.
244 mFeatureHwCompositing
->Disable(FeatureStatus::Blocked
,
245 "Acceleration blocked by platform", ""_ns
);
248 if (!mFeatureHwCompositing
->IsEnabled() &&
249 mFeatureGPUProcess
->IsEnabled() && !mGPUProcessAllowSoftware
) {
250 // We have neither WebRender nor OpenGL, we don't allow the GPU process
251 // for basic compositor, and it wasn't disabled already.
252 mFeatureGPUProcess
->Disable(FeatureStatus::Unavailable
,
253 "Hardware compositing is unavailable.",
258 mFeatureWrDComp
->EnableByDefault();
259 if (!mWrDCompWinEnabled
) {
260 mFeatureWrDComp
->UserDisable("User disabled via pref",
261 "FEATURE_FAILURE_DCOMP_PREF_DISABLED"_ns
);
264 if (!mFeatureGPUProcess
->IsEnabled()) {
265 mFeatureWrDComp
->Disable(FeatureStatus::Unavailable
, "Requires GPU process",
266 "FEATURE_FAILURE_NO_GPU_PROCESS"_ns
);
269 if (!mIsWin11OrLater
) {
270 // Disable DirectComposition for NVIDIA users on Windows 10 with high/mixed
271 // refresh rate monitors due to rendering artifacts. (See bug 1638709.)
272 nsAutoString adapterVendorID
;
273 mGfxInfo
->GetAdapterVendorID(adapterVendorID
);
274 if (adapterVendorID
== u
"0x10de") {
276 int32_t maxRefreshRate
= mGfxInfo
->GetMaxRefreshRate(&mixed
);
277 if (maxRefreshRate
> 60 && mixed
) {
278 mFeatureWrDComp
->Disable(FeatureStatus::Blocked
,
279 "Monitor refresh rate too high/mixed",
280 "NVIDIA_REFRESH_RATE_MIXED"_ns
);
285 mFeatureWrDComp
->MaybeSetFailed(
286 mFeatureWr
->IsEnabled(), FeatureStatus::Unavailable
, "Requires WebRender",
287 "FEATURE_FAILURE_DCOMP_NOT_WR"_ns
);
288 mFeatureWrDComp
->MaybeSetFailed(mFeatureWrAngle
->IsEnabled(),
289 FeatureStatus::Unavailable
, "Requires ANGLE",
290 "FEATURE_FAILURE_DCOMP_NOT_ANGLE"_ns
);
292 if (!mFeatureWrDComp
->IsEnabled() && mWrCompositorDCompRequired
) {
293 mFeatureWrCompositor
->ForceDisable(FeatureStatus::Unavailable
,
294 "No DirectComposition usage",
295 mFeatureWrDComp
->GetFailureId());
298 // Initialize WebRender partial present config.
299 // Partial present is used only when WebRender compositor is not used.
300 mFeatureWrPartial
->SetDefault(mWrPartialPresent
, FeatureStatus::Disabled
,
301 "User disabled via pref");
302 if (mWrForcePartialPresent
) {
303 mFeatureWrPartial
->UserForceEnable("Force enabled by pref");
306 ConfigureFromBlocklist(nsIGfxInfo::FEATURE_WEBRENDER_PARTIAL_PRESENT
,
309 mFeatureWrShaderCache
->SetDefaultFromPref(
310 StaticPrefs::GetPrefName_gfx_webrender_program_binary_disk(), true,
311 StaticPrefs::GetPrefDefault_gfx_webrender_program_binary_disk(),
313 ConfigureFromBlocklist(nsIGfxInfo::FEATURE_WEBRENDER_SHADER_CACHE
,
314 mFeatureWrShaderCache
);
315 if (!mFeatureWr
->IsEnabled()) {
316 mFeatureWrShaderCache
->ForceDisable(FeatureStatus::Unavailable
,
317 "WebRender disabled",
318 "FEATURE_FAILURE_WR_DISABLED"_ns
);
321 mFeatureWrOptimizedShaders
->EnableByDefault();
322 if (!mWrOptimizedShaders
) {
323 mFeatureWrOptimizedShaders
->UserDisable("User disabled via pref",
324 "FEATURE_FAILURE_PREF_DISABLED"_ns
);
326 ConfigureFromBlocklist(nsIGfxInfo::FEATURE_WEBRENDER_OPTIMIZED_SHADERS
,
327 mFeatureWrOptimizedShaders
);
328 if (!mFeatureWr
->IsEnabled()) {
329 mFeatureWrOptimizedShaders
->ForceDisable(FeatureStatus::Unavailable
,
330 "WebRender disabled",
331 "FEATURE_FAILURE_WR_DISABLED"_ns
);
334 mFeatureWrScissoredCacheClears
->SetDefault(mWrScissoredCacheClearsEnabled
,
335 FeatureStatus::Disabled
,
336 "User disabled via pref");
337 if (mWrScissoredCacheClearsForceEnabled
) {
338 mFeatureWrScissoredCacheClears
->UserForceEnable("Force enabled by pref");
340 ConfigureFromBlocklist(nsIGfxInfo::FEATURE_WEBRENDER_SCISSORED_CACHE_CLEARS
,
341 mFeatureWrScissoredCacheClears
);
345 } // namespace mozilla