// Copyright (c) 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef GPU_CONFIG_GPU_CONTROL_LIST_H_
#define GPU_CONFIG_GPU_CONTROL_LIST_H_

#include <stddef.h>

#include <set>
#include <string>
#include <vector>

#include "base/containers/hash_tables.h"
#include "base/values.h"
#include "gpu/gpu_export.h"

namespace gpu {
struct GpuControlListData;
struct GPUInfo;

class GPU_EXPORT GpuControlList {
 public:
  typedef base::hash_map<int, std::string> FeatureMap;

  enum OsType {
    kOsLinux,
    kOsMacosx,
    kOsWin,
    kOsChromeOS,
    kOsAndroid,
    kOsFuchsia,
    kOsAny
  };

  enum OsFilter {
    // In loading, ignore all entries that belong to other OS.
    kCurrentOsOnly,
    // In loading, keep all entries. This is for testing only.
    kAllOs
  };

  enum NumericOp {
    kBetween,  // <= * <=
    kEQ,  // =
    kLT,  // <
    kLE,  // <=
    kGT,  // >
    kGE,  // >=
    kAny,
    kUnknown  // Indicates the data is invalid.
  };

  enum MultiGpuStyle {
    kMultiGpuStyleOptimus,
    kMultiGpuStyleAMDSwitchable,
    kMultiGpuStyleAMDSwitchableIntegrated,
    kMultiGpuStyleAMDSwitchableDiscrete,
    kMultiGpuStyleNone
  };

  enum MultiGpuCategory {
    // This entry applies if this is the primary GPU on the system.
    kMultiGpuCategoryPrimary,
    // This entry applies if this is a secondary GPU on the system.
    kMultiGpuCategorySecondary,
    // This entry applies if this is the active GPU on the system.
    kMultiGpuCategoryActive,
    // This entry applies if this is any of the GPUs on the system.
    kMultiGpuCategoryAny,
    kMultiGpuCategoryNone
  };

  enum GLType {
    kGLTypeGL,     // This is default on MacOSX, Linux, ChromeOS
    kGLTypeGLES,   // This is default on Android
    kGLTypeANGLE,  // This is default on Windows
    kGLTypeNone
  };

  enum VersionStyle {
    kVersionStyleNumerical,
    kVersionStyleLexical,
    kVersionStyleUnknown
  };

  enum class GpuSeriesType {
    // Intel 6th gen
    kIntelSandyBridge,
    // Intel 7th gen
    kIntelValleyView,  // BayTrail
    kIntelIvyBridge,
    kIntelHaswell,
    // Intel 8th gen
    kIntelCherryView,  // Braswell
    kIntelBroadwell,
    // Intel 9th gen
    kIntelApolloLake,
    kIntelSkyLake,
    kIntelGeminiLake,
    kIntelKabyLake,
    kIntelCoffeeLake,
    // Please also update |gpu_series_map| in process_json.py.

    kUnknown,
  };

  struct GPU_EXPORT Version {
    NumericOp op;
    VersionStyle style;
    const char* value1;
    const char* value2;

    bool IsSpecified() const { return op != kUnknown; }

    bool Contains(const std::string& version_string, char splitter) const;

    bool Contains(const std::string& version_string) const {
      return Contains(version_string, '.');
    }

    // Compare two version strings.
    // Return 1 if version > version_ref,
    //        0 if version = version_ref,
    //       -1 if version < version_ref.
    // Note that we only compare as many segments as both versions contain.
    // For example: Compare("10.3.1", "10.3") returns 0,
    //              Compare("10.3", "10.3.1") returns 0.
    // If "version_style" is Lexical, the first segment is compared
    // numerically, all other segments are compared lexically.
    // Lexical is used for AMD Linux driver versions only.
    static int Compare(const std::vector<std::string>& version,
                       const std::vector<std::string>& version_ref,
                       VersionStyle version_style);
  };

  struct GPU_EXPORT DriverInfo {
    const char* driver_vendor;
    Version driver_version;
    Version driver_date;

    bool Contains(const GPUInfo& gpu_info) const;
  };

  struct GPU_EXPORT GLStrings {
    const char* gl_vendor;
    const char* gl_renderer;
    const char* gl_extensions;
    const char* gl_version;

    bool Contains(const GPUInfo& gpu_info) const;
  };

  struct GPU_EXPORT MachineModelInfo {
    size_t machine_model_name_size;
    const char* const* machine_model_names;
    Version machine_model_version;

    bool Contains(const GPUInfo& gpu_info) const;
  };

  struct GPU_EXPORT More {
    // These are just part of Entry fields that are less common.
    // Putting them to a separate struct to save Entry data size.
    GLType gl_type;
    Version gl_version;
    Version pixel_shader_version;
    bool in_process_gpu;
    uint32_t gl_reset_notification_strategy;
    bool direct_rendering;
    Version gpu_count;

    uint32_t test_group;

    // Return true if GL_VERSION string does not fit the entry info
    // on GL type and GL version.
    bool GLVersionInfoMismatch(const std::string& gl_version_string) const;

    bool Contains(const GPUInfo& gpu_info) const;

    // Return the default GL type, depending on the OS.
    // See GLType declaration.
    static GLType GetDefaultGLType();
  };

  struct GPU_EXPORT Conditions {
    OsType os_type;
    Version os_version;
    uint32_t vendor_id;
    size_t device_id_size;
    const uint32_t* device_ids;
    MultiGpuCategory multi_gpu_category;
    MultiGpuStyle multi_gpu_style;
    const DriverInfo* driver_info;
    const GLStrings* gl_strings;
    const MachineModelInfo* machine_model_info;
    size_t gpu_series_list_size;
    const GpuSeriesType* gpu_series_list;
    const More* more;

    bool Contains(OsType os_type,
                  const std::string& os_version,
                  const GPUInfo& gpu_info) const;

    // Determines whether we needs more gpu info to make the blacklisting
    // decision.  It should only be checked if Contains() returns true.
    bool NeedsMoreInfo(const GPUInfo& gpu_info) const;
  };

  struct GPU_EXPORT Entry {
    uint32_t id;
    const char* description;
    size_t feature_size;
    const int* features;
    size_t disabled_extension_size;
    const char* const* disabled_extensions;
    size_t disabled_webgl_extension_size;
    const char* const* disabled_webgl_extensions;
    size_t cr_bug_size;
    const uint32_t* cr_bugs;
    Conditions conditions;
    size_t exception_size;
    const Conditions* exceptions;

    bool Contains(OsType os_type,
                  const std::string& os_version,
                  const GPUInfo& gpu_info) const;

    bool AppliesToTestGroup(uint32_t target_test_group) const;

    // Determines whether we needs more gpu info to make the blacklisting
    // decision.  It should only be checked if Contains() returns true.
    bool NeedsMoreInfo(const GPUInfo& gpu_info, bool consider_exceptions) const;

    void GetFeatureNames(base::ListValue* feature_names,
                         const FeatureMap& feature_map) const;

    // Logs a control list match for this rule in the list identified by
    // |control_list_logging_name|.
    void LogControlListMatch(
        const std::string& control_list_logging_name) const;
  };

  explicit GpuControlList(const GpuControlListData& data);
  virtual ~GpuControlList();

  // Collects system information and combines them with gpu_info and control
  // list information to decide which entries are applied to the current
  // system and returns the union of features specified in each entry.
  // If os is kOsAny, use the current OS; if os_version is empty, use the
  // current OS version.
  std::set<int32_t> MakeDecision(OsType os,
                                 const std::string& os_version,
                                 const GPUInfo& gpu_info);
  // Same as the above function, but instead of using the entries with no
  // "test_group" specified or "test_group" = 0, using the entries with
  // "test_group" = |target_test_group|.
  std::set<int32_t> MakeDecision(OsType os,
                                 const std::string& os_version,
                                 const GPUInfo& gpu_info,
                                 uint32_t target_test_group);

  // Return the active entry indices from the last MakeDecision() call.
  const std::vector<uint32_t>& GetActiveEntries() const;
  // Return corresponding entry IDs from entry indices.
  std::vector<uint32_t> GetEntryIDsFromIndices(
      const std::vector<uint32_t>& entry_indices) const;

  // Collects all disabled extensions.
  std::vector<std::string> GetDisabledExtensions();
  // Collects all disabled WebGL extensions.
  std::vector<std::string> GetDisabledWebGLExtensions();

  // Returns the description and bugs from active entries provided.
  // Each problems has:
  // {
  //    "description": "Your GPU is too old",
  //    "crBugs": [1234],
  // }
  // The use case is we compute the entries from GPU process and send them to
  // browser process, and call GetReasons() in browser process.
  void GetReasons(base::ListValue* problem_list,
                  const std::string& tag,
                  const std::vector<uint32_t>& entries) const;

  // Return the largest entry id.  This is used for histogramming.
  uint32_t max_entry_id() const;

  // Check if we need more gpu info to make the decisions.
  // This is computed from the last MakeDecision() call.
  // If yes, we should create a gl context and do a full gpu info collection.
  bool needs_more_info() const { return needs_more_info_; }

  // Returns the number of entries.  This is only for tests.
  size_t num_entries() const;

  // Register a feature to FeatureMap.
  void AddSupportedFeature(const std::string& feature_name, int feature_id);

  // Enables logging of control list decisions.
  void EnableControlListLogging(const std::string& control_list_logging_name) {
    control_list_logging_enabled_ = true;
    control_list_logging_name_ = control_list_logging_name;
  }

 protected:
  // Return false if an entry index goes beyond |total_entries|.
  static bool AreEntryIndicesValid(const std::vector<uint32_t>& entry_indices,
                                   size_t total_entries);

 private:
  friend class GpuControlListEntryTest;
  friend class VersionInfoTest;

  // Gets the current OS type.
  static OsType GetOsType();

  static GpuSeriesType GetGpuSeriesType(uint32_t vendor_id, uint32_t device_id);

  size_t entry_count_;
  const Entry* entries_;
  // This records all the entries that are appliable to the current user
  // machine.  It is updated everytime MakeDecision() is called and is used
  // later by GetDecisionEntries().
  std::vector<uint32_t> active_entries_;

  uint32_t max_entry_id_;

  bool needs_more_info_;

  // The features a GpuControlList recognizes and handles.
  FeatureMap feature_map_;

  bool control_list_logging_enabled_;
  std::string control_list_logging_name_;
};

struct GPU_EXPORT GpuControlListData {
  size_t entry_count;
  const GpuControlList::Entry* entries;

  GpuControlListData() : entry_count(0u), entries(nullptr) {}

  GpuControlListData(size_t a_entry_count,
                     const GpuControlList::Entry* a_entries)
      : entry_count(a_entry_count), entries(a_entries) {}
};

}  // namespace gpu

#endif  // GPU_CONFIG_GPU_CONTROL_LIST_H_
