Commit a9d579e8 by Ian Elliott Committed by Commit Bot

Version-2 API of the A4A opt-in/out (a.k.a. feature-support utilities)

This version-2 API splits up and renames parts of the version-1 API. Some initial unit tests were added. The code is now built and tested on Linux, Windows, and Mac (in addition to Android, which is where it's being used). Memory leaks were fixed and some memory/list-management TODOs were also dealt with (associated with an Android bug). Some review items deferred. See: angleproject:2993 Bug: angleproject:2794 Bug: b/113346561 Change-Id: Iff307f9347fb05a733fe96b6774fb32d36e25590 Reviewed-on: https://chromium-review.googlesource.com/c/1291837Reviewed-by: 's avatarIan Elliott <ianelliott@google.com> Reviewed-by: 's avatarYuly Novikov <ynovikov@chromium.org> Commit-Queue: Ian Elliott <ianelliott@google.com>
parent 317a9ebd
...@@ -920,44 +920,53 @@ executable("angle_shader_translator") { ...@@ -920,44 +920,53 @@ executable("angle_shader_translator") {
] ]
} }
if (is_android) { config("angle_feature_support_config") {
config("angle_feature_support_config") { include_dirs = [
include_dirs = [ "include",
"include", "src",
"src", ]
] defines = [ "LIBFEATURE_SUPPORT_IMPLEMENTATION" ]
defines = [ "LIBFEATURE_SUPPORT_IMPLEMENTATION" ] if (is_debug) {
if (is_debug) { defines += [ "ANGLE_FEATURE_UTIL_LOG_VERBOSE" ]
defines += [ "ANGLE_FEATURE_UTIL_LOG_VERBOSE" ]
}
} }
}
shared_library("libfeature_support${angle_libs_suffix}") { shared_library("libfeature_support${angle_libs_suffix}") {
if (is_android) {
configs -= [ "//build/config/android:hide_all_but_jni_onload" ] configs -= [ "//build/config/android:hide_all_but_jni_onload" ]
configs += [ ":build_id_config" ] configs += [ ":build_id_config" ]
configs -= angle_undefine_configs
configs += [
":internal_config",
":extra_warnings",
]
public_configs = [
":angle_feature_support_config",
"third_party/jsoncpp:jsoncpp_config",
]
libs = [ "log" ] libs = [ "log" ]
}
configs -= angle_undefine_configs
configs += [
":extra_warnings",
":internal_config",
]
sources = [ public_configs = [
"src/feature_support_util/angle_feature_support_util.h", ":angle_feature_support_config",
"src/feature_support_util/feature_support_util.cpp", "third_party/jsoncpp:jsoncpp_config",
"src/feature_support_util/feature_support_util.h", ]
]
deps = [ if (is_mac && !is_component_build) {
"third_party/jsoncpp:jsoncpp", ldflags = [
"-install_name",
"@rpath/${target_name}.dylib",
] ]
public_configs += [ ":shared_library_public_config" ]
} }
sources = [
"src/feature_support_util/feature_support_util.cpp",
"src/feature_support_util/feature_support_util.h",
]
deps = [
":angle_gpu_info_util",
"third_party/jsoncpp:jsoncpp",
]
}
if (is_android) {
# Package ANGLE libraries for pre-installed system image # Package ANGLE libraries for pre-installed system image
android_assets("angle_apk_assets") { android_assets("angle_apk_assets") {
disable_compression = true disable_compression = true
......
R"=====({"Rules": {
[ "Rules":[
{"Rule" : "Default Rule (i.e. use native driver)", {
"AppChoice" : true, "NonChoice" : false "Rule":"Default Rule (i.e. use native driver)",
}, "UseANGLE":false
{"Rule" : "Supported application(s) (e.g. Maps on Google devices)", },
"AppChoice" : true, "NonChoice" : true, {
"Applications" : "Rule":"Supported application(s) (e.g. Maps on Google devices)",
[ "UseANGLE":true,
{"AppName" : "com.google.android.apps.internal.cubey"}, "Applications":[
{"AppName" : "com.android.gl2jni"} {
], "AppName":"com.google.android.apps.internal.cubey"
"Devices" : },
[ {
{"Manufacturer" : "Google" "AppName":"com.android.gl2jni"
} }
],
"Devices":[
{
"Manufacturer":"Google"
}
]
}
] ]
}
]
} }
)====="
//
// 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.
//
// angle_feature_support_util.h: External header file for feature-support utilities.
// feature_support_util.cpp: Helps Android EGL loader to determine whether to
// use ANGLE or a native GLES driver. Can be extended in the future for
// more-general feature selection.
#ifndef ANGLE_FEATURE_SUPPORT_UTIL_H_
#define ANGLE_FEATURE_SUPPORT_UTIL_H_
#if defined(ANDROID)
// FIXME - NEED TO #define ANGLE_EXPORT in a way that works for Android builds
# include "export.h"
#else
# include "export.h"
#endif
#ifdef __cplusplus
extern "C" {
#endif
// The following is the "version 1" external interface that the Android EGL loader used.
// Callers of the ANGLE feature-support-utility API (e.g. the Android EGL loader) will call this
// function in order to determine what version of the API it can use (if any).
//
// The caller supplies the highest version of the API that it knows about. If that version is
// supported by the feature-support-utility, true is returned and the version isn't changed. If
// the supplied version is higher than supported by the feature-support-utility, true is returned
// and the version is changed to the highest supported by the feature-support-utility. If the
// supplied version is lower than supported by the feature-support-utility, false is returned.
//
// Parameters:
//
// - versionToUse (IN/OUT) - The application supplies the highest version of the interface that it
// knows about. If successful, the output value is either unchanged or is the highest supported
// by the interface.
//
ANGLE_EXPORT bool ANGLEGetUtilityAPI(unsigned int *versionToUse);
// The Android EGL loader will call this function in order to determine whether
// to use ANGLE instead of a native OpenGL-ES (GLES) driver.
//
// Parameters:
// - rules_fd - File descriptor of the rules file to use
// - rules_offset - Offset into the fd before finding the contents of the rules file
// - rules_length - length of the rules file content
// - appName - Java name of the application (e.g. "com.google.android.apps.maps")
// - deviceMfr - Device manufacturer, from the "ro.product.manufacturer"com.google.android" property
// - deviceModel - Device model, from the "ro.product.model"com.google.android" property
//
ANGLE_EXPORT bool AndroidUseANGLEForApplication(int rules_fd,
long rules_offset,
long rules_length,
const char *appName,
const char *deviceMfr,
const char *deviceModel);
#ifdef __cplusplus
} // extern "C"
#endif
#endif // ANGLE_FEATURE_SUPPORT_UTIL_H_
...@@ -9,47 +9,164 @@ ...@@ -9,47 +9,164 @@
#ifndef FEATURE_SUPPORT_UTIL_H_ #ifndef FEATURE_SUPPORT_UTIL_H_
#define FEATURE_SUPPORT_UTIL_H_ #define FEATURE_SUPPORT_UTIL_H_
#include "angle_feature_support_util.h" #include "export.h"
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
// The following are internal versions supported by the current feature-support-utility API. /**************************************************************************************************
*
constexpr unsigned int kFeatureVersion_LowestSupported = 0; * The following is the "version 1" private API for the Android EGL loader:
constexpr unsigned int kFeatureVersion_HighestSupported = 1; *
**************************************************************************************************/
// The following is the "version 0" external interface that the Android EGL loader used. It is // Callers of the ANGLE feature-support-utility API (e.g. the Android EGL loader) will call this
// deprecated and will soon be obsoleted. It was never declared in the shared header file. // function in order to determine what version of the API it can use (if any).
//
// TODO(ianelliott@google.com angleproject:2801): Revisit this enum. Make it // The caller supplies the highest version of the API that it knows about. If that version is
// strongly typed, and look at renaming it and its values. // supported by the feature-support-utility, true is returned and the version isn't changed. If
typedef enum ANGLEPreference // the supplied version is higher than supported by the feature-support-utility, true is
{ // returned and the version is changed to the highest supported by the feature-support-utility.
ANGLE_NO_PREFERENCE = 0, // If the supplied version is lower than supported by the feature-support-utility, false is
ANGLE_PREFER_NATIVE = 1, // returned.
ANGLE_PREFER_ANGLE = 2, //
} ANGLEPreference; // Parameters:
//
// - versionToUse (IN/OUT) - The application supplies the highest version of the interface that
// it knows about. If successful, the output value is either unchanged or is the highest
// supported by the interface.
//
ANGLE_EXPORT bool ANGLEGetUtilityAPI(unsigned int *versionToUse);
// The Android EGL loader will call this function in order to determine whether // The Android EGL loader will call this function in order to determine whether
// to use ANGLE instead of a native OpenGL-ES (GLES) driver. // to use ANGLE instead of a native OpenGL-ES (GLES) driver.
// //
// Parameters: // Parameters:
// - rules_fd - File descriptor of the rules file to use
// - rules_offset - Offset into the fd before finding the contents of the rules file
// - rules_length - length of the rules file content
// - appName - Java name of the application (e.g. "com.google.android.apps.maps") // - appName - Java name of the application (e.g. "com.google.android.apps.maps")
// - deviceMfr - Device manufacturer, from the "ro.product.manufacturer"com.google.android" property // - deviceMfr - Device manufacturer, from the "ro.product.manufacturer"com.google.android"
// property
// - deviceModel - Device model, from the "ro.product.model"com.google.android" property // - deviceModel - Device model, from the "ro.product.model"com.google.android" property
// - developerOption - Whether the "Developer Options" setting was set, and if so, how //
// - appPreference - Whether the application expressed a preference, and if so, how ANGLE_EXPORT bool AndroidUseANGLEForApplication(int rules_fd,
// long rules_offset,
// TODO(ianelliott@google.com angleproject:2801): Revisit this function long rules_length,
// name/interface. Look at generalizing it and making it more "feature" const char *appName,
// oriented. const char *deviceMfr,
ANGLE_EXPORT bool ANGLEUseForApplication(const char *appName, const char *deviceModel);
const char *deviceMfr,
const char *deviceModel, /**************************************************************************************************
ANGLEPreference developerOption, *
ANGLEPreference appPreference); * The following is the "version 2" private API for the Android EGL loader:
*
**************************************************************************************************/
// Typedefs for handles:
typedef void *RulesHandle;
typedef void *SystemInfoHandle;
// Callers of the ANGLE feature-support-utility API (e.g. the Android EGL loader) will call this
// function in order to determine what version of the API it can use (if any).
//
// The caller supplies the highest version of the API that it knows about. If that version is
// supported by the feature-support-utility, true is returned and the version isn't changed. If
// the supplied version is higher than supported by the feature-support-utility, true is
// returned and the version is changed to the highest supported by the feature-support-utility.
// If the supplied version is lower than supported by the feature-support-utility, false is
// returned.
//
// Parameters:
//
// - versionToUse (IN/OUT) - The application supplies the highest version of the interface that
// it knows about. If successful, the output value is either
// unchanged or is the highest supported by the interface.
//
ANGLE_EXPORT bool ANGLEGetFeatureSupportUtilAPIVersion(unsigned int *versionToUse);
// The Android EGL loader will call this function in order to parse a rules file
// and create a set of rules, for which a handle is returned.
//
// Parameters:
// - rulesString (IN) - Rules-file contents, as a non-zero length, null-terminated char*
// string
// - rulesHandle (OUT) - Handle to the rules data structure
// - rulesVersion (OUT) - Version of the rules data structure (potentially because of schema
// changes) that should be passed to ANGLEShouldBeUsedForApplication()
//
// Return value:
// - bool - true if no errors, otherwise false
//
ANGLE_EXPORT bool ANGLEAndroidParseRulesString(const char *rulesString,
RulesHandle *rulesHandle,
int *rulesVersion);
// The Android EGL loader will call this function in order to obtain a handle to
// the SystemInfo struct.
//
// Parameters:
// - systemInfoHandle (OUT) - handle to the SystemInfo structure
//
// Return value:
// - bool - true if no errors, otherwise false
//
ANGLE_EXPORT bool ANGLEGetSystemInfo(SystemInfoHandle *systemInfoHandle);
// The Android EGL loader will call this function in order to add the device's manufacturer and
// model to the SystemInfo struct associated with the handle returned by ANGLEGetSystemInfo.
//
// Parameters:
// - deviceMfr (IN) - Device manufacturer, from the
// "ro.product.manufacturer"com.google.android" property
// - deviceModel (IN) - Device model, from the "ro.product.model"com.google.android" property
// - systemInfoHandle (IN) - handle to the SystemInfo structure
//
// Return value:
// - bool - true if no errors, otherwise false
//
ANGLE_EXPORT bool ANGLEAddDeviceInfoToSystemInfo(const char *deviceMfr,
const char *deviceModel,
SystemInfoHandle systemInfoHandle);
// The Android EGL loader will call this function in order to determine whether
// to use ANGLE instead of a native OpenGL-ES (GLES) driver.
//
// Parameters:
// - rulesHandle (IN) - Handle to the rules data structure
// - rulesVersion (IN) - Version of the rules data structure (potentially because of schema
// changes) that was passed from AndroidParseRulesFile()
// - systemInfoHandle (IN) - Handle to the SystemInfo structure
// - appName (IN) - Java name of the application (e.g. "com.google.android.apps.maps")
//
// Return value:
// - bool - true if Android should use ANGLE for appName, otherwise false (i.e. use the native
// GLES driver)
//
ANGLE_EXPORT bool ANGLEShouldBeUsedForApplication(const RulesHandle rulesHandle,
int rulesVersion,
const SystemInfoHandle systemInfoHandle,
const char *appName);
// The Android EGL loader will call this function in order to free a rules handle.
//
// Parameters:
// - rulesHandle (IN) - Handle to the rules data structure
//
ANGLE_EXPORT void ANGLEFreeRulesHandle(const RulesHandle rulesHandle);
// The Android EGL loader will call this function in order to free a SystemInfo handle.
//
// Parameters:
// - systemInfoHandle (IN) - Handle to the SystemInfo structure
//
ANGLE_EXPORT void ANGLEFreeSystemInfoHandle(const SystemInfoHandle systemInfoHandle);
// The following are internal versions supported by the current feature-support-utility API.
constexpr unsigned int kFeatureVersion_LowestSupported = 1;
constexpr unsigned int kFeatureVersion_HighestSupported = 2;
#ifdef __cplusplus #ifdef __cplusplus
} // extern "C" } // extern "C"
......
//
// Copyright (c) 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_unittest.cpp: Unit test for the feature-support utility.
#include <gtest/gtest.h>
#include "../gpu_info_util/SystemInfo.h"
#include "feature_support_util.h"
using namespace angle;
// Test the ANGLEGetFeatureSupportUtilAPIVersion function
TEST(FeatureSupportUtilTest, APIVersion)
{
unsigned int versionToUse;
unsigned int zero = 0;
versionToUse = kFeatureVersion_LowestSupported;
EXPECT_TRUE(ANGLEGetFeatureSupportUtilAPIVersion(&versionToUse));
EXPECT_EQ(kFeatureVersion_LowestSupported, versionToUse);
versionToUse = kFeatureVersion_HighestSupported;
EXPECT_TRUE(ANGLEGetFeatureSupportUtilAPIVersion(&versionToUse));
EXPECT_EQ(kFeatureVersion_HighestSupported, versionToUse);
versionToUse = zero;
EXPECT_FALSE(ANGLEGetFeatureSupportUtilAPIVersion(&versionToUse));
EXPECT_EQ(zero, versionToUse);
versionToUse = kFeatureVersion_HighestSupported + 1;
EXPECT_TRUE(ANGLEGetFeatureSupportUtilAPIVersion(&versionToUse));
EXPECT_EQ(kFeatureVersion_HighestSupported, versionToUse);
}
// Test the ANGLEAddDeviceInfoToSystemInfo function
TEST(FeatureSupportUtilTest, SystemInfo)
{
// TODO(ianelliott): Replace this with a gtest "fixture", per review feedback.
SystemInfo systemInfo;
systemInfo.machineManufacturer = "BAD";
systemInfo.machineModelName = "BAD";
systemInfo.gpus.resize(1);
systemInfo.gpus[0].vendorId = 123;
systemInfo.gpus[0].deviceId = 234;
systemInfo.gpus[0].driverVendor = "DriverVendorA";
systemInfo.gpus[0].detailedDriverVersion = {1, 2, 3, 4};
char mfr[] = "Google";
char model[] = "Pixel1";
ANGLEAddDeviceInfoToSystemInfo(mfr, model, &systemInfo);
EXPECT_EQ("Google", systemInfo.machineManufacturer);
EXPECT_EQ("Pixel1", systemInfo.machineModelName);
}
// Test the ANGLEAndroidParseRulesString function
TEST(FeatureSupportUtilTest, ParseRules)
{
// TODO(ianelliott): Replace this with a gtest "fixture", per review feedback.
SystemInfo systemInfo;
systemInfo.machineManufacturer = "Google";
systemInfo.machineModelName = "Pixel1";
systemInfo.gpus.resize(1);
systemInfo.gpus[0].vendorId = 123;
systemInfo.gpus[0].deviceId = 234;
systemInfo.gpus[0].driverVendor = "DriverVendorA";
systemInfo.gpus[0].detailedDriverVersion = {1, 2, 3, 4};
constexpr char rulesFileContents[] =
"{\"Rules\":[{\"Rule\":\"Default Rule (i.e. use native driver)\", \"AppChoice\":true, "
"\"NonChoice\":false}]}\n";
RulesHandle rulesHandle = nullptr;
int rulesVersion = 0;
EXPECT_TRUE(ANGLEAndroidParseRulesString(rulesFileContents, &rulesHandle, &rulesVersion));
EXPECT_NE(nullptr, rulesHandle);
ANGLEFreeRulesHandle(rulesHandle);
}
...@@ -64,6 +64,9 @@ struct SystemInfo ...@@ -64,6 +64,9 @@ struct SystemInfo
bool isOptimus = false; bool isOptimus = false;
bool isAMDSwitchable = false; bool isAMDSwitchable = false;
// Only available on Android, when added by the feature support utility
std::string machineManufacturer;
// Only available on macOS // Only available on macOS
std::string machineModelName; std::string machineModelName;
std::string machineModelVersion; std::string machineModelVersion;
......
...@@ -113,10 +113,16 @@ test("angle_unittests") { ...@@ -113,10 +113,16 @@ test("angle_unittests") {
sources += [ "angle_unittests_main.cpp" ] sources += [ "angle_unittests_main.cpp" ]
} }
if (is_linux && !is_component_build) {
# Set rpath to find shared libs in a non-component build.
configs += [ "//build/config/gcc:rpath_for_built_shared_libraries" ]
}
deps = googletest_deps + [ deps = googletest_deps + [
angle_root + ":libANGLE", angle_root + ":libANGLE",
angle_root + ":preprocessor", angle_root + ":preprocessor",
angle_root + ":translator", angle_root + ":translator",
angle_root + ":libfeature_support${angle_libs_suffix}",
] ]
} }
......
...@@ -15,6 +15,7 @@ angle_unittests_sources = [ ...@@ -15,6 +15,7 @@ angle_unittests_sources = [
"../common/string_utils_unittest.cpp", "../common/string_utils_unittest.cpp",
"../common/utilities_unittest.cpp", "../common/utilities_unittest.cpp",
"../common/vector_utils_unittest.cpp", "../common/vector_utils_unittest.cpp",
"../feature_support_util/feature_support_util_unittest.cpp",
"../gpu_info_util/SystemInfo_unittest.cpp", "../gpu_info_util/SystemInfo_unittest.cpp",
"../libANGLE/BinaryStream_unittest.cpp", "../libANGLE/BinaryStream_unittest.cpp",
"../libANGLE/BlobCache_unittest.cpp", "../libANGLE/BlobCache_unittest.cpp",
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment