1// Copyright (c) 2013 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef GPU_CONFIG_GPU_CONTROL_LIST_H_
6#define GPU_CONFIG_GPU_CONTROL_LIST_H_
7
8#include <set>
9#include <string>
10#include <vector>
11
12#include "base/basictypes.h"
13#include "base/containers/hash_tables.h"
14#include "base/gtest_prod_util.h"
15#include "base/memory/ref_counted.h"
16#include "base/memory/scoped_ptr.h"
17#include "base/values.h"
18#include "build/build_config.h"
19#include "gpu/gpu_export.h"
20
21namespace gpu {
22struct GPUInfo;
23
24class GPU_EXPORT GpuControlList {
25 public:
26  enum OsType {
27    kOsLinux,
28    kOsMacosx,
29    kOsWin,
30    kOsChromeOS,
31    kOsAndroid,
32    kOsAny,
33    kOsUnknown
34  };
35
36  enum OsFilter {
37    // In loading, ignore all entries that belong to other OS.
38    kCurrentOsOnly,
39    // In loading, keep all entries. This is for testing only.
40    kAllOs
41  };
42
43  GpuControlList();
44  virtual ~GpuControlList();
45
46  // Loads control list information from a json file.
47  // If failed, the current GpuControlList is un-touched.
48  bool LoadList(const std::string& json_context, OsFilter os_filter);
49  bool LoadList(const std::string& browser_version_string,
50                const std::string& json_context, OsFilter os_filter);
51
52  // Collects system information and combines them with gpu_info and control
53  // list information to decide which entries are applied to the current
54  // system and returns the union of features specified in each entry.
55  // If os is kOsAny, use the current OS; if os_version is empty, use the
56  // current OS version.
57  std::set<int> MakeDecision(
58      OsType os, std::string os_version, const GPUInfo& gpu_info);
59
60  // Collects the active entries from the last MakeDecision() call.
61  // If disabled set to true, return entries that are disabled; otherwise,
62  // return enabled entries.
63  void GetDecisionEntries(std::vector<uint32>* entry_ids,
64                          bool disabled) const;
65
66  // Returns the description and bugs from active entries from the last
67  // MakeDecision() call.
68  //
69  // Each problems has:
70  // {
71  //    "description": "Your GPU is too old",
72  //    "crBugs": [1234],
73  //    "webkitBugs": []
74  // }
75  void GetReasons(base::ListValue* problem_list) const;
76
77  // Return the largest entry id.  This is used for histogramming.
78  uint32 max_entry_id() const;
79
80  // Returns the version of the control list.
81  std::string version() const;
82
83  // Check if we need more gpu info to make the decisions.
84  // This is computed from the last MakeDecision() call.
85  // If yes, we should create a gl context and do a full gpu info collection.
86  bool needs_more_info() const { return needs_more_info_; }
87
88  // Check if any entries contain unknown fields.  This is only for tests.
89  bool contains_unknown_fields() const { return contains_unknown_fields_; }
90
91  // Returns the number of entries.  This is only for tests.
92  size_t num_entries() const;
93
94  // Register a feature to FeatureMap - used to construct a GpuControlList.
95  void AddSupportedFeature(const std::string& feature_name, int feature_id);
96  // Register whether "all" is recognized as all features.
97  void set_supports_feature_type_all(bool supported);
98
99 private:
100  friend class GpuControlListEntryTest;
101  friend class MachineModelInfoTest;
102  friend class NumberInfoTest;
103  friend class OsInfoTest;
104  friend class StringInfoTest;
105  friend class VersionInfoTest;
106
107  enum BrowserVersionSupport {
108    kSupported,
109    kUnsupported,
110    kMalformed
111  };
112
113  enum NumericOp {
114    kBetween,  // <= * <=
115    kEQ,  // =
116    kLT,  // <
117    kLE,  // <=
118    kGT,  // >
119    kGE,  // >=
120    kAny,
121    kUnknown  // Indicates the data is invalid.
122  };
123
124  class GPU_EXPORT VersionInfo {
125   public:
126    // If version_style is empty, it defaults to kNumerical.
127    VersionInfo(const std::string& version_op,
128                const std::string& version_style,
129                const std::string& version_string,
130                const std::string& version_string2);
131    ~VersionInfo();
132
133    // Determines if a given version is included in the VersionInfo range.
134    // "splitter" divides version string into segments.
135    bool Contains(const std::string& version, char splitter) const;
136    // Same as above, using '.' as splitter.
137    bool Contains(const std::string& version) const;
138
139    // Determine if the version_style is lexical.
140    bool IsLexical() const;
141
142    // Determines if the VersionInfo contains valid information.
143    bool IsValid() const;
144
145   private:
146    enum VersionStyle {
147      kVersionStyleNumerical,
148      kVersionStyleLexical,
149      kVersionStyleUnknown
150    };
151
152    static VersionStyle StringToVersionStyle(const std::string& version_style);
153
154    // Compare two version strings.
155    // Return 1 if version > version_ref,
156    //        0 if version = version_ref,
157    //       -1 if version < version_ref.
158    // Note that we only compare as many segments as both versions contain.
159    // For example: Compare("10.3.1", "10.3") returns 0,
160    //              Compare("10.3", "10.3.1") returns 0.
161    // If "version_style" is Lexical, the first segment is compared
162    // numerically, all other segments are compared lexically.
163    // Lexical is used for AMD Linux driver versions only.
164    static int Compare(const std::vector<std::string>& version,
165                       const std::vector<std::string>& version_ref,
166                       VersionStyle version_style);
167
168    NumericOp op_;
169    VersionStyle version_style_;
170    std::vector<std::string> version_;
171    std::vector<std::string> version2_;
172  };
173
174  class GPU_EXPORT OsInfo {
175   public:
176    OsInfo(const std::string& os,
177           const std::string& version_op,
178           const std::string& version_string,
179           const std::string& version_string2);
180    ~OsInfo();
181
182    // Determines if a given os/version is included in the OsInfo set.
183    bool Contains(OsType type, const std::string& version) const;
184
185    // Determines if the VersionInfo contains valid information.
186    bool IsValid() const;
187
188    OsType type() const;
189
190    // Maps string to OsType; returns kOsUnknown if it's not a valid os.
191    static OsType StringToOsType(const std::string& os);
192
193   private:
194    OsType type_;
195    scoped_ptr<VersionInfo> version_info_;
196  };
197
198  class GPU_EXPORT StringInfo {
199   public:
200    StringInfo(const std::string& string_op, const std::string& string_value);
201
202    // Determines if a given string is included in the StringInfo.
203    bool Contains(const std::string& value) const;
204
205    // Determines if the StringInfo contains valid information.
206    bool IsValid() const;
207
208   private:
209    enum Op {
210      kContains,
211      kBeginWith,
212      kEndWith,
213      kEQ,  // =
214      kUnknown  // Indicates StringInfo data is invalid.
215    };
216
217    // Maps string to Op; returns kUnknown if it's not a valid Op.
218    static Op StringToOp(const std::string& string_op);
219
220    Op op_;
221    std::string value_;
222  };
223
224  class GPU_EXPORT FloatInfo {
225   public:
226    FloatInfo(const std::string& float_op,
227              const std::string& float_value,
228              const std::string& float_value2);
229
230    // Determines if a given float is included in the FloatInfo.
231    bool Contains(float value) const;
232
233    // Determines if the FloatInfo contains valid information.
234    bool IsValid() const;
235
236   private:
237    NumericOp op_;
238    float value_;
239    float value2_;
240  };
241
242  class GPU_EXPORT IntInfo {
243   public:
244    IntInfo(const std::string& int_op,
245            const std::string& int_value,
246            const std::string& int_value2);
247
248    // Determines if a given int is included in the IntInfo.
249    bool Contains(int value) const;
250
251    // Determines if the IntInfo contains valid information.
252    bool IsValid() const;
253
254   private:
255    NumericOp op_;
256    int value_;
257    int value2_;
258  };
259
260  class GPU_EXPORT MachineModelInfo {
261   public:
262    MachineModelInfo(const std::string& name_op,
263                     const std::string& name_value,
264                     const std::string& version_op,
265                     const std::string& version_string,
266                     const std::string& version_string2);
267    ~MachineModelInfo();
268
269    // Determines if a given name/version is included in the MachineModelInfo.
270    bool Contains(const std::string& name, const std::string& version) const;
271
272    // Determines if the MachineModelInfo contains valid information.
273    bool IsValid() const;
274
275   private:
276    scoped_ptr<StringInfo> name_info_;
277    scoped_ptr<VersionInfo> version_info_;
278  };
279
280  class GpuControlListEntry;
281  typedef scoped_refptr<GpuControlListEntry> ScopedGpuControlListEntry;
282
283  typedef base::hash_map<std::string, int> FeatureMap;
284
285  class GPU_EXPORT GpuControlListEntry
286      : public base::RefCounted<GpuControlListEntry> {
287   public:
288    // Constructs GpuControlListEntry from DictionaryValue loaded from json.
289    // Top-level entry must have an id number.  Others are exceptions.
290    static ScopedGpuControlListEntry GetEntryFromValue(
291        const base::DictionaryValue* value, bool top_level,
292        const FeatureMap& feature_map,
293        bool supports_feature_type_all);
294
295    // Determines if a given os/gc/machine_model/driver is included in the
296    // Entry set.
297    bool Contains(OsType os_type, const std::string& os_version,
298                  const GPUInfo& gpu_info) const;
299
300    // Determines whether we needs more gpu info to make the blacklisting
301    // decision.  It should only be checked if Contains() returns true.
302    bool NeedsMoreInfo(const GPUInfo& gpu_info) const;
303
304    // Returns the OsType.
305    OsType GetOsType() const;
306
307    // Returns the entry's unique id.  0 is reserved.
308    uint32 id() const;
309
310    // Returns whether the entry is disabled.
311    bool disabled() const;
312
313    // Returns the description of the entry
314    const std::string& description() const { return description_; }
315
316    // Returns a list of Chromium and Webkit bugs applicable to this entry
317    const std::vector<int>& cr_bugs() const { return cr_bugs_; }
318    const std::vector<int>& webkit_bugs() const { return webkit_bugs_; }
319
320    // Returns the blacklisted features in this entry.
321    const std::set<int>& features() const;
322
323    // Returns true if an unknown field is encountered.
324    bool contains_unknown_fields() const {
325      return contains_unknown_fields_;
326    }
327    // Returns true if an unknown blacklist feature is encountered.
328    bool contains_unknown_features() const {
329      return contains_unknown_features_;
330    }
331
332   private:
333    friend class base::RefCounted<GpuControlListEntry>;
334
335    enum MultiGpuStyle {
336      kMultiGpuStyleOptimus,
337      kMultiGpuStyleAMDSwitchable,
338      kMultiGpuStyleNone
339    };
340
341    enum MultiGpuCategory {
342      kMultiGpuCategoryPrimary,
343      kMultiGpuCategorySecondary,
344      kMultiGpuCategoryAny,
345      kMultiGpuCategoryNone
346    };
347
348    GpuControlListEntry();
349    ~GpuControlListEntry();
350
351    bool SetId(uint32 id);
352
353    void SetDisabled(bool disabled);
354
355    bool SetOsInfo(const std::string& os,
356                   const std::string& version_op,
357                   const std::string& version_string,
358                   const std::string& version_string2);
359
360    bool SetVendorId(const std::string& vendor_id_string);
361
362    bool AddDeviceId(const std::string& device_id_string);
363
364    bool SetMultiGpuStyle(const std::string& multi_gpu_style_string);
365
366    bool SetMultiGpuCategory(const std::string& multi_gpu_category_string);
367
368    bool SetDriverVendorInfo(const std::string& vendor_op,
369                             const std::string& vendor_value);
370
371    bool SetDriverVersionInfo(const std::string& version_op,
372                              const std::string& version_style,
373                              const std::string& version_string,
374                              const std::string& version_string2);
375
376    bool SetDriverDateInfo(const std::string& date_op,
377                           const std::string& date_string,
378                           const std::string& date_string2);
379
380    bool SetGLVendorInfo(const std::string& vendor_op,
381                         const std::string& vendor_value);
382
383    bool SetGLRendererInfo(const std::string& renderer_op,
384                           const std::string& renderer_value);
385
386    bool SetGLExtensionsInfo(const std::string& extensions_op,
387                             const std::string& extensions_value);
388
389    bool SetGLResetNotificationStrategyInfo(const std::string& op,
390                                            const std::string& int_string,
391                                            const std::string& int_string2);
392
393    bool SetCpuBrand(const std::string& cpu_op,
394                     const std::string& cpu_value);
395
396    bool SetPerfGraphicsInfo(const std::string& op,
397                             const std::string& float_string,
398                             const std::string& float_string2);
399
400    bool SetPerfGamingInfo(const std::string& op,
401                           const std::string& float_string,
402                           const std::string& float_string2);
403
404    bool SetPerfOverallInfo(const std::string& op,
405                            const std::string& float_string,
406                            const std::string& float_string2);
407
408    bool SetMachineModelInfo(const std::string& name_op,
409                             const std::string& name_value,
410                             const std::string& version_op,
411                             const std::string& version_string,
412                             const std::string& version_string2);
413
414    bool SetGpuCountInfo(const std::string& op,
415                         const std::string& int_string,
416                         const std::string& int_string2);
417
418    bool SetFeatures(const std::vector<std::string>& features,
419                     const FeatureMap& feature_map,
420                     bool supports_feature_type_all);
421
422    void AddException(ScopedGpuControlListEntry exception);
423
424    static MultiGpuStyle StringToMultiGpuStyle(const std::string& style);
425
426    static MultiGpuCategory StringToMultiGpuCategory(
427        const std::string& category);
428
429    // map a feature_name to feature_id. If the string is not a registered
430    // feature name, return false.
431    static bool StringToFeature(const std::string& feature_name,
432                                int* feature_id,
433                                const FeatureMap& feature_map);
434
435    uint32 id_;
436    bool disabled_;
437    std::string description_;
438    std::vector<int> cr_bugs_;
439    std::vector<int> webkit_bugs_;
440    scoped_ptr<OsInfo> os_info_;
441    uint32 vendor_id_;
442    std::vector<uint32> device_id_list_;
443    MultiGpuStyle multi_gpu_style_;
444    MultiGpuCategory multi_gpu_category_;
445    scoped_ptr<StringInfo> driver_vendor_info_;
446    scoped_ptr<VersionInfo> driver_version_info_;
447    scoped_ptr<VersionInfo> driver_date_info_;
448    scoped_ptr<StringInfo> gl_vendor_info_;
449    scoped_ptr<StringInfo> gl_renderer_info_;
450    scoped_ptr<StringInfo> gl_extensions_info_;
451    scoped_ptr<IntInfo> gl_reset_notification_strategy_info_;
452    scoped_ptr<StringInfo> cpu_brand_;
453    scoped_ptr<FloatInfo> perf_graphics_info_;
454    scoped_ptr<FloatInfo> perf_gaming_info_;
455    scoped_ptr<FloatInfo> perf_overall_info_;
456    scoped_ptr<MachineModelInfo> machine_model_info_;
457    scoped_ptr<IntInfo> gpu_count_info_;
458    std::set<int> features_;
459    std::vector<ScopedGpuControlListEntry> exceptions_;
460    bool contains_unknown_fields_;
461    bool contains_unknown_features_;
462  };
463
464  // Gets the current OS type.
465  static OsType GetOsType();
466
467  bool LoadList(const base::DictionaryValue& parsed_json, OsFilter os_filter);
468
469  void Clear();
470
471  // Check if the entry is supported by the current version of browser.
472  // By default, if there is no browser version information in the entry,
473  // return kSupported;
474  BrowserVersionSupport IsEntrySupportedByCurrentBrowserVersion(
475      const base::DictionaryValue* value);
476
477  static NumericOp StringToNumericOp(const std::string& op);
478
479  std::string version_;
480  std::vector<ScopedGpuControlListEntry> entries_;
481
482  std::string browser_version_;
483
484  // This records all the blacklist entries that are appliable to the current
485  // user machine.  It is updated everytime MakeDecision() is called and is
486  // used later by GetDecisionEntries().
487  std::vector<ScopedGpuControlListEntry> active_entries_;
488
489  uint32 max_entry_id_;
490
491  bool contains_unknown_fields_;
492
493  bool needs_more_info_;
494
495  // The features a GpuControlList recognizes and handles.
496  FeatureMap feature_map_;
497  bool supports_feature_type_all_;
498};
499
500}  // namespace gpu
501
502#endif  // GPU_CONFIG_GPU_CONTROL_LIST_H_
503
504