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();
39 StaticPrefs::gfx_webrender_max_partial_present_rects_AtStartup() > 0;
40 EmplaceUserPref(StaticPrefs::GetPrefName_gfx_webrender_program_binary_disk(),
43 StaticPrefs::gfx_webrender_use_optimized_shaders_AtStartup();
45 mWrForceAngle
= StaticPrefs::gfx_webrender_force_angle_AtStartup();
46 mWrForceAngleNoGPUProcess
= StaticPrefs::
47 gfx_webrender_enabled_no_gpu_process_with_angle_win_AtStartup();
49 Preferences::GetBool("gfx.webrender.dcomp-win.enabled", false);
52 mWrEnvForceEnabled
= gfxPlatform::WebRenderEnvvarEnabled();
55 DeviceManagerDx::Get()->CheckHardwareStretchingSupport(mHwStretchingSupport
);
56 mScaledResolution
= HasScaledResolution();
57 mIsWin10OrLater
= IsWin10OrLater();
58 mWrCompositorDCompRequired
= true;
60 ++mHwStretchingSupport
.mBoth
;
64 mDisableHwCompositingNoWr
= true;
70 #ifdef EARLY_BETA_OR_EARLIER
71 mIsEarlyBetaOrEarlier
= true;
73 mSafeMode
= gfxPlatform::InSafeMode();
75 mGfxInfo
= components::GfxInfo::Service();
77 mFeatureWr
= &gfxConfig::GetFeature(Feature::WEBRENDER
);
78 mFeatureWrQualified
= &gfxConfig::GetFeature(Feature::WEBRENDER_QUALIFIED
);
79 mFeatureWrCompositor
= &gfxConfig::GetFeature(Feature::WEBRENDER_COMPOSITOR
);
80 mFeatureWrAngle
= &gfxConfig::GetFeature(Feature::WEBRENDER_ANGLE
);
81 mFeatureWrDComp
= &gfxConfig::GetFeature(Feature::WEBRENDER_DCOMP_PRESENT
);
82 mFeatureWrPartial
= &gfxConfig::GetFeature(Feature::WEBRENDER_PARTIAL
);
83 mFeatureWrShaderCache
=
84 &gfxConfig::GetFeature(Feature::WEBRENDER_SHADER_CACHE
);
85 mFeatureWrOptimizedShaders
=
86 &gfxConfig::GetFeature(Feature::WEBRENDER_OPTIMIZED_SHADERS
);
87 mFeatureWrSoftware
= &gfxConfig::GetFeature(Feature::WEBRENDER_SOFTWARE
);
89 mFeatureHwCompositing
= &gfxConfig::GetFeature(Feature::HW_COMPOSITING
);
91 mFeatureD3D11HwAngle
= &gfxConfig::GetFeature(Feature::D3D11_HW_ANGLE
);
92 mFeatureD3D11Compositing
= &gfxConfig::GetFeature(Feature::D3D11_COMPOSITING
);
94 mFeatureGPUProcess
= &gfxConfig::GetFeature(Feature::GPU_PROCESS
);
97 void gfxConfigManager::EmplaceUserPref(const char* aPrefName
,
98 Maybe
<bool>& aValue
) {
99 if (Preferences::HasUserValue(aPrefName
)) {
100 aValue
.emplace(Preferences::GetBool(aPrefName
, false));
104 void gfxConfigManager::ConfigureFromBlocklist(long aFeature
,
105 FeatureState
* aFeatureState
) {
106 MOZ_ASSERT(aFeatureState
);
110 if (!NS_SUCCEEDED(mGfxInfo
->GetFeatureStatus(aFeature
, blockId
, &status
))) {
111 aFeatureState
->Disable(FeatureStatus::BlockedNoGfxInfo
, "gfxInfo is broken",
112 "FEATURE_FAILURE_NO_GFX_INFO"_ns
);
115 if (status
!= nsIGfxInfo::FEATURE_STATUS_OK
) {
116 aFeatureState
->Disable(FeatureStatus::Blocklisted
,
117 "Blocklisted by gfxInfo", blockId
);
122 void gfxConfigManager::ConfigureWebRenderQualified() {
123 MOZ_ASSERT(mFeatureWrQualified
);
124 MOZ_ASSERT(mFeatureWrCompositor
);
126 mFeatureWrQualified
->EnableByDefault();
130 if (NS_FAILED(mGfxInfo
->GetFeatureStatus(nsIGfxInfo::FEATURE_WEBRENDER
,
131 failureId
, &status
))) {
132 mFeatureWrQualified
->Disable(FeatureStatus::BlockedNoGfxInfo
,
134 "FEATURE_FAILURE_WR_NO_GFX_INFO"_ns
);
139 case nsIGfxInfo::FEATURE_ALLOW_ALWAYS
:
140 case nsIGfxInfo::FEATURE_ALLOW_QUALIFIED
:
142 case nsIGfxInfo::FEATURE_DENIED
:
143 mFeatureWrQualified
->Disable(FeatureStatus::Denied
, "Not on allowlist",
147 mFeatureWrQualified
->Disable(FeatureStatus::Blocklisted
,
148 "No qualified hardware", failureId
);
150 case nsIGfxInfo::FEATURE_STATUS_OK
:
151 MOZ_ASSERT_UNREACHABLE("We should still be rolling out WebRender!");
152 mFeatureWrQualified
->Disable(FeatureStatus::Blocked
,
153 "Not controlled by rollout", failureId
);
158 void gfxConfigManager::ConfigureWebRender() {
159 MOZ_ASSERT(XRE_IsParentProcess());
160 MOZ_ASSERT(mFeatureWr
);
161 MOZ_ASSERT(mFeatureWrQualified
);
162 MOZ_ASSERT(mFeatureWrCompositor
);
163 MOZ_ASSERT(mFeatureWrAngle
);
164 MOZ_ASSERT(mFeatureWrDComp
);
165 MOZ_ASSERT(mFeatureWrPartial
);
166 MOZ_ASSERT(mFeatureWrShaderCache
);
167 MOZ_ASSERT(mFeatureWrOptimizedShaders
);
168 MOZ_ASSERT(mFeatureWrSoftware
);
169 MOZ_ASSERT(mFeatureHwCompositing
);
170 MOZ_ASSERT(mFeatureGPUProcess
);
172 // Initialize WebRender native compositor usage
173 mFeatureWrCompositor
->SetDefaultFromPref("gfx.webrender.compositor", true,
174 false, mWrCompositorEnabled
);
176 if (mWrCompositorForceEnabled
) {
177 mFeatureWrCompositor
->UserForceEnable("Force enabled by pref");
180 ConfigureFromBlocklist(nsIGfxInfo::FEATURE_WEBRENDER_COMPOSITOR
,
181 mFeatureWrCompositor
);
183 // Disable native compositor when hardware stretching is not supported. It is
184 // for avoiding a problem like Bug 1618370.
185 // XXX Is there a better check for Bug 1618370?
186 if (!mHwStretchingSupport
.IsFullySupported() && mScaledResolution
) {
187 nsPrintfCString
failureId(
188 "FEATURE_FAILURE_NO_HARDWARE_STRETCHING_B%uW%uF%uN%uE%u",
189 mHwStretchingSupport
.mBoth
, mHwStretchingSupport
.mWindowOnly
,
190 mHwStretchingSupport
.mFullScreenOnly
, mHwStretchingSupport
.mNone
,
191 mHwStretchingSupport
.mError
);
192 mFeatureWrCompositor
->Disable(FeatureStatus::Unavailable
,
193 "No hardware stretching support", failureId
);
196 mFeatureWr
->EnableByDefault();
197 mFeatureWrSoftware
->EnableByDefault();
198 ConfigureWebRenderQualified();
200 // envvar works everywhere; note that we need this for testing in CI.
201 // Prior to bug 1523788, the `prefEnabled` check was only done on Nightly,
202 // so as to prevent random users from easily enabling WebRender on
203 // unqualified hardware in beta/release.
204 if (mWrSoftwareForceEnabled
) {
205 MOZ_ASSERT(mFeatureWrSoftware
->IsEnabled());
206 mFeatureWr
->UserDisable("User force-enabled software WR",
207 "FEATURE_FAILURE_USER_FORCE_ENABLED_SW_WR"_ns
);
208 } else if (mWrEnvForceEnabled
) {
209 mFeatureWr
->UserForceEnable("Force enabled by envvar");
210 } else if (mWrForceEnabled
) {
211 mFeatureWr
->UserForceEnable("Force enabled by pref");
214 if (!mFeatureWrQualified
->IsEnabled()) {
215 // No qualified hardware. If we haven't allowed software fallback,
216 // then we need to disable WR.
217 mFeatureWr
->Disable(FeatureStatus::Disabled
, "Not qualified",
218 "FEATURE_FAILURE_NOT_QUALIFIED"_ns
);
221 // HW_COMPOSITING being disabled implies interfacing with the GPU might break
222 if (!mFeatureHwCompositing
->IsEnabled()) {
223 mFeatureWr
->ForceDisable(FeatureStatus::UnavailableNoHwCompositing
,
224 "Hardware compositing is disabled",
225 "FEATURE_FAILURE_WEBRENDER_NEED_HWCOMP"_ns
);
229 mFeatureWr
->ForceDisable(FeatureStatus::UnavailableInSafeMode
,
230 "Safe-mode is enabled",
231 "FEATURE_FAILURE_SAFE_MODE"_ns
);
234 mFeatureWrAngle
->EnableByDefault();
235 if (mFeatureD3D11HwAngle
) {
237 if (!mFeatureD3D11HwAngle
->IsEnabled()) {
238 mFeatureWrAngle
->ForceDisable(FeatureStatus::UnavailableNoAngle
,
240 mFeatureD3D11HwAngle
->GetFailureId());
241 } else if (!mFeatureGPUProcess
->IsEnabled() &&
242 !mWrForceAngleNoGPUProcess
) {
243 // WebRender with ANGLE relies on the GPU process when on Windows
244 mFeatureWrAngle
->ForceDisable(
245 FeatureStatus::UnavailableNoGpuProcess
, "GPU Process is disabled",
246 "FEATURE_FAILURE_GPU_PROCESS_DISABLED"_ns
);
247 } else if (!mFeatureWr
->IsEnabled() && !mFeatureWrSoftware
->IsEnabled()) {
248 mFeatureWrAngle
->ForceDisable(FeatureStatus::Unavailable
,
249 "WebRender disabled",
250 "FEATURE_FAILURE_WR_DISABLED"_ns
);
253 mFeatureWrAngle
->Disable(FeatureStatus::Disabled
, "ANGLE is not forced",
254 "FEATURE_FAILURE_ANGLE_NOT_FORCED"_ns
);
257 mFeatureWrAngle
->Disable(FeatureStatus::Unavailable
, "OS not supported",
258 "FEATURE_FAILURE_OS_NOT_SUPPORTED"_ns
);
261 if (mWrForceAngle
&& mFeatureWr
->IsEnabled() &&
262 !mFeatureWrAngle
->IsEnabled()) {
263 // Ensure we disable WebRender if ANGLE is unavailable and it is required.
264 mFeatureWr
->ForceDisable(FeatureStatus::UnavailableNoAngle
,
266 mFeatureWrAngle
->GetFailureId());
269 if (!mFeatureWr
->IsEnabled() && mDisableHwCompositingNoWr
) {
270 if (mFeatureHwCompositing
->IsEnabled()) {
271 // Hardware compositing should be disabled by default if we aren't using
272 // WebRender. We had to check if it is enabled at all, because it may
273 // already have been forced disabled (e.g. safe mode, headless). It may
274 // still be forced on by the user, and if so, this should have no effect.
275 mFeatureHwCompositing
->Disable(FeatureStatus::Blocked
,
276 "Acceleration blocked by platform", ""_ns
);
279 if (!mFeatureHwCompositing
->IsEnabled() &&
280 mFeatureGPUProcess
->IsEnabled() && !mGPUProcessAllowSoftware
) {
281 // We have neither WebRender nor OpenGL, we don't allow the GPU process
282 // for basic compositor, and it wasn't disabled already.
283 mFeatureGPUProcess
->Disable(FeatureStatus::Unavailable
,
284 "Hardware compositing is unavailable.",
289 mFeatureWrDComp
->EnableByDefault();
290 if (!mWrDCompWinEnabled
) {
291 mFeatureWrDComp
->UserDisable("User disabled via pref",
292 "FEATURE_FAILURE_DCOMP_PREF_DISABLED"_ns
);
295 if (!mIsWin10OrLater
) {
296 // XXX relax win version to windows 8.
297 mFeatureWrDComp
->Disable(FeatureStatus::Unavailable
,
298 "Requires Windows 10 or later",
299 "FEATURE_FAILURE_DCOMP_NOT_WIN10"_ns
);
303 // Disable DirectComposition for NVIDIA users with high/mixed refresh rate
304 // monitors due to rendering artifacts.
305 nsAutoString adapterVendorID
;
306 mGfxInfo
->GetAdapterVendorID(adapterVendorID
);
307 if (adapterVendorID
== u
"0x10de") {
309 int32_t maxRefreshRate
= mGfxInfo
->GetMaxRefreshRate(&mixed
);
310 if (maxRefreshRate
> 60 && mixed
) {
311 mFeatureWrDComp
->Disable(FeatureStatus::Blocked
,
312 "Monitor refresh rate too high/mixed",
313 "NVIDIA_REFRESH_RATE_MIXED"_ns
);
318 mFeatureWrDComp
->MaybeSetFailed(
319 mFeatureWr
->IsEnabled(), FeatureStatus::Unavailable
, "Requires WebRender",
320 "FEATURE_FAILURE_DCOMP_NOT_WR"_ns
);
321 mFeatureWrDComp
->MaybeSetFailed(mFeatureWrAngle
->IsEnabled(),
322 FeatureStatus::Unavailable
, "Requires ANGLE",
323 "FEATURE_FAILURE_DCOMP_NOT_ANGLE"_ns
);
325 if (!mFeatureWrDComp
->IsEnabled() && mWrCompositorDCompRequired
) {
326 mFeatureWrCompositor
->ForceDisable(FeatureStatus::Unavailable
,
327 "No DirectComposition usage",
328 mFeatureWrDComp
->GetFailureId());
331 // Initialize WebRender partial present config.
332 // Partial present is used only when WebRender compositor is not used.
333 if (mWrPartialPresent
) {
334 if (mFeatureWr
->IsEnabled() || mFeatureWrSoftware
->IsEnabled()) {
335 mFeatureWrPartial
->EnableByDefault();
338 mGfxInfo
->GetAdapterDeviceID(adapter
);
339 // Block partial present on some devices due to rendering issues.
340 // On Mali-Txxx due to bug 1680087 and bug 1707815.
341 // On Adreno 3xx GPUs due to bug 1695771.
342 if (adapter
.Find("Mali-T", /*ignoreCase*/ true) >= 0 ||
343 adapter
.Find("Adreno (TM) 3", /*ignoreCase*/ true) >= 0) {
344 mFeatureWrPartial
->Disable(
345 FeatureStatus::Blocked
, "Partial present blocked",
346 "FEATURE_FAILURE_PARTIAL_PRESENT_BLOCKED"_ns
);
351 mFeatureWrShaderCache
->SetDefaultFromPref(
352 StaticPrefs::GetPrefName_gfx_webrender_program_binary_disk(), true,
353 StaticPrefs::GetPrefDefault_gfx_webrender_program_binary_disk(),
355 ConfigureFromBlocklist(nsIGfxInfo::FEATURE_WEBRENDER_SHADER_CACHE
,
356 mFeatureWrShaderCache
);
357 if (!mFeatureWr
->IsEnabled()) {
358 mFeatureWrShaderCache
->ForceDisable(FeatureStatus::Unavailable
,
359 "WebRender disabled",
360 "FEATURE_FAILURE_WR_DISABLED"_ns
);
363 mFeatureWrOptimizedShaders
->EnableByDefault();
364 if (!mWrOptimizedShaders
) {
365 mFeatureWrOptimizedShaders
->UserDisable("User disabled via pref",
366 "FEATURE_FAILURE_PREF_DISABLED"_ns
);
368 ConfigureFromBlocklist(nsIGfxInfo::FEATURE_WEBRENDER_OPTIMIZED_SHADERS
,
369 mFeatureWrOptimizedShaders
);
370 if (!mFeatureWr
->IsEnabled()) {
371 mFeatureWrOptimizedShaders
->ForceDisable(FeatureStatus::Unavailable
,
372 "WebRender disabled",
373 "FEATURE_FAILURE_WR_DISABLED"_ns
);
378 } // namespace mozilla