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 #include "gfxConfig.h"
7 #include "mozilla/UniquePtr.h"
8 #include "mozilla/Unused.h"
9 #include "mozilla/gfx/GPUParent.h"
10 #include "mozilla/gfx/GraphicsMessages.h"
11 #include "plstr.h"
12
13 namespace mozilla {
14 namespace gfx {
15
16 static UniquePtr<gfxConfig> sConfig;
17
GetFeature(Feature aFeature)18 /* static */ FeatureState& gfxConfig::GetFeature(Feature aFeature) {
19 return sConfig->GetState(aFeature);
20 }
21
22 /* static */
IsEnabled(Feature aFeature)23 bool gfxConfig::IsEnabled(Feature aFeature) {
24 const FeatureState& state = sConfig->GetState(aFeature);
25 return state.IsEnabled();
26 }
27
28 /* static */
IsDisabledByDefault(Feature aFeature)29 bool gfxConfig::IsDisabledByDefault(Feature aFeature) {
30 const FeatureState& state = sConfig->GetState(aFeature);
31 return state.DisabledByDefault();
32 }
33
34 /* static */
IsForcedOnByUser(Feature aFeature)35 bool gfxConfig::IsForcedOnByUser(Feature aFeature) {
36 const FeatureState& state = sConfig->GetState(aFeature);
37 return state.IsForcedOnByUser();
38 }
39
40 /* static */
GetValue(Feature aFeature)41 FeatureStatus gfxConfig::GetValue(Feature aFeature) {
42 const FeatureState& state = sConfig->GetState(aFeature);
43 return state.GetValue();
44 }
45
46 /* static */
SetDefault(Feature aFeature,bool aEnable,FeatureStatus aDisableStatus,const char * aDisableMessage)47 bool gfxConfig::SetDefault(Feature aFeature, bool aEnable,
48 FeatureStatus aDisableStatus,
49 const char* aDisableMessage) {
50 FeatureState& state = sConfig->GetState(aFeature);
51 return state.SetDefault(aEnable, aDisableStatus, aDisableMessage);
52 }
53
54 /* static */
DisableByDefault(Feature aFeature,FeatureStatus aDisableStatus,const char * aDisableMessage,const nsACString & aFailureId)55 void gfxConfig::DisableByDefault(Feature aFeature, FeatureStatus aDisableStatus,
56 const char* aDisableMessage,
57 const nsACString& aFailureId) {
58 FeatureState& state = sConfig->GetState(aFeature);
59 state.DisableByDefault(aDisableStatus, aDisableMessage, aFailureId);
60 }
61
62 /* static */
EnableByDefault(Feature aFeature)63 void gfxConfig::EnableByDefault(Feature aFeature) {
64 FeatureState& state = sConfig->GetState(aFeature);
65 state.EnableByDefault();
66 }
67
68 /* static */
SetDefaultFromPref(Feature aFeature,const char * aPrefName,bool aIsEnablePref,bool aDefaultValue)69 void gfxConfig::SetDefaultFromPref(Feature aFeature, const char* aPrefName,
70 bool aIsEnablePref, bool aDefaultValue) {
71 FeatureState& state = sConfig->GetState(aFeature);
72 return state.SetDefaultFromPref(aPrefName, aIsEnablePref, aDefaultValue);
73 }
74
75 /* static */
InitOrUpdate(Feature aFeature,bool aEnable,FeatureStatus aDisableStatus,const char * aDisableMessage)76 bool gfxConfig::InitOrUpdate(Feature aFeature, bool aEnable,
77 FeatureStatus aDisableStatus,
78 const char* aDisableMessage) {
79 FeatureState& state = sConfig->GetState(aFeature);
80 return state.InitOrUpdate(aEnable, aDisableStatus, aDisableMessage);
81 }
82
83 /* static */
SetFailed(Feature aFeature,FeatureStatus aStatus,const char * aMessage,const nsACString & aFailureId)84 void gfxConfig::SetFailed(Feature aFeature, FeatureStatus aStatus,
85 const char* aMessage, const nsACString& aFailureId) {
86 FeatureState& state = sConfig->GetState(aFeature);
87 state.SetFailed(aStatus, aMessage, aFailureId);
88 }
89
90 /* static */
Disable(Feature aFeature,FeatureStatus aStatus,const char * aMessage,const nsACString & aFailureId)91 void gfxConfig::Disable(Feature aFeature, FeatureStatus aStatus,
92 const char* aMessage, const nsACString& aFailureId) {
93 FeatureState& state = sConfig->GetState(aFeature);
94 state.Disable(aStatus, aMessage, aFailureId);
95 }
96
97 /* static */
UserEnable(Feature aFeature,const char * aMessage)98 void gfxConfig::UserEnable(Feature aFeature, const char* aMessage) {
99 FeatureState& state = sConfig->GetState(aFeature);
100 state.UserEnable(aMessage);
101 }
102
103 /* static */
UserForceEnable(Feature aFeature,const char * aMessage)104 void gfxConfig::UserForceEnable(Feature aFeature, const char* aMessage) {
105 FeatureState& state = sConfig->GetState(aFeature);
106 state.UserForceEnable(aMessage);
107 }
108
109 /* static */
UserDisable(Feature aFeature,const char * aMessage,const nsACString & aFailureId)110 void gfxConfig::UserDisable(Feature aFeature, const char* aMessage,
111 const nsACString& aFailureId) {
112 FeatureState& state = sConfig->GetState(aFeature);
113 state.UserDisable(aMessage, aFailureId);
114 }
115
116 /* static */
Reenable(Feature aFeature,Fallback aFallback)117 void gfxConfig::Reenable(Feature aFeature, Fallback aFallback) {
118 FeatureState& state = sConfig->GetState(aFeature);
119 MOZ_ASSERT(IsFeatureStatusFailure(state.GetValue()));
120
121 const char* message = state.GetRuntimeMessage();
122 EnableFallback(aFallback, message);
123 state.SetRuntime(FeatureStatus::Available, nullptr, nsCString());
124 }
125
126 /* static */
Reset(Feature aFeature)127 void gfxConfig::Reset(Feature aFeature) {
128 FeatureState& state = sConfig->GetState(aFeature);
129 state.Reset();
130 }
131
132 /* static */
Inherit(Feature aFeature,FeatureStatus aStatus)133 void gfxConfig::Inherit(Feature aFeature, FeatureStatus aStatus) {
134 FeatureState& state = sConfig->GetState(aFeature);
135
136 state.Reset();
137
138 switch (aStatus) {
139 case FeatureStatus::Unused:
140 break;
141 case FeatureStatus::Available:
142 gfxConfig::EnableByDefault(aFeature);
143 break;
144 case FeatureStatus::ForceEnabled:
145 gfxConfig::EnableByDefault(aFeature);
146 gfxConfig::UserForceEnable(aFeature, "Inherited from parent process");
147 break;
148 default:
149 gfxConfig::SetDefault(aFeature, false, aStatus,
150 "Disabled in parent process");
151 break;
152 }
153 }
154
155 /* static */
Inherit(EnumSet<Feature> aFeatures,const DevicePrefs & aDevicePrefs)156 void gfxConfig::Inherit(EnumSet<Feature> aFeatures,
157 const DevicePrefs& aDevicePrefs) {
158 for (Feature feature : aFeatures) {
159 FeatureStatus status = FeatureStatus::Unused;
160 switch (feature) {
161 case Feature::HW_COMPOSITING:
162 status = aDevicePrefs.hwCompositing();
163 break;
164 case Feature::D3D11_COMPOSITING:
165 status = aDevicePrefs.d3d11Compositing();
166 break;
167 case Feature::OPENGL_COMPOSITING:
168 status = aDevicePrefs.oglCompositing();
169 break;
170 case Feature::DIRECT2D:
171 status = aDevicePrefs.useD2D1();
172 break;
173 case Feature::WEBGPU:
174 status = aDevicePrefs.webGPU();
175 break;
176 default:
177 break;
178 }
179 gfxConfig::Inherit(feature, status);
180 }
181 }
182
183 /* static */
UseFallback(Fallback aFallback)184 bool gfxConfig::UseFallback(Fallback aFallback) {
185 return sConfig->UseFallbackImpl(aFallback);
186 }
187
188 /* static */
EnableFallback(Fallback aFallback,const char * aMessage)189 void gfxConfig::EnableFallback(Fallback aFallback, const char* aMessage) {
190 if (!NS_IsMainThread()) {
191 nsCString message(aMessage);
192 NS_DispatchToMainThread(
193 NS_NewRunnableFunction("gfxConfig::EnableFallback", [=]() -> void {
194 gfxConfig::EnableFallback(aFallback, message.get());
195 }));
196 return;
197 }
198
199 if (XRE_IsGPUProcess()) {
200 nsCString message(aMessage);
201 Unused << GPUParent::GetSingleton()->SendUsedFallback(aFallback, message);
202 return;
203 }
204
205 sConfig->EnableFallbackImpl(aFallback, aMessage);
206 }
207
UseFallbackImpl(Fallback aFallback) const208 bool gfxConfig::UseFallbackImpl(Fallback aFallback) const {
209 return !!(mFallbackBits & (uint64_t(1) << uint64_t(aFallback)));
210 }
211
EnableFallbackImpl(Fallback aFallback,const char * aMessage)212 void gfxConfig::EnableFallbackImpl(Fallback aFallback, const char* aMessage) {
213 if (!UseFallbackImpl(aFallback)) {
214 MOZ_ASSERT(mNumFallbackLogEntries < kNumFallbacks);
215
216 FallbackLogEntry& entry = mFallbackLog[mNumFallbackLogEntries];
217 mNumFallbackLogEntries++;
218
219 entry.mFallback = aFallback;
220 PL_strncpyz(entry.mMessage, aMessage, sizeof(entry.mMessage));
221 }
222 mFallbackBits |= (uint64_t(1) << uint64_t(aFallback));
223 }
224
225 struct FeatureInfo {
226 const char* name;
227 const char* description;
228 };
229 static const FeatureInfo sFeatureInfo[] = {
230 #define FOR_EACH_FEATURE(name, type, desc) {#name, desc},
231 GFX_FEATURE_MAP(FOR_EACH_FEATURE)
232 #undef FOR_EACH_FEATURE
233 {nullptr, nullptr}};
234
235 /* static */
ForEachFeature(const FeatureIterCallback & aCallback)236 void gfxConfig::ForEachFeature(const FeatureIterCallback& aCallback) {
237 for (size_t i = 0; i < kNumFeatures; i++) {
238 FeatureState& state = GetFeature(static_cast<Feature>(i));
239 if (!state.IsInitialized()) {
240 continue;
241 }
242
243 aCallback(sFeatureInfo[i].name, sFeatureInfo[i].description, state);
244 }
245 }
246
247 static const char* sFallbackNames[] = {
248 #define FOR_EACH_FALLBACK(name) #name,
249 GFX_FALLBACK_MAP(FOR_EACH_FALLBACK)
250 #undef FOR_EACH_FALLBACK
251 nullptr};
252
253 /* static */
ForEachFallback(const FallbackIterCallback & aCallback)254 void gfxConfig::ForEachFallback(const FallbackIterCallback& aCallback) {
255 sConfig->ForEachFallbackImpl(aCallback);
256 }
257
ForEachFallbackImpl(const FallbackIterCallback & aCallback)258 void gfxConfig::ForEachFallbackImpl(const FallbackIterCallback& aCallback) {
259 for (size_t i = 0; i < mNumFallbackLogEntries; i++) {
260 const FallbackLogEntry& entry = mFallbackLog[i];
261 aCallback(sFallbackNames[size_t(entry.mFallback)], entry.mMessage);
262 }
263 }
264
GetFailureId(Feature aFeature)265 /* static */ const nsCString& gfxConfig::GetFailureId(Feature aFeature) {
266 const FeatureState& state = sConfig->GetState(aFeature);
267 return state.GetFailureId();
268 }
269
270 /* static */
ImportChange(Feature aFeature,const Maybe<FeatureFailure> & aChange)271 void gfxConfig::ImportChange(Feature aFeature,
272 const Maybe<FeatureFailure>& aChange) {
273 if (aChange.isNothing()) {
274 return;
275 }
276
277 const FeatureFailure& failure = aChange.ref();
278 gfxConfig::SetFailed(aFeature, failure.status(), failure.message().get(),
279 failure.failureId());
280 }
281
282 /* static */
Init()283 void gfxConfig::Init() { sConfig = mozilla::MakeUnique<gfxConfig>(); }
284
285 /* static */
Shutdown()286 void gfxConfig::Shutdown() { sConfig = nullptr; }
287
288 } // namespace gfx
289 } // namespace mozilla
290