// // Copyright 2018 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // // feature_support_util.cpp: Helps client APIs make decisions based on rules // data files. For example, the Android EGL loader uses this library to // determine whether to use ANGLE or a native GLES driver. #include "feature_support_util.h" #include <json/json.h> #include <string.h> #include "common/platform.h" #if defined(ANGLE_PLATFORM_ANDROID) # include <android/log.h> # include <unistd.h> #endif #include <fstream> #include <ios> #include <list> #include <memory> #include <sstream> #include <utility> #include <vector> #include "../gpu_info_util/SystemInfo.h" namespace angle { #if defined(ANGLE_PLATFORM_ANDROID) // Define ANGLE_FEATURE_UTIL_LOG_VERBOSE if you want VERBOSE to output // ANGLE_FEATURE_UTIL_LOG_VERBOSE is automatically defined when is_debug = true #define ERR … #define WARN … #define INFO … #define DEBUG … # ifdef ANGLE_FEATURE_UTIL_LOG_VERBOSE #define VERBOSE … # else #define VERBOSE … # endif #else // defined(ANDROID) #define ERR(...) … #define WARN(...) … #define INFO(...) … #define DEBUG(...) … // Uncomment for debugging. // # define VERBOSE(...) printf(__VA_ARGS__) #define VERBOSE(...) … #endif // defined(ANDROID) // JSON values are generally composed of either: // - Objects, which are a set of comma-separated string:value pairs (note the recursive nature) // - Arrays, which are a set of comma-separated values. // We'll call the string in a string:value pair the "identifier". These identifiers are defined // below, as follows: // The JSON identifier for the top-level set of rules. This is an object, the value of which is an // array of rules. The rules will be processed in order. If a rule matches, the rule's version of // the answer (true or false) becomes the new answer. After all rules are processed, the // most-recent answer is the final answer. constexpr char kJsonRules[] = …; // The JSON identifier for a given rule. A rule is an object, the first string:value pair is this // identifier (i.e. "Rule") as the string and the value is a user-firendly description of the rule: constexpr char kJsonRule[] = …; // Within a rule, the JSON identifier for the answer--whether or not to use ANGLE. The value is a // boolean (i.e. true or false). constexpr char kJsonUseANGLE[] = …; // Within a rule, the JSON identifier for describing one or more applications. The value is an // array of objects, each object of which can specify attributes of an application. constexpr char kJsonApplications[] = …; // Within an object that describes the attributes of an application, the JSON identifier for the // name of the application (e.g. "com.google.maps"). The value is a string. If any other // attributes will be specified, this must be the first attribute specified in the object. constexpr char kJsonAppName[] = …; // Within a rule, the JSON identifier for describing one or more devices. The value is an // array of objects, each object of which can specify attributes of a device. constexpr char kJsonDevices[] = …; // Within an object that describes the attributes of a device, the JSON identifier for the // manufacturer of the device. The value is a string. If any other non-GPU attributes will be // specified, this must be the first attribute specified in the object. constexpr char kJsonManufacturer[] = …; // Within an object that describes the attributes of a device, the JSON identifier for the // model of the device. The value is a string. constexpr char kJsonModel[] = …; // Within an object that describes the attributes of a device, the JSON identifier for describing // one or more GPUs/drivers used in the device. The value is an // array of objects, each object of which can specify attributes of a GPU and its driver. constexpr char kJsonGPUs[] = …; // Within an object that describes the attributes of a GPU and driver, the JSON identifier for the // vendor of the device/driver. The value is a string. If any other attributes will be specified, // this must be the first attribute specified in the object. constexpr char kJsonVendor[] = …; // Within an object that describes the attributes of a GPU and driver, the JSON identifier for the // deviceId of the device. The value is an unsigned integer. If the driver version will be // specified, this must preceded the version attributes specified in the object. constexpr char kJsonDeviceId[] = …; // Within an object that describes the attributes of either an application or a GPU, the JSON // identifier for the major version of that application or GPU driver. The value is a positive // integer number. Not specifying a major version implies a wildcard for all values of a version. constexpr char kJsonVerMajor[] = …; // Within an object that describes the attributes of either an application or a GPU, the JSON // identifier for the minor version of that application or GPU driver. The value is a positive // integer number. In order to specify a minor version, it must be specified immediately after the // major number associated with it. Not specifying a minor version implies a wildcard for the // minor, subminor, and patch values of a version. constexpr char kJsonVerMinor[] = …; // Within an object that describes the attributes of either an application or a GPU, the JSON // identifier for the subminor version of that application or GPU driver. The value is a positive // integer number. In order to specify a subminor version, it must be specified immediately after // the minor number associated with it. Not specifying a subminor version implies a wildcard for // the subminor and patch values of a version. constexpr char kJsonVerSubMinor[] = …; // Within an object that describes the attributes of either an application or a GPU, the JSON // identifier for the patch version of that application or GPU driver. The value is a positive // integer number. In order to specify a patch version, it must be specified immediately after the // subminor number associated with it. Not specifying a patch version implies a wildcard for the // patch value of a version. constexpr char kJsonVerPatch[] = …; // This encapsulates a std::string. The default constructor (not given a string) assumes that this // is a wildcard (i.e. will match all other StringPart objects). class StringPart { … }; // This encapsulates a 32-bit unsigned integer. The default constructor (not given a number) // assumes that this is a wildcard (i.e. will match all other IntegerPart objects). class IntegerPart { … }; // This encapsulates a list of other classes, each of which will have a match() and logItem() // method. The common constructor (given a type, but not any list items) assumes that this is // a wildcard (i.e. will match all other ListOf<t> objects). template <class T> class ListOf { … }; // This encapsulates up-to four 32-bit unsigned integers, that represent a potentially-complex // version number. The default constructor (not given any numbers) assumes that this is a wildcard // (i.e. will match all other Version objects). Each part of a Version is stored in an IntegerPart // class, and so may be wildcarded as well. class Version { … }; // This encapsulates an application, and potentially the application's Version. The default // constructor (not given any values) assumes that this is a wildcard (i.e. will match all // other Application objects). Each part of an Application is stored in a class that may // also be wildcarded. class Application { … }; // This encapsulates a GPU and its driver. The default constructor (not given any values) assumes // that this is a wildcard (i.e. will match all other GPU objects). Each part of a GPU is stored // in a class that may also be wildcarded. class GPU { … }; // This encapsulates a device, and potentially the device's model and/or a list of GPUs/drivers // associated with the Device. The default constructor (not given any values) assumes that this is // a wildcard (i.e. will match all other Device objects). Each part of a Device is stored in a // class that may also be wildcarded. class Device { … }; // This encapsulates a particular scenario to check against the rules. A Scenario is similar to a // Rule, except that a Rule has an answer and potentially many wildcards, and a Scenario is the // fully-specified combination of an Application and a Device that is proposed to be run with // ANGLE. It is compared with the list of Rules. class Scenario { … }; // This encapsulates a Rule that provides an answer based on whether a particular Scenario matches // the Rule. A Rule always has an answer, but can potentially wildcard every item in it (i.e. // match every scenario). class Rule { … }; // This encapsulates a list of Rules that Scenarios are matched against. A Scenario is compared // with each Rule, in order. Any time a Scenario matches a Rule, the current answer is overridden // with the answer of the matched Rule. class RuleList { … }; } // namespace angle extern "C" { usingnamespaceangle; // This function is part of the version-2 API: ANGLE_EXPORT bool ANGLEGetFeatureSupportUtilAPIVersion(unsigned int *versionToUse) { … } // This function is part of the version-2 API: ANGLE_EXPORT bool ANGLEAndroidParseRulesString(const char *rulesString, RulesHandle *rulesHandle, int *rulesVersion) { … } // This function is part of the version-2 API: ANGLE_EXPORT bool ANGLEGetSystemInfo(SystemInfoHandle *systemInfoHandle) { … } // This function is part of the version-2 API: ANGLE_EXPORT bool ANGLEAddDeviceInfoToSystemInfo(const char *deviceMfr, const char *deviceModel, SystemInfoHandle systemInfoHandle) { … } // This function is part of the version-2 API: ANGLE_EXPORT bool ANGLEShouldBeUsedForApplication(const RulesHandle rulesHandle, int rulesVersion, const SystemInfoHandle systemInfoHandle, const char *appName) { … } // This function is part of the version-2 API: ANGLE_EXPORT void ANGLEFreeRulesHandle(const RulesHandle rulesHandle) { … } // This function is part of the version-2 API: ANGLE_EXPORT void ANGLEFreeSystemInfoHandle(const SystemInfoHandle systemInfoHandle) { … } } // extern "C"