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 #ifndef mozilla_gfx_config_gfxConfig_h
7 #define mozilla_gfx_config_gfxConfig_h
8 
9 #include <functional>
10 #include "gfxFeature.h"
11 #include "gfxFallback.h"
12 #include "mozilla/Assertions.h"
13 #include "mozilla/EnumSet.h"
14 #include "mozilla/Maybe.h"
15 
16 namespace mozilla {
17 namespace gfx {
18 
19 // Defined in GraphicsMessages.ipdlh.
20 class DevicePrefs;
21 class FeatureFailure;
22 
23 // Manages the history and state of a graphics feature. The flow of a feature
24 // is:
25 //   - A default value, set by all.js, or gfxPlatform.
26 //   - A user value, set by an external value or user pref.
27 //   - An environment value, determined by system/hardware factors or
28 //   nsIGfxInfo.
29 //   - A runtime value, determined by any failures encountered after enabling
30 //     the feature.
31 //
32 // Each state change for a feature is recorded in this class.
33 class gfxConfig {
34  public:
35   // Return the full state history of a feature.
36   static FeatureState& GetFeature(Feature aFeature);
37 
38   // Query whether a parameter is enabled, taking into account any user or
39   // runtime overrides. The algorithm works as follow:
40   //
41   //  1. If a runtime decision disabled the feature, return false.
42   //  2. If the user force-enabled the feature, return true.
43   //  3. If the environment disabled the feature, return false.
44   //  4. If the user specified a decision, return it.
45   //  5. Return the base setting for the feature.
46   static bool IsEnabled(Feature aFeature);
47 
48   // Query the history of a parameter. ForcedOnByUser returns whether or not
49   // the user specifically used a "force" preference to enable the parameter.
50   // IsDisabledByDefault returns whether or not the initial status of the
51   // feature, before adding user prefs and runtime decisions, was disabled.
52   static bool IsForcedOnByUser(Feature aFeature);
53 
54   // This returns true if the feature was disabled by default, or was never
55   // initialized to begin with.
56   static bool IsDisabledByDefault(Feature aFeature);
57 
58   // Query the status value of a parameter. This is computed similar to
59   // IsEnabled:
60   //
61   //  1. If a runtime failure was set, return it.
62   //  2. If the user force-enabled the feature, return ForceEnabled.
63   //  3. If an environment status was set, return it.
64   //  4. If a user status was set, return it.
65   //  5. Return the default status.
66   static FeatureStatus GetValue(Feature aFeature);
67 
68   // Reset the entire state of a feature.
69   static void Reset(Feature aFeature);
70 
71   // Initialize the base value of a parameter. The return value is aEnable.
72   static bool SetDefault(Feature aFeature, bool aEnable,
73                          FeatureStatus aDisableStatus,
74                          const char* aDisableMessage);
75   static void DisableByDefault(Feature aFeature, FeatureStatus aDisableStatus,
76                                const char* aDisableMessage,
77                                const nsACString& aFailureId = ""_ns);
78   static void EnableByDefault(Feature aFeature);
79 
80   // Inherit a computed value from another process.
81   static void Inherit(Feature aFeature, FeatureStatus aStatus);
82 
83   // Inherit a set of computed values from another process.
84   static void Inherit(EnumSet<Feature> aFeatures,
85                       const DevicePrefs& aDevicePrefs);
86 
87   // Set a environment status that overrides both the default and user
88   // statuses; this should be used to disable features based on system
89   // or hardware problems that can be determined up-front. The only
90   // status that can override this decision is the user force-enabling
91   // the feature.
92   static void Disable(Feature aFeature, FeatureStatus aStatus,
93                       const char* aMessage,
94                       const nsACString& aFailureId = ""_ns);
95 
96   // Given a preference name, infer the default value and whether or not the
97   // user has changed it. |aIsEnablePref| specifies whether or not the pref
98   // is intended to enable a feature (true), or disable it (false).
99   static void SetDefaultFromPref(Feature aFeature, const char* aPrefName,
100                                  bool aIsEnablePref, bool aDefaultValue);
101 
102   // Disable a parameter based on a runtime decision. This permanently
103   // disables the feature, since runtime decisions override all other
104   // decisions.
105   static void SetFailed(Feature aFeature, FeatureStatus aStatus,
106                         const char* aMessage,
107                         const nsACString& aFailureId = ""_ns);
108 
109   // Force a feature to be disabled permanently. This is the same as
110   // SetFailed(), but the name may be clearer depending on the context.
111   static void ForceDisable(Feature aFeature, FeatureStatus aStatus,
112                            const char* aMessage,
113                            const nsACString& aFailureId = ""_ns) {
114     SetFailed(aFeature, aStatus, aMessage, aFailureId);
115   }
116 
117   // Convenience helpers for SetFailed().
118   static bool MaybeSetFailed(Feature aFeature, bool aEnable,
119                              FeatureStatus aDisableStatus,
120                              const char* aDisableMessage,
121                              const nsACString& aFailureId = ""_ns) {
122     if (!aEnable) {
123       SetFailed(aFeature, aDisableStatus, aDisableMessage, aFailureId);
124       return false;
125     }
126     return true;
127   }
128 
129   // Convenience helper for SetFailed().
130   static bool MaybeSetFailed(Feature aFeature, FeatureStatus aStatus,
131                              const char* aDisableMessage,
132                              const nsACString& aFailureId = ""_ns) {
133     return MaybeSetFailed(aFeature,
134                           (aStatus != FeatureStatus::Available &&
135                            aStatus != FeatureStatus::ForceEnabled),
136                           aStatus, aDisableMessage, aFailureId);
137   }
138 
139   // Re-enables a feature that was previously disabled, by attaching it to a
140   // fallback. The fallback inherits the message that was used for disabling
141   // the feature. This can be used, for example, when D3D11 fails at runtime
142   // but we acquire a second, successful device with WARP.
143   static void Reenable(Feature aFeature, Fallback aFallback);
144 
145   // Same as SetDefault, except if the feature already has a default value
146   // set, the new value will be set as a runtime value. This is useful for
147   // when the base value can change (for example, via an update from the
148   // parent process).
149   static bool InitOrUpdate(Feature aFeature, bool aEnable,
150                            FeatureStatus aDisableStatus,
151                            const char* aDisableMessage);
152 
153   // Set a user status that overrides the base value (but not runtime value)
154   // of a parameter.
155   static void UserEnable(Feature aFeature, const char* aMessage);
156   static void UserForceEnable(Feature aFeature, const char* aMessage);
157   static void UserDisable(Feature aFeature, const char* aMessage,
158                           const nsACString& aFailureId = ""_ns);
159 
160   // Query whether a fallback has been toggled.
161   static bool UseFallback(Fallback aFallback);
162 
163   // Add a log entry denoting that a given fallback had to be used. This can
164   // be called from any thread in the UI or GPU process.
165   static void EnableFallback(Fallback aFallback, const char* aMessage);
166 
167   // Run a callback for each initialized FeatureState.
168   typedef std::function<void(const char* aName, const char* aDescription,
169                              FeatureState& aFeature)>
170       FeatureIterCallback;
171   static void ForEachFeature(const FeatureIterCallback& aCallback);
172 
173   // Run a callback for each enabled fallback.
174   typedef std::function<void(const char* aName, const char* aMsg)>
175       FallbackIterCallback;
176   static void ForEachFallback(const FallbackIterCallback& aCallback);
177 
178   // Get the most descriptive failure id message for this feature.
179   static const nsCString& GetFailureId(Feature aFeature);
180 
181   static void ImportChange(Feature aFeature,
182                            const Maybe<FeatureFailure>& aChange);
183 
184   static void Init();
185   static void Shutdown();
186 
187  private:
188   void ForEachFallbackImpl(const FallbackIterCallback& aCallback);
189 
190  private:
GetState(Feature aFeature)191   FeatureState& GetState(Feature aFeature) {
192     MOZ_ASSERT(size_t(aFeature) < kNumFeatures);
193     return mFeatures[size_t(aFeature)];
194   }
GetState(Feature aFeature)195   const FeatureState& GetState(Feature aFeature) const {
196     MOZ_ASSERT(size_t(aFeature) < kNumFeatures);
197     return mFeatures[size_t(aFeature)];
198   }
199 
200   bool UseFallbackImpl(Fallback aFallback) const;
201   void EnableFallbackImpl(Fallback aFallback, const char* aMessage);
202 
203  private:
204   static const size_t kNumFeatures = size_t(Feature::NumValues);
205   static const size_t kNumFallbacks = size_t(Fallback::NumValues);
206 
207  private:
208   FeatureState mFeatures[kNumFeatures];
209   uint64_t mFallbackBits;
210 
211  private:
212   struct FallbackLogEntry {
213     Fallback mFallback;
214     char mMessage[80];
215   };
216 
217   FallbackLogEntry mFallbackLog[kNumFallbacks];
218   size_t mNumFallbackLogEntries;
219 };
220 
221 }  // namespace gfx
222 }  // namespace mozilla
223 
224 #endif  // mozilla_gfx_config_gfxConfig_h
225