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