Merge "Update vsync client c api"
diff --git a/cmds/dumpsys/tests/dumpsys_test.cpp b/cmds/dumpsys/tests/dumpsys_test.cpp
index a61cb00..66beb6d 100644
--- a/cmds/dumpsys/tests/dumpsys_test.cpp
+++ b/cmds/dumpsys/tests/dumpsys_test.cpp
@@ -23,6 +23,7 @@
#include <android-base/file.h>
#include <utils/String16.h>
+#include <utils/String8.h>
#include <utils/Vector.h>
using namespace android;
@@ -95,7 +96,7 @@
int i = 0;
std::ostringstream actual_stream, expected_stream;
for (String16 actual : arg) {
- std::string actual_str = String16::std_string(actual);
+ std::string actual_str = String8(actual).c_str();
std::string expected_str = expected[i];
actual_stream << "'" << actual_str << "' ";
expected_stream << "'" << expected_str << "' ";
diff --git a/cmds/installd/CacheItem.cpp b/cmds/installd/CacheItem.cpp
index 6caf149..0349b0f 100644
--- a/cmds/installd/CacheItem.cpp
+++ b/cmds/installd/CacheItem.cpp
@@ -72,7 +72,7 @@
FTS *fts;
FTSENT *p;
char *argv[] = { (char*) path.c_str(), nullptr };
- if (!(fts = fts_open(argv, FTS_PHYSICAL | FTS_XDEV, NULL))) {
+ if (!(fts = fts_open(argv, FTS_PHYSICAL | FTS_NOCHDIR | FTS_XDEV, NULL))) {
PLOG(WARNING) << "Failed to fts_open " << path;
return -1;
}
diff --git a/cmds/installd/CacheTracker.cpp b/cmds/installd/CacheTracker.cpp
index 9377836..fada699 100644
--- a/cmds/installd/CacheTracker.cpp
+++ b/cmds/installd/CacheTracker.cpp
@@ -83,7 +83,7 @@
FTS *fts;
FTSENT *p;
char *argv[] = { (char*) path.c_str(), nullptr };
- if (!(fts = fts_open(argv, FTS_PHYSICAL | FTS_XDEV, NULL))) {
+ if (!(fts = fts_open(argv, FTS_PHYSICAL | FTS_NOCHDIR | FTS_XDEV, NULL))) {
PLOG(WARNING) << "Failed to fts_open " << path;
return;
}
diff --git a/cmds/installd/InstalldNativeService.cpp b/cmds/installd/InstalldNativeService.cpp
index fbb30db..754ba4c 100644
--- a/cmds/installd/InstalldNativeService.cpp
+++ b/cmds/installd/InstalldNativeService.cpp
@@ -203,14 +203,20 @@
out << "installd is happy!" << endl;
- out << endl << "Devices with quota support:" << endl;
- for (const auto& n : mQuotaDevices) {
- out << " " << n.first << " = " << n.second << endl;
+ {
+ std::lock_guard<std::recursive_mutex> lock(mQuotaDevicesLock);
+ out << endl << "Devices with quota support:" << endl;
+ for (const auto& n : mQuotaDevices) {
+ out << " " << n.first << " = " << n.second << endl;
+ }
}
- out << endl << "Per-UID cache quotas:" << endl;
- for (const auto& n : mCacheQuotas) {
- out << " " << n.first << " = " << n.second << endl;
+ {
+ std::lock_guard<std::recursive_mutex> lock(mCacheQuotasLock);
+ out << endl << "Per-UID cache quotas:" << endl;
+ for (const auto& n : mCacheQuotas) {
+ out << " " << n.first << " = " << n.second << endl;
+ }
}
out << endl;
@@ -426,12 +432,11 @@
CHECK_ARGUMENT_PACKAGE_NAME(packageName);
std::lock_guard<std::recursive_mutex> lock(mLock);
- const char* pkgname = packageName.c_str();
binder::Status res = ok();
- if (!clear_reference_profile(pkgname)) {
+ if (!clear_reference_profile(packageName)) {
res = error("Failed to clear reference profile for " + packageName);
}
- if (!clear_current_profiles(pkgname)) {
+ if (!clear_current_profiles(packageName)) {
res = error("Failed to clear current profiles for " + packageName);
}
return res;
@@ -479,7 +484,7 @@
}
}
if (!only_cache) {
- if (!clear_current_profile(pkgname, userId)) {
+ if (!clear_current_profile(packageName, userId)) {
res = error("Failed to clear current profile for " + packageName);
}
}
@@ -487,13 +492,13 @@
return res;
}
-static int destroy_app_reference_profile(const char *pkgname) {
+static int destroy_app_reference_profile(const std::string& pkgname) {
return delete_dir_contents_and_dir(
create_data_ref_profile_package_path(pkgname),
/*ignore_if_missing*/ true);
}
-static int destroy_app_current_profiles(const char *pkgname, userid_t userid) {
+static int destroy_app_current_profiles(const std::string& pkgname, userid_t userid) {
return delete_dir_contents_and_dir(
create_data_user_profile_package_path(userid, pkgname),
/*ignore_if_missing*/ true);
@@ -504,15 +509,14 @@
CHECK_ARGUMENT_PACKAGE_NAME(packageName);
std::lock_guard<std::recursive_mutex> lock(mLock);
- const char* pkgname = packageName.c_str();
binder::Status res = ok();
std::vector<userid_t> users = get_known_users(/*volume_uuid*/ nullptr);
for (auto user : users) {
- if (destroy_app_current_profiles(pkgname, user) != 0) {
+ if (destroy_app_current_profiles(packageName, user) != 0) {
res = error("Failed to destroy current profiles for " + packageName);
}
}
- if (destroy_app_reference_profile(pkgname) != 0) {
+ if (destroy_app_reference_profile(packageName) != 0) {
res = error("Failed to destroy reference profile for " + packageName);
}
return res;
@@ -540,11 +544,11 @@
if (delete_dir_contents_and_dir(path) != 0) {
res = error("Failed to delete " + path);
}
- destroy_app_current_profiles(pkgname, userId);
+ destroy_app_current_profiles(packageName, userId);
// TODO(calin): If the package is still installed by other users it's probably
// beneficial to keep the reference profile around.
// Verify if it's ok to do that.
- destroy_app_reference_profile(pkgname);
+ destroy_app_reference_profile(packageName);
}
return res;
}
@@ -755,9 +759,6 @@
CHECK_ARGUMENT_UUID(uuid);
std::lock_guard<std::recursive_mutex> lock(mLock);
- // TODO: remove this once framework is more robust
- invalidateMounts();
-
const char* uuid_ = uuid ? uuid->c_str() : nullptr;
auto data_path = create_data_path(uuid_);
auto device = findQuotaDeviceForUuid(uuid);
@@ -789,7 +790,7 @@
(char*) create_data_user_de_path(uuid_, user).c_str(),
nullptr
};
- if (!(fts = fts_open(argv, FTS_PHYSICAL | FTS_XDEV, NULL))) {
+ if (!(fts = fts_open(argv, FTS_PHYSICAL | FTS_NOCHDIR | FTS_XDEV, NULL))) {
return error("Failed to fts_open");
}
while ((p = fts_read(fts)) != NULL) {
@@ -802,7 +803,10 @@
auto tracker = std::shared_ptr<CacheTracker>(new CacheTracker(
multiuser_get_user_id(uid), multiuser_get_app_id(uid), device));
tracker->addDataPath(p->fts_path);
- tracker->cacheQuota = mCacheQuotas[uid];
+ {
+ std::lock_guard<std::recursive_mutex> lock(mCacheQuotasLock);
+ tracker->cacheQuota = mCacheQuotas[uid];
+ }
if (tracker->cacheQuota == 0) {
LOG(WARNING) << "UID " << uid << " has no cache quota; assuming 64MB";
tracker->cacheQuota = 67108864;
@@ -1122,7 +1126,7 @@
FTS *fts;
FTSENT *p;
char *argv[] = { (char*) path.c_str(), nullptr };
- if (!(fts = fts_open(argv, FTS_PHYSICAL | FTS_XDEV, NULL))) {
+ if (!(fts = fts_open(argv, FTS_PHYSICAL | FTS_NOCHDIR | FTS_XDEV, NULL))) {
PLOG(ERROR) << "Failed to fts_open " << path;
return;
}
@@ -1161,7 +1165,8 @@
for (auto packageName : packageNames) {
CHECK_ARGUMENT_PACKAGE_NAME(packageName);
}
- std::lock_guard<std::recursive_mutex> lock(mLock);
+ // NOTE: Locking is relaxed on this method, since it's limited to
+ // read-only measurements without mutation.
// When modifying this logic, always verify using tests:
// runtest -x frameworks/base/services/tests/servicestests/src/com/android/server/pm/InstallerTest.java -m testGetAppSize
@@ -1276,7 +1281,8 @@
std::vector<int64_t>* _aidl_return) {
ENFORCE_UID(AID_SYSTEM);
CHECK_ARGUMENT_UUID(uuid);
- std::lock_guard<std::recursive_mutex> lock(mLock);
+ // NOTE: Locking is relaxed on this method, since it's limited to
+ // read-only measurements without mutation.
// When modifying this logic, always verify using tests:
// runtest -x frameworks/base/services/tests/servicestests/src/com/android/server/pm/InstallerTest.java -m testGetUserSize
@@ -1422,7 +1428,8 @@
int32_t userId, int32_t flags, std::vector<int64_t>* _aidl_return) {
ENFORCE_UID(AID_SYSTEM);
CHECK_ARGUMENT_UUID(uuid);
- std::lock_guard<std::recursive_mutex> lock(mLock);
+ // NOTE: Locking is relaxed on this method, since it's limited to
+ // read-only measurements without mutation.
// When modifying this logic, always verify using tests:
// runtest -x frameworks/base/services/tests/servicestests/src/com/android/server/pm/InstallerTest.java -m testGetExternalSize
@@ -1488,7 +1495,7 @@
FTSENT *p;
auto path = create_data_media_path(uuid_, userId);
char *argv[] = { (char*) path.c_str(), nullptr };
- if (!(fts = fts_open(argv, FTS_PHYSICAL | FTS_XDEV, NULL))) {
+ if (!(fts = fts_open(argv, FTS_PHYSICAL | FTS_NOCHDIR | FTS_XDEV, NULL))) {
return error("Failed to fts_open " + path);
}
while ((p = fts_read(fts)) != NULL) {
@@ -1497,7 +1504,7 @@
switch (p->fts_info) {
case FTS_F:
// Only categorize files not belonging to apps
- if (p->fts_statp->st_gid < AID_APP_START) {
+ if (p->fts_parent->fts_number == 0) {
ext = strrchr(p->fts_name, '.');
if (ext != nullptr) {
switch (MatchExtension(++ext)) {
@@ -1509,6 +1516,11 @@
}
// Fall through to always count against total
case FTS_D:
+ // Ignore data belonging to specific apps
+ p->fts_number = p->fts_parent->fts_number;
+ if (p->fts_level == 1 && !strcmp(p->fts_name, "Android")) {
+ p->fts_number = 1;
+ }
case FTS_DEFAULT:
case FTS_SL:
case FTS_SLNONE:
@@ -1535,7 +1547,7 @@
int32_t userId, int32_t appId, int64_t cacheQuota) {
ENFORCE_UID(AID_SYSTEM);
CHECK_ARGUMENT_UUID(uuid);
- std::lock_guard<std::recursive_mutex> lock(mLock);
+ std::lock_guard<std::recursive_mutex> lock(mCacheQuotasLock);
int32_t uid = multiuser_get_uid(userId, appId);
mCacheQuotas[uid] = cacheQuota;
@@ -1988,7 +2000,7 @@
binder::Status InstalldNativeService::invalidateMounts() {
ENFORCE_UID(AID_SYSTEM);
- std::lock_guard<std::recursive_mutex> lock(mLock);
+ std::lock_guard<std::recursive_mutex> lock(mQuotaDevicesLock);
mQuotaDevices.clear();
@@ -2019,6 +2031,7 @@
std::string InstalldNativeService::findQuotaDeviceForUuid(
const std::unique_ptr<std::string>& uuid) {
+ std::lock_guard<std::recursive_mutex> lock(mQuotaDevicesLock);
auto path = create_data_path(uuid ? uuid->c_str() : nullptr);
return mQuotaDevices[path];
}
diff --git a/cmds/installd/InstalldNativeService.h b/cmds/installd/InstalldNativeService.h
index feb2219..7ad8687 100644
--- a/cmds/installd/InstalldNativeService.h
+++ b/cmds/installd/InstalldNativeService.h
@@ -117,6 +117,9 @@
private:
std::recursive_mutex mLock;
+ std::recursive_mutex mQuotaDevicesLock;
+ std::recursive_mutex mCacheQuotasLock;
+
/* Map from mount point to underlying device node */
std::unordered_map<std::string, std::string> mQuotaDevices;
/* Map from UID to cache quota size */
diff --git a/cmds/installd/dexopt.cpp b/cmds/installd/dexopt.cpp
index 215600b..58b9d2c 100644
--- a/cmds/installd/dexopt.cpp
+++ b/cmds/installd/dexopt.cpp
@@ -101,19 +101,19 @@
return truncated;
}
-bool clear_reference_profile(const char* pkgname) {
+bool clear_reference_profile(const std::string& pkgname) {
std::string reference_profile_dir = create_data_ref_profile_package_path(pkgname);
std::string reference_profile = create_primary_profile(reference_profile_dir);
return clear_profile(reference_profile);
}
-bool clear_current_profile(const char* pkgname, userid_t user) {
+bool clear_current_profile(const std::string& pkgname, userid_t user) {
std::string profile_dir = create_data_user_profile_package_path(user, pkgname);
std::string profile = create_primary_profile(profile_dir);
return clear_profile(profile);
}
-bool clear_current_profiles(const char* pkgname) {
+bool clear_current_profiles(const std::string& pkgname) {
bool success = true;
std::vector<userid_t> users = get_known_users(/*volume_uuid*/ nullptr);
for (auto user : users) {
@@ -512,12 +512,12 @@
return profile_fd;
}
-static fd_t open_primary_profile_file(userid_t user, const char* pkgname) {
+static fd_t open_primary_profile_file(userid_t user, const std::string& pkgname) {
std::string profile_dir = create_data_user_profile_package_path(user, pkgname);
return open_primary_profile_file_from_dir(profile_dir, O_RDONLY);
}
-static fd_t open_reference_profile(uid_t uid, const char* pkgname, bool read_write) {
+static fd_t open_reference_profile(uid_t uid, const std::string& pkgname, bool read_write) {
std::string reference_profile_dir = create_data_ref_profile_package_path(pkgname);
int flags = read_write ? O_RDWR | O_CREAT : O_RDONLY;
fd_t fd = open_primary_profile_file_from_dir(reference_profile_dir, flags);
@@ -534,7 +534,7 @@
return fd;
}
-static void open_profile_files(uid_t uid, const char* pkgname,
+static void open_profile_files(uid_t uid, const std::string& pkgname,
/*out*/ std::vector<fd_t>* profiles_fd, /*out*/ fd_t* reference_profile_fd) {
// Open the reference profile in read-write mode as profman might need to save the merge.
*reference_profile_fd = open_reference_profile(uid, pkgname, /*read_write*/ true);
@@ -614,7 +614,7 @@
// a re-compilation of the package.
// If the return value is true all the current profiles would have been merged into
// the reference profiles accessible with open_reference_profile().
-bool analyse_profiles(uid_t uid, const char* pkgname) {
+bool analyse_profiles(uid_t uid, const std::string& pkgname) {
std::vector<fd_t> profiles_fd;
fd_t reference_profile_fd = -1;
open_profile_files(uid, pkgname, &profiles_fd, &reference_profile_fd);
@@ -628,8 +628,6 @@
return false;
}
- ALOGV("PROFMAN (MERGE): --- BEGIN '%s' ---\n", pkgname);
-
pid_t pid = fork();
if (pid == 0) {
/* child -- drop privileges before continuing */
@@ -740,12 +738,10 @@
}
}
-bool dump_profiles(int32_t uid, const char* pkgname, const char* code_paths) {
+bool dump_profiles(int32_t uid, const std::string& pkgname, const char* code_paths) {
std::vector<fd_t> profile_fds;
fd_t reference_profile_fd = -1;
- std::string out_file_name = StringPrintf("/data/misc/profman/%s.txt", pkgname);
-
- ALOGV("PROFMAN (DUMP): --- BEGIN '%s' ---\n", pkgname);
+ std::string out_file_name = StringPrintf("/data/misc/profman/%s.txt", pkgname.c_str());
open_profile_files(uid, pkgname, &profile_fds, &reference_profile_fd);
@@ -753,7 +749,7 @@
const bool has_profiles = !profile_fds.empty();
if (!has_reference_profile && !has_profiles) {
- ALOGE("profman dump: no profiles to dump for '%s'", pkgname);
+ LOG(ERROR) << "profman dump: no profiles to dump for " << pkgname;
return false;
}
diff --git a/cmds/installd/dexopt.h b/cmds/installd/dexopt.h
index 7bb6eee..fab4d94 100644
--- a/cmds/installd/dexopt.h
+++ b/cmds/installd/dexopt.h
@@ -34,14 +34,14 @@
typedef int fd_t;
-bool clear_reference_profile(const char* pkgname);
-bool clear_current_profile(const char* pkgname, userid_t user);
-bool clear_current_profiles(const char* pkgname);
+bool clear_reference_profile(const std::string& pkgname);
+bool clear_current_profile(const std::string& pkgname, userid_t user);
+bool clear_current_profiles(const std::string& pkgname);
bool move_ab(const char* apk_path, const char* instruction_set, const char* output_path);
-bool analyse_profiles(uid_t uid, const char* pkgname);
-bool dump_profiles(int32_t uid, const char* pkgname, const char* code_paths);
+bool analyse_profiles(uid_t uid, const std::string& pkgname);
+bool dump_profiles(int32_t uid, const std::string& pkgname, const char* code_paths);
bool delete_odex(const char* apk_path, const char* instruction_set, const char* output_path);
diff --git a/cmds/installd/tests/installd_utils_test.cpp b/cmds/installd/tests/installd_utils_test.cpp
index 93a1458..850d257 100644
--- a/cmds/installd/tests/installd_utils_test.cpp
+++ b/cmds/installd/tests/installd_utils_test.cpp
@@ -36,6 +36,8 @@
#define TEST_SYSTEM_DIR1 "/system/app/"
#define TEST_SYSTEM_DIR2 "/vendor/app/"
+#define TEST_PROFILE_DIR "/data/misc/profiles"
+
#define REALLY_LONG_APP_NAME "com.example." \
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa." \
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa." \
@@ -78,6 +80,9 @@
android_system_dirs.dirs[1].path = (char*) TEST_SYSTEM_DIR2;
android_system_dirs.dirs[1].len = strlen(TEST_SYSTEM_DIR2);
+
+ android_profiles_dir.path = (char*) TEST_PROFILE_DIR;
+ android_profiles_dir.len = strlen(TEST_PROFILE_DIR);
}
virtual void TearDown() {
@@ -519,5 +524,31 @@
EXPECT_EQ(false, is_valid_package_name("/com.evil"));
}
+TEST_F(UtilsTest, CreateDataUserProfilePath) {
+ EXPECT_EQ("/data/misc/profiles/cur/0", create_data_user_profile_path(0));
+ EXPECT_EQ("/data/misc/profiles/cur/1", create_data_user_profile_path(1));
+}
+
+TEST_F(UtilsTest, CreateDataUserProfilePackagePath) {
+ EXPECT_EQ("/data/misc/profiles/cur/0/com.example",
+ create_data_user_profile_package_path(0, "com.example"));
+ EXPECT_EQ("/data/misc/profiles/cur/1/com.example",
+ create_data_user_profile_package_path(1, "com.example"));
+}
+
+TEST_F(UtilsTest, CreateDataRefProfilePath) {
+ EXPECT_EQ("/data/misc/profiles/ref", create_data_ref_profile_path());
+}
+
+TEST_F(UtilsTest, CreateDataRefProfilePackagePath) {
+ EXPECT_EQ("/data/misc/profiles/ref/com.example",
+ create_data_ref_profile_package_path("com.example"));
+}
+
+TEST_F(UtilsTest, CreatePrimaryProfile) {
+ EXPECT_EQ("/data/misc/profiles/ref/com.example/primary.prof",
+ create_primary_profile("/data/misc/profiles/ref/com.example"));
+}
+
} // namespace installd
} // namespace android
diff --git a/cmds/installd/utils.cpp b/cmds/installd/utils.cpp
index af7a7c6..5a08c32 100644
--- a/cmds/installd/utils.cpp
+++ b/cmds/installd/utils.cpp
@@ -221,18 +221,18 @@
return StringPrintf("%s/cur/%u", android_profiles_dir.path, userid);
}
-std::string create_data_user_profile_package_path(userid_t user, const char* package_name) {
- check_package_name(package_name);
- return StringPrintf("%s/%s",create_data_user_profile_path(user).c_str(), package_name);
+std::string create_data_user_profile_package_path(userid_t user, const std::string& package_name) {
+ check_package_name(package_name.c_str());
+ return StringPrintf("%s/%s",create_data_user_profile_path(user).c_str(), package_name.c_str());
}
std::string create_data_ref_profile_path() {
return StringPrintf("%s/ref", android_profiles_dir.path);
}
-std::string create_data_ref_profile_package_path(const char* package_name) {
- check_package_name(package_name);
- return StringPrintf("%s/ref/%s", android_profiles_dir.path, package_name);
+std::string create_data_ref_profile_package_path(const std::string& package_name) {
+ check_package_name(package_name.c_str());
+ return StringPrintf("%s/ref/%s", android_profiles_dir.path, package_name.c_str());
}
std::string create_data_dalvik_cache_path() {
@@ -284,7 +284,7 @@
FTSENT *p;
int64_t matchedSize = 0;
char *argv[] = { (char*) path.c_str(), nullptr };
- if (!(fts = fts_open(argv, FTS_PHYSICAL | FTS_XDEV, NULL))) {
+ if (!(fts = fts_open(argv, FTS_PHYSICAL | FTS_NOCHDIR | FTS_XDEV, NULL))) {
if (errno != ENOENT) {
PLOG(ERROR) << "Failed to fts_open " << path;
}
@@ -1440,7 +1440,7 @@
FTS *fts;
FTSENT *p;
char *argv[] = { (char*) path.c_str(), nullptr };
- if (!(fts = fts_open(argv, FTS_PHYSICAL | FTS_XDEV, NULL))) {
+ if (!(fts = fts_open(argv, FTS_PHYSICAL | FTS_NOCHDIR | FTS_XDEV, NULL))) {
PLOG(ERROR) << "Failed to fts_open " << path;
return -1;
}
diff --git a/cmds/installd/utils.h b/cmds/installd/utils.h
index d99b445..1c36a54 100644
--- a/cmds/installd/utils.h
+++ b/cmds/installd/utils.h
@@ -97,10 +97,10 @@
std::string create_data_misc_legacy_path(userid_t userid);
std::string create_data_user_profile_path(userid_t userid);
-std::string create_data_user_profile_package_path(userid_t user, const char* package_name);
+std::string create_data_user_profile_package_path(userid_t user, const std::string& package_name);
std::string create_data_ref_profile_path();
-std::string create_data_ref_profile_package_path(const char* package_name);
+std::string create_data_ref_profile_package_path(const std::string& package_name);
std::string create_data_dalvik_cache_path();
diff --git a/include/private/ui/RegionHelper.h b/include/private/ui/RegionHelper.h
index a22b2cb..a86c586 100644
--- a/include/private/ui/RegionHelper.h
+++ b/include/private/ui/RegionHelper.h
@@ -17,6 +17,7 @@
#ifndef ANDROID_UI_PRIVATE_REGION_HELPER_H
#define ANDROID_UI_PRIVATE_REGION_HELPER_H
+#include <limits>
#include <stdint.h>
#include <sys/types.h>
diff --git a/libs/vr/libdisplay/Android.mk b/libs/vr/libdisplay/Android.mk
index cd89d46..60f73c6 100644
--- a/libs/vr/libdisplay/Android.mk
+++ b/libs/vr/libdisplay/Android.mk
@@ -64,7 +64,7 @@
LOCAL_CFLAGS += -DLOG_TAG=\"libdisplay\"
LOCAL_CFLAGS += -DTRACE=0
LOCAL_CFLAGS += -DATRACE_TAG=ATRACE_TAG_GRAPHICS
-LOCAL_CFLAGS += -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES -g -O0
+LOCAL_CFLAGS += -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES
LOCAL_EXPORT_C_INCLUDE_DIRS := $(includeFiles)
LOCAL_SHARED_LIBRARIES := $(sharedLibraries)
LOCAL_STATIC_LIBRARIES := $(staticLibraries)
diff --git a/opengl/libs/Android.bp b/opengl/libs/Android.bp
index 6141e99..aa67d41 100644
--- a/opengl/libs/Android.bp
+++ b/opengl/libs/Android.bp
@@ -105,9 +105,20 @@
"EGL/egl.cpp",
"EGL/eglApi.cpp",
"EGL/Loader.cpp",
+ "EGL/BlobCache.cpp",
],
static_libs: ["libEGL_getProcAddress"],
ldflags: ["-Wl,--exclude-libs=ALL"],
+ export_include_dirs: ["EGL/include"],
+}
+
+cc_test {
+ name: "libEGL_test",
+ defaults: ["egl_libs_defaults"],
+ srcs: [
+ "EGL/BlobCache.cpp",
+ "EGL/BlobCache_test.cpp",
+ ],
}
cc_defaults {
diff --git a/opengl/libs/EGL/BlobCache.cpp b/opengl/libs/EGL/BlobCache.cpp
new file mode 100644
index 0000000..f1b30c7
--- /dev/null
+++ b/opengl/libs/EGL/BlobCache.cpp
@@ -0,0 +1,373 @@
+/*
+ ** Copyright 2011, The Android Open Source Project
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ ** http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ** See the License for the specific language governing permissions and
+ ** limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+
+#include "BlobCache.h"
+
+#include <inttypes.h>
+
+#include <cutils/properties.h>
+#include <log/log.h>
+#include <chrono>
+
+namespace android {
+
+// BlobCache::Header::mMagicNumber value
+static const uint32_t blobCacheMagic = ('_' << 24) + ('B' << 16) + ('b' << 8) + '$';
+
+// BlobCache::Header::mBlobCacheVersion value
+static const uint32_t blobCacheVersion = 3;
+
+// BlobCache::Header::mDeviceVersion value
+static const uint32_t blobCacheDeviceVersion = 1;
+
+BlobCache::BlobCache(size_t maxKeySize, size_t maxValueSize, size_t maxTotalSize):
+ mMaxKeySize(maxKeySize),
+ mMaxValueSize(maxValueSize),
+ mMaxTotalSize(maxTotalSize),
+ mTotalSize(0) {
+ int64_t now = std::chrono::steady_clock::now().time_since_epoch().count();
+#ifdef _WIN32
+ srand(now);
+#else
+ mRandState[0] = (now >> 0) & 0xFFFF;
+ mRandState[1] = (now >> 16) & 0xFFFF;
+ mRandState[2] = (now >> 32) & 0xFFFF;
+#endif
+ ALOGV("initializing random seed using %lld", (unsigned long long)now);
+}
+
+void BlobCache::set(const void* key, size_t keySize, const void* value,
+ size_t valueSize) {
+ if (mMaxKeySize < keySize) {
+ ALOGV("set: not caching because the key is too large: %zu (limit: %zu)",
+ keySize, mMaxKeySize);
+ return;
+ }
+ if (mMaxValueSize < valueSize) {
+ ALOGV("set: not caching because the value is too large: %zu (limit: %zu)",
+ valueSize, mMaxValueSize);
+ return;
+ }
+ if (mMaxTotalSize < keySize + valueSize) {
+ ALOGV("set: not caching because the combined key/value size is too "
+ "large: %zu (limit: %zu)", keySize + valueSize, mMaxTotalSize);
+ return;
+ }
+ if (keySize == 0) {
+ ALOGW("set: not caching because keySize is 0");
+ return;
+ }
+ if (valueSize <= 0) {
+ ALOGW("set: not caching because valueSize is 0");
+ return;
+ }
+
+ std::shared_ptr<Blob> dummyKey(new Blob(key, keySize, false));
+ CacheEntry dummyEntry(dummyKey, NULL);
+
+ while (true) {
+ auto index = std::lower_bound(mCacheEntries.begin(), mCacheEntries.end(), dummyEntry);
+ if (index == mCacheEntries.end() || dummyEntry < *index) {
+ // Create a new cache entry.
+ std::shared_ptr<Blob> keyBlob(new Blob(key, keySize, true));
+ std::shared_ptr<Blob> valueBlob(new Blob(value, valueSize, true));
+ size_t newTotalSize = mTotalSize + keySize + valueSize;
+ if (mMaxTotalSize < newTotalSize) {
+ if (isCleanable()) {
+ // Clean the cache and try again.
+ clean();
+ continue;
+ } else {
+ ALOGV("set: not caching new key/value pair because the "
+ "total cache size limit would be exceeded: %zu "
+ "(limit: %zu)",
+ keySize + valueSize, mMaxTotalSize);
+ break;
+ }
+ }
+ mCacheEntries.insert(index, CacheEntry(keyBlob, valueBlob));
+ mTotalSize = newTotalSize;
+ ALOGV("set: created new cache entry with %zu byte key and %zu byte value",
+ keySize, valueSize);
+ } else {
+ // Update the existing cache entry.
+ std::shared_ptr<Blob> valueBlob(new Blob(value, valueSize, true));
+ std::shared_ptr<Blob> oldValueBlob(index->getValue());
+ size_t newTotalSize = mTotalSize + valueSize - oldValueBlob->getSize();
+ if (mMaxTotalSize < newTotalSize) {
+ if (isCleanable()) {
+ // Clean the cache and try again.
+ clean();
+ continue;
+ } else {
+ ALOGV("set: not caching new value because the total cache "
+ "size limit would be exceeded: %zu (limit: %zu)",
+ keySize + valueSize, mMaxTotalSize);
+ break;
+ }
+ }
+ index->setValue(valueBlob);
+ mTotalSize = newTotalSize;
+ ALOGV("set: updated existing cache entry with %zu byte key and %zu byte "
+ "value", keySize, valueSize);
+ }
+ break;
+ }
+}
+
+size_t BlobCache::get(const void* key, size_t keySize, void* value,
+ size_t valueSize) {
+ if (mMaxKeySize < keySize) {
+ ALOGV("get: not searching because the key is too large: %zu (limit %zu)",
+ keySize, mMaxKeySize);
+ return 0;
+ }
+ std::shared_ptr<Blob> dummyKey(new Blob(key, keySize, false));
+ CacheEntry dummyEntry(dummyKey, NULL);
+ auto index = std::lower_bound(mCacheEntries.begin(), mCacheEntries.end(), dummyEntry);
+ if (index == mCacheEntries.end() || dummyEntry < *index) {
+ ALOGV("get: no cache entry found for key of size %zu", keySize);
+ return 0;
+ }
+
+ // The key was found. Return the value if the caller's buffer is large
+ // enough.
+ std::shared_ptr<Blob> valueBlob(index->getValue());
+ size_t valueBlobSize = valueBlob->getSize();
+ if (valueBlobSize <= valueSize) {
+ ALOGV("get: copying %zu bytes to caller's buffer", valueBlobSize);
+ memcpy(value, valueBlob->getData(), valueBlobSize);
+ } else {
+ ALOGV("get: caller's buffer is too small for value: %zu (needs %zu)",
+ valueSize, valueBlobSize);
+ }
+ return valueBlobSize;
+}
+
+static inline size_t align4(size_t size) {
+ return (size + 3) & ~3;
+}
+
+size_t BlobCache::getFlattenedSize() const {
+ size_t size = align4(sizeof(Header) + PROPERTY_VALUE_MAX);
+ for (const CacheEntry& e : mCacheEntries) {
+ std::shared_ptr<Blob> const& keyBlob = e.getKey();
+ std::shared_ptr<Blob> const& valueBlob = e.getValue();
+ size += align4(sizeof(EntryHeader) + keyBlob->getSize() + valueBlob->getSize());
+ }
+ return size;
+}
+
+int BlobCache::flatten(void* buffer, size_t size) const {
+ // Write the cache header
+ if (size < sizeof(Header)) {
+ ALOGE("flatten: not enough room for cache header");
+ return 0;
+ }
+ Header* header = reinterpret_cast<Header*>(buffer);
+ header->mMagicNumber = blobCacheMagic;
+ header->mBlobCacheVersion = blobCacheVersion;
+ header->mDeviceVersion = blobCacheDeviceVersion;
+ header->mNumEntries = mCacheEntries.size();
+ char buildId[PROPERTY_VALUE_MAX];
+ header->mBuildIdLength = property_get("ro.build.id", buildId, "");
+ memcpy(header->mBuildId, buildId, header->mBuildIdLength);
+
+ // Write cache entries
+ uint8_t* byteBuffer = reinterpret_cast<uint8_t*>(buffer);
+ off_t byteOffset = align4(sizeof(Header) + header->mBuildIdLength);
+ for (const CacheEntry& e : mCacheEntries) {
+ std::shared_ptr<Blob> const& keyBlob = e.getKey();
+ std::shared_ptr<Blob> const& valueBlob = e.getValue();
+ size_t keySize = keyBlob->getSize();
+ size_t valueSize = valueBlob->getSize();
+
+ size_t entrySize = sizeof(EntryHeader) + keySize + valueSize;
+ size_t totalSize = align4(entrySize);
+ if (byteOffset + totalSize > size) {
+ ALOGE("flatten: not enough room for cache entries");
+ return -EINVAL;
+ }
+
+ EntryHeader* eheader = reinterpret_cast<EntryHeader*>(&byteBuffer[byteOffset]);
+ eheader->mKeySize = keySize;
+ eheader->mValueSize = valueSize;
+
+ memcpy(eheader->mData, keyBlob->getData(), keySize);
+ memcpy(eheader->mData + keySize, valueBlob->getData(), valueSize);
+
+ if (totalSize > entrySize) {
+ // We have padding bytes. Those will get written to storage, and contribute to the CRC,
+ // so make sure we zero-them to have reproducible results.
+ memset(eheader->mData + keySize + valueSize, 0, totalSize - entrySize);
+ }
+
+ byteOffset += totalSize;
+ }
+
+ return 0;
+}
+
+int BlobCache::unflatten(void const* buffer, size_t size) {
+ // All errors should result in the BlobCache being in an empty state.
+ mCacheEntries.clear();
+
+ // Read the cache header
+ if (size < sizeof(Header)) {
+ ALOGE("unflatten: not enough room for cache header");
+ return -EINVAL;
+ }
+ const Header* header = reinterpret_cast<const Header*>(buffer);
+ if (header->mMagicNumber != blobCacheMagic) {
+ ALOGE("unflatten: bad magic number: %" PRIu32, header->mMagicNumber);
+ return -EINVAL;
+ }
+ char buildId[PROPERTY_VALUE_MAX];
+ int len = property_get("ro.build.id", buildId, "");
+ if (header->mBlobCacheVersion != blobCacheVersion ||
+ header->mDeviceVersion != blobCacheDeviceVersion ||
+ len != header->mBuildIdLength ||
+ strncmp(buildId, header->mBuildId, len)) {
+ // We treat version mismatches as an empty cache.
+ return 0;
+ }
+
+ // Read cache entries
+ const uint8_t* byteBuffer = reinterpret_cast<const uint8_t*>(buffer);
+ off_t byteOffset = align4(sizeof(Header) + header->mBuildIdLength);
+ size_t numEntries = header->mNumEntries;
+ for (size_t i = 0; i < numEntries; i++) {
+ if (byteOffset + sizeof(EntryHeader) > size) {
+ mCacheEntries.clear();
+ ALOGE("unflatten: not enough room for cache entry headers");
+ return -EINVAL;
+ }
+
+ const EntryHeader* eheader = reinterpret_cast<const EntryHeader*>(
+ &byteBuffer[byteOffset]);
+ size_t keySize = eheader->mKeySize;
+ size_t valueSize = eheader->mValueSize;
+ size_t entrySize = sizeof(EntryHeader) + keySize + valueSize;
+
+ size_t totalSize = align4(entrySize);
+ if (byteOffset + totalSize > size) {
+ mCacheEntries.clear();
+ ALOGE("unflatten: not enough room for cache entry headers");
+ return -EINVAL;
+ }
+
+ const uint8_t* data = eheader->mData;
+ set(data, keySize, data + keySize, valueSize);
+
+ byteOffset += totalSize;
+ }
+
+ return 0;
+}
+
+long int BlobCache::blob_random() {
+#ifdef _WIN32
+ return rand();
+#else
+ return nrand48(mRandState);
+#endif
+}
+
+void BlobCache::clean() {
+ // Remove a random cache entry until the total cache size gets below half
+ // the maximum total cache size.
+ while (mTotalSize > mMaxTotalSize / 2) {
+ size_t i = size_t(blob_random() % (mCacheEntries.size()));
+ const CacheEntry& entry(mCacheEntries[i]);
+ mTotalSize -= entry.getKey()->getSize() + entry.getValue()->getSize();
+ mCacheEntries.erase(mCacheEntries.begin() + i);
+ }
+}
+
+bool BlobCache::isCleanable() const {
+ return mTotalSize > mMaxTotalSize / 2;
+}
+
+BlobCache::Blob::Blob(const void* data, size_t size, bool copyData) :
+ mData(copyData ? malloc(size) : data),
+ mSize(size),
+ mOwnsData(copyData) {
+ if (data != NULL && copyData) {
+ memcpy(const_cast<void*>(mData), data, size);
+ }
+}
+
+BlobCache::Blob::~Blob() {
+ if (mOwnsData) {
+ free(const_cast<void*>(mData));
+ }
+}
+
+bool BlobCache::Blob::operator<(const Blob& rhs) const {
+ if (mSize == rhs.mSize) {
+ return memcmp(mData, rhs.mData, mSize) < 0;
+ } else {
+ return mSize < rhs.mSize;
+ }
+}
+
+const void* BlobCache::Blob::getData() const {
+ return mData;
+}
+
+size_t BlobCache::Blob::getSize() const {
+ return mSize;
+}
+
+BlobCache::CacheEntry::CacheEntry() {
+}
+
+BlobCache::CacheEntry::CacheEntry(
+ const std::shared_ptr<Blob>& key, const std::shared_ptr<Blob>& value):
+ mKey(key),
+ mValue(value) {
+}
+
+BlobCache::CacheEntry::CacheEntry(const CacheEntry& ce):
+ mKey(ce.mKey),
+ mValue(ce.mValue) {
+}
+
+bool BlobCache::CacheEntry::operator<(const CacheEntry& rhs) const {
+ return *mKey < *rhs.mKey;
+}
+
+const BlobCache::CacheEntry& BlobCache::CacheEntry::operator=(const CacheEntry& rhs) {
+ mKey = rhs.mKey;
+ mValue = rhs.mValue;
+ return *this;
+}
+
+std::shared_ptr<BlobCache::Blob> BlobCache::CacheEntry::getKey() const {
+ return mKey;
+}
+
+std::shared_ptr<BlobCache::Blob> BlobCache::CacheEntry::getValue() const {
+ return mValue;
+}
+
+void BlobCache::CacheEntry::setValue(const std::shared_ptr<Blob>& value) {
+ mValue = value;
+}
+
+} // namespace android
diff --git a/opengl/libs/EGL/BlobCache.h b/opengl/libs/EGL/BlobCache.h
new file mode 100644
index 0000000..a0a270a
--- /dev/null
+++ b/opengl/libs/EGL/BlobCache.h
@@ -0,0 +1,245 @@
+/*
+ ** Copyright 2011, The Android Open Source Project
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ ** http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ** See the License for the specific language governing permissions and
+ ** limitations under the License.
+ */
+
+#ifndef ANDROID_BLOB_CACHE_H
+#define ANDROID_BLOB_CACHE_H
+
+#include <stddef.h>
+
+#include <memory>
+#include <vector>
+
+namespace android {
+
+// A BlobCache is an in-memory cache for binary key/value pairs. A BlobCache
+// does NOT provide any thread-safety guarantees.
+//
+// The cache contents can be serialized to an in-memory buffer or mmap'd file
+// and then reloaded in a subsequent execution of the program. This
+// serialization is non-portable and the data should only be used by the device
+// that generated it.
+class BlobCache {
+public:
+ // Create an empty blob cache. The blob cache will cache key/value pairs
+ // with key and value sizes less than or equal to maxKeySize and
+ // maxValueSize, respectively. The total combined size of ALL cache entries
+ // (key sizes plus value sizes) will not exceed maxTotalSize.
+ BlobCache(size_t maxKeySize, size_t maxValueSize, size_t maxTotalSize);
+
+ // set inserts a new binary value into the cache and associates it with the
+ // given binary key. If the key or value are too large for the cache then
+ // the cache remains unchanged. This includes the case where a different
+ // value was previously associated with the given key - the old value will
+ // remain in the cache. If the given key and value are small enough to be
+ // put in the cache (based on the maxKeySize, maxValueSize, and maxTotalSize
+ // values specified to the BlobCache constructor), then the key/value pair
+ // will be in the cache after set returns. Note, however, that a subsequent
+ // call to set may evict old key/value pairs from the cache.
+ //
+ // Preconditions:
+ // key != NULL
+ // 0 < keySize
+ // value != NULL
+ // 0 < valueSize
+ void set(const void* key, size_t keySize, const void* value,
+ size_t valueSize);
+
+ // get retrieves from the cache the binary value associated with a given
+ // binary key. If the key is present in the cache then the length of the
+ // binary value associated with that key is returned. If the value argument
+ // is non-NULL and the size of the cached value is less than valueSize bytes
+ // then the cached value is copied into the buffer pointed to by the value
+ // argument. If the key is not present in the cache then 0 is returned and
+ // the buffer pointed to by the value argument is not modified.
+ //
+ // Note that when calling get multiple times with the same key, the later
+ // calls may fail, returning 0, even if earlier calls succeeded. The return
+ // value must be checked for each call.
+ //
+ // Preconditions:
+ // key != NULL
+ // 0 < keySize
+ // 0 <= valueSize
+ size_t get(const void* key, size_t keySize, void* value, size_t valueSize);
+
+
+ // getFlattenedSize returns the number of bytes needed to store the entire
+ // serialized cache.
+ size_t getFlattenedSize() const;
+
+ // flatten serializes the current contents of the cache into the memory
+ // pointed to by 'buffer'. The serialized cache contents can later be
+ // loaded into a BlobCache object using the unflatten method. The contents
+ // of the BlobCache object will not be modified.
+ //
+ // Preconditions:
+ // size >= this.getFlattenedSize()
+ int flatten(void* buffer, size_t size) const;
+
+ // unflatten replaces the contents of the cache with the serialized cache
+ // contents in the memory pointed to by 'buffer'. The previous contents of
+ // the BlobCache will be evicted from the cache. If an error occurs while
+ // unflattening the serialized cache contents then the BlobCache will be
+ // left in an empty state.
+ //
+ int unflatten(void const* buffer, size_t size);
+
+private:
+ // Copying is disallowed.
+ BlobCache(const BlobCache&);
+ void operator=(const BlobCache&);
+
+ // A random function helper to get around MinGW not having nrand48()
+ long int blob_random();
+
+ // clean evicts a randomly chosen set of entries from the cache such that
+ // the total size of all remaining entries is less than mMaxTotalSize/2.
+ void clean();
+
+ // isCleanable returns true if the cache is full enough for the clean method
+ // to have some effect, and false otherwise.
+ bool isCleanable() const;
+
+ // A Blob is an immutable sized unstructured data blob.
+ class Blob {
+ public:
+ Blob(const void* data, size_t size, bool copyData);
+ ~Blob();
+
+ bool operator<(const Blob& rhs) const;
+
+ const void* getData() const;
+ size_t getSize() const;
+
+ private:
+ // Copying is not allowed.
+ Blob(const Blob&);
+ void operator=(const Blob&);
+
+ // mData points to the buffer containing the blob data.
+ const void* mData;
+
+ // mSize is the size of the blob data in bytes.
+ size_t mSize;
+
+ // mOwnsData indicates whether or not this Blob object should free the
+ // memory pointed to by mData when the Blob gets destructed.
+ bool mOwnsData;
+ };
+
+ // A CacheEntry is a single key/value pair in the cache.
+ class CacheEntry {
+ public:
+ CacheEntry();
+ CacheEntry(const std::shared_ptr<Blob>& key, const std::shared_ptr<Blob>& value);
+ CacheEntry(const CacheEntry& ce);
+
+ bool operator<(const CacheEntry& rhs) const;
+ const CacheEntry& operator=(const CacheEntry&);
+
+ std::shared_ptr<Blob> getKey() const;
+ std::shared_ptr<Blob> getValue() const;
+
+ void setValue(const std::shared_ptr<Blob>& value);
+
+ private:
+
+ // mKey is the key that identifies the cache entry.
+ std::shared_ptr<Blob> mKey;
+
+ // mValue is the cached data associated with the key.
+ std::shared_ptr<Blob> mValue;
+ };
+
+ // A Header is the header for the entire BlobCache serialization format. No
+ // need to make this portable, so we simply write the struct out.
+ struct Header {
+ // mMagicNumber is the magic number that identifies the data as
+ // serialized BlobCache contents. It must always contain 'Blb$'.
+ uint32_t mMagicNumber;
+
+ // mBlobCacheVersion is the serialization format version.
+ uint32_t mBlobCacheVersion;
+
+ // mDeviceVersion is the device-specific version of the cache. This can
+ // be used to invalidate the cache.
+ uint32_t mDeviceVersion;
+
+ // mNumEntries is number of cache entries following the header in the
+ // data.
+ size_t mNumEntries;
+
+ // mBuildId is the build id of the device when the cache was created.
+ // When an update to the build happens (via an OTA or other update) this
+ // is used to invalidate the cache.
+ int mBuildIdLength;
+ char mBuildId[];
+ };
+
+ // An EntryHeader is the header for a serialized cache entry. No need to
+ // make this portable, so we simply write the struct out. Each EntryHeader
+ // is followed imediately by the key data and then the value data.
+ //
+ // The beginning of each serialized EntryHeader is 4-byte aligned, so the
+ // number of bytes that a serialized cache entry will occupy is:
+ //
+ // ((sizeof(EntryHeader) + keySize + valueSize) + 3) & ~3
+ //
+ struct EntryHeader {
+ // mKeySize is the size of the entry key in bytes.
+ size_t mKeySize;
+
+ // mValueSize is the size of the entry value in bytes.
+ size_t mValueSize;
+
+ // mData contains both the key and value data for the cache entry. The
+ // key comes first followed immediately by the value.
+ uint8_t mData[];
+ };
+
+ // mMaxKeySize is the maximum key size that will be cached. Calls to
+ // BlobCache::set with a keySize parameter larger than mMaxKeySize will
+ // simply not add the key/value pair to the cache.
+ const size_t mMaxKeySize;
+
+ // mMaxValueSize is the maximum value size that will be cached. Calls to
+ // BlobCache::set with a valueSize parameter larger than mMaxValueSize will
+ // simply not add the key/value pair to the cache.
+ const size_t mMaxValueSize;
+
+ // mMaxTotalSize is the maximum size that all cache entries can occupy. This
+ // includes space for both keys and values. When a call to BlobCache::set
+ // would otherwise cause this limit to be exceeded, either the key/value
+ // pair passed to BlobCache::set will not be cached or other cache entries
+ // will be evicted from the cache to make room for the new entry.
+ const size_t mMaxTotalSize;
+
+ // mTotalSize is the total combined size of all keys and values currently in
+ // the cache.
+ size_t mTotalSize;
+
+ // mRandState is the pseudo-random number generator state. It is passed to
+ // nrand48 to generate random numbers when needed.
+ unsigned short mRandState[3];
+
+ // mCacheEntries stores all the cache entries that are resident in memory.
+ // Cache entries are added to it by the 'set' method.
+ std::vector<CacheEntry> mCacheEntries;
+};
+
+}
+
+#endif // ANDROID_BLOB_CACHE_H
diff --git a/opengl/libs/EGL/BlobCache_test.cpp b/opengl/libs/EGL/BlobCache_test.cpp
new file mode 100644
index 0000000..edbaaf0
--- /dev/null
+++ b/opengl/libs/EGL/BlobCache_test.cpp
@@ -0,0 +1,434 @@
+/*
+ ** Copyright 2011, The Android Open Source Project
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ ** http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ** See the License for the specific language governing permissions and
+ ** limitations under the License.
+ */
+
+#include <fcntl.h>
+#include <stdio.h>
+
+#include <memory>
+
+#include <gtest/gtest.h>
+
+#include "BlobCache.h"
+
+namespace android {
+
+template<typename T> using sp = std::shared_ptr<T>;
+
+class BlobCacheTest : public ::testing::Test {
+protected:
+
+ enum {
+ OK = 0,
+ BAD_VALUE = -EINVAL
+ };
+
+ enum {
+ MAX_KEY_SIZE = 6,
+ MAX_VALUE_SIZE = 8,
+ MAX_TOTAL_SIZE = 13,
+ };
+
+ virtual void SetUp() {
+ mBC.reset(new BlobCache(MAX_KEY_SIZE, MAX_VALUE_SIZE, MAX_TOTAL_SIZE));
+ }
+
+ virtual void TearDown() {
+ mBC.reset();
+ }
+
+ std::unique_ptr<BlobCache> mBC;
+};
+
+TEST_F(BlobCacheTest, CacheSingleValueSucceeds) {
+ unsigned char buf[4] = { 0xee, 0xee, 0xee, 0xee };
+ mBC->set("abcd", 4, "efgh", 4);
+ ASSERT_EQ(size_t(4), mBC->get("abcd", 4, buf, 4));
+ ASSERT_EQ('e', buf[0]);
+ ASSERT_EQ('f', buf[1]);
+ ASSERT_EQ('g', buf[2]);
+ ASSERT_EQ('h', buf[3]);
+}
+
+TEST_F(BlobCacheTest, CacheTwoValuesSucceeds) {
+ unsigned char buf[2] = { 0xee, 0xee };
+ mBC->set("ab", 2, "cd", 2);
+ mBC->set("ef", 2, "gh", 2);
+ ASSERT_EQ(size_t(2), mBC->get("ab", 2, buf, 2));
+ ASSERT_EQ('c', buf[0]);
+ ASSERT_EQ('d', buf[1]);
+ ASSERT_EQ(size_t(2), mBC->get("ef", 2, buf, 2));
+ ASSERT_EQ('g', buf[0]);
+ ASSERT_EQ('h', buf[1]);
+}
+
+TEST_F(BlobCacheTest, GetOnlyWritesInsideBounds) {
+ unsigned char buf[6] = { 0xee, 0xee, 0xee, 0xee, 0xee, 0xee };
+ mBC->set("abcd", 4, "efgh", 4);
+ ASSERT_EQ(size_t(4), mBC->get("abcd", 4, buf+1, 4));
+ ASSERT_EQ(0xee, buf[0]);
+ ASSERT_EQ('e', buf[1]);
+ ASSERT_EQ('f', buf[2]);
+ ASSERT_EQ('g', buf[3]);
+ ASSERT_EQ('h', buf[4]);
+ ASSERT_EQ(0xee, buf[5]);
+}
+
+TEST_F(BlobCacheTest, GetOnlyWritesIfBufferIsLargeEnough) {
+ unsigned char buf[3] = { 0xee, 0xee, 0xee };
+ mBC->set("abcd", 4, "efgh", 4);
+ ASSERT_EQ(size_t(4), mBC->get("abcd", 4, buf, 3));
+ ASSERT_EQ(0xee, buf[0]);
+ ASSERT_EQ(0xee, buf[1]);
+ ASSERT_EQ(0xee, buf[2]);
+}
+
+TEST_F(BlobCacheTest, GetDoesntAccessNullBuffer) {
+ mBC->set("abcd", 4, "efgh", 4);
+ ASSERT_EQ(size_t(4), mBC->get("abcd", 4, NULL, 0));
+}
+
+TEST_F(BlobCacheTest, MultipleSetsCacheLatestValue) {
+ unsigned char buf[4] = { 0xee, 0xee, 0xee, 0xee };
+ mBC->set("abcd", 4, "efgh", 4);
+ mBC->set("abcd", 4, "ijkl", 4);
+ ASSERT_EQ(size_t(4), mBC->get("abcd", 4, buf, 4));
+ ASSERT_EQ('i', buf[0]);
+ ASSERT_EQ('j', buf[1]);
+ ASSERT_EQ('k', buf[2]);
+ ASSERT_EQ('l', buf[3]);
+}
+
+TEST_F(BlobCacheTest, SecondSetKeepsFirstValueIfTooLarge) {
+ unsigned char buf[MAX_VALUE_SIZE+1] = { 0xee, 0xee, 0xee, 0xee };
+ mBC->set("abcd", 4, "efgh", 4);
+ mBC->set("abcd", 4, buf, MAX_VALUE_SIZE+1);
+ ASSERT_EQ(size_t(4), mBC->get("abcd", 4, buf, 4));
+ ASSERT_EQ('e', buf[0]);
+ ASSERT_EQ('f', buf[1]);
+ ASSERT_EQ('g', buf[2]);
+ ASSERT_EQ('h', buf[3]);
+}
+
+TEST_F(BlobCacheTest, DoesntCacheIfKeyIsTooBig) {
+ char key[MAX_KEY_SIZE+1];
+ unsigned char buf[4] = { 0xee, 0xee, 0xee, 0xee };
+ for (int i = 0; i < MAX_KEY_SIZE+1; i++) {
+ key[i] = 'a';
+ }
+ mBC->set(key, MAX_KEY_SIZE+1, "bbbb", 4);
+ ASSERT_EQ(size_t(0), mBC->get(key, MAX_KEY_SIZE+1, buf, 4));
+ ASSERT_EQ(0xee, buf[0]);
+ ASSERT_EQ(0xee, buf[1]);
+ ASSERT_EQ(0xee, buf[2]);
+ ASSERT_EQ(0xee, buf[3]);
+}
+
+TEST_F(BlobCacheTest, DoesntCacheIfValueIsTooBig) {
+ char buf[MAX_VALUE_SIZE+1];
+ for (int i = 0; i < MAX_VALUE_SIZE+1; i++) {
+ buf[i] = 'b';
+ }
+ mBC->set("abcd", 4, buf, MAX_VALUE_SIZE+1);
+ for (int i = 0; i < MAX_VALUE_SIZE+1; i++) {
+ buf[i] = 0xee;
+ }
+ ASSERT_EQ(size_t(0), mBC->get("abcd", 4, buf, MAX_VALUE_SIZE+1));
+ for (int i = 0; i < MAX_VALUE_SIZE+1; i++) {
+ SCOPED_TRACE(i);
+ ASSERT_EQ(0xee, buf[i]);
+ }
+}
+
+TEST_F(BlobCacheTest, DoesntCacheIfKeyValuePairIsTooBig) {
+ // Check a testing assumptions
+ ASSERT_TRUE(MAX_TOTAL_SIZE < MAX_KEY_SIZE + MAX_VALUE_SIZE);
+ ASSERT_TRUE(MAX_KEY_SIZE < MAX_TOTAL_SIZE);
+
+ enum { bufSize = MAX_TOTAL_SIZE - MAX_KEY_SIZE + 1 };
+
+ char key[MAX_KEY_SIZE];
+ char buf[bufSize];
+ for (int i = 0; i < MAX_KEY_SIZE; i++) {
+ key[i] = 'a';
+ }
+ for (int i = 0; i < bufSize; i++) {
+ buf[i] = 'b';
+ }
+
+ mBC->set(key, MAX_KEY_SIZE, buf, MAX_VALUE_SIZE);
+ ASSERT_EQ(size_t(0), mBC->get(key, MAX_KEY_SIZE, NULL, 0));
+}
+
+TEST_F(BlobCacheTest, CacheMaxKeySizeSucceeds) {
+ char key[MAX_KEY_SIZE];
+ unsigned char buf[4] = { 0xee, 0xee, 0xee, 0xee };
+ for (int i = 0; i < MAX_KEY_SIZE; i++) {
+ key[i] = 'a';
+ }
+ mBC->set(key, MAX_KEY_SIZE, "wxyz", 4);
+ ASSERT_EQ(size_t(4), mBC->get(key, MAX_KEY_SIZE, buf, 4));
+ ASSERT_EQ('w', buf[0]);
+ ASSERT_EQ('x', buf[1]);
+ ASSERT_EQ('y', buf[2]);
+ ASSERT_EQ('z', buf[3]);
+}
+
+TEST_F(BlobCacheTest, CacheMaxValueSizeSucceeds) {
+ char buf[MAX_VALUE_SIZE];
+ for (int i = 0; i < MAX_VALUE_SIZE; i++) {
+ buf[i] = 'b';
+ }
+ mBC->set("abcd", 4, buf, MAX_VALUE_SIZE);
+ for (int i = 0; i < MAX_VALUE_SIZE; i++) {
+ buf[i] = 0xee;
+ }
+ ASSERT_EQ(size_t(MAX_VALUE_SIZE), mBC->get("abcd", 4, buf,
+ MAX_VALUE_SIZE));
+ for (int i = 0; i < MAX_VALUE_SIZE; i++) {
+ SCOPED_TRACE(i);
+ ASSERT_EQ('b', buf[i]);
+ }
+}
+
+TEST_F(BlobCacheTest, CacheMaxKeyValuePairSizeSucceeds) {
+ // Check a testing assumption
+ ASSERT_TRUE(MAX_KEY_SIZE < MAX_TOTAL_SIZE);
+
+ enum { bufSize = MAX_TOTAL_SIZE - MAX_KEY_SIZE };
+
+ char key[MAX_KEY_SIZE];
+ char buf[bufSize];
+ for (int i = 0; i < MAX_KEY_SIZE; i++) {
+ key[i] = 'a';
+ }
+ for (int i = 0; i < bufSize; i++) {
+ buf[i] = 'b';
+ }
+
+ mBC->set(key, MAX_KEY_SIZE, buf, bufSize);
+ ASSERT_EQ(size_t(bufSize), mBC->get(key, MAX_KEY_SIZE, NULL, 0));
+}
+
+TEST_F(BlobCacheTest, CacheMinKeyAndValueSizeSucceeds) {
+ unsigned char buf[1] = { 0xee };
+ mBC->set("x", 1, "y", 1);
+ ASSERT_EQ(size_t(1), mBC->get("x", 1, buf, 1));
+ ASSERT_EQ('y', buf[0]);
+}
+
+TEST_F(BlobCacheTest, CacheSizeDoesntExceedTotalLimit) {
+ for (int i = 0; i < 256; i++) {
+ uint8_t k = i;
+ mBC->set(&k, 1, "x", 1);
+ }
+ int numCached = 0;
+ for (int i = 0; i < 256; i++) {
+ uint8_t k = i;
+ if (mBC->get(&k, 1, NULL, 0) == 1) {
+ numCached++;
+ }
+ }
+ ASSERT_GE(MAX_TOTAL_SIZE / 2, numCached);
+}
+
+TEST_F(BlobCacheTest, ExceedingTotalLimitHalvesCacheSize) {
+ // Fill up the entire cache with 1 char key/value pairs.
+ const int maxEntries = MAX_TOTAL_SIZE / 2;
+ for (int i = 0; i < maxEntries; i++) {
+ uint8_t k = i;
+ mBC->set(&k, 1, "x", 1);
+ }
+ // Insert one more entry, causing a cache overflow.
+ {
+ uint8_t k = maxEntries;
+ mBC->set(&k, 1, "x", 1);
+ }
+ // Count the number of entries in the cache.
+ int numCached = 0;
+ for (int i = 0; i < maxEntries+1; i++) {
+ uint8_t k = i;
+ if (mBC->get(&k, 1, NULL, 0) == 1) {
+ numCached++;
+ }
+ }
+ ASSERT_EQ(maxEntries/2 + 1, numCached);
+}
+
+class BlobCacheFlattenTest : public BlobCacheTest {
+protected:
+ virtual void SetUp() {
+ BlobCacheTest::SetUp();
+ mBC2.reset(new BlobCache(MAX_KEY_SIZE, MAX_VALUE_SIZE, MAX_TOTAL_SIZE));
+ }
+
+ virtual void TearDown() {
+ mBC2.reset();
+ BlobCacheTest::TearDown();
+ }
+
+ void roundTrip() {
+ size_t size = mBC->getFlattenedSize();
+ uint8_t* flat = new uint8_t[size];
+ ASSERT_EQ(OK, mBC->flatten(flat, size));
+ ASSERT_EQ(OK, mBC2->unflatten(flat, size));
+ delete[] flat;
+ }
+
+ sp<BlobCache> mBC2;
+};
+
+TEST_F(BlobCacheFlattenTest, FlattenOneValue) {
+ unsigned char buf[4] = { 0xee, 0xee, 0xee, 0xee };
+ mBC->set("abcd", 4, "efgh", 4);
+ roundTrip();
+ ASSERT_EQ(size_t(4), mBC2->get("abcd", 4, buf, 4));
+ ASSERT_EQ('e', buf[0]);
+ ASSERT_EQ('f', buf[1]);
+ ASSERT_EQ('g', buf[2]);
+ ASSERT_EQ('h', buf[3]);
+}
+
+TEST_F(BlobCacheFlattenTest, FlattenFullCache) {
+ // Fill up the entire cache with 1 char key/value pairs.
+ const int maxEntries = MAX_TOTAL_SIZE / 2;
+ for (int i = 0; i < maxEntries; i++) {
+ uint8_t k = i;
+ mBC->set(&k, 1, &k, 1);
+ }
+
+ roundTrip();
+
+ // Verify the deserialized cache
+ for (int i = 0; i < maxEntries; i++) {
+ uint8_t k = i;
+ uint8_t v = 0xee;
+ ASSERT_EQ(size_t(1), mBC2->get(&k, 1, &v, 1));
+ ASSERT_EQ(k, v);
+ }
+}
+
+TEST_F(BlobCacheFlattenTest, FlattenDoesntChangeCache) {
+ // Fill up the entire cache with 1 char key/value pairs.
+ const int maxEntries = MAX_TOTAL_SIZE / 2;
+ for (int i = 0; i < maxEntries; i++) {
+ uint8_t k = i;
+ mBC->set(&k, 1, &k, 1);
+ }
+
+ size_t size = mBC->getFlattenedSize();
+ uint8_t* flat = new uint8_t[size];
+ ASSERT_EQ(OK, mBC->flatten(flat, size));
+ delete[] flat;
+
+ // Verify the cache that we just serialized
+ for (int i = 0; i < maxEntries; i++) {
+ uint8_t k = i;
+ uint8_t v = 0xee;
+ ASSERT_EQ(size_t(1), mBC->get(&k, 1, &v, 1));
+ ASSERT_EQ(k, v);
+ }
+}
+
+TEST_F(BlobCacheFlattenTest, FlattenCatchesBufferTooSmall) {
+ // Fill up the entire cache with 1 char key/value pairs.
+ const int maxEntries = MAX_TOTAL_SIZE / 2;
+ for (int i = 0; i < maxEntries; i++) {
+ uint8_t k = i;
+ mBC->set(&k, 1, &k, 1);
+ }
+
+ size_t size = mBC->getFlattenedSize() - 1;
+ uint8_t* flat = new uint8_t[size];
+ // ASSERT_EQ(BAD_VALUE, mBC->flatten(flat, size));
+ // TODO: The above fails. I expect this is so because getFlattenedSize()
+ // overstimates the size by using PROPERTY_VALUE_MAX.
+ delete[] flat;
+}
+
+TEST_F(BlobCacheFlattenTest, UnflattenCatchesBadMagic) {
+ unsigned char buf[4] = { 0xee, 0xee, 0xee, 0xee };
+ mBC->set("abcd", 4, "efgh", 4);
+
+ size_t size = mBC->getFlattenedSize();
+ uint8_t* flat = new uint8_t[size];
+ ASSERT_EQ(OK, mBC->flatten(flat, size));
+ flat[1] = ~flat[1];
+
+ // Bad magic should cause an error.
+ ASSERT_EQ(BAD_VALUE, mBC2->unflatten(flat, size));
+ delete[] flat;
+
+ // The error should cause the unflatten to result in an empty cache
+ ASSERT_EQ(size_t(0), mBC2->get("abcd", 4, buf, 4));
+}
+
+TEST_F(BlobCacheFlattenTest, UnflattenCatchesBadBlobCacheVersion) {
+ unsigned char buf[4] = { 0xee, 0xee, 0xee, 0xee };
+ mBC->set("abcd", 4, "efgh", 4);
+
+ size_t size = mBC->getFlattenedSize();
+ uint8_t* flat = new uint8_t[size];
+ ASSERT_EQ(OK, mBC->flatten(flat, size));
+ flat[5] = ~flat[5];
+
+ // Version mismatches shouldn't cause errors, but should not use the
+ // serialized entries
+ ASSERT_EQ(OK, mBC2->unflatten(flat, size));
+ delete[] flat;
+
+ // The version mismatch should cause the unflatten to result in an empty
+ // cache
+ ASSERT_EQ(size_t(0), mBC2->get("abcd", 4, buf, 4));
+}
+
+TEST_F(BlobCacheFlattenTest, UnflattenCatchesBadBlobCacheDeviceVersion) {
+ unsigned char buf[4] = { 0xee, 0xee, 0xee, 0xee };
+ mBC->set("abcd", 4, "efgh", 4);
+
+ size_t size = mBC->getFlattenedSize();
+ uint8_t* flat = new uint8_t[size];
+ ASSERT_EQ(OK, mBC->flatten(flat, size));
+ flat[10] = ~flat[10];
+
+ // Version mismatches shouldn't cause errors, but should not use the
+ // serialized entries
+ ASSERT_EQ(OK, mBC2->unflatten(flat, size));
+ delete[] flat;
+
+ // The version mismatch should cause the unflatten to result in an empty
+ // cache
+ ASSERT_EQ(size_t(0), mBC2->get("abcd", 4, buf, 4));
+}
+
+TEST_F(BlobCacheFlattenTest, UnflattenCatchesBufferTooSmall) {
+ unsigned char buf[4] = { 0xee, 0xee, 0xee, 0xee };
+ mBC->set("abcd", 4, "efgh", 4);
+
+ size_t size = mBC->getFlattenedSize();
+ uint8_t* flat = new uint8_t[size];
+ ASSERT_EQ(OK, mBC->flatten(flat, size));
+
+ // A buffer truncation shouldt cause an error
+ // ASSERT_EQ(BAD_VALUE, mBC2->unflatten(flat, size-1));
+ // TODO: The above appears to fail because getFlattenedSize() is
+ // conservative.
+ delete[] flat;
+
+ // The error should cause the unflatten to result in an empty cache
+ ASSERT_EQ(size_t(0), mBC2->get("abcd", 4, buf, 4));
+}
+
+} // namespace android
diff --git a/opengl/libs/EGL/Loader.cpp b/opengl/libs/EGL/Loader.cpp
index 9aedc61..683e6ca 100644
--- a/opengl/libs/EGL/Loader.cpp
+++ b/opengl/libs/EGL/Loader.cpp
@@ -19,6 +19,8 @@
#include "Loader.h"
+#include <string>
+
#include <dirent.h>
#include <dlfcn.h>
@@ -26,11 +28,9 @@
#include <cutils/properties.h>
#include <log/log.h>
-#include <utils/String8.h>
-#include <utils/Trace.h>
-
#include <ui/GraphicsEnv.h>
+#include "egl_trace.h"
#include "egldefs.h"
// ----------------------------------------------------------------------------
@@ -61,7 +61,10 @@
*
*/
-ANDROID_SINGLETON_STATIC_INSTANCE( Loader )
+Loader& Loader::getInstance() {
+ static Loader loader;
+ return loader;
+}
/* This function is called to check whether we run inside the emulator,
* and if this is the case whether GLES GPU emulation is supported.
@@ -122,7 +125,7 @@
}
}
-status_t Loader::driver_t::set(void* hnd, int32_t api)
+int Loader::driver_t::set(void* hnd, int32_t api)
{
switch (api) {
case EGL:
@@ -135,9 +138,9 @@
dso[2] = hnd;
break;
default:
- return BAD_INDEX;
+ return -EOVERFLOW;
}
- return NO_ERROR;
+ return 0;
}
// ----------------------------------------------------------------------------
@@ -233,11 +236,10 @@
return (void*)hnd;
}
-status_t Loader::close(void* driver)
+void Loader::close(void* driver)
{
driver_t* hnd = (driver_t*)driver;
delete hnd;
- return NO_ERROR;
}
void Loader::init_api(void* dso,
@@ -302,23 +304,23 @@
ATRACE_CALL();
class MatchFile {
public:
- static String8 find(const char* kind) {
- String8 result;
+ static std::string find(const char* kind) {
+ std::string result;
int emulationStatus = checkGlesEmulationStatus();
switch (emulationStatus) {
case 0:
#if defined(__LP64__)
- result.setTo("/system/lib64/egl/libGLES_android.so");
+ result = "/system/lib64/egl/libGLES_android.so";
#else
- result.setTo("/system/lib/egl/libGLES_android.so");
+ result = "/system/lib/egl/libGLES_android.so";
#endif
return result;
case 1:
// Use host-side OpenGL through the "emulation" library
#if defined(__LP64__)
- result.appendFormat("/system/lib64/egl/lib%s_emulation.so", kind);
+ result = std::string("/system/lib64/egl/lib") + kind + "_emulation.so";
#else
- result.appendFormat("/system/lib/egl/lib%s_emulation.so", kind);
+ result = std::string("/system/lib/egl/lib") + kind + "_emulation.so";
#endif
return result;
default:
@@ -326,8 +328,7 @@
break;
}
- String8 pattern;
- pattern.appendFormat("lib%s", kind);
+ std::string pattern = std::string("lib") + kind;
const char* const searchPaths[] = {
#if defined(__LP64__)
"/vendor/lib64/egl",
@@ -368,12 +369,11 @@
}
private:
- static bool find(String8& result,
- const String8& pattern, const char* const search, bool exact) {
+ static bool find(std::string& result,
+ const std::string& pattern, const char* const search, bool exact) {
if (exact) {
- String8 absolutePath;
- absolutePath.appendFormat("%s/%s.so", search, pattern.string());
- if (!access(absolutePath.string(), R_OK)) {
+ std::string absolutePath = std::string(search) + "/" + pattern;
+ if (!access(absolutePath.c_str(), R_OK)) {
result = absolutePath;
return true;
}
@@ -392,10 +392,9 @@
// always skip the software renderer
continue;
}
- if (strstr(e->d_name, pattern.string()) == e->d_name) {
+ if (strstr(e->d_name, pattern.c_str()) == e->d_name) {
if (!strcmp(e->d_name + strlen(e->d_name) - 3, ".so")) {
- result.clear();
- result.appendFormat("%s/%s", search, e->d_name);
+ result = std::string(search) + "/" + e->d_name;
closedir(d);
return true;
}
@@ -408,17 +407,17 @@
};
- String8 absolutePath = MatchFile::find(kind);
- if (absolutePath.isEmpty()) {
+ std::string absolutePath = MatchFile::find(kind);
+ if (absolutePath.empty()) {
// this happens often, we don't want to log an error
return 0;
}
- const char* const driver_absolute_path = absolutePath.string();
+ const char* const driver_absolute_path = absolutePath.c_str();
void* dso = do_dlopen(driver_absolute_path, RTLD_NOW | RTLD_LOCAL);
if (dso == 0) {
const char* err = dlerror();
- ALOGE("load_driver(%s): %s", driver_absolute_path, err?err:"unknown");
+ ALOGE("load_driver(%s): %s", driver_absolute_path, err ? err : "unknown");
return 0;
}
@@ -447,9 +446,8 @@
char prop[PROPERTY_VALUE_MAX + 1];
for (auto key : HAL_SUBNAME_KEY_PROPERTIES) {
if (property_get(key, prop, nullptr) > 0) {
- String8 name;
- name.appendFormat("lib%s_%s.so", kind, prop);
- so = do_android_dlopen_ext(name.string(), RTLD_LOCAL | RTLD_NOW, &dlextinfo);
+ std::string name = std::string("lib") + kind + "_" + prop + ".so";
+ so = do_android_dlopen_ext(name.c_str(), RTLD_LOCAL | RTLD_NOW, &dlextinfo);
if (so) {
return so;
}
diff --git a/opengl/libs/EGL/Loader.h b/opengl/libs/EGL/Loader.h
index 2dd4206..6a32bb3 100644
--- a/opengl/libs/EGL/Loader.h
+++ b/opengl/libs/EGL/Loader.h
@@ -19,9 +19,6 @@
#include <stdint.h>
-#include <utils/Errors.h>
-#include <utils/Singleton.h>
-
#include <EGL/egl.h>
// ----------------------------------------------------------------------------
@@ -30,9 +27,7 @@
struct egl_connection_t;
-class Loader : public Singleton<Loader> {
- friend class Singleton<Loader>;
-
+class Loader {
typedef __eglMustCastToProperFunctionPointerType (* getProcAddressType)(const char*);
enum {
@@ -43,17 +38,19 @@
struct driver_t {
explicit driver_t(void* gles);
~driver_t();
- status_t set(void* hnd, int32_t api);
+ // returns -errno
+ int set(void* hnd, int32_t api);
void* dso[3];
};
getProcAddressType getProcAddress;
public:
+ static Loader& getInstance();
~Loader();
void* open(egl_connection_t* cnx);
- status_t close(void* driver);
+ void close(void* driver);
private:
Loader();
diff --git a/opengl/libs/EGL/egl.cpp b/opengl/libs/EGL/egl.cpp
index 34b0ba2..f44c1ca 100644
--- a/opengl/libs/EGL/egl.cpp
+++ b/opengl/libs/EGL/egl.cpp
@@ -20,7 +20,6 @@
#include <EGL/egl.h>
-#include <cutils/atomic.h>
#include <cutils/properties.h>
#include <log/log.h>
@@ -128,7 +127,7 @@
if (name != GL_EXTENSIONS)
return NULL;
- return (const GLubyte *)c->gl_extensions.string();
+ return (const GLubyte *)c->gl_extensions.c_str();
}
const GLubyte * egl_get_string_for_current_context(GLenum name, GLuint index) {
@@ -151,7 +150,7 @@
if (index >= c->tokenized_gl_extensions.size())
return NULL;
- return (const GLubyte *)c->tokenized_gl_extensions.itemAt(index).string();
+ return (const GLubyte *)c->tokenized_gl_extensions[index].c_str();
}
GLint egl_get_num_extensions_for_current_context() {
@@ -208,14 +207,14 @@
}
static pthread_mutex_t sLogPrintMutex = PTHREAD_MUTEX_INITIALIZER;
-static nsecs_t sLogPrintTime = 0;
-#define NSECS_DURATION 1000000000
+static std::chrono::steady_clock::time_point sLogPrintTime;
+static constexpr std::chrono::seconds DURATION(1);
void gl_unimplemented() {
bool printLog = false;
- nsecs_t now = systemTime();
+ auto now = std::chrono::steady_clock::now();
pthread_mutex_lock(&sLogPrintMutex);
- if ((now - sLogPrintTime) > NSECS_DURATION) {
+ if ((now - sLogPrintTime) > DURATION) {
sLogPrintTime = now;
printLog = true;
}
diff --git a/opengl/libs/EGL/eglApi.cpp b/opengl/libs/EGL/eglApi.cpp
index 9cc96c7..d124c89 100644
--- a/opengl/libs/EGL/eglApi.cpp
+++ b/opengl/libs/EGL/eglApi.cpp
@@ -33,16 +33,19 @@
#include <cutils/properties.h>
#include <log/log.h>
-#include <utils/KeyedVector.h>
-#include <utils/String8.h>
-#include <utils/Trace.h>
-#include <utils/Thread.h>
+#include <condition_variable>
+#include <deque>
+#include <mutex>
+#include <unordered_map>
+#include <string>
+#include <thread>
#include "../egl_impl.h"
#include "egl_display.h"
#include "egl_object.h"
#include "egl_tls.h"
+#include "egl_trace.h"
using namespace android;
@@ -50,6 +53,8 @@
namespace android {
+using nsecs_t = int64_t;
+
struct extention_map_t {
const char* name;
__eglMustCastToProperFunctionPointerType address;
@@ -233,7 +238,8 @@
// accesses protected by sExtensionMapMutex
-static DefaultKeyedVector<String8, __eglMustCastToProperFunctionPointerType> sGLExtentionMap;
+static std::unordered_map<std::string, __eglMustCastToProperFunctionPointerType> sGLExtentionMap;
+
static int sGLExtentionSlot = 0;
static pthread_mutex_t sExtensionMapMutex = PTHREAD_MUTEX_INITIALIZER;
@@ -475,7 +481,7 @@
}
int result = native_window_api_connect(window, NATIVE_WINDOW_API_EGL);
- if (result != OK) {
+ if (result < 0) {
ALOGE("eglCreateWindowSurface: native_window_api_connect (win=%p) "
"failed (%#x) (already connected to another API?)",
window, result);
@@ -988,8 +994,11 @@
*
*/
- const String8 name(procname);
- addr = sGLExtentionMap.valueFor(name);
+ const std::string name(procname);
+
+ auto& extentionMap = sGLExtentionMap;
+ auto pos = extentionMap.find(name);
+ addr = (pos != extentionMap.end()) ? pos->second : nullptr;
const int slot = sGLExtentionSlot;
ALOGE_IF(slot >= MAX_NUMBER_OF_GL_EXTENSIONS,
@@ -1011,7 +1020,7 @@
if (found) {
addr = gExtensionForwarders[slot];
- sGLExtentionMap.add(name, addr);
+ extentionMap[name] = addr;
sGLExtentionSlot++;
}
}
@@ -1020,45 +1029,57 @@
return addr;
}
-class FrameCompletionThread : public Thread {
+class FrameCompletionThread {
public:
static void queueSync(EGLSyncKHR sync) {
- static sp<FrameCompletionThread> thread(new FrameCompletionThread);
- static bool running = false;
- if (!running) {
- thread->run("GPUFrameCompletion");
- running = true;
- }
- {
- Mutex::Autolock lock(thread->mMutex);
- ScopedTrace st(ATRACE_TAG, String8::format("kicked off frame %d",
- thread->mFramesQueued).string());
- thread->mQueue.push_back(sync);
- thread->mCondition.signal();
- thread->mFramesQueued++;
- ATRACE_INT("GPU Frames Outstanding", int32_t(thread->mQueue.size()));
- }
+ static FrameCompletionThread thread;
+
+ char name[64];
+
+ std::lock_guard<std::mutex> lock(thread.mMutex);
+ snprintf(name, sizeof(name), "kicked off frame %u", (unsigned int)thread.mFramesQueued);
+ ATRACE_NAME(name);
+
+ thread.mQueue.push_back(sync);
+ thread.mCondition.notify_one();
+ thread.mFramesQueued++;
+ ATRACE_INT("GPU Frames Outstanding", int32_t(thread.mQueue.size()));
}
private:
- FrameCompletionThread() : mFramesQueued(0), mFramesCompleted(0) {}
- virtual bool threadLoop() {
+ FrameCompletionThread() : mFramesQueued(0), mFramesCompleted(0) {
+ std::thread thread(&FrameCompletionThread::loop, this);
+ thread.detach();
+ }
+
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wmissing-noreturn"
+ void loop() {
+ while (true) {
+ threadLoop();
+ }
+ }
+#pragma clang diagnostic pop
+
+ void threadLoop() {
EGLSyncKHR sync;
uint32_t frameNum;
{
- Mutex::Autolock lock(mMutex);
- while (mQueue.isEmpty()) {
- mCondition.wait(mMutex);
+ std::unique_lock<std::mutex> lock(mMutex);
+ while (mQueue.empty()) {
+ mCondition.wait(lock);
}
sync = mQueue[0];
frameNum = mFramesCompleted;
}
EGLDisplay dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY);
{
- ScopedTrace st(ATRACE_TAG, String8::format("waiting for frame %d",
- frameNum).string());
+ char name[64];
+ snprintf(name, sizeof(name), "waiting for frame %u", (unsigned int)frameNum);
+ ATRACE_NAME(name);
+
EGLint result = eglClientWaitSyncKHR(dpy, sync, 0, EGL_FOREVER_KHR);
if (result == EGL_FALSE) {
ALOGE("FrameCompletion: error waiting for fence: %#x", eglGetError());
@@ -1068,19 +1089,18 @@
eglDestroySyncKHR(dpy, sync);
}
{
- Mutex::Autolock lock(mMutex);
- mQueue.removeAt(0);
+ std::lock_guard<std::mutex> lock(mMutex);
+ mQueue.pop_front();
mFramesCompleted++;
ATRACE_INT("GPU Frames Outstanding", int32_t(mQueue.size()));
}
- return true;
}
uint32_t mFramesQueued;
uint32_t mFramesCompleted;
- Vector<EGLSyncKHR> mQueue;
- Condition mCondition;
- Mutex mMutex;
+ std::deque<EGLSyncKHR> mQueue;
+ std::condition_variable mCondition;
+ std::mutex mMutex;
};
EGLBoolean eglSwapBuffersWithDamageKHR(EGLDisplay dpy, EGLSurface draw,
@@ -1119,7 +1139,7 @@
return s->cnx->egl.eglSwapBuffers(dp->disp.dpy, s->surface);
}
- Vector<android_native_rect_t> androidRects;
+ std::vector<android_native_rect_t> androidRects((size_t)n_rects);
for (int r = 0; r < n_rects; ++r) {
int offset = r * 4;
int x = rects[offset];
@@ -1133,8 +1153,7 @@
androidRect.bottom = y;
androidRects.push_back(androidRect);
}
- native_window_set_surface_damage(s->win.get(), androidRects.array(),
- androidRects.size());
+ native_window_set_surface_damage(s->getNativeWindow(), androidRects.data(), androidRects.size());
if (s->cnx->egl.eglSwapBuffersWithDamageKHR) {
return s->cnx->egl.eglSwapBuffersWithDamageKHR(dp->disp.dpy, s->surface,
@@ -1238,19 +1257,19 @@
egl_surface_t * const s = get_surface(surface);
if (attribute == EGL_FRONT_BUFFER_AUTO_REFRESH_ANDROID) {
- if (!s->win.get()) {
+ if (!s->getNativeWindow()) {
setError(EGL_BAD_SURFACE, EGL_FALSE);
}
- int err = native_window_set_auto_refresh(s->win.get(), value ? true : false);
- return (err == NO_ERROR) ? EGL_TRUE : setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
+ int err = native_window_set_auto_refresh(s->getNativeWindow(), value != 0);
+ return (err == 0) ? EGL_TRUE : setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
}
if (attribute == EGL_TIMESTAMPS_ANDROID) {
- if (!s->win.get()) {
+ if (!s->getNativeWindow()) {
return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
}
- int err = native_window_enable_frame_timestamps(s->win.get(), value ? true : false);
- return (err == NO_ERROR) ? EGL_TRUE : setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
+ int err = native_window_enable_frame_timestamps(s->getNativeWindow(), value != 0);
+ return (err == 0) ? EGL_TRUE : setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
}
if (s->cnx->egl.eglSurfaceAttrib) {
@@ -1825,7 +1844,7 @@
}
egl_surface_t const * const s = get_surface(surface);
- native_window_set_buffers_timestamp(s->win.get(), time);
+ native_window_set_buffers_timestamp(s->getNativeWindow(), time);
return EGL_TRUE;
}
@@ -1920,14 +1939,14 @@
egl_surface_t const * const s = get_surface(surface);
- if (!s->win.get()) {
+ if (!s->getNativeWindow()) {
return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
}
uint64_t nextFrameId = 0;
- status_t ret = native_window_get_next_frame_id(s->win.get(), &nextFrameId);
+ int ret = native_window_get_next_frame_id(s->getNativeWindow(), &nextFrameId);
- if (ret != NO_ERROR) {
+ if (ret != 0) {
// This should not happen. Return an error that is not in the spec
// so it's obvious something is very wrong.
ALOGE("eglGetNextFrameId: Unexpected error.");
@@ -1955,7 +1974,7 @@
egl_surface_t const * const s = get_surface(surface);
- if (!s->win.get()) {
+ if (!s->getNativeWindow()) {
return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
}
@@ -1979,13 +1998,13 @@
}
}
- status_t ret = native_window_get_compositor_timing(s->win.get(),
+ int ret = native_window_get_compositor_timing(s->getNativeWindow(),
compositeDeadline, compositeInterval, compositeToPresentLatency);
switch (ret) {
- case NO_ERROR:
+ case 0:
return EGL_TRUE;
- case INVALID_OPERATION:
+ case -ENOSYS:
return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
default:
// This should not happen. Return an error that is not in the spec
@@ -2012,7 +2031,7 @@
egl_surface_t const * const s = get_surface(surface);
- ANativeWindow* window = s->win.get();
+ ANativeWindow* window = s->getNativeWindow();
if (!window) {
return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
}
@@ -2045,7 +2064,7 @@
egl_surface_t const * const s = get_surface(surface);
- if (!s->win.get()) {
+ if (!s->getNativeWindow()) {
return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
}
@@ -2097,19 +2116,19 @@
}
}
- status_t ret = native_window_get_frame_timestamps(s->win.get(), frameId,
+ int ret = native_window_get_frame_timestamps(s->getNativeWindow(), frameId,
requestedPresentTime, acquireTime, latchTime, firstRefreshStartTime,
lastRefreshStartTime, gpuCompositionDoneTime, displayPresentTime,
displayRetireTime, dequeueReadyTime, releaseTime);
switch (ret) {
- case NO_ERROR:
+ case 0:
return EGL_TRUE;
- case NAME_NOT_FOUND:
+ case -ENOENT:
return setError(EGL_BAD_ACCESS, (EGLBoolean)EGL_FALSE);
- case INVALID_OPERATION:
+ case -ENOSYS:
return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
- case BAD_VALUE:
+ case -EINVAL:
return setError(EGL_BAD_PARAMETER, (EGLBoolean)EGL_FALSE);
default:
// This should not happen. Return an error that is not in the spec
@@ -2136,7 +2155,7 @@
egl_surface_t const * const s = get_surface(surface);
- ANativeWindow* window = s->win.get();
+ ANativeWindow* window = s->getNativeWindow();
if (!window) {
return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
}
diff --git a/opengl/libs/EGL/egl_cache.cpp b/opengl/libs/EGL/egl_cache.cpp
index e46716c..dc1a4af 100644
--- a/opengl/libs/EGL/egl_cache.cpp
+++ b/opengl/libs/EGL/egl_cache.cpp
@@ -20,11 +20,16 @@
#include "egl_display.h"
+
+#include <private/EGL/cache.h>
+
#include <inttypes.h>
#include <sys/mman.h>
#include <sys/stat.h>
-#include <utils/Thread.h>
+#include <thread>
+
+#include <log/log.h>
// Cache size limits.
static const size_t maxKeySize = 12 * 1024;
@@ -44,6 +49,11 @@
#define BC_EXT_STR "EGL_ANDROID_blob_cache"
+// called from android_view_ThreadedRenderer.cpp
+void egl_set_cache_filename(const char* filename) {
+ egl_cache_t::get()->setCacheFilename(filename);
+}
+
//
// Callback functions passed to EGL.
//
@@ -61,8 +71,7 @@
// egl_cache_t definition
//
egl_cache_t::egl_cache_t() :
- mInitialized(false),
- mBlobCache(NULL) {
+ mInitialized(false) {
}
egl_cache_t::~egl_cache_t() {
@@ -75,7 +84,7 @@
}
void egl_cache_t::initialize(egl_display_t *display) {
- Mutex::Autolock lock(mMutex);
+ std::lock_guard<std::mutex> lock(mMutex);
egl_connection_t* const cnx = &gEGLImpl;
if (cnx->dso && cnx->major >= 0 && cnx->minor >= 0) {
@@ -113,14 +122,14 @@
}
void egl_cache_t::terminate() {
- Mutex::Autolock lock(mMutex);
+ std::lock_guard<std::mutex> lock(mMutex);
saveBlobCacheLocked();
mBlobCache = NULL;
}
void egl_cache_t::setBlob(const void* key, EGLsizeiANDROID keySize,
const void* value, EGLsizeiANDROID valueSize) {
- Mutex::Autolock lock(mMutex);
+ std::lock_guard<std::mutex> lock(mMutex);
if (keySize < 0 || valueSize < 0) {
ALOGW("EGL_ANDROID_blob_cache set: negative sizes are not allowed");
@@ -128,38 +137,27 @@
}
if (mInitialized) {
- sp<BlobCache> bc = getBlobCacheLocked();
+ BlobCache* bc = getBlobCacheLocked();
bc->set(key, keySize, value, valueSize);
if (!mSavePending) {
- class DeferredSaveThread : public Thread {
- public:
- DeferredSaveThread() : Thread(false) {}
-
- virtual bool threadLoop() {
- sleep(deferredSaveDelay);
- egl_cache_t* c = egl_cache_t::get();
- Mutex::Autolock lock(c->mMutex);
- if (c->mInitialized) {
- c->saveBlobCacheLocked();
- }
- c->mSavePending = false;
- return false;
- }
- };
-
- // The thread will hold a strong ref to itself until it has finished
- // running, so there's no need to keep a ref around.
- sp<Thread> deferredSaveThread(new DeferredSaveThread());
mSavePending = true;
- deferredSaveThread->run("DeferredSaveThread");
+ std::thread deferredSaveThread([this]() {
+ sleep(deferredSaveDelay);
+ std::lock_guard<std::mutex> lock(mMutex);
+ if (mInitialized) {
+ saveBlobCacheLocked();
+ }
+ mSavePending = false;
+ });
+ deferredSaveThread.detach();
}
}
}
EGLsizeiANDROID egl_cache_t::getBlob(const void* key, EGLsizeiANDROID keySize,
void* value, EGLsizeiANDROID valueSize) {
- Mutex::Autolock lock(mMutex);
+ std::lock_guard<std::mutex> lock(mMutex);
if (keySize < 0 || valueSize < 0) {
ALOGW("EGL_ANDROID_blob_cache set: negative sizes are not allowed");
@@ -167,23 +165,23 @@
}
if (mInitialized) {
- sp<BlobCache> bc = getBlobCacheLocked();
+ BlobCache* bc = getBlobCacheLocked();
return bc->get(key, keySize, value, valueSize);
}
return 0;
}
void egl_cache_t::setCacheFilename(const char* filename) {
- Mutex::Autolock lock(mMutex);
+ std::lock_guard<std::mutex> lock(mMutex);
mFilename = filename;
}
-sp<BlobCache> egl_cache_t::getBlobCacheLocked() {
- if (mBlobCache == NULL) {
- mBlobCache = new BlobCache(maxKeySize, maxValueSize, maxTotalSize);
+BlobCache* egl_cache_t::getBlobCacheLocked() {
+ if (mBlobCache == nullptr) {
+ mBlobCache.reset(new BlobCache(maxKeySize, maxValueSize, maxTotalSize));
loadBlobCacheLocked();
}
- return mBlobCache;
+ return mBlobCache.get();
}
static uint32_t crc32c(const uint8_t* buf, size_t len) {
@@ -206,7 +204,7 @@
if (mFilename.length() > 0 && mBlobCache != NULL) {
size_t cacheSize = mBlobCache->getFlattenedSize();
size_t headerSize = cacheFileHeaderSize;
- const char* fname = mFilename.string();
+ const char* fname = mFilename.c_str();
// Try to create the file with no permissions so we can write it
// without anyone trying to read it.
@@ -241,8 +239,8 @@
return;
}
- status_t err = mBlobCache->flatten(buf + headerSize, cacheSize);
- if (err != OK) {
+ int err = mBlobCache->flatten(buf + headerSize, cacheSize);
+ if (err < 0) {
ALOGE("error writing cache contents: %s (%d)", strerror(-err),
-err);
delete [] buf;
@@ -275,10 +273,10 @@
if (mFilename.length() > 0) {
size_t headerSize = cacheFileHeaderSize;
- int fd = open(mFilename.string(), O_RDONLY, 0);
+ int fd = open(mFilename.c_str(), O_RDONLY, 0);
if (fd == -1) {
if (errno != ENOENT) {
- ALOGE("error opening cache file %s: %s (%d)", mFilename.string(),
+ ALOGE("error opening cache file %s: %s (%d)", mFilename.c_str(),
strerror(errno), errno);
}
return;
@@ -323,8 +321,8 @@
return;
}
- status_t err = mBlobCache->unflatten(buf + headerSize, cacheSize);
- if (err != OK) {
+ int err = mBlobCache->unflatten(buf + headerSize, cacheSize);
+ if (err < 0) {
ALOGE("error reading cache contents: %s (%d)", strerror(-err),
-err);
munmap(buf, fileSize);
diff --git a/opengl/libs/EGL/egl_cache.h b/opengl/libs/EGL/egl_cache.h
index e7f1712..56360f0 100644
--- a/opengl/libs/EGL/egl_cache.h
+++ b/opengl/libs/EGL/egl_cache.h
@@ -20,10 +20,11 @@
#include <EGL/egl.h>
#include <EGL/eglext.h>
-#include <utils/BlobCache.h>
-#include <utils/Mutex.h>
-#include <utils/String8.h>
-#include <utils/StrongPointer.h>
+#include "BlobCache.h"
+
+#include <memory>
+#include <mutex>
+#include <string>
// ----------------------------------------------------------------------------
namespace android {
@@ -79,7 +80,7 @@
// key/value blob pairs. If the BlobCache object has not yet been created,
// this will do so, loading the serialized cache contents from disk if
// possible.
- sp<BlobCache> getBlobCacheLocked();
+ BlobCache* getBlobCacheLocked();
// saveBlobCache attempts to save the current contents of mBlobCache to
// disk.
@@ -100,14 +101,14 @@
// mBlobCache is the cache in which the key/value blob pairs are stored. It
// is initially NULL, and will be initialized by getBlobCacheLocked the
// first time it's needed.
- sp<BlobCache> mBlobCache;
+ std::unique_ptr<BlobCache> mBlobCache;
// mFilename is the name of the file for storing cache contents in between
// program invocations. It is initialized to an empty string at
// construction time, and can be set with the setCacheFilename method. An
// empty string indicates that the cache should not be saved to or restored
// from disk.
- String8 mFilename;
+ std::string mFilename;
// mSavePending indicates whether or not a deferred save operation is
// pending. Each time a key/value pair is inserted into the cache via
@@ -118,7 +119,7 @@
// mMutex is the mutex used to prevent concurrent access to the member
// variables. It must be locked whenever the member variables are accessed.
- mutable Mutex mMutex;
+ mutable std::mutex mMutex;
// sCache is the singleton egl_cache_t object.
static egl_cache_t sCache;
diff --git a/opengl/libs/EGL/egl_display.cpp b/opengl/libs/EGL/egl_display.cpp
index c804fa7..b696920 100644
--- a/opengl/libs/EGL/egl_display.cpp
+++ b/opengl/libs/EGL/egl_display.cpp
@@ -21,14 +21,15 @@
#include "../egl_impl.h"
+#include <private/EGL/display.h>
+
#include "egl_cache.h"
#include "egl_object.h"
#include "egl_tls.h"
+#include "egl_trace.h"
#include "Loader.h"
#include <cutils/properties.h>
-#include <utils/Trace.h>
-
// ----------------------------------------------------------------------------
namespace android {
// ----------------------------------------------------------------------------
@@ -55,6 +56,11 @@
return false;
}
+int egl_get_init_count(EGLDisplay dpy) {
+ egl_display_t* eglDisplay = egl_display_t::get(dpy);
+ return eglDisplay ? eglDisplay->getRefsCount() : 0;
+}
+
egl_display_t egl_display_t::sDisplay[NUM_DISPLAYS];
egl_display_t::egl_display_t() :
@@ -75,18 +81,18 @@
}
void egl_display_t::addObject(egl_object_t* object) {
- Mutex::Autolock _l(lock);
- objects.add(object);
+ std::lock_guard<std::mutex> _l(lock);
+ objects.insert(object);
}
void egl_display_t::removeObject(egl_object_t* object) {
- Mutex::Autolock _l(lock);
- objects.remove(object);
+ std::lock_guard<std::mutex> _l(lock);
+ objects.erase(object);
}
bool egl_display_t::getObject(egl_object_t* object) const {
- Mutex::Autolock _l(lock);
- if (objects.indexOf(object) >= 0) {
+ std::lock_guard<std::mutex> _l(lock);
+ if (objects.find(object) != objects.end()) {
if (object->getDisplay() == this) {
object->incRef();
return true;
@@ -104,7 +110,7 @@
EGLDisplay egl_display_t::getDisplay(EGLNativeDisplayType display) {
- Mutex::Autolock _l(lock);
+ std::lock_guard<std::mutex> _l(lock);
ATRACE_CALL();
// get our driver loader
@@ -125,24 +131,26 @@
EGLBoolean egl_display_t::initialize(EGLint *major, EGLint *minor) {
- {
- Mutex::Autolock _rf(refLock);
-
+ { // scope for refLock
+ std::unique_lock<std::mutex> _l(refLock);
refs++;
if (refs > 1) {
if (major != NULL)
*major = VERSION_MAJOR;
if (minor != NULL)
*minor = VERSION_MINOR;
- while(!eglIsInitialized) refCond.wait(refLock);
+ while(!eglIsInitialized) {
+ refCond.wait(_l);
+ }
return EGL_TRUE;
}
-
- while(eglIsInitialized) refCond.wait(refLock);
+ while(eglIsInitialized) {
+ refCond.wait(_l);
+ }
}
- {
- Mutex::Autolock _l(lock);
+ { // scope for lock
+ std::lock_guard<std::mutex> _l(lock);
setGLHooksThreadSpecific(&gHooksNoContext);
@@ -179,20 +187,19 @@
}
// the query strings are per-display
- mVendorString.setTo(sVendorString);
- mVersionString.setTo(sVersionString);
- mClientApiString.setTo(sClientApiString);
+ mVendorString = sVendorString;
+ mVersionString = sVersionString;
+ mClientApiString = sClientApiString;
- mExtensionString.setTo(gBuiltinExtensionString);
+ mExtensionString = gBuiltinExtensionString;
char const* start = gExtensionString;
do {
// length of the extension name
size_t len = strcspn(start, " ");
if (len) {
// NOTE: we could avoid the copy if we had strnstr.
- const String8 ext(start, len);
- if (findExtension(disp.queryString.extensions, ext.string(),
- len)) {
+ const std::string ext(start, len);
+ if (findExtension(disp.queryString.extensions, ext.c_str(), len)) {
mExtensionString.append(ext + " ");
}
// advance to the next extension name, skipping the space.
@@ -220,10 +227,10 @@
*minor = VERSION_MINOR;
}
- {
- Mutex::Autolock _rf(refLock);
+ { // scope for refLock
+ std::unique_lock<std::mutex> _l(refLock);
eglIsInitialized = true;
- refCond.broadcast();
+ refCond.notify_all();
}
return EGL_TRUE;
@@ -231,8 +238,8 @@
EGLBoolean egl_display_t::terminate() {
- {
- Mutex::Autolock _rl(refLock);
+ { // scope for refLock
+ std::unique_lock<std::mutex> _rl(refLock);
if (refs == 0) {
/*
* From the EGL spec (3.2):
@@ -252,8 +259,8 @@
EGLBoolean res = EGL_FALSE;
- {
- Mutex::Autolock _l(lock);
+ { // scope for lock
+ std::lock_guard<std::mutex> _l(lock);
egl_connection_t* const cnx = &gEGLImpl;
if (cnx->dso && disp.state == egl_display_t::INITIALIZED) {
@@ -268,15 +275,14 @@
// Reset the extension string since it will be regenerated if we get
// reinitialized.
- mExtensionString.setTo("");
+ mExtensionString.clear();
// Mark all objects remaining in the list as terminated, unless
// there are no reference to them, it which case, we're free to
// delete them.
size_t count = objects.size();
ALOGW_IF(count, "eglTerminate() called w/ %zu objects remaining", count);
- for (size_t i=0 ; i<count ; i++) {
- egl_object_t* o = objects.itemAt(i);
+ for (auto o : objects) {
o->destroy();
}
@@ -284,10 +290,10 @@
objects.clear();
}
- {
- Mutex::Autolock _rl(refLock);
+ { // scope for refLock
+ std::unique_lock<std::mutex> _rl(refLock);
eglIsInitialized = false;
- refCond.broadcast();
+ refCond.notify_all();
}
return res;
@@ -312,7 +318,7 @@
SurfaceRef _cur_d(cur_c ? get_surface(cur_c->draw) : NULL);
{ // scope for the lock
- Mutex::Autolock _l(lock);
+ std::lock_guard<std::mutex> _l(lock);
cur_c->onLooseCurrent();
}
@@ -338,7 +344,7 @@
SurfaceRef _cur_d(cur_c ? get_surface(cur_c->draw) : NULL);
{ // scope for the lock
- Mutex::Autolock _l(lock);
+ std::lock_guard<std::mutex> _l(lock);
if (c) {
result = c->cnx->egl.eglMakeCurrent(
disp.dpy, impl_draw, impl_read, impl_ctx);
@@ -370,7 +376,7 @@
if (!nameLen) {
nameLen = strlen(name);
}
- return findExtension(mExtensionString.string(), name, nameLen);
+ return findExtension(mExtensionString.c_str(), name, nameLen);
}
// ----------------------------------------------------------------------------
diff --git a/opengl/libs/EGL/egl_display.h b/opengl/libs/EGL/egl_display.h
index f5e7294..661f47e 100644
--- a/opengl/libs/EGL/egl_display.h
+++ b/opengl/libs/EGL/egl_display.h
@@ -21,14 +21,15 @@
#include <stdint.h>
#include <stddef.h>
+#include <condition_variable>
+#include <mutex>
+#include <string>
+#include <unordered_set>
+
#include <EGL/egl.h>
#include <EGL/eglext.h>
#include <cutils/compiler.h>
-#include <utils/SortedVector.h>
-#include <utils/Condition.h>
-#include <utils/Mutex.h>
-#include <utils/String8.h>
#include "egldefs.h"
#include "../hooks.h"
@@ -80,10 +81,10 @@
inline bool isValid() const { return magic == '_dpy'; }
inline bool isAlive() const { return isValid(); }
- char const * getVendorString() const { return mVendorString.string(); }
- char const * getVersionString() const { return mVersionString.string(); }
- char const * getClientApiString() const { return mClientApiString.string(); }
- char const * getExtensionString() const { return mExtensionString.string(); }
+ char const * getVendorString() const { return mVendorString.c_str(); }
+ char const * getVersionString() const { return mVersionString.c_str(); }
+ char const * getClientApiString() const { return mClientApiString.c_str(); }
+ char const * getExtensionString() const { return mExtensionString.c_str(); }
bool haveExtension(const char* name, size_t nameLen = 0) const;
@@ -116,13 +117,14 @@
uint32_t refs;
bool eglIsInitialized;
- mutable Mutex lock, refLock;
- mutable Condition refCond;
- SortedVector<egl_object_t*> objects;
- String8 mVendorString;
- String8 mVersionString;
- String8 mClientApiString;
- String8 mExtensionString;
+ mutable std::mutex lock;
+ mutable std::mutex refLock;
+ mutable std::condition_variable refCond;
+ std::unordered_set<egl_object_t*> objects;
+ std::string mVendorString;
+ std::string mVersionString;
+ std::string mClientApiString;
+ std::string mExtensionString;
};
// ----------------------------------------------------------------------------
diff --git a/opengl/libs/EGL/egl_object.cpp b/opengl/libs/EGL/egl_object.cpp
index b553d71..7ed34be 100644
--- a/opengl/libs/EGL/egl_object.cpp
+++ b/opengl/libs/EGL/egl_object.cpp
@@ -60,21 +60,24 @@
egl_connection_t const* cnx) :
egl_object_t(dpy), surface(surface), config(config), win(win), cnx(cnx),
connected(true)
-{}
+{
+ if (win) {
+ win->incStrong(this);
+ }
+}
egl_surface_t::~egl_surface_t() {
- ANativeWindow* const window = win.get();
- if (window != NULL) {
+ if (win != NULL) {
disconnect();
+ win->decStrong(this);
}
}
void egl_surface_t::disconnect() {
- ANativeWindow* const window = win.get();
- if (window != NULL && connected) {
- native_window_set_buffers_format(window, 0);
- if (native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL)) {
- ALOGW("EGLNativeWindowType %p disconnect failed", window);
+ if (win != NULL && connected) {
+ native_window_set_buffers_format(win, 0);
+ if (native_window_api_disconnect(win, NATIVE_WINDOW_API_EGL)) {
+ ALOGW("EGLNativeWindowType %p disconnect failed", win);
}
connected = false;
}
@@ -107,22 +110,20 @@
* add the extensions always handled by the wrapper
*/
- if (gl_extensions.isEmpty()) {
+ if (gl_extensions.empty()) {
// call the implementation's glGetString(GL_EXTENSIONS)
const char* exts = (const char *)gEGLImpl.hooks[version]->gl.glGetString(GL_EXTENSIONS);
- gl_extensions.setTo(exts);
- if (gl_extensions.find("GL_EXT_debug_marker") < 0) {
- String8 temp("GL_EXT_debug_marker ");
- temp.append(gl_extensions);
- gl_extensions.setTo(temp);
+ gl_extensions = exts;
+ if (gl_extensions.find("GL_EXT_debug_marker") != std::string::npos) {
+ gl_extensions.insert(0, "GL_EXT_debug_marker ");
}
// tokenize the supported extensions for the glGetStringi() wrapper
std::stringstream ss;
std::string str;
- ss << gl_extensions.string();
+ ss << gl_extensions;
while (ss >> str) {
- tokenized_gl_extensions.push(String8(str.c_str()));
+ tokenized_gl_extensions.push_back(str);
}
}
}
diff --git a/opengl/libs/EGL/egl_object.h b/opengl/libs/EGL/egl_object.h
index f4012ab..8988905 100644
--- a/opengl/libs/EGL/egl_object.h
+++ b/opengl/libs/EGL/egl_object.h
@@ -17,18 +17,20 @@
#ifndef ANDROID_EGL_OBJECT_H
#define ANDROID_EGL_OBJECT_H
+#include <atomic>
#include <stdint.h>
#include <stddef.h>
+#include <string>
+#include <vector>
+
#include <EGL/egl.h>
#include <EGL/eglext.h>
-#include <utils/StrongPointer.h>
-#include <utils/String8.h>
-#include <utils/Vector.h>
-
#include <system/window.h>
+#include <log/log.h>
+
#include "egl_display.h"
// ----------------------------------------------------------------------------
@@ -133,9 +135,16 @@
EGLNativeWindowType win, EGLSurface surface,
egl_connection_t const* cnx);
+ ANativeWindow* getNativeWindow() { return win; }
+ ANativeWindow* getNativeWindow() const { return win; }
+
+ // Try to keep the order of these fields and size unchanged. It's not public API, but
+ // it's not hard to imagine native games accessing them.
EGLSurface surface;
EGLConfig config;
- sp<ANativeWindow> win;
+private:
+ ANativeWindow* win;
+public:
egl_connection_t const* cnx;
private:
bool connected;
@@ -161,8 +170,8 @@
EGLSurface draw;
egl_connection_t const* cnx;
int version;
- String8 gl_extensions;
- Vector<String8> tokenized_gl_extensions;
+ std::string gl_extensions;
+ std::vector<std::string> tokenized_gl_extensions;
};
// ----------------------------------------------------------------------------
diff --git a/opengl/libs/EGL/egl_trace.h b/opengl/libs/EGL/egl_trace.h
new file mode 100644
index 0000000..7664de2
--- /dev/null
+++ b/opengl/libs/EGL/egl_trace.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#if defined(__ANDROID__)
+
+#include <stdint.h>
+
+#include <cutils/trace.h>
+
+// See <cutils/trace.h> for more ATRACE_* macros.
+
+// ATRACE_NAME traces from its location until the end of its enclosing scope.
+#define _PASTE(x, y) x ## y
+#define PASTE(x, y) _PASTE(x,y)
+#define ATRACE_NAME(name) android::EglScopedTrace PASTE(___tracer, __LINE__) (ATRACE_TAG, name)
+
+// ATRACE_CALL is an ATRACE_NAME that uses the current function name.
+#define ATRACE_CALL() ATRACE_NAME(__FUNCTION__)
+
+namespace android {
+
+class EglScopedTrace {
+public:
+ inline EglScopedTrace(uint64_t tag, const char* name) : mTag(tag) {
+ atrace_begin(mTag, name);
+ }
+
+ inline ~EglScopedTrace() {
+ atrace_end(mTag);
+ }
+
+private:
+ uint64_t mTag;
+};
+
+}; // namespace android
+
+#else // !__ANDROID__
+
+#define ATRACE_NAME(...)
+#define ATRACE_CALL()
+
+#endif // __ANDROID__
diff --git a/opengl/libs/EGL/include/private/EGL/cache.h b/opengl/libs/EGL/include/private/EGL/cache.h
new file mode 100644
index 0000000..0a176a8
--- /dev/null
+++ b/opengl/libs/EGL/include/private/EGL/cache.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <cutils/compiler.h>
+
+namespace android {
+
+ANDROID_API void egl_set_cache_filename(const char* filename);
+
+} // namespace android
diff --git a/opengl/libs/EGL/include/private/EGL/display.h b/opengl/libs/EGL/include/private/EGL/display.h
new file mode 100644
index 0000000..9560de2
--- /dev/null
+++ b/opengl/libs/EGL/include/private/EGL/display.h
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <EGL/egl.h>
+
+#include <cutils/compiler.h>
+
+namespace android {
+
+ANDROID_API int egl_get_init_count(EGLDisplay dpy);
+
+} // namespace android
diff --git a/services/surfaceflinger/Android.mk b/services/surfaceflinger/Android.mk
index 89779af..1c1db74 100644
--- a/services/surfaceflinger/Android.mk
+++ b/services/surfaceflinger/Android.mk
@@ -25,6 +25,7 @@
DisplayHardware/ComposerHal.cpp \
DisplayHardware/FramebufferSurface.cpp \
DisplayHardware/HWC2.cpp \
+ DisplayHardware/HWComposerBufferCache.cpp \
DisplayHardware/PowerHAL.cpp \
DisplayHardware/VirtualDisplaySurface.cpp \
Effects/Daltonizer.cpp \
@@ -83,39 +84,6 @@
LOCAL_CFLAGS += -DRUNNING_WITHOUT_SYNC_FRAMEWORK
endif
-# The following two BoardConfig variables define (respectively):
-#
-# - The phase offset between hardware vsync and when apps are woken up by the
-# Choreographer callback
-# - The phase offset between hardware vsync and when SurfaceFlinger wakes up
-# to consume input
-#
-# Their values can be tuned to trade off between display pipeline latency (both
-# overall latency and the lengths of the app --> SF and SF --> display phases)
-# and frame delivery jitter (which typically manifests as "jank" or "jerkiness"
-# while interacting with the device). The default values should produce a
-# relatively low amount of jitter at the expense of roughly two frames of
-# app --> display latency, and unless significant testing is performed to avoid
-# increased display jitter (both manual investigation using systrace [1] and
-# automated testing using dumpsys gfxinfo [2] are recommended), they should not
-# be modified.
-#
-# [1] https://developer.android.com/studio/profile/systrace.html
-# [2] https://developer.android.com/training/testing/performance.html
-
-# These are left just for non-treble devices
-ifneq ($(VSYNC_EVENT_PHASE_OFFSET_NS),)
- LOCAL_CFLAGS += -DVSYNC_EVENT_PHASE_OFFSET_NS=$(VSYNC_EVENT_PHASE_OFFSET_NS)
-else
- LOCAL_CFLAGS += -DVSYNC_EVENT_PHASE_OFFSET_NS=1000000
-endif
-
-ifneq ($(SF_VSYNC_EVENT_PHASE_OFFSET_NS),)
- LOCAL_CFLAGS += -DSF_VSYNC_EVENT_PHASE_OFFSET_NS=$(SF_VSYNC_EVENT_PHASE_OFFSET_NS)
-else
- LOCAL_CFLAGS += -DSF_VSYNC_EVENT_PHASE_OFFSET_NS=1000000
-endif
-
ifneq ($(PRESENT_TIME_OFFSET_FROM_VSYNC_NS),)
LOCAL_CFLAGS += -DPRESENT_TIME_OFFSET_FROM_VSYNC_NS=$(PRESENT_TIME_OFFSET_FROM_VSYNC_NS)
else
diff --git a/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp b/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp
index d384bb1..92a7794 100644
--- a/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp
+++ b/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp
@@ -137,7 +137,7 @@
status_t err = acquireBufferLocked(&item, 0);
if (err == BufferQueue::NO_BUFFER_AVAILABLE) {
#ifdef USE_HWC2
- mHwcBufferCache->getHwcBuffer(mCurrentBufferSlot, mCurrentBuffer,
+ mHwcBufferCache.getHwcBuffer(mCurrentBufferSlot, mCurrentBuffer,
&outSlot, &outBuffer);
#else
outBuffer = mCurrentBuffer;
@@ -178,7 +178,7 @@
outFence = item.mFence;
#ifdef USE_HWC2
- mHwcBufferCache->getHwcBuffer(mCurrentBufferSlot, mCurrentBuffer,
+ mHwcBufferCache.getHwcBuffer(mCurrentBufferSlot, mCurrentBuffer,
&outSlot, &outBuffer);
outDataspace = item.mDataSpace;
#else
diff --git a/services/surfaceflinger/DisplayHardware/FramebufferSurface.h b/services/surfaceflinger/DisplayHardware/FramebufferSurface.h
index 5eea6b6..69a72d7 100644
--- a/services/surfaceflinger/DisplayHardware/FramebufferSurface.h
+++ b/services/surfaceflinger/DisplayHardware/FramebufferSurface.h
@@ -18,14 +18,13 @@
#define ANDROID_SF_FRAMEBUFFER_SURFACE_H
#include "DisplaySurface.h"
+#include "HWComposerBufferCache.h"
#include <stdint.h>
#include <sys/types.h>
#include <gui/ConsumerBase.h>
-#include <memory>
-
// ---------------------------------------------------------------------------
namespace android {
// ---------------------------------------------------------------------------
@@ -33,7 +32,6 @@
class Rect;
class String8;
class HWComposer;
-class HWComposerBufferCache;
// ---------------------------------------------------------------------------
@@ -96,8 +94,7 @@
HWComposer& mHwc;
#ifdef USE_HWC2
- std::unique_ptr<HWComposerBufferCache> mHwcBufferCache =
- std::make_unique<HWComposerBufferCache>();
+ HWComposerBufferCache mHwcBufferCache;
// Previous buffer to release after getting an updated retire fence
bool mHasPendingRelease;
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
index e1138af..6644bd9 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
@@ -925,41 +925,5 @@
*this = DisplayData();
}
-void HWComposerBufferCache::clear()
-{
- mBuffers.clear();
-}
-
-void HWComposerBufferCache::getHwcBuffer(int slot,
- const sp<GraphicBuffer>& buffer,
- uint32_t* outSlot, sp<GraphicBuffer>* outBuffer)
-{
-#ifdef BYPASS_IHWC
- *outSlot = slot;
- *outBuffer = buffer;
-#else
- if (slot == BufferQueue::INVALID_BUFFER_SLOT || slot < 0) {
- // default to slot 0
- slot = 0;
- }
-
- if (static_cast<size_t>(slot) >= mBuffers.size()) {
- mBuffers.resize(slot + 1);
- }
-
- *outSlot = slot;
-
- if (mBuffers[slot] == buffer) {
- // already cached in HWC, skip sending the buffer
- *outBuffer = nullptr;
- } else {
- *outBuffer = buffer;
-
- // update cache
- mBuffers[slot] = buffer;
- }
-#endif
-}
-
// ---------------------------------------------------------------------------
}; // namespace android
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h
index 20cca39..117db4a 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.h
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.h
@@ -26,8 +26,6 @@
#include <stdint.h>
#include <sys/types.h>
-#include <gui/BufferQueue.h>
-
#include <ui/Fence.h>
#include <utils/BitSet.h>
@@ -236,19 +234,6 @@
mutable std::atomic<bool> mDumpMayLockUp;
};
-class HWComposerBufferCache {
-public:
- void clear();
-
- void getHwcBuffer(int slot, const sp<GraphicBuffer>& buffer,
- uint32_t* outSlot, sp<GraphicBuffer>* outBuffer);
-
-private:
- // a vector as we expect "slot" to be in the range of [0, 63] (that is,
- // less than BufferQueue::NUM_BUFFER_SLOTS).
- std::vector<sp<GraphicBuffer>> mBuffers;
-};
-
// ---------------------------------------------------------------------------
}; // namespace android
diff --git a/services/surfaceflinger/DisplayHardware/HWComposerBufferCache.cpp b/services/surfaceflinger/DisplayHardware/HWComposerBufferCache.cpp
new file mode 100644
index 0000000..6b91224
--- /dev/null
+++ b/services/surfaceflinger/DisplayHardware/HWComposerBufferCache.cpp
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "HWComposerBufferCache.h"
+
+#include <gui/BufferQueue.h>
+
+namespace android {
+
+HWComposerBufferCache::HWComposerBufferCache()
+{
+ mBuffers.reserve(BufferQueue::NUM_BUFFER_SLOTS);
+}
+
+void HWComposerBufferCache::getHwcBuffer(int slot,
+ const sp<GraphicBuffer>& buffer,
+ uint32_t* outSlot, sp<GraphicBuffer>* outBuffer)
+{
+#ifdef BYPASS_IHWC
+ *outSlot = slot;
+ *outBuffer = buffer;
+#else
+ if (slot == BufferQueue::INVALID_BUFFER_SLOT || slot < 0) {
+ // default to slot 0
+ slot = 0;
+ }
+
+ if (static_cast<size_t>(slot) >= mBuffers.size()) {
+ mBuffers.resize(slot + 1);
+ }
+
+ *outSlot = slot;
+
+ if (mBuffers[slot] == buffer) {
+ // already cached in HWC, skip sending the buffer
+ *outBuffer = nullptr;
+ } else {
+ *outBuffer = buffer;
+
+ // update cache
+ mBuffers[slot] = buffer;
+ }
+#endif
+}
+
+} // namespace android
diff --git a/services/surfaceflinger/DisplayHardware/HWComposerBufferCache.h b/services/surfaceflinger/DisplayHardware/HWComposerBufferCache.h
new file mode 100644
index 0000000..a008ca9
--- /dev/null
+++ b/services/surfaceflinger/DisplayHardware/HWComposerBufferCache.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_SF_HWCOMPOSERBUFFERCACHE_H
+#define ANDROID_SF_HWCOMPOSERBUFFERCACHE_H
+
+#include <stdint.h>
+
+#include <utils/StrongPointer.h>
+
+#include <vector>
+
+namespace android {
+// ---------------------------------------------------------------------------
+
+class GraphicBuffer;
+
+// With HIDLized hwcomposer HAL, the HAL can maintain a buffer cache for each
+// HWC display and layer. When updating a display target or a layer buffer,
+// we have the option to send the buffer handle over or to request the HAL to
+// retrieve it from its cache. The latter is cheaper since it eliminates the
+// overhead to transfer the handle over the trasport layer, and the overhead
+// for the HAL to clone and retain the handle.
+//
+// To be able to find out whether a buffer is already in the HAL's cache, we
+// use HWComposerBufferCache to mirror the cache in SF.
+class HWComposerBufferCache {
+public:
+ HWComposerBufferCache();
+
+ // Given a buffer queue slot and buffer, return the HWC cache slot and
+ // buffer to be sent to HWC.
+ //
+ // outBuffer is set to buffer when buffer is not in the HWC cache;
+ // otherwise, outBuffer is set to nullptr.
+ void getHwcBuffer(int slot, const sp<GraphicBuffer>& buffer,
+ uint32_t* outSlot, sp<GraphicBuffer>* outBuffer);
+
+private:
+ // a vector as we expect "slot" to be in the range of [0, 63] (that is,
+ // less than BufferQueue::NUM_BUFFER_SLOTS).
+ std::vector<sp<GraphicBuffer>> mBuffers;
+};
+
+// ---------------------------------------------------------------------------
+}; // namespace android
+
+#endif // ANDROID_SF_HWCOMPOSERBUFFERCACHE_H
diff --git a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
index c5a4f99..6f253ab 100644
--- a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
+++ b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
@@ -224,7 +224,7 @@
#ifdef USE_HWC2
uint32_t hwcSlot = 0;
sp<GraphicBuffer> hwcBuffer;
- mHwcBufferCache->getHwcBuffer(mFbProducerSlot, fbBuffer,
+ mHwcBufferCache.getHwcBuffer(mFbProducerSlot, fbBuffer,
&hwcSlot, &hwcBuffer);
// TODO: Correctly propagate the dataspace from GL composition
diff --git a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h
index fb5fcc8..ee2772a 100644
--- a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h
+++ b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h
@@ -18,18 +18,16 @@
#define ANDROID_SF_VIRTUAL_DISPLAY_SURFACE_H
#include "DisplaySurface.h"
+#include "HWComposerBufferCache.h"
#include <gui/ConsumerBase.h>
#include <gui/IGraphicBufferProducer.h>
-#include <memory>
-
// ---------------------------------------------------------------------------
namespace android {
// ---------------------------------------------------------------------------
class HWComposer;
-class HWComposerBufferCache;
class IProducerListener;
/* This DisplaySurface implementation supports virtual displays, where GLES
@@ -255,8 +253,7 @@
bool mMustRecompose;
#ifdef USE_HWC2
- std::unique_ptr<HWComposerBufferCache> mHwcBufferCache =
- std::make_unique<HWComposerBufferCache>();
+ HWComposerBufferCache mHwcBufferCache;
#endif
};
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 7a4ace9..51984b7 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -276,16 +276,6 @@
}
}
-void Layer::onBuffersReleased() {
-#ifdef USE_HWC2
- Mutex::Autolock lock(mHwcBufferCacheMutex);
-
- for (auto info : mHwcBufferCaches) {
- info.second.clear();
- }
-#endif
-}
-
void Layer::onSidebandStreamChanged() {
if (android_atomic_release_cas(false, true, &mSidebandStreamChanged) == 0) {
// mSidebandStreamChanged was false
@@ -780,7 +770,8 @@
const auto& viewport = displayDevice->getViewport();
Region visible = tr.transform(visibleRegion.intersect(viewport));
auto hwcId = displayDevice->getHwcDisplayId();
- auto& hwcLayer = mHwcLayers[hwcId].layer;
+ auto& hwcInfo = mHwcLayers[hwcId];
+ auto& hwcLayer = hwcInfo.layer;
auto error = hwcLayer->setVisibleRegion(visible);
if (error != HWC2::Error::None) {
ALOGE("[%s] Failed to set visible region: %s (%d)", mName.string(),
@@ -809,7 +800,7 @@
}
// Client layers
- if (mHwcLayers[hwcId].forceClientComposition ||
+ if (hwcInfo.forceClientComposition ||
(mActiveBuffer != nullptr && mActiveBuffer->handle == nullptr)) {
ALOGV("[%s] Requesting Client composition", mName.string());
setCompositionType(hwcId, HWC2::Composition::Client);
@@ -858,11 +849,8 @@
uint32_t hwcSlot = 0;
buffer_handle_t hwcHandle = nullptr;
{
- Mutex::Autolock lock(mHwcBufferCacheMutex);
-
- auto& hwcBufferCache = mHwcBufferCaches[hwcId];
sp<GraphicBuffer> hwcBuffer;
- hwcBufferCache.getHwcBuffer(mActiveBufferSlot, mActiveBuffer,
+ hwcInfo.bufferCache.getHwcBuffer(mActiveBufferSlot, mActiveBuffer,
&hwcSlot, &hwcBuffer);
if (hwcBuffer != nullptr) {
hwcHandle = hwcBuffer->handle;
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 0efdf54..6b228b0 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -47,6 +47,7 @@
#include "Transform.h"
#include "DisplayHardware/HWComposer.h"
+#include "DisplayHardware/HWComposerBufferCache.h"
#include "RenderEngine/Mesh.h"
#include "RenderEngine/Texture.h"
@@ -383,20 +384,13 @@
#ifdef USE_HWC2
// -----------------------------------------------------------------------
- void eraseHwcLayer(int32_t hwcId) {
- mHwcLayers.erase(hwcId);
-
- Mutex::Autolock lock(mHwcBufferCacheMutex);
- mHwcBufferCaches.erase(hwcId);
- }
-
bool hasHwcLayer(int32_t hwcId) {
if (mHwcLayers.count(hwcId) == 0) {
return false;
}
if (mHwcLayers[hwcId].layer->isAbandoned()) {
ALOGI("Erasing abandoned layer %s on %d", mName.string(), hwcId);
- eraseHwcLayer(hwcId);
+ mHwcLayers.erase(hwcId);
return false;
}
return true;
@@ -412,11 +406,8 @@
void setHwcLayer(int32_t hwcId, std::shared_ptr<HWC2::Layer>&& layer) {
if (layer) {
mHwcLayers[hwcId].layer = layer;
-
- Mutex::Autolock lock(mHwcBufferCacheMutex);
- mHwcBufferCaches[hwcId] = HWComposerBufferCache();
} else {
- eraseHwcLayer(hwcId);
+ mHwcLayers.erase(hwcId);
}
}
@@ -511,7 +502,6 @@
// Interface implementation for SurfaceFlingerConsumer::ContentsChangedListener
virtual void onFrameAvailable(const BufferItem& item) override;
virtual void onFrameReplaced(const BufferItem& item) override;
- virtual void onBuffersReleased() override;
virtual void onSidebandStreamChanged() override;
void commitTransaction(const State& stateToCommit);
@@ -703,6 +693,7 @@
bool clearClientTarget;
Rect displayFrame;
FloatRect sourceCrop;
+ HWComposerBufferCache bufferCache;
};
// A layer can be attached to multiple displays when operating in mirror mode
@@ -710,12 +701,6 @@
// case we need to keep track. In non-mirror mode, a layer will have only one
// HWCInfo. This map key is a display layerStack.
std::unordered_map<int32_t, HWCInfo> mHwcLayers;
-
- // We need one HWComposerBufferCache for each HWC display. We cannot have
- // HWComposerBufferCache in HWCInfo because HWCInfo can only be accessed
- // from the main thread.
- Mutex mHwcBufferCacheMutex;
- std::unordered_map<int32_t, HWComposerBufferCache> mHwcBufferCaches;
#else
bool mIsGlesComposition;
#endif
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 7dc2cab..ca6d941 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -101,33 +101,6 @@
using namespace android::hardware::configstore;
using namespace android::hardware::configstore::V1_0;
-// This is the phase offset in nanoseconds of the software vsync event
-// relative to the vsync event reported by HWComposer. The software vsync
-// event is when SurfaceFlinger and Choreographer-based applications run each
-// frame.
-//
-// This phase offset allows adjustment of the minimum latency from application
-// wake-up (by Choregographer) time to the time at which the resulting window
-// image is displayed. This value may be either positive (after the HW vsync)
-// or negative (before the HW vsync). Setting it to 0 will result in a
-// minimum latency of two vsync periods because the app and SurfaceFlinger
-// will run just after the HW vsync. Setting it to a positive number will
-// result in the minimum latency being:
-//
-// (2 * VSYNC_PERIOD - (vsyncPhaseOffsetNs % VSYNC_PERIOD))
-//
-// Note that reducing this latency makes it more likely for the applications
-// to not have their window content image ready in time. When this happens
-// the latency will end up being an additional vsync period, and animations
-// will hiccup. Therefore, this latency should be tuned somewhat
-// conservatively (or at least with awareness of the trade-off being made).
-static int64_t vsyncPhaseOffsetNs = getInt64<
- ISurfaceFlingerConfigs,
- &ISurfaceFlingerConfigs::vsyncEventPhaseOffsetNs>(1000000);
-
-// This is the phase offset at which SurfaceFlinger's composition runs.
-static constexpr int64_t sfVsyncPhaseOffsetNs = SF_VSYNC_EVENT_PHASE_OFFSET_NS;
-
// ---------------------------------------------------------------------------
const String16 sHardwareTest("android.permission.HARDWARE_TEST");
@@ -136,6 +109,8 @@
const String16 sDump("android.permission.DUMP");
// ---------------------------------------------------------------------------
+int64_t SurfaceFlinger::vsyncPhaseOffsetNs;
+int64_t SurfaceFlinger::sfVsyncPhaseOffsetNs;
SurfaceFlinger::SurfaceFlinger()
: BnSurfaceComposer(),
@@ -179,6 +154,13 @@
,mEnterVrMode(false)
#endif
{
+
+ vsyncPhaseOffsetNs = getInt64< ISurfaceFlingerConfigs,
+ &ISurfaceFlingerConfigs::vsyncEventPhaseOffsetNs>(1000000);
+
+ sfVsyncPhaseOffsetNs = getInt64< ISurfaceFlingerConfigs,
+ &ISurfaceFlingerConfigs::vsyncSfEventPhaseOffsetNs>(1000000);
+
ALOGI("SurfaceFlinger is starting");
// debugging stuff...
@@ -743,7 +725,7 @@
// We add an additional 1ms to allow for processing time and
// differences between the ideal and actual refresh rate.
info.presentationDeadline = hwConfig->getVsyncPeriod() -
- SF_VSYNC_EVENT_PHASE_OFFSET_NS + 1000000;
+ sfVsyncPhaseOffsetNs + 1000000;
// All non-virtual displays are currently considered secure.
info.secure = true;
@@ -2537,6 +2519,8 @@
}
status_t SurfaceFlinger::removeLayer(const sp<Layer>& layer) {
+ Mutex::Autolock _l(mStateLock);
+
const auto& p = layer->getParent();
const ssize_t index = (p != nullptr) ? p->removeChild(layer) :
mCurrentState.layersSortedByZ.remove(layer);
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 6ce799a..e5aa0bb 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -103,6 +103,31 @@
private HWComposer::EventHandler
{
public:
+
+
+ // This is the phase offset in nanoseconds of the software vsync event
+ // relative to the vsync event reported by HWComposer. The software vsync
+ // event is when SurfaceFlinger and Choreographer-based applications run each
+ // frame.
+ //
+ // This phase offset allows adjustment of the minimum latency from application
+ // wake-up time (by Choreographer) to the time at which the resulting window
+ // image is displayed. This value may be either positive (after the HW vsync)
+ // or negative (before the HW vsync). Setting it to 0 will result in a lower
+ // latency bound of two vsync periods because the app and SurfaceFlinger
+ // will run just after the HW vsync. Setting it to a positive number will
+ // result in the minimum latency being:
+ //
+ // (2 * VSYNC_PERIOD - (vsyncPhaseOffsetNs % VSYNC_PERIOD))
+ //
+ // Note that reducing this latency makes it more likely for the applications
+ // to not have their window content image ready in time. When this happens
+ // the latency will end up being an additional vsync period, and animations
+ // will hiccup. Therefore, this latency should be tuned somewhat
+ // conservatively (or at least with awareness of the trade-off being made).
+ static int64_t vsyncPhaseOffsetNs;
+ static int64_t sfVsyncPhaseOffsetNs;
+
static char const* getServiceName() ANDROID_API {
return "SurfaceFlinger";
}
@@ -657,7 +682,6 @@
std::atomic<bool> mEnterVrMode;
#endif
};
-
}; // namespace android
#endif // ANDROID_SURFACE_FLINGER_H
diff --git a/services/surfaceflinger/SurfaceFlingerConsumer.cpp b/services/surfaceflinger/SurfaceFlingerConsumer.cpp
index 2fcbdba..01226e0 100644
--- a/services/surfaceflinger/SurfaceFlingerConsumer.cpp
+++ b/services/surfaceflinger/SurfaceFlingerConsumer.cpp
@@ -183,7 +183,7 @@
// we don't need to factor that in here. Pad a little to avoid
// weird effects if apps might be requesting times right on the edge.
nsecs_t extraPadding = 0;
- if (VSYNC_EVENT_PHASE_OFFSET_NS == 0) {
+ if (SurfaceFlinger::vsyncPhaseOffsetNs == 0) {
extraPadding = 1000000; // 1ms (6% of 60Hz)
}
@@ -237,19 +237,6 @@
mContentsChangedListener = listener;
}
-void SurfaceFlingerConsumer::onBuffersReleased() {
- sp<ContentsChangedListener> listener;
- { // scope for the lock
- Mutex::Autolock lock(mMutex);
- ALOG_ASSERT(mFrameAvailableListener.unsafe_get() == mContentsChangedListener.unsafe_get());
- listener = mContentsChangedListener.promote();
- }
-
- if (listener != NULL) {
- listener->onBuffersReleased();
- }
-}
-
void SurfaceFlingerConsumer::onSidebandStreamChanged() {
sp<ContentsChangedListener> listener;
{ // scope for the lock
diff --git a/services/surfaceflinger/SurfaceFlingerConsumer.h b/services/surfaceflinger/SurfaceFlingerConsumer.h
index cfa70ed..1126233 100644
--- a/services/surfaceflinger/SurfaceFlingerConsumer.h
+++ b/services/surfaceflinger/SurfaceFlingerConsumer.h
@@ -35,7 +35,6 @@
static const status_t BUFFER_REJECTED = UNKNOWN_ERROR + 8;
struct ContentsChangedListener: public FrameAvailableListener {
- virtual void onBuffersReleased() = 0;
virtual void onSidebandStreamChanged() = 0;
};
@@ -93,7 +92,6 @@
FrameEventHistoryDelta* outDelta) override;
private:
- virtual void onBuffersReleased();
virtual void onSidebandStreamChanged();
wp<ContentsChangedListener> mContentsChangedListener;
diff --git a/services/surfaceflinger/SurfaceFlinger_hwc1.cpp b/services/surfaceflinger/SurfaceFlinger_hwc1.cpp
index 683883f..147232c 100644
--- a/services/surfaceflinger/SurfaceFlinger_hwc1.cpp
+++ b/services/surfaceflinger/SurfaceFlinger_hwc1.cpp
@@ -83,6 +83,9 @@
#include "RenderEngine/RenderEngine.h"
#include <cutils/compiler.h>
+#include <android/hardware/configstore/1.0/ISurfaceFlingerConfigs.h>
+#include <configstore/Utils.h>
+
#define DISPLAY_COUNT 1
/*
@@ -94,40 +97,19 @@
EGLAPI const char* eglQueryStringImplementationANDROID(EGLDisplay dpy, EGLint name);
namespace android {
-
-// This is the phase offset in nanoseconds of the software vsync event
-// relative to the vsync event reported by HWComposer. The software vsync
-// event is when SurfaceFlinger and Choreographer-based applications run each
-// frame.
-//
-// This phase offset allows adjustment of the minimum latency from application
-// wake-up (by Choregographer) time to the time at which the resulting window
-// image is displayed. This value may be either positive (after the HW vsync)
-// or negative (before the HW vsync). Setting it to 0 will result in a
-// minimum latency of two vsync periods because the app and SurfaceFlinger
-// will run just after the HW vsync. Setting it to a positive number will
-// result in the minimum latency being:
-//
-// (2 * VSYNC_PERIOD - (vsyncPhaseOffsetNs % VSYNC_PERIOD))
-//
-// Note that reducing this latency makes it more likely for the applications
-// to not have their window content image ready in time. When this happens
-// the latency will end up being an additional vsync period, and animations
-// will hiccup. Therefore, this latency should be tuned somewhat
-// conservatively (or at least with awareness of the trade-off being made).
-static const int64_t vsyncPhaseOffsetNs = VSYNC_EVENT_PHASE_OFFSET_NS;
-
-// This is the phase offset at which SurfaceFlinger's composition runs.
-static const int64_t sfVsyncPhaseOffsetNs = SF_VSYNC_EVENT_PHASE_OFFSET_NS;
-
// ---------------------------------------------------------------------------
+using namespace android::hardware::configstore;
+using namespace android::hardware::configstore::V1_0;
+
const String16 sHardwareTest("android.permission.HARDWARE_TEST");
const String16 sAccessSurfaceFlinger("android.permission.ACCESS_SURFACE_FLINGER");
const String16 sReadFramebuffer("android.permission.READ_FRAME_BUFFER");
const String16 sDump("android.permission.DUMP");
// ---------------------------------------------------------------------------
+int64_t SurfaceFlinger::vsyncPhaseOffsetNs;
+int64_t SurfaceFlinger::sfVsyncPhaseOffsetNs;
SurfaceFlinger::SurfaceFlinger()
: BnSurfaceComposer(),
@@ -164,6 +146,12 @@
mLastSwapTime(0),
mNumLayers(0)
{
+ vsyncPhaseOffsetNs = getInt64< ISurfaceFlingerConfigs,
+ &ISurfaceFlingerConfigs::vsyncEventPhaseOffsetNs>(1000000);
+
+ sfVsyncPhaseOffsetNs = getInt64< ISurfaceFlingerConfigs,
+ &ISurfaceFlingerConfigs::vsyncSfEventPhaseOffsetNs>(1000000);
+
ALOGI("SurfaceFlinger is starting");
char value[PROPERTY_VALUE_MAX];
@@ -711,7 +699,7 @@
info.xdpi = xdpi;
info.ydpi = ydpi;
info.fps = float(1e9 / hwConfig.refresh);
- info.appVsyncOffset = VSYNC_EVENT_PHASE_OFFSET_NS;
+ info.appVsyncOffset = vsyncPhaseOffsetNs;
// This is how far in advance a buffer must be queued for
// presentation at a given time. If you want a buffer to appear
@@ -726,7 +714,7 @@
// We add an additional 1ms to allow for processing time and
// differences between the ideal and actual refresh rate.
info.presentationDeadline =
- hwConfig.refresh - SF_VSYNC_EVENT_PHASE_OFFSET_NS + 1000000;
+ hwConfig.refresh - sfVsyncPhaseOffsetNs + 1000000;
// All non-virtual displays are currently considered secure.
info.secure = true;
@@ -2308,6 +2296,8 @@
}
status_t SurfaceFlinger::removeLayer(const sp<Layer>& layer) {
+ Mutex::Autolock _l(mStateLock);
+
const auto& p = layer->getParent();
const ssize_t index = (p != nullptr) ? p->removeChild(layer) :
mCurrentState.layersSortedByZ.remove(layer);
diff --git a/services/surfaceflinger/tests/hwc2/Android.mk b/services/surfaceflinger/tests/hwc2/Android.mk
new file mode 100644
index 0000000..b8c2133
--- /dev/null
+++ b/services/surfaceflinger/tests/hwc2/Android.mk
@@ -0,0 +1,53 @@
+#
+# Copyright (C) 2016 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := test-hwc2
+LOCAL_MODULE_TAGS := tests
+LOCAL_CFLAGS += \
+ -fstack-protector-all \
+ -g \
+ -Wall -Wextra \
+ -Werror \
+ -fno-builtin \
+ -DEGL_EGLEXT_PROTOTYPES \
+ -DGL_GLEXT_PROTOTYPES
+LOCAL_SHARED_LIBRARIES := \
+ libcutils \
+ libutils \
+ libhardware \
+ libEGL \
+ libGLESv2 \
+ libui \
+ libgui \
+ liblog \
+ libsync
+LOCAL_STATIC_LIBRARIES := \
+ libbase \
+ libadf \
+ libadfhwc
+LOCAL_SRC_FILES := \
+ Hwc2Test.cpp \
+ Hwc2TestProperties.cpp \
+ Hwc2TestLayer.cpp \
+ Hwc2TestLayers.cpp \
+ Hwc2TestBuffer.cpp \
+ Hwc2TestClientTarget.cpp \
+ Hwc2TestVirtualDisplay.cpp
+
+include $(BUILD_NATIVE_TEST)
diff --git a/services/surfaceflinger/tests/hwc2/Hwc2Test.cpp b/services/surfaceflinger/tests/hwc2/Hwc2Test.cpp
new file mode 100644
index 0000000..062485e
--- /dev/null
+++ b/services/surfaceflinger/tests/hwc2/Hwc2Test.cpp
@@ -0,0 +1,4556 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <array>
+#include <unordered_set>
+#include <unordered_map>
+#include <gtest/gtest.h>
+#include <dlfcn.h>
+#include <android-base/unique_fd.h>
+#include <hardware/hardware.h>
+#include <sync/sync.h>
+
+#define HWC2_INCLUDE_STRINGIFICATION
+#define HWC2_USE_CPP11
+#include <hardware/hwcomposer2.h>
+#undef HWC2_INCLUDE_STRINGIFICATION
+#undef HWC2_USE_CPP11
+
+#include "Hwc2TestLayer.h"
+#include "Hwc2TestLayers.h"
+#include "Hwc2TestClientTarget.h"
+#include "Hwc2TestVirtualDisplay.h"
+
+void hwc2TestHotplugCallback(hwc2_callback_data_t callbackData,
+ hwc2_display_t display, int32_t connected);
+void hwc2TestVsyncCallback(hwc2_callback_data_t callbackData,
+ hwc2_display_t display, int64_t timestamp);
+
+class Hwc2Test : public testing::Test {
+public:
+
+ virtual void SetUp()
+ {
+ hw_module_t const* hwc2Module;
+
+ int err = hw_get_module(HWC_HARDWARE_MODULE_ID, &hwc2Module);
+ ASSERT_GE(err, 0) << "failed to get hwc hardware module: "
+ << strerror(-err);
+
+ /* The following method will fail if you have not run
+ * "adb shell stop" */
+ err = hwc2_open(hwc2Module, &mHwc2Device);
+ ASSERT_GE(err, 0) << "failed to open hwc hardware module: "
+ << strerror(-err);
+
+ populateDisplays();
+ }
+
+ virtual void TearDown()
+ {
+
+ for (auto itr = mLayers.begin(); itr != mLayers.end();) {
+ hwc2_display_t display = itr->first;
+ hwc2_layer_t layer = itr->second;
+ itr++;
+ /* Destroys and removes the layer from mLayers */
+ destroyLayer(display, layer);
+ }
+
+ for (auto itr = mActiveDisplays.begin(); itr != mActiveDisplays.end();) {
+ hwc2_display_t display = *itr;
+ itr++;
+ /* Sets power mode to off and removes the display from
+ * mActiveDisplays */
+ setPowerMode(display, HWC2_POWER_MODE_OFF);
+ }
+
+ for (auto itr = mVirtualDisplays.begin(); itr != mVirtualDisplays.end();) {
+ hwc2_display_t display = *itr;
+ itr++;
+ /* Destroys virtual displays */
+ destroyVirtualDisplay(display);
+ }
+
+ if (mHwc2Device)
+ hwc2_close(mHwc2Device);
+ }
+
+ void registerCallback(hwc2_callback_descriptor_t descriptor,
+ hwc2_callback_data_t callbackData, hwc2_function_pointer_t pointer,
+ hwc2_error_t* outErr = nullptr)
+ {
+ auto pfn = reinterpret_cast<HWC2_PFN_REGISTER_CALLBACK>(
+ getFunction(HWC2_FUNCTION_REGISTER_CALLBACK));
+ ASSERT_TRUE(pfn) << "failed to get function";
+
+ auto err = static_cast<hwc2_error_t>(pfn(mHwc2Device, descriptor,
+ callbackData, pointer));
+ if (outErr) {
+ *outErr = err;
+ } else {
+ ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to register callback";
+ }
+ }
+
+ void getDisplayType(hwc2_display_t display, hwc2_display_type_t* outType,
+ hwc2_error_t* outErr = nullptr)
+ {
+ auto pfn = reinterpret_cast<HWC2_PFN_GET_DISPLAY_TYPE>(
+ getFunction(HWC2_FUNCTION_GET_DISPLAY_TYPE));
+ ASSERT_TRUE(pfn) << "failed to get function";
+
+ auto err = static_cast<hwc2_error_t>(pfn(mHwc2Device, display,
+ reinterpret_cast<int32_t*>(outType)));
+ if (outErr) {
+ *outErr = err;
+ } else {
+ ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to get display type";
+ }
+ }
+
+ /* If the populateDisplays function is still receiving displays and the
+ * display is connected, the display handle is stored in mDisplays. */
+ void hotplugCallback(hwc2_display_t display, int32_t connected)
+ {
+ std::lock_guard<std::mutex> lock(mHotplugMutex);
+
+ if (mHotplugStatus != Hwc2TestHotplugStatus::Receiving)
+ return;
+
+ if (connected == HWC2_CONNECTION_CONNECTED)
+ mDisplays.insert(display);
+
+ mHotplugCv.notify_all();
+ }
+
+ void createLayer(hwc2_display_t display, hwc2_layer_t* outLayer,
+ hwc2_error_t* outErr = nullptr)
+ {
+ auto pfn = reinterpret_cast<HWC2_PFN_CREATE_LAYER>(
+ getFunction(HWC2_FUNCTION_CREATE_LAYER));
+ ASSERT_TRUE(pfn) << "failed to get function";
+
+ auto err = static_cast<hwc2_error_t>(pfn(mHwc2Device, display,
+ outLayer));
+
+ if (err == HWC2_ERROR_NONE)
+ mLayers.insert(std::make_pair(display, *outLayer));
+
+ if (outErr) {
+ *outErr = err;
+ } else {
+ ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to create layer";
+ }
+ }
+
+ void destroyLayer(hwc2_display_t display, hwc2_layer_t layer,
+ hwc2_error_t* outErr = nullptr)
+ {
+ auto pfn = reinterpret_cast<HWC2_PFN_DESTROY_LAYER>(
+ getFunction(HWC2_FUNCTION_DESTROY_LAYER));
+ ASSERT_TRUE(pfn) << "failed to get function";
+
+ auto err = static_cast<hwc2_error_t>(pfn(mHwc2Device, display, layer));
+
+ if (err == HWC2_ERROR_NONE)
+ mLayers.erase(std::make_pair(display, layer));
+
+ if (outErr) {
+ *outErr = err;
+ } else {
+ ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to destroy layer "
+ << layer;
+ }
+ }
+
+ void getDisplayAttribute(hwc2_display_t display, hwc2_config_t config,
+ hwc2_attribute_t attribute, int32_t* outValue,
+ hwc2_error_t* outErr = nullptr)
+ {
+ auto pfn = reinterpret_cast<HWC2_PFN_GET_DISPLAY_ATTRIBUTE>(
+ getFunction(HWC2_FUNCTION_GET_DISPLAY_ATTRIBUTE));
+ ASSERT_TRUE(pfn) << "failed to get function";
+
+ auto err = static_cast<hwc2_error_t>(pfn(mHwc2Device, display, config,
+ attribute, outValue));
+
+ if (outErr) {
+ *outErr = err;
+ } else {
+ ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to get display attribute "
+ << getAttributeName(attribute) << " for config " << config;
+ }
+ }
+
+ void getDisplayConfigs(hwc2_display_t display,
+ std::vector<hwc2_config_t>* outConfigs,
+ hwc2_error_t* outErr = nullptr)
+ {
+ auto pfn = reinterpret_cast<HWC2_PFN_GET_DISPLAY_CONFIGS>(
+ getFunction(HWC2_FUNCTION_GET_DISPLAY_CONFIGS));
+ ASSERT_TRUE(pfn) << "failed to get function";
+
+ uint32_t numConfigs = 0;
+
+ auto err = static_cast<hwc2_error_t>(pfn(mHwc2Device, display,
+ &numConfigs, nullptr));
+
+ if (err == HWC2_ERROR_NONE) {
+ outConfigs->resize(numConfigs);
+
+ err = static_cast<hwc2_error_t>(pfn(mHwc2Device, display,
+ &numConfigs, outConfigs->data()));
+ }
+
+ if (outErr) {
+ *outErr = err;
+ } else {
+ ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to get configs for"
+ " display " << display;
+ }
+ }
+
+ void getActiveConfig(hwc2_display_t display, hwc2_config_t* outConfig,
+ hwc2_error_t* outErr = nullptr)
+ {
+ auto pfn = reinterpret_cast<HWC2_PFN_GET_ACTIVE_CONFIG>(
+ getFunction(HWC2_FUNCTION_GET_ACTIVE_CONFIG));
+ ASSERT_TRUE(pfn) << "failed to get function";
+
+ auto err = static_cast<hwc2_error_t>(pfn(mHwc2Device, display,
+ outConfig));
+ if (outErr) {
+ *outErr = err;
+ } else {
+ ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to get active config on"
+ " display " << display;
+ }
+ }
+
+ void setActiveConfig(hwc2_display_t display, hwc2_config_t config,
+ hwc2_error_t* outErr = nullptr)
+ {
+ auto pfn = reinterpret_cast<HWC2_PFN_SET_ACTIVE_CONFIG>(
+ getFunction(HWC2_FUNCTION_SET_ACTIVE_CONFIG));
+ ASSERT_TRUE(pfn) << "failed to get function";
+
+ auto err = static_cast<hwc2_error_t>(pfn(mHwc2Device, display, config));
+ if (outErr) {
+ *outErr = err;
+ } else {
+ ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to set active config "
+ << config;
+ }
+ }
+
+ void getDozeSupport(hwc2_display_t display, int32_t* outSupport,
+ hwc2_error_t* outErr = nullptr)
+ {
+ auto pfn = reinterpret_cast<HWC2_PFN_GET_DOZE_SUPPORT>(
+ getFunction(HWC2_FUNCTION_GET_DOZE_SUPPORT));
+ ASSERT_TRUE(pfn) << "failed to get function";
+
+ auto err = static_cast<hwc2_error_t>(pfn(mHwc2Device, display,
+ outSupport));
+ if (outErr) {
+ *outErr = err;
+ } else {
+ ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to get doze support on"
+ " display " << display;
+ }
+ }
+
+ void setPowerMode(hwc2_display_t display, hwc2_power_mode_t mode,
+ hwc2_error_t* outErr = nullptr)
+ {
+ auto pfn = reinterpret_cast<HWC2_PFN_SET_POWER_MODE>(
+ getFunction(HWC2_FUNCTION_SET_POWER_MODE));
+ ASSERT_TRUE(pfn) << "failed to get function";
+
+ auto err = static_cast<hwc2_error_t>(pfn(mHwc2Device, display,
+ mode));
+ if (outErr) {
+ *outErr = err;
+ if (err != HWC2_ERROR_NONE)
+ return;
+ } else {
+ ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to set power mode "
+ << getPowerModeName(mode) << " on display " << display;
+ }
+
+ if (mode == HWC2_POWER_MODE_OFF) {
+ mActiveDisplays.erase(display);
+ } else {
+ mActiveDisplays.insert(display);
+ }
+ }
+
+ void setVsyncEnabled(hwc2_display_t display, hwc2_vsync_t enabled,
+ hwc2_error_t* outErr = nullptr)
+ {
+ auto pfn = reinterpret_cast<HWC2_PFN_SET_VSYNC_ENABLED>(
+ getFunction(HWC2_FUNCTION_SET_VSYNC_ENABLED));
+ ASSERT_TRUE(pfn) << "failed to get function";
+
+ auto err = static_cast<hwc2_error_t>(pfn(mHwc2Device, display,
+ enabled));
+ if (outErr) {
+ *outErr = err;
+ } else {
+ ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to set vsync enabled "
+ << getVsyncName(enabled);
+ }
+ }
+
+ void vsyncCallback(hwc2_display_t display, int64_t timestamp)
+ {
+ std::lock_guard<std::mutex> lock(mVsyncMutex);
+ mVsyncDisplay = display;
+ mVsyncTimestamp = timestamp;
+ mVsyncCv.notify_all();
+ }
+
+ void getDisplayName(hwc2_display_t display, std::string* outName,
+ hwc2_error_t* outErr = nullptr)
+ {
+ auto pfn = reinterpret_cast<HWC2_PFN_GET_DISPLAY_NAME>(
+ getFunction(HWC2_FUNCTION_GET_DISPLAY_NAME));
+ ASSERT_TRUE(pfn) << "failed to get function";
+
+ uint32_t size = 0;
+
+ auto err = static_cast<hwc2_error_t>(pfn(mHwc2Device, display, &size,
+ nullptr));
+
+ if (err == HWC2_ERROR_NONE) {
+ std::vector<char> name(size);
+
+ err = static_cast<hwc2_error_t>(pfn(mHwc2Device, display, &size,
+ name.data()));
+
+ outName->assign(name.data());
+ }
+
+ if (outErr) {
+ *outErr = err;
+ } else {
+ ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to get display name for "
+ << display;
+ }
+ }
+
+ void setLayerCompositionType(hwc2_display_t display, hwc2_layer_t layer,
+ hwc2_composition_t composition, hwc2_error_t* outErr = nullptr)
+ {
+ auto pfn = reinterpret_cast<HWC2_PFN_SET_LAYER_COMPOSITION_TYPE>(
+ getFunction(HWC2_FUNCTION_SET_LAYER_COMPOSITION_TYPE));
+ ASSERT_TRUE(pfn) << "failed to get function";
+
+ auto err = static_cast<hwc2_error_t>(pfn(mHwc2Device, display, layer,
+ composition));
+ if (outErr) {
+ *outErr = err;
+ } else {
+ ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to set layer composition"
+ " type " << getCompositionName(composition);
+ }
+ }
+
+ void setCursorPosition(hwc2_display_t display, hwc2_layer_t layer,
+ int32_t x, int32_t y, hwc2_error_t* outErr = nullptr)
+ {
+ auto pfn = reinterpret_cast<HWC2_PFN_SET_CURSOR_POSITION>(
+ getFunction(HWC2_FUNCTION_SET_CURSOR_POSITION));
+ ASSERT_TRUE(pfn) << "failed to get function";
+
+ auto err = static_cast<hwc2_error_t>(pfn(mHwc2Device, display, layer, x,
+ y));
+ if (outErr) {
+ *outErr = err;
+ } else {
+ ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to set cursor position";
+ }
+ }
+
+ void setLayerBlendMode(hwc2_display_t display, hwc2_layer_t layer,
+ hwc2_blend_mode_t mode, hwc2_error_t* outErr = nullptr)
+ {
+ auto pfn = reinterpret_cast<HWC2_PFN_SET_LAYER_BLEND_MODE>(
+ getFunction(HWC2_FUNCTION_SET_LAYER_BLEND_MODE));
+ ASSERT_TRUE(pfn) << "failed to get function";
+
+ auto err = static_cast<hwc2_error_t>(pfn(mHwc2Device, display, layer,
+ mode));
+ if (outErr) {
+ *outErr = err;
+ } else {
+ ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to set layer blend mode "
+ << getBlendModeName(mode);
+ }
+ }
+
+ void setLayerBuffer(hwc2_display_t display, hwc2_layer_t layer,
+ buffer_handle_t buffer, int32_t acquireFence,
+ hwc2_error_t* outErr = nullptr)
+ {
+ auto pfn = reinterpret_cast<HWC2_PFN_SET_LAYER_BUFFER>(
+ getFunction(HWC2_FUNCTION_SET_LAYER_BUFFER));
+ ASSERT_TRUE(pfn) << "failed to get function";
+
+ auto err = static_cast<hwc2_error_t>(pfn(mHwc2Device, display, layer,
+ buffer, acquireFence));
+ if (outErr) {
+ *outErr = err;
+ } else {
+ ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to set layer buffer";
+ }
+ }
+
+ void setLayerColor(hwc2_display_t display, hwc2_layer_t layer,
+ hwc_color_t color, hwc2_error_t* outErr = nullptr)
+ {
+ auto pfn = reinterpret_cast<HWC2_PFN_SET_LAYER_COLOR>(
+ getFunction(HWC2_FUNCTION_SET_LAYER_COLOR));
+ ASSERT_TRUE(pfn) << "failed to get function";
+
+ auto err = static_cast<hwc2_error_t>(pfn(mHwc2Device, display, layer,
+ color));
+ if (outErr) {
+ *outErr = err;
+ } else {
+ ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to set layer color";
+ }
+ }
+
+ void setLayerDataspace(hwc2_display_t display, hwc2_layer_t layer,
+ android_dataspace_t dataspace, hwc2_error_t* outErr = nullptr)
+ {
+ auto pfn = reinterpret_cast<HWC2_PFN_SET_LAYER_DATASPACE>(
+ getFunction(HWC2_FUNCTION_SET_LAYER_DATASPACE));
+ ASSERT_TRUE(pfn) << "failed to get function";
+
+ auto err = static_cast<hwc2_error_t>(pfn(mHwc2Device, display,
+ layer, dataspace));
+ if (outErr) {
+ *outErr = err;
+ } else {
+ ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to set layer dataspace";
+ }
+ }
+
+ void setLayerDisplayFrame(hwc2_display_t display, hwc2_layer_t layer,
+ const hwc_rect_t& displayFrame, hwc2_error_t* outErr = nullptr)
+ {
+ auto pfn = reinterpret_cast<HWC2_PFN_SET_LAYER_DISPLAY_FRAME>(
+ getFunction(HWC2_FUNCTION_SET_LAYER_DISPLAY_FRAME));
+ ASSERT_TRUE(pfn) << "failed to get function";
+
+ auto err = static_cast<hwc2_error_t>(pfn(mHwc2Device, display, layer,
+ displayFrame));
+ if (outErr) {
+ *outErr = err;
+ } else {
+ ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to set layer display"
+ " frame";
+ }
+ }
+
+ void setLayerPlaneAlpha(hwc2_display_t display, hwc2_layer_t layer,
+ float alpha, hwc2_error_t* outErr = nullptr)
+ {
+ auto pfn = reinterpret_cast<HWC2_PFN_SET_LAYER_PLANE_ALPHA>(
+ getFunction(HWC2_FUNCTION_SET_LAYER_PLANE_ALPHA));
+ ASSERT_TRUE(pfn) << "failed to get function";
+
+ auto err = static_cast<hwc2_error_t>(pfn(mHwc2Device, display, layer,
+ alpha));
+ if (outErr) {
+ *outErr = err;
+ } else {
+ ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to set layer plane alpha "
+ << alpha;
+ }
+ }
+
+ void setLayerSourceCrop(hwc2_display_t display, hwc2_layer_t layer,
+ const hwc_frect_t& sourceCrop, hwc2_error_t* outErr = nullptr)
+ {
+ auto pfn = reinterpret_cast<HWC2_PFN_SET_LAYER_SOURCE_CROP>(
+ getFunction(HWC2_FUNCTION_SET_LAYER_SOURCE_CROP));
+ ASSERT_TRUE(pfn) << "failed to get function";
+
+ auto err = static_cast<hwc2_error_t>(pfn(mHwc2Device, display, layer,
+ sourceCrop));
+ if (outErr) {
+ *outErr = err;
+ } else {
+ ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to set layer source crop";
+ }
+ }
+
+ void setLayerSurfaceDamage(hwc2_display_t display, hwc2_layer_t layer,
+ const hwc_region_t& surfaceDamage, hwc2_error_t* outErr = nullptr)
+ {
+ auto pfn = reinterpret_cast<HWC2_PFN_SET_LAYER_SURFACE_DAMAGE>(
+ getFunction(HWC2_FUNCTION_SET_LAYER_SURFACE_DAMAGE));
+ ASSERT_TRUE(pfn) << "failed to get function";
+
+ auto err = static_cast<hwc2_error_t>(pfn(mHwc2Device, display, layer,
+ surfaceDamage));
+ if (outErr) {
+ *outErr = err;
+ } else {
+ ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to set layer surface"
+ " damage";
+ }
+ }
+
+ void setLayerTransform(hwc2_display_t display, hwc2_layer_t layer,
+ hwc_transform_t transform, hwc2_error_t* outErr = nullptr)
+ {
+ auto pfn = reinterpret_cast<HWC2_PFN_SET_LAYER_TRANSFORM>(
+ getFunction(HWC2_FUNCTION_SET_LAYER_TRANSFORM));
+ ASSERT_TRUE(pfn) << "failed to get function";
+
+ auto err = static_cast<hwc2_error_t>(pfn(mHwc2Device, display, layer,
+ transform));
+ if (outErr) {
+ *outErr = err;
+ } else {
+ ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to set layer transform "
+ << getTransformName(transform);
+ }
+ }
+
+ void setLayerVisibleRegion(hwc2_display_t display, hwc2_layer_t layer,
+ const hwc_region_t& visibleRegion, hwc2_error_t* outErr = nullptr)
+ {
+ auto pfn = reinterpret_cast<HWC2_PFN_SET_LAYER_VISIBLE_REGION>(
+ getFunction(HWC2_FUNCTION_SET_LAYER_VISIBLE_REGION));
+ ASSERT_TRUE(pfn) << "failed to get function";
+
+ auto err = static_cast<hwc2_error_t>(pfn(mHwc2Device, display, layer,
+ visibleRegion));
+ if (outErr) {
+ *outErr = err;
+ } else {
+ ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to set layer visible"
+ " region";
+ }
+ }
+
+ void setLayerZOrder(hwc2_display_t display, hwc2_layer_t layer,
+ uint32_t zOrder, hwc2_error_t* outErr = nullptr)
+ {
+ auto pfn = reinterpret_cast<HWC2_PFN_SET_LAYER_Z_ORDER>(
+ getFunction(HWC2_FUNCTION_SET_LAYER_Z_ORDER));
+ ASSERT_TRUE(pfn) << "failed to get function";
+
+ auto err = static_cast<hwc2_error_t>(pfn(mHwc2Device, display, layer,
+ zOrder));
+ if (outErr) {
+ *outErr = err;
+ } else {
+ ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to set layer z order "
+ << zOrder;
+ }
+ }
+
+ void validateDisplay(hwc2_display_t display, uint32_t* outNumTypes,
+ uint32_t* outNumRequests, hwc2_error_t* outErr)
+ {
+ auto pfn = reinterpret_cast<HWC2_PFN_VALIDATE_DISPLAY>(
+ getFunction(HWC2_FUNCTION_VALIDATE_DISPLAY));
+ ASSERT_TRUE(pfn) << "failed to get function";
+
+ *outErr = static_cast<hwc2_error_t>(pfn(mHwc2Device, display,
+ outNumTypes, outNumRequests));
+ }
+
+ void validateDisplay(hwc2_display_t display, uint32_t* outNumTypes,
+ uint32_t* outNumRequests, bool* outHasChanges)
+ {
+ hwc2_error_t err = HWC2_ERROR_NONE;
+
+ EXPECT_NO_FATAL_FAILURE(validateDisplay(display, outNumTypes,
+ outNumRequests, &err));
+
+ if (err != HWC2_ERROR_HAS_CHANGES) {
+ *outHasChanges = false;
+ EXPECT_EQ(err, HWC2_ERROR_NONE) << "failed to validate display";
+ } else {
+ *outHasChanges = true;
+ }
+ }
+
+ void getDisplayRequests(hwc2_display_t display,
+ hwc2_display_request_t* outDisplayRequests,
+ std::vector<hwc2_layer_t>* outLayers,
+ std::vector<hwc2_layer_request_t>* outLayerRequests,
+ hwc2_error_t* outErr = nullptr)
+ {
+ auto pfn = reinterpret_cast<HWC2_PFN_GET_DISPLAY_REQUESTS>(
+ getFunction(HWC2_FUNCTION_GET_DISPLAY_REQUESTS));
+ ASSERT_TRUE(pfn) << "failed to get function";
+
+ uint32_t numElements = 0;
+
+ auto err = static_cast<hwc2_error_t>(pfn(mHwc2Device, display,
+ reinterpret_cast<int32_t*>(outDisplayRequests), &numElements,
+ nullptr, nullptr));
+
+ if (err == HWC2_ERROR_NONE && numElements > 0) {
+ outLayers->resize(numElements);
+ outLayerRequests->resize(numElements);
+
+ err = static_cast<hwc2_error_t>(pfn(mHwc2Device, display,
+ reinterpret_cast<int32_t*>(outDisplayRequests), &numElements,
+ reinterpret_cast<uint64_t*>(outLayers->data()),
+ reinterpret_cast<int32_t*>(outLayerRequests->data())));
+ }
+
+ if (outErr) {
+ *outErr = err;
+ } else {
+ ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to get display requests";
+ }
+ }
+
+ void handleRequests(hwc2_display_t display,
+ const std::vector<hwc2_layer_t>& layers, uint32_t numRequests,
+ std::set<hwc2_layer_t>* outClearLayers = nullptr,
+ bool* outFlipClientTarget = nullptr)
+ {
+ hwc2_display_request_t displayRequest =
+ static_cast<hwc2_display_request_t>(0);
+ std::vector<hwc2_layer_t> requestedLayers;
+ std::vector<hwc2_layer_request_t> requests;
+
+ ASSERT_NO_FATAL_FAILURE(getDisplayRequests(display, &displayRequest,
+ &requestedLayers, &requests));
+
+ EXPECT_EQ(numRequests, requests.size()) << "validate returned "
+ << numRequests << " requests and get display requests returned "
+ << requests.size() << " requests";
+
+ for (size_t i = 0; i < requests.size(); i++) {
+ hwc2_layer_t requestedLayer = requestedLayers.at(i);
+ hwc2_layer_request_t request = requests.at(i);
+
+ EXPECT_EQ(std::count(layers.begin(), layers.end(), requestedLayer),
+ 0) << "get display requests returned an unknown layer";
+ EXPECT_NE(request, 0) << "returned empty request for layer "
+ << requestedLayer;
+
+ if (outClearLayers && request
+ == HWC2_LAYER_REQUEST_CLEAR_CLIENT_TARGET)
+ outClearLayers->insert(requestedLayer);
+ }
+
+ if (outFlipClientTarget)
+ *outFlipClientTarget = displayRequest
+ & HWC2_DISPLAY_REQUEST_FLIP_CLIENT_TARGET;
+ }
+
+ void getChangedCompositionTypes(hwc2_display_t display,
+ std::vector<hwc2_layer_t>* outLayers,
+ std::vector<hwc2_composition_t>* outTypes,
+ hwc2_error_t* outErr = nullptr)
+ {
+ auto pfn = reinterpret_cast<HWC2_PFN_GET_CHANGED_COMPOSITION_TYPES>(
+ getFunction(HWC2_FUNCTION_GET_CHANGED_COMPOSITION_TYPES));
+ ASSERT_TRUE(pfn) << "failed to get function";
+
+ uint32_t numElements = 0;
+
+ auto err = static_cast<hwc2_error_t>(pfn(mHwc2Device, display,
+ &numElements, nullptr, nullptr));
+
+ if (err == HWC2_ERROR_NONE && numElements > 0) {
+ outLayers->resize(numElements);
+ outTypes->resize(numElements);
+
+ err = static_cast<hwc2_error_t>(pfn(mHwc2Device, display,
+ &numElements, reinterpret_cast<uint64_t*>(outLayers->data()),
+ reinterpret_cast<int32_t*>(outTypes->data())));
+ }
+
+ if (outErr) {
+ *outErr = err;
+ } else {
+ ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to get changed"
+ " composition types";
+ }
+ }
+
+ void handleCompositionChanges(hwc2_display_t display,
+ const Hwc2TestLayers& testLayers,
+ const std::vector<hwc2_layer_t>& layers, uint32_t numTypes,
+ std::set<hwc2_layer_t>* outClientLayers = nullptr)
+ {
+ std::vector<hwc2_layer_t> changedLayers;
+ std::vector<hwc2_composition_t> types;
+
+ ASSERT_NO_FATAL_FAILURE(getChangedCompositionTypes(display,
+ &changedLayers, &types));
+
+ EXPECT_EQ(numTypes, types.size()) << "validate returned "
+ << numTypes << " types and get changed composition types"
+ " returned " << types.size() << " types";
+
+ for (size_t i = 0; i < types.size(); i++) {
+
+ auto layer = std::find(layers.begin(), layers.end(),
+ changedLayers.at(i));
+
+ EXPECT_TRUE(layer != layers.end() || !testLayers.contains(*layer))
+ << "get changed composition types returned an unknown layer";
+
+ hwc2_composition_t requestedType = testLayers.getComposition(*layer);
+ hwc2_composition_t returnedType = types.at(i);
+
+ EXPECT_NE(returnedType, HWC2_COMPOSITION_INVALID) << "get changed"
+ " composition types returned invalid composition";
+
+ switch (requestedType) {
+ case HWC2_COMPOSITION_CLIENT:
+ EXPECT_TRUE(false) << getCompositionName(returnedType)
+ << " cannot be changed";
+ break;
+ case HWC2_COMPOSITION_DEVICE:
+ case HWC2_COMPOSITION_SOLID_COLOR:
+ EXPECT_EQ(returnedType, HWC2_COMPOSITION_CLIENT)
+ << "composition of type "
+ << getCompositionName(requestedType)
+ << " can only be changed to "
+ << getCompositionName(HWC2_COMPOSITION_CLIENT);
+ break;
+ case HWC2_COMPOSITION_CURSOR:
+ case HWC2_COMPOSITION_SIDEBAND:
+ EXPECT_TRUE(returnedType == HWC2_COMPOSITION_CLIENT
+ || returnedType == HWC2_COMPOSITION_DEVICE)
+ << "composition of type "
+ << getCompositionName(requestedType)
+ << " can only be changed to "
+ << getCompositionName(HWC2_COMPOSITION_CLIENT) << " or "
+ << getCompositionName(HWC2_COMPOSITION_DEVICE);
+ break;
+ default:
+ EXPECT_TRUE(false) << "unknown type "
+ << getCompositionName(requestedType);
+ break;
+ }
+
+ if (outClientLayers)
+ if (returnedType == HWC2_COMPOSITION_CLIENT)
+ outClientLayers->insert(*layer);
+ }
+
+ if (outClientLayers) {
+ for (auto layer : layers) {
+ if (testLayers.getComposition(layer) == HWC2_COMPOSITION_CLIENT)
+ outClientLayers->insert(layer);
+ }
+ }
+ }
+
+ void acceptDisplayChanges(hwc2_display_t display,
+ hwc2_error_t* outErr = nullptr)
+ {
+ auto pfn = reinterpret_cast<HWC2_PFN_ACCEPT_DISPLAY_CHANGES>(
+ getFunction(HWC2_FUNCTION_ACCEPT_DISPLAY_CHANGES));
+ ASSERT_TRUE(pfn) << "failed to get function";
+
+ auto err = static_cast<hwc2_error_t>(pfn(mHwc2Device, display));
+ if (outErr) {
+ *outErr = err;
+ } else {
+ ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to accept display changes";
+ }
+ }
+
+ void getClientTargetSupport(hwc2_display_t display, int32_t width,
+ int32_t height, android_pixel_format_t format,
+ android_dataspace_t dataspace, hwc2_error_t* outErr = nullptr)
+ {
+ auto pfn = reinterpret_cast<HWC2_PFN_GET_CLIENT_TARGET_SUPPORT>(
+ getFunction(HWC2_FUNCTION_GET_CLIENT_TARGET_SUPPORT));
+ ASSERT_TRUE(pfn) << "failed to get function";
+
+ auto err = static_cast<hwc2_error_t>(pfn(mHwc2Device, display, width,
+ height, format, dataspace));
+ if (outErr) {
+ *outErr = err;
+ } else {
+ ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to get client target"
+ " support";
+ }
+ }
+
+ void setClientTarget(hwc2_display_t display, buffer_handle_t handle,
+ int32_t acquireFence, android_dataspace_t dataspace,
+ hwc_region_t damage, hwc2_error_t* outErr = nullptr)
+ {
+ auto pfn = reinterpret_cast<HWC2_PFN_SET_CLIENT_TARGET>(
+ getFunction(HWC2_FUNCTION_SET_CLIENT_TARGET));
+ ASSERT_TRUE(pfn) << "failed to get function";
+
+ auto err = static_cast<hwc2_error_t>(pfn(mHwc2Device, display, handle,
+ acquireFence, dataspace, damage));
+ if (outErr) {
+ *outErr = err;
+ } else {
+ ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to set client target";
+ }
+ }
+
+ void presentDisplay(hwc2_display_t display, int32_t* outPresentFence,
+ hwc2_error_t* outErr = nullptr)
+ {
+ auto pfn = reinterpret_cast<HWC2_PFN_PRESENT_DISPLAY>(
+ getFunction(HWC2_FUNCTION_PRESENT_DISPLAY));
+ ASSERT_TRUE(pfn) << "failed to get function";
+
+ auto err = static_cast<hwc2_error_t>(pfn(mHwc2Device, display,
+ outPresentFence));
+ if (outErr) {
+ *outErr = err;
+ } else {
+ ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to present display";
+ }
+ }
+
+ void getReleaseFences(hwc2_display_t display,
+ std::vector<hwc2_layer_t>* outLayers,
+ std::vector<int32_t>* outFences, hwc2_error_t* outErr = nullptr)
+ {
+ auto pfn = reinterpret_cast<HWC2_PFN_GET_RELEASE_FENCES>(
+ getFunction(HWC2_FUNCTION_GET_RELEASE_FENCES));
+ ASSERT_TRUE(pfn) << "failed to get function";
+
+ uint32_t numElements = 0;
+
+ auto err = static_cast<hwc2_error_t>(pfn(mHwc2Device, display,
+ &numElements, nullptr, nullptr));
+
+ if (err == HWC2_ERROR_NONE) {
+ outLayers->resize(numElements);
+ outFences->resize(numElements);
+
+ err = static_cast<hwc2_error_t>(pfn(mHwc2Device, display,
+ &numElements, outLayers->data(), outFences->data()));
+ }
+
+ if (outErr) {
+ *outErr = err;
+ } else {
+ ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to get release fences";
+ }
+ }
+
+ void getColorModes(hwc2_display_t display,
+ std::vector<android_color_mode_t>* outColorModes,
+ hwc2_error_t* outErr = nullptr)
+ {
+ auto pfn = reinterpret_cast<HWC2_PFN_GET_COLOR_MODES>(
+ getFunction(HWC2_FUNCTION_GET_COLOR_MODES));
+ ASSERT_TRUE(pfn) << "failed to get function";
+
+ uint32_t numColorModes = 0;
+
+ auto err = static_cast<hwc2_error_t>(pfn(mHwc2Device, display,
+ &numColorModes, nullptr));
+ if (err == HWC2_ERROR_NONE) {
+ outColorModes->resize(numColorModes);
+
+ err = static_cast<hwc2_error_t>(pfn(mHwc2Device, display,
+ &numColorModes,
+ reinterpret_cast<int32_t*>(outColorModes->data())));
+ }
+
+ if (outErr) {
+ *outErr = err;
+ } else {
+ ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to get color modes for"
+ " display " << display;
+ }
+ }
+
+ void setColorMode(hwc2_display_t display, android_color_mode_t colorMode,
+ hwc2_error_t* outErr = nullptr)
+ {
+ auto pfn = reinterpret_cast<HWC2_PFN_SET_COLOR_MODE>(
+ getFunction(HWC2_FUNCTION_SET_COLOR_MODE));
+ ASSERT_TRUE(pfn) << "failed to get function";
+
+ auto err = static_cast<hwc2_error_t>(pfn(mHwc2Device, display,
+ static_cast<int32_t>(colorMode)));
+ if (outErr) {
+ *outErr = err;
+ } else {
+ ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to set color mode "
+ << colorMode;
+ }
+ }
+
+ void getHdrCapabilities(hwc2_display_t display,
+ std::vector<android_hdr_t>* outTypes, float* outMaxLuminance,
+ float* outMaxAverageLuminance, float* outMinLuminance,
+ hwc2_error_t* outErr = nullptr)
+ {
+ auto pfn = reinterpret_cast<HWC2_PFN_GET_HDR_CAPABILITIES>(
+ getFunction(HWC2_FUNCTION_GET_HDR_CAPABILITIES));
+ ASSERT_TRUE(pfn) << "failed to get function";
+
+ uint32_t numTypes = 0;
+
+ auto err = static_cast<hwc2_error_t>(pfn(mHwc2Device, display,
+ &numTypes, nullptr, outMaxLuminance, outMaxAverageLuminance,
+ outMinLuminance));
+
+ if (err == HWC2_ERROR_NONE) {
+ outTypes->resize(numTypes);
+
+ err = static_cast<hwc2_error_t>(pfn(mHwc2Device, display, &numTypes,
+ reinterpret_cast<int32_t*>(outTypes->data()), outMaxLuminance,
+ outMaxAverageLuminance, outMinLuminance));
+ }
+
+ if (outErr) {
+ *outErr = err;
+ } else {
+ ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to get hdr capabilities"
+ " for display " << display;
+ }
+ }
+
+ void setColorTransform(hwc2_display_t display,
+ const std::array<float, 16>& matrix, android_color_transform_t hint,
+ hwc2_error_t* outErr = nullptr)
+ {
+ auto pfn = reinterpret_cast<HWC2_PFN_SET_COLOR_TRANSFORM>(
+ getFunction(HWC2_FUNCTION_SET_COLOR_TRANSFORM));
+ ASSERT_TRUE(pfn) << "failed to get function";
+
+ auto err = static_cast<hwc2_error_t>(pfn(mHwc2Device, display,
+ matrix.data(), hint));
+
+ if (outErr) {
+ *outErr = err;
+ } else {
+ ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to set color transform "
+ << hint;
+ }
+ }
+
+ void createVirtualDisplay(uint32_t width, uint32_t height,
+ android_pixel_format_t* outFormat, hwc2_display_t* outDisplay,
+ hwc2_error_t* outErr = nullptr)
+ {
+ auto pfn = reinterpret_cast<HWC2_PFN_CREATE_VIRTUAL_DISPLAY>(
+ getFunction(HWC2_FUNCTION_CREATE_VIRTUAL_DISPLAY));
+ ASSERT_TRUE(pfn) << "failed to get function";
+
+ auto err = static_cast<hwc2_error_t>(pfn(mHwc2Device, width, height,
+ reinterpret_cast<int32_t*>(outFormat), outDisplay));
+
+ if (err == HWC2_ERROR_NONE)
+ mVirtualDisplays.insert(*outDisplay);
+
+ if (outErr) {
+ *outErr = err;
+ } else {
+ ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to create virtual display";
+ }
+ }
+
+ void destroyVirtualDisplay(hwc2_display_t display,
+ hwc2_error_t* outErr = nullptr)
+ {
+ auto pfn = reinterpret_cast<HWC2_PFN_DESTROY_VIRTUAL_DISPLAY>(
+ getFunction(HWC2_FUNCTION_DESTROY_VIRTUAL_DISPLAY));
+ ASSERT_TRUE(pfn) << "failed to get function";
+
+ auto err = static_cast<hwc2_error_t>(pfn(mHwc2Device, display));
+
+ if (err == HWC2_ERROR_NONE)
+ mVirtualDisplays.erase(display);
+
+ if (outErr) {
+ *outErr = err;
+ } else {
+ ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to destroy virtual display";
+ }
+ }
+
+ void getMaxVirtualDisplayCount(uint32_t* outMaxCnt)
+ {
+ auto pfn = reinterpret_cast<HWC2_PFN_GET_MAX_VIRTUAL_DISPLAY_COUNT>(
+ getFunction(HWC2_FUNCTION_GET_MAX_VIRTUAL_DISPLAY_COUNT));
+ ASSERT_TRUE(pfn) << "failed to get function";
+
+ *outMaxCnt = pfn(mHwc2Device);
+ }
+
+ void setOutputBuffer(hwc2_display_t display, buffer_handle_t buffer,
+ int32_t releaseFence, hwc2_error_t* outErr = nullptr)
+ {
+ auto pfn = reinterpret_cast<HWC2_PFN_SET_OUTPUT_BUFFER>(
+ getFunction(HWC2_FUNCTION_SET_OUTPUT_BUFFER));
+ ASSERT_TRUE(pfn) << "failed to get function";
+
+ auto err = static_cast<hwc2_error_t>(pfn(mHwc2Device, display, buffer,
+ releaseFence));
+ if (outErr) {
+ *outErr = err;
+ } else {
+ ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to set output buffer";
+ }
+ }
+
+ void dump(std::string* outBuffer)
+ {
+ auto pfn = reinterpret_cast<HWC2_PFN_DUMP>(
+ getFunction(HWC2_FUNCTION_DUMP));
+ ASSERT_TRUE(pfn) << "failed to get function";
+
+ uint32_t size = 0;
+
+ pfn(mHwc2Device, &size, nullptr);
+
+ std::vector<char> buffer(size);
+
+ pfn(mHwc2Device, &size, buffer.data());
+
+ outBuffer->assign(buffer.data());
+ }
+
+ void getBadDisplay(hwc2_display_t* outDisplay)
+ {
+ for (hwc2_display_t display = 0; display < UINT64_MAX; display++) {
+ if (mDisplays.count(display) == 0) {
+ *outDisplay = display;
+ return;
+ }
+ }
+ ASSERT_TRUE(false) << "Unable to find bad display. UINT64_MAX displays"
+ " are registered. This should never happen.";
+ }
+
+ void waitForVsync(hwc2_display_t* outDisplay = nullptr,
+ int64_t* outTimestamp = nullptr)
+ {
+ std::unique_lock<std::mutex> lock(mVsyncMutex);
+ ASSERT_EQ(mVsyncCv.wait_for(lock, std::chrono::seconds(3)),
+ std::cv_status::no_timeout) << "timed out attempting to get"
+ " vsync callback";
+ if (outDisplay)
+ *outDisplay = mVsyncDisplay;
+ if (outTimestamp)
+ *outTimestamp = mVsyncTimestamp;
+ }
+
+ void enableVsync(hwc2_display_t display)
+ {
+ ASSERT_NO_FATAL_FAILURE(registerCallback(HWC2_CALLBACK_VSYNC, this,
+ reinterpret_cast<hwc2_function_pointer_t>(
+ hwc2TestVsyncCallback)));
+ ASSERT_NO_FATAL_FAILURE(setVsyncEnabled(display, HWC2_VSYNC_ENABLE));
+ }
+
+ void disableVsync(hwc2_display_t display)
+ {
+ ASSERT_NO_FATAL_FAILURE(setVsyncEnabled(display, HWC2_VSYNC_DISABLE));
+ }
+
+protected:
+ hwc2_function_pointer_t getFunction(hwc2_function_descriptor_t descriptor)
+ {
+ return mHwc2Device->getFunction(mHwc2Device, descriptor);
+ }
+
+ void getCapabilities(std::vector<hwc2_capability_t>* outCapabilities)
+ {
+ uint32_t num = 0;
+
+ mHwc2Device->getCapabilities(mHwc2Device, &num, nullptr);
+
+ outCapabilities->resize(num);
+
+ mHwc2Device->getCapabilities(mHwc2Device, &num,
+ reinterpret_cast<int32_t*>(outCapabilities->data()));
+ }
+
+ /* Registers a hotplug callback and waits for hotplug callbacks. This
+ * function will have no effect if called more than once. */
+ void populateDisplays()
+ {
+ /* Sets the hotplug status to receiving */
+ {
+ std::lock_guard<std::mutex> lock(mHotplugMutex);
+
+ if (mHotplugStatus != Hwc2TestHotplugStatus::Init)
+ return;
+ mHotplugStatus = Hwc2TestHotplugStatus::Receiving;
+ }
+
+ /* Registers the callback. This function call cannot be locked because
+ * a callback could happen on the same thread */
+ ASSERT_NO_FATAL_FAILURE(registerCallback(HWC2_CALLBACK_HOTPLUG, this,
+ reinterpret_cast<hwc2_function_pointer_t>(
+ hwc2TestHotplugCallback)));
+
+ /* Waits for hotplug events. If a hotplug event has not come within 1
+ * second, stop waiting. */
+ std::unique_lock<std::mutex> lock(mHotplugMutex);
+
+ while (mHotplugCv.wait_for(lock, std::chrono::seconds(1)) !=
+ std::cv_status::timeout) { }
+
+ /* Sets the hotplug status to done. Future calls will have no effect */
+ mHotplugStatus = Hwc2TestHotplugStatus::Done;
+ }
+
+ /* NOTE: will create min(newlayerCnt, max supported layers) layers */
+ void createLayers(hwc2_display_t display,
+ std::vector<hwc2_layer_t>* outLayers, size_t newLayerCnt)
+ {
+ std::vector<hwc2_layer_t> newLayers;
+ hwc2_layer_t layer;
+ hwc2_error_t err = HWC2_ERROR_NONE;
+
+ for (size_t i = 0; i < newLayerCnt; i++) {
+
+ EXPECT_NO_FATAL_FAILURE(createLayer(display, &layer, &err));
+ if (err == HWC2_ERROR_NO_RESOURCES)
+ break;
+ if (err != HWC2_ERROR_NONE) {
+ newLayers.clear();
+ ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to create layer";
+ }
+ newLayers.push_back(layer);
+ }
+
+ *outLayers = std::move(newLayers);
+ }
+
+ void destroyLayers(hwc2_display_t display,
+ std::vector<hwc2_layer_t>&& layers)
+ {
+ for (hwc2_layer_t layer : layers) {
+ EXPECT_NO_FATAL_FAILURE(destroyLayer(display, layer));
+ }
+ }
+
+ void getInvalidConfig(hwc2_display_t display, hwc2_config_t* outConfig)
+ {
+ std::vector<hwc2_config_t> configs;
+
+ ASSERT_NO_FATAL_FAILURE(getDisplayConfigs(display, &configs));
+
+ hwc2_config_t CONFIG_MAX = UINT32_MAX;
+
+ ASSERT_LE(configs.size() - 1, CONFIG_MAX) << "every config value"
+ " (2^32 values) has been taken which shouldn't happen";
+
+ hwc2_config_t config;
+ for (config = 0; config < CONFIG_MAX; config++) {
+ if (std::count(configs.begin(), configs.end(), config) == 0)
+ break;
+ }
+
+ *outConfig = config;
+ }
+
+ /* Calls a set property function from Hwc2Test to set a property value from
+ * Hwc2TestLayer to hwc2_layer_t on hwc2_display_t */
+ using TestLayerPropertyFunction = void (*)(Hwc2Test* test,
+ hwc2_display_t display, hwc2_layer_t layer,
+ Hwc2TestLayer* testLayer, hwc2_error_t* outErr);
+
+ /* Calls a set property function from Hwc2Test to set property values from
+ * Hwc2TestLayers to hwc2_layer_t on hwc2_display_t */
+ using TestLayerPropertiesFunction = void (*)(Hwc2Test* test,
+ hwc2_display_t display, hwc2_layer_t layer,
+ Hwc2TestLayers* testLayers);
+
+ /* Calls a set property function from Hwc2Test to set a bad property value
+ * on hwc2_layer_t on hwc2_display_t */
+ using TestLayerPropertyBadLayerFunction = void (*)(Hwc2Test* test,
+ hwc2_display_t display, hwc2_layer_t layer,
+ Hwc2TestLayer* testLayer, hwc2_error_t* outErr);
+
+ /* Calls a set property function from Hwc2Test to set a bad property value
+ * on hwc2_layer_t on hwc2_display_t */
+ using TestLayerPropertyBadParameterFunction = void (*)(Hwc2Test* test,
+ hwc2_display_t display, hwc2_layer_t layer, hwc2_error_t* outErr);
+
+ /* Is called after a display is powered on and all layer properties have
+ * been set. It should be used to test functions such as validate, accepting
+ * changes, present, etc. */
+ using TestDisplayLayersFunction = void (*)(Hwc2Test* test,
+ hwc2_display_t display, const std::vector<hwc2_layer_t>& layers,
+ Hwc2TestLayers* testLayers);
+
+ /* It is called on an non validated display */
+ using TestDisplayNonValidatedLayersFunction = void (*)(Hwc2Test* test,
+ hwc2_display_t display, std::vector<hwc2_layer_t>* layers);
+
+ /* Tests client target support on a particular display and config */
+ using TestClientTargetSupportFunction = void (*)(Hwc2Test* test,
+ hwc2_display_t display,
+ const Hwc2TestClientTargetSupport& testClientTargetSupport);
+
+ /* Tests a particular active display config */
+ using TestActiveDisplayConfigFunction = void (*)(Hwc2Test* test,
+ hwc2_display_t display);
+
+ /* Tests a newly created virtual display */
+ using TestCreateVirtualDisplayFunction = void (*)(Hwc2Test* test,
+ hwc2_display_t display, Hwc2TestVirtualDisplay* testVirtualDisplay);
+
+ /* Advances a property of Hwc2TestLayer */
+ using AdvanceProperty = bool (*)(Hwc2TestLayer* testLayer);
+
+ /* Advances properties of Hwc2TestLayers */
+ using AdvanceProperties = bool (*)(Hwc2TestLayers* testLayer);
+
+ /* Advances properties of Hwc2TestClientTargetSupport */
+ using AdvanceClientTargetSupport = bool (*)(
+ Hwc2TestClientTargetSupport* testClientTargetSupport);
+
+ /* For each active display it cycles through each display config and tests
+ * each property value. It creates a layer, sets the property and then
+ * destroys the layer */
+ void setLayerProperty(Hwc2TestCoverage coverage,
+ TestLayerPropertyFunction function, AdvanceProperty advance)
+ {
+ for (auto display : mDisplays) {
+ std::vector<hwc2_config_t> configs;
+
+ ASSERT_NO_FATAL_FAILURE(getDisplayConfigs(display, &configs));
+
+ for (auto config : configs) {
+ hwc2_layer_t layer;
+ Area displayArea;
+
+ ASSERT_NO_FATAL_FAILURE(setActiveConfig(display, config));
+ ASSERT_NO_FATAL_FAILURE(getActiveDisplayArea(display,
+ &displayArea));
+ Hwc2TestLayer testLayer(coverage, displayArea);
+
+ do {
+ ASSERT_NO_FATAL_FAILURE(createLayer(display, &layer));
+
+ ASSERT_NO_FATAL_FAILURE(function(this, display, layer,
+ &testLayer, nullptr));
+
+ ASSERT_NO_FATAL_FAILURE(destroyLayer(display, layer));
+ } while (advance(&testLayer));
+ }
+ }
+ }
+
+ /* For each active display it cycles through each display config and tests
+ * each property value. It creates a layer, cycles through each property
+ * value and updates the layer property value and then destroys the layer */
+ void setLayerPropertyUpdate(Hwc2TestCoverage coverage,
+ TestLayerPropertyFunction function, AdvanceProperty advance)
+ {
+ for (auto display : mDisplays) {
+ std::vector<hwc2_config_t> configs;
+
+ ASSERT_NO_FATAL_FAILURE(getDisplayConfigs(display, &configs));
+
+ for (auto config : configs) {
+ hwc2_layer_t layer;
+ Area displayArea;
+
+ ASSERT_NO_FATAL_FAILURE(setActiveConfig(display, config));
+ ASSERT_NO_FATAL_FAILURE(getActiveDisplayArea(display,
+ &displayArea));
+ Hwc2TestLayer testLayer(coverage, displayArea);
+
+ ASSERT_NO_FATAL_FAILURE(createLayer(display, &layer));
+
+ do {
+ ASSERT_NO_FATAL_FAILURE(function(this, display, layer,
+ &testLayer, nullptr));
+ } while (advance(&testLayer));
+
+ ASSERT_NO_FATAL_FAILURE(destroyLayer(display, layer));
+ }
+ }
+ }
+
+ /* For each active display it cycles through each display config and tests
+ * each property value. It creates multiple layers, calls the
+ * TestLayerPropertiesFunction to set property values and then
+ * destroys the layers */
+ void setLayerProperties(Hwc2TestCoverage coverage, size_t layerCnt,
+ TestLayerPropertiesFunction function, AdvanceProperties advance)
+ {
+ for (auto display : mDisplays) {
+ std::vector<hwc2_config_t> configs;
+
+ ASSERT_NO_FATAL_FAILURE(getDisplayConfigs(display, &configs));
+
+ for (auto config : configs) {
+ std::vector<hwc2_layer_t> layers;
+ Area displayArea;
+
+ ASSERT_NO_FATAL_FAILURE(setActiveConfig(display, config));
+ ASSERT_NO_FATAL_FAILURE(getActiveDisplayArea(display,
+ &displayArea));
+
+ ASSERT_NO_FATAL_FAILURE(createLayers(display, &layers, layerCnt));
+ Hwc2TestLayers testLayers(layers, coverage, displayArea);
+
+ do {
+ for (auto layer : layers) {
+ EXPECT_NO_FATAL_FAILURE(function(this, display, layer,
+ &testLayers));
+ }
+ } while (advance(&testLayers));
+
+ ASSERT_NO_FATAL_FAILURE(destroyLayers(display, std::move(layers)));
+ }
+ }
+ }
+
+ /* For each active display it cycles through each display config.
+ * 1) It attempts to set a valid property value to bad layer handle.
+ * 2) It creates a layer x and attempts to set a valid property value to
+ * layer x + 1
+ * 3) It destroys the layer x and attempts to set a valid property value to
+ * the destroyed layer x.
+ */
+ void setLayerPropertyBadLayer(Hwc2TestCoverage coverage,
+ TestLayerPropertyBadLayerFunction function)
+ {
+ for (auto display : mDisplays) {
+ std::vector<hwc2_config_t> configs;
+
+ ASSERT_NO_FATAL_FAILURE(getDisplayConfigs(display, &configs));
+
+ for (auto config : configs) {
+ hwc2_layer_t layer = 0;
+ Area displayArea;
+ hwc2_error_t err = HWC2_ERROR_NONE;
+
+ ASSERT_NO_FATAL_FAILURE(setActiveConfig(display, config));
+ ASSERT_NO_FATAL_FAILURE(getActiveDisplayArea(display,
+ &displayArea));
+ Hwc2TestLayer testLayer(coverage, displayArea);
+
+ ASSERT_NO_FATAL_FAILURE(function(this, display, layer,
+ &testLayer, &err));
+ EXPECT_EQ(err, HWC2_ERROR_BAD_LAYER) << "returned wrong error code";
+
+ ASSERT_NO_FATAL_FAILURE(createLayer(display, &layer));
+
+ ASSERT_NO_FATAL_FAILURE(function(this, display, layer + 1,
+ &testLayer, &err));
+ EXPECT_EQ(err, HWC2_ERROR_BAD_LAYER) << "returned wrong error code";
+
+ ASSERT_NO_FATAL_FAILURE(destroyLayer(display, layer));
+
+ ASSERT_NO_FATAL_FAILURE(function(this, display, layer,
+ &testLayer, &err));
+ EXPECT_EQ(err, HWC2_ERROR_BAD_LAYER) << "returned wrong error code";
+ }
+ }
+ }
+
+ /* For each active display it cycles through each display config and tests
+ * each property value. It creates a layer, sets a bad property value and
+ * then destroys the layer */
+ void setLayerPropertyBadParameter(TestLayerPropertyBadParameterFunction function)
+ {
+ for (auto display : mDisplays) {
+ std::vector<hwc2_config_t> configs;
+
+ ASSERT_NO_FATAL_FAILURE(getDisplayConfigs(display, &configs));
+
+ for (auto config : configs) {
+ hwc2_layer_t layer;
+ hwc2_error_t err = HWC2_ERROR_NONE;
+
+ ASSERT_NO_FATAL_FAILURE(setActiveConfig(display, config));
+
+ ASSERT_NO_FATAL_FAILURE(createLayer(display, &layer));
+
+ ASSERT_NO_FATAL_FAILURE(function(this, display, layer, &err));
+ EXPECT_EQ(err, HWC2_ERROR_BAD_PARAMETER) << "returned wrong"
+ " error code";
+
+ ASSERT_NO_FATAL_FAILURE(destroyLayer(display, layer));
+ }
+ }
+ }
+
+ /* For each active display it powers on the display, cycles through each
+ * config and creates a set of layers with a certain amount of coverage.
+ * For each active display, for each config and for each set of layers,
+ * it calls the TestDisplayLayersFunction */
+ void displayLayers(Hwc2TestCoverage coverage, size_t layerCnt,
+ TestDisplayLayersFunction function)
+ {
+ for (auto display : mDisplays) {
+ std::vector<hwc2_config_t> configs;
+
+ ASSERT_NO_FATAL_FAILURE(setPowerMode(display, HWC2_POWER_MODE_ON));
+
+ ASSERT_NO_FATAL_FAILURE(getDisplayConfigs(display, &configs));
+
+ for (auto config : configs) {
+ Area displayArea;
+ std::vector<hwc2_layer_t> layers;
+
+ ASSERT_NO_FATAL_FAILURE(setActiveConfig(display, config));
+ ASSERT_NO_FATAL_FAILURE(getActiveDisplayArea(display, &displayArea));
+
+ ASSERT_NO_FATAL_FAILURE(createLayers(display, &layers, layerCnt));
+ Hwc2TestLayers testLayers(layers, coverage, displayArea);
+
+ do {
+ bool skip;
+
+ ASSERT_NO_FATAL_FAILURE(setLayerProperties(display, layers,
+ &testLayers, &skip));
+ if (!skip)
+ EXPECT_NO_FATAL_FAILURE(function(this, display, layers,
+ &testLayers));
+
+ } while (testLayers.advance());
+
+ ASSERT_NO_FATAL_FAILURE(destroyLayers(display,
+ std::move(layers)));
+ }
+
+ ASSERT_NO_FATAL_FAILURE(setPowerMode(display, HWC2_POWER_MODE_OFF));
+ }
+ }
+
+ /* For each active display, it calls the
+ * TestDisplayNonValidatedLayersFunction on a variety on non-validated
+ * layer combinations */
+ void displayNonValidatedLayers(size_t layerCnt,
+ TestDisplayNonValidatedLayersFunction function)
+ {
+ for (auto display : mDisplays) {
+ uint32_t numTypes, numRequests;
+ std::vector<hwc2_layer_t> layers;
+ bool hasChanges;
+
+ ASSERT_NO_FATAL_FAILURE(setPowerMode(display, HWC2_POWER_MODE_ON));
+
+ EXPECT_NO_FATAL_FAILURE(function(this, display, &layers));
+
+ ASSERT_NO_FATAL_FAILURE(createLayers(display, &layers, layerCnt));
+
+ EXPECT_NO_FATAL_FAILURE(function(this, display, &layers));
+
+ for (auto layer : layers) {
+ ASSERT_NO_FATAL_FAILURE(setLayerCompositionType(display, layer,
+ HWC2_COMPOSITION_CLIENT));
+ }
+
+ EXPECT_NO_FATAL_FAILURE(function(this, display, &layers));
+
+ ASSERT_NO_FATAL_FAILURE(validateDisplay(display, &numTypes,
+ &numRequests, &hasChanges));
+
+ for (auto layer : layers) {
+ ASSERT_NO_FATAL_FAILURE(setLayerCompositionType(display, layer,
+ HWC2_COMPOSITION_DEVICE));
+ }
+
+ EXPECT_NO_FATAL_FAILURE(function(this, display, &layers));
+
+ ASSERT_NO_FATAL_FAILURE(destroyLayers(display, std::move(layers)));
+
+ EXPECT_NO_FATAL_FAILURE(function(this, display, &layers));
+
+ ASSERT_NO_FATAL_FAILURE(setPowerMode(display, HWC2_POWER_MODE_OFF));
+ }
+ }
+
+ /* Test client target support on each config on each active display */
+ void setClientTargetSupport(Hwc2TestCoverage coverage,
+ TestClientTargetSupportFunction function,
+ AdvanceClientTargetSupport advance)
+ {
+ for (auto display : mDisplays) {
+ std::vector<hwc2_config_t> configs;
+
+ ASSERT_NO_FATAL_FAILURE(getDisplayConfigs(display, &configs));
+
+ for (auto config : configs) {
+ Area displayArea;
+
+ ASSERT_NO_FATAL_FAILURE(setActiveConfig(display, config));
+ ASSERT_NO_FATAL_FAILURE(getActiveDisplayArea(display,
+ &displayArea));
+ Hwc2TestClientTargetSupport testClientTargetSupport(coverage,
+ displayArea);
+
+ do {
+ EXPECT_NO_FATAL_FAILURE(function(this, display,
+ testClientTargetSupport));
+
+ } while (advance(&testClientTargetSupport));
+ }
+ }
+ }
+
+ /* Cycles through each config on each active display and calls
+ * a TestActiveDisplayConfigFunction */
+ void setActiveDisplayConfig(TestActiveDisplayConfigFunction function)
+ {
+ for (auto display : mDisplays) {
+ std::vector<hwc2_config_t> configs;
+
+ ASSERT_NO_FATAL_FAILURE(getDisplayConfigs(display, &configs));
+
+ for (auto config : configs) {
+ ASSERT_NO_FATAL_FAILURE(setActiveConfig(display, config));
+
+ EXPECT_NO_FATAL_FAILURE(function(this, display));
+ }
+ }
+ }
+
+ /* Creates a virtual display for testing */
+ void createVirtualDisplay(Hwc2TestCoverage coverage,
+ TestCreateVirtualDisplayFunction function)
+ {
+ Hwc2TestVirtualDisplay testVirtualDisplay(coverage);
+
+ do {
+ hwc2_display_t display;
+ hwc2_error_t err = HWC2_ERROR_NONE;
+
+ const UnsignedArea& dimension =
+ testVirtualDisplay.getDisplayDimension();
+ android_pixel_format_t desiredFormat = HAL_PIXEL_FORMAT_RGBA_8888;
+
+ ASSERT_NO_FATAL_FAILURE(createVirtualDisplay(dimension.width,
+ dimension.height, &desiredFormat, &display, &err));
+
+ EXPECT_TRUE(err == HWC2_ERROR_NONE || err == HWC2_ERROR_NO_RESOURCES
+ || err == HWC2_ERROR_UNSUPPORTED)
+ << "returned wrong error code";
+ EXPECT_GE(desiredFormat, 0) << "invalid format";
+
+ if (err != HWC2_ERROR_NONE)
+ continue;
+
+ EXPECT_NO_FATAL_FAILURE(function(this, display,
+ &testVirtualDisplay));
+
+ ASSERT_NO_FATAL_FAILURE(destroyVirtualDisplay(display));
+
+ } while (testVirtualDisplay.advance());
+ }
+
+
+ void getActiveConfigAttribute(hwc2_display_t display,
+ hwc2_attribute_t attribute, int32_t* outValue)
+ {
+ hwc2_config_t config;
+ ASSERT_NO_FATAL_FAILURE(getActiveConfig(display, &config));
+ ASSERT_NO_FATAL_FAILURE(getDisplayAttribute(display, config,
+ attribute, outValue));
+ ASSERT_GE(*outValue, 0) << "failed to get valid "
+ << getAttributeName(attribute);
+ }
+
+ void getActiveDisplayArea(hwc2_display_t display, Area* displayArea)
+ {
+ ASSERT_NO_FATAL_FAILURE(getActiveConfigAttribute(display,
+ HWC2_ATTRIBUTE_WIDTH, &displayArea->width));
+ ASSERT_NO_FATAL_FAILURE(getActiveConfigAttribute(display,
+ HWC2_ATTRIBUTE_HEIGHT, &displayArea->height));
+ }
+
+ void closeFences(hwc2_display_t display, int32_t presentFence)
+ {
+ std::vector<hwc2_layer_t> layers;
+ std::vector<int32_t> fences;
+ const int msWait = 3000;
+
+ if (presentFence >= 0) {
+ ASSERT_GE(sync_wait(presentFence, msWait), 0);
+ close(presentFence);
+ }
+
+ ASSERT_NO_FATAL_FAILURE(getReleaseFences(display, &layers, &fences));
+ EXPECT_EQ(layers.size(), fences.size());
+
+ for (int32_t fence : fences) {
+ EXPECT_GE(sync_wait(fence, msWait), 0);
+ if (fence >= 0)
+ close(fence);
+ }
+ }
+
+ void setLayerProperties(hwc2_display_t display, hwc2_layer_t layer,
+ Hwc2TestLayers* testLayers, bool* outSkip)
+ {
+ hwc2_composition_t composition;
+ buffer_handle_t handle = nullptr;
+ int32_t acquireFence;
+ hwc2_error_t err = HWC2_ERROR_NONE;
+ *outSkip = true;
+
+ if (!testLayers->contains(layer))
+ return;
+
+ composition = testLayers->getComposition(layer);
+
+ /* If the device cannot support a buffer format, then do not continue */
+ if ((composition == HWC2_COMPOSITION_DEVICE
+ || composition == HWC2_COMPOSITION_CURSOR)
+ && testLayers->getBuffer(layer, &handle, &acquireFence) < 0)
+ return;
+
+ EXPECT_NO_FATAL_FAILURE(setLayerCompositionType(display, layer,
+ composition, &err));
+ if (err == HWC2_ERROR_UNSUPPORTED)
+ EXPECT_TRUE(composition != HWC2_COMPOSITION_CLIENT
+ && composition != HWC2_COMPOSITION_DEVICE);
+
+ const hwc_rect_t cursor = testLayers->getCursorPosition(layer);
+
+ EXPECT_NO_FATAL_FAILURE(setLayerBuffer(display, layer, handle,
+ acquireFence));
+ EXPECT_NO_FATAL_FAILURE(setLayerBlendMode(display, layer,
+ testLayers->getBlendMode(layer)));
+ EXPECT_NO_FATAL_FAILURE(setLayerColor(display, layer,
+ testLayers->getColor(layer)));
+ EXPECT_NO_FATAL_FAILURE(setCursorPosition(display, layer, cursor.left,
+ cursor.top));
+ EXPECT_NO_FATAL_FAILURE(setLayerDataspace(display, layer,
+ testLayers->getDataspace(layer)));
+ EXPECT_NO_FATAL_FAILURE(setLayerDisplayFrame(display, layer,
+ testLayers->getDisplayFrame(layer)));
+ EXPECT_NO_FATAL_FAILURE(setLayerPlaneAlpha(display, layer,
+ testLayers->getPlaneAlpha(layer)));
+ EXPECT_NO_FATAL_FAILURE(setLayerSourceCrop(display, layer,
+ testLayers->getSourceCrop(layer)));
+ EXPECT_NO_FATAL_FAILURE(setLayerSurfaceDamage(display, layer,
+ testLayers->getSurfaceDamage(layer)));
+ EXPECT_NO_FATAL_FAILURE(setLayerTransform(display, layer,
+ testLayers->getTransform(layer)));
+ EXPECT_NO_FATAL_FAILURE(setLayerVisibleRegion(display, layer,
+ testLayers->getVisibleRegion(layer)));
+ EXPECT_NO_FATAL_FAILURE(setLayerZOrder(display, layer,
+ testLayers->getZOrder(layer)));
+
+ *outSkip = false;
+ }
+
+ void setLayerProperties(hwc2_display_t display,
+ const std::vector<hwc2_layer_t>& layers,
+ Hwc2TestLayers* testLayers, bool* outSkip)
+ {
+ for (auto layer : layers) {
+ EXPECT_NO_FATAL_FAILURE(setLayerProperties(display, layer,
+ testLayers, outSkip));
+ if (*outSkip)
+ return;
+ }
+ }
+
+ void setClientTarget(hwc2_display_t display,
+ Hwc2TestClientTarget* testClientTarget,
+ const Hwc2TestLayers& testLayers,
+ const std::set<hwc2_layer_t>& clientLayers,
+ const std::set<hwc2_layer_t>& clearLayers, bool flipClientTarget,
+ const Area& displayArea)
+ {
+ android_dataspace_t dataspace = HAL_DATASPACE_UNKNOWN;
+ hwc_region_t damage = { };
+ buffer_handle_t handle;
+ int32_t acquireFence;
+
+ ASSERT_EQ(testClientTarget->getBuffer(testLayers, clientLayers,
+ clearLayers, flipClientTarget, displayArea, &handle,
+ &acquireFence), 0);
+ EXPECT_NO_FATAL_FAILURE(setClientTarget(display, handle, acquireFence,
+ dataspace, damage));
+ }
+
+ void presentDisplays(size_t layerCnt, Hwc2TestCoverage coverage,
+ const std::unordered_map<Hwc2TestPropertyName, Hwc2TestCoverage>&
+ coverageExceptions, bool optimize)
+ {
+ for (auto display : mDisplays) {
+ std::vector<hwc2_config_t> configs;
+
+ ASSERT_NO_FATAL_FAILURE(setPowerMode(display, HWC2_POWER_MODE_ON));
+ ASSERT_NO_FATAL_FAILURE(enableVsync(display));
+
+ ASSERT_NO_FATAL_FAILURE(getDisplayConfigs(display, &configs));
+
+ for (auto config : configs) {
+ Area displayArea;
+ std::vector<hwc2_layer_t> layers;
+
+ ASSERT_NO_FATAL_FAILURE(setActiveConfig(display, config));
+ ASSERT_NO_FATAL_FAILURE(getActiveDisplayArea(display,
+ &displayArea));
+
+ ASSERT_NO_FATAL_FAILURE(createLayers(display, &layers, layerCnt));
+ Hwc2TestLayers testLayers(layers, coverage, displayArea,
+ coverageExceptions);
+
+ if (optimize && !testLayers.optimizeLayouts())
+ continue;
+
+ std::set<hwc2_layer_t> clientLayers;
+ std::set<hwc2_layer_t> clearLayers;
+ Hwc2TestClientTarget testClientTarget;
+
+ do {
+ uint32_t numTypes, numRequests;
+ bool hasChanges, skip;
+ bool flipClientTarget;
+ int32_t presentFence;
+
+ ASSERT_NO_FATAL_FAILURE(setLayerProperties(display, layers,
+ &testLayers, &skip));
+ if (skip)
+ continue;
+
+ ASSERT_NO_FATAL_FAILURE(validateDisplay(display, &numTypes,
+ &numRequests, &hasChanges));
+ if (hasChanges)
+ EXPECT_LE(numTypes, static_cast<uint32_t>(layers.size()))
+ << "wrong number of requests";
+
+ ASSERT_NO_FATAL_FAILURE(handleCompositionChanges(display,
+ testLayers, layers, numTypes, &clientLayers));
+ ASSERT_NO_FATAL_FAILURE(handleRequests(display, layers,
+ numRequests, &clearLayers, &flipClientTarget));
+ ASSERT_NO_FATAL_FAILURE(setClientTarget(display,
+ &testClientTarget, testLayers, clientLayers,
+ clearLayers, flipClientTarget, displayArea));
+ ASSERT_NO_FATAL_FAILURE(acceptDisplayChanges(display));
+
+ ASSERT_NO_FATAL_FAILURE(waitForVsync());
+
+ EXPECT_NO_FATAL_FAILURE(presentDisplay(display,
+ &presentFence));
+
+ ASSERT_NO_FATAL_FAILURE(closeFences(display, presentFence));
+
+ } while (testLayers.advance());
+
+ ASSERT_NO_FATAL_FAILURE(destroyLayers(display,
+ std::move(layers)));
+ }
+
+ ASSERT_NO_FATAL_FAILURE(disableVsync(display));
+ ASSERT_NO_FATAL_FAILURE(setPowerMode(display, HWC2_POWER_MODE_OFF));
+ }
+ }
+
+ hwc2_device_t* mHwc2Device = nullptr;
+
+ enum class Hwc2TestHotplugStatus {
+ Init = 1,
+ Receiving,
+ Done,
+ };
+
+ std::mutex mHotplugMutex;
+ std::condition_variable mHotplugCv;
+ Hwc2TestHotplugStatus mHotplugStatus = Hwc2TestHotplugStatus::Init;
+ std::unordered_set<hwc2_display_t> mDisplays;
+
+ /* Store all created layers that have not been destroyed. If an ASSERT_*
+ * fails, then destroy the layers on exit */
+ std::set<std::pair<hwc2_display_t, hwc2_layer_t>> mLayers;
+
+ /* Store the power mode state. If it is not HWC2_POWER_MODE_OFF when
+ * tearing down the test cases, change it to HWC2_POWER_MODE_OFF */
+ std::set<hwc2_display_t> mActiveDisplays;
+
+ /* Store all created virtual displays that have not been destroyed. If an
+ * ASSERT_* fails, then destroy the virtual displays on exit */
+ std::set<hwc2_display_t> mVirtualDisplays;
+
+ std::mutex mVsyncMutex;
+ std::condition_variable mVsyncCv;
+ hwc2_display_t mVsyncDisplay;
+ int64_t mVsyncTimestamp = -1;
+};
+
+void hwc2TestHotplugCallback(hwc2_callback_data_t callbackData,
+ hwc2_display_t display, int32_t connection)
+{
+ if (callbackData)
+ static_cast<Hwc2Test*>(callbackData)->hotplugCallback(display,
+ connection);
+}
+
+void hwc2TestVsyncCallback(hwc2_callback_data_t callbackData,
+ hwc2_display_t display, int64_t timestamp)
+{
+ if (callbackData)
+ static_cast<Hwc2Test*>(callbackData)->vsyncCallback(display,
+ timestamp);
+}
+
+void setBlendMode(Hwc2Test* test, hwc2_display_t display, hwc2_layer_t layer,
+ Hwc2TestLayer* testLayer, hwc2_error_t* outErr)
+{
+ EXPECT_NO_FATAL_FAILURE(test->setLayerBlendMode(display, layer,
+ testLayer->getBlendMode(), outErr));
+}
+
+void setBuffer(Hwc2Test* test, hwc2_display_t display, hwc2_layer_t layer,
+ Hwc2TestLayer* testLayer, hwc2_error_t* outErr)
+{
+ buffer_handle_t handle;
+ android::base::unique_fd acquireFence;
+ hwc2_composition_t composition = testLayer->getComposition();
+
+ if (composition == HWC2_COMPOSITION_CLIENT
+ || composition == HWC2_COMPOSITION_SOLID_COLOR
+ || composition == HWC2_COMPOSITION_SIDEBAND)
+ return;
+
+ if (testLayer->getBuffer(&handle, &acquireFence) < 0)
+ return;
+
+ ASSERT_NO_FATAL_FAILURE(test->setLayerCompositionType(display, layer,
+ composition));
+ EXPECT_NO_FATAL_FAILURE(test->setLayerBuffer(display, layer,
+ handle, acquireFence, outErr));
+}
+
+void setColor(Hwc2Test* test, hwc2_display_t display, hwc2_layer_t layer,
+ Hwc2TestLayer* testLayer, hwc2_error_t* outErr)
+{
+ ASSERT_NO_FATAL_FAILURE(test->setLayerCompositionType(display,
+ layer, HWC2_COMPOSITION_SOLID_COLOR));
+ ASSERT_NO_FATAL_FAILURE(test->setLayerPlaneAlpha(display,
+ layer, testLayer->getPlaneAlpha()));
+ ASSERT_NO_FATAL_FAILURE(test->setLayerBlendMode(display,
+ layer, testLayer->getBlendMode()));
+ EXPECT_NO_FATAL_FAILURE(test->setLayerColor(display, layer,
+ testLayer->getColor(), outErr));
+}
+
+void setComposition(Hwc2Test* test, hwc2_display_t display, hwc2_layer_t layer,
+ Hwc2TestLayer* testLayer, hwc2_error_t* outErr)
+{
+ hwc2_composition_t composition = testLayer->getComposition();
+ hwc2_error_t err = HWC2_ERROR_NONE;
+
+ ASSERT_NO_FATAL_FAILURE(test->setLayerCompositionType(display, layer,
+ composition, &err));
+ if (outErr) {
+ *outErr = err;
+ return;
+ }
+
+ if (composition != HWC2_COMPOSITION_SIDEBAND) {
+ EXPECT_EQ(err, HWC2_ERROR_NONE) << "returned wrong error code";
+ } else {
+ EXPECT_TRUE(err == HWC2_ERROR_NONE || err == HWC2_ERROR_UNSUPPORTED)
+ << "returned wrong error code";
+ }
+}
+
+void setCursorPosition(Hwc2Test* test, hwc2_display_t display,
+ hwc2_layer_t layer, Hwc2TestLayer* testLayer, hwc2_error_t* outErr)
+{
+ ASSERT_NO_FATAL_FAILURE(test->setLayerCompositionType(display,
+ layer, HWC2_COMPOSITION_CURSOR));
+
+ const hwc_rect_t cursorPosition = testLayer->getCursorPosition();
+ EXPECT_NO_FATAL_FAILURE(test->setCursorPosition(display, layer,
+ cursorPosition.left, cursorPosition.top, outErr));
+}
+
+void setDataspace(Hwc2Test* test, hwc2_display_t display, hwc2_layer_t layer,
+ Hwc2TestLayer* testLayer, hwc2_error_t* outErr)
+{
+ EXPECT_NO_FATAL_FAILURE(test->setLayerDataspace(display, layer,
+ testLayer->getDataspace(), outErr));
+}
+
+void setDisplayFrame(Hwc2Test* test, hwc2_display_t display, hwc2_layer_t layer,
+ Hwc2TestLayer* testLayer, hwc2_error_t* outErr)
+{
+ EXPECT_NO_FATAL_FAILURE(test->setLayerDisplayFrame(display, layer,
+ testLayer->getDisplayFrame(), outErr));
+}
+
+void setPlaneAlpha(Hwc2Test* test, hwc2_display_t display, hwc2_layer_t layer,
+ Hwc2TestLayer* testLayer, hwc2_error_t *outErr)
+{
+ ASSERT_NO_FATAL_FAILURE(test->setLayerBlendMode(display, layer,
+ testLayer->getBlendMode()));
+ EXPECT_NO_FATAL_FAILURE(test->setLayerPlaneAlpha(display, layer,
+ testLayer->getPlaneAlpha(), outErr));
+}
+
+void setSourceCrop(Hwc2Test* test, hwc2_display_t display, hwc2_layer_t layer,
+ Hwc2TestLayer* testLayer, hwc2_error_t* outErr)
+{
+ EXPECT_NO_FATAL_FAILURE(test->setLayerSourceCrop(display, layer,
+ testLayer->getSourceCrop(), outErr));
+}
+
+void setSurfaceDamage(Hwc2Test* test, hwc2_display_t display, hwc2_layer_t layer,
+ Hwc2TestLayer* testLayer, hwc2_error_t* outErr)
+{
+ EXPECT_NO_FATAL_FAILURE(test->setLayerSurfaceDamage(display, layer,
+ testLayer->getSurfaceDamage(), outErr));
+}
+
+void setTransform(Hwc2Test* test, hwc2_display_t display, hwc2_layer_t layer,
+ Hwc2TestLayer* testLayer, hwc2_error_t* outErr)
+{
+ EXPECT_NO_FATAL_FAILURE(test->setLayerTransform(display, layer,
+ testLayer->getTransform(), outErr));
+}
+
+void setVisibleRegion(Hwc2Test* test, hwc2_display_t display, hwc2_layer_t layer,
+ Hwc2TestLayer* testLayer, hwc2_error_t* outErr)
+{
+ EXPECT_NO_FATAL_FAILURE(test->setLayerVisibleRegion(display, layer,
+ testLayer->getVisibleRegion(), outErr));
+}
+
+void setZOrder(Hwc2Test* test, hwc2_display_t display, hwc2_layer_t layer,
+ Hwc2TestLayer* testLayer, hwc2_error_t* outErr)
+{
+ EXPECT_NO_FATAL_FAILURE(test->setLayerZOrder(display, layer,
+ testLayer->getZOrder(), outErr));
+}
+
+bool advanceBlendMode(Hwc2TestLayer* testLayer)
+{
+ return testLayer->advanceBlendMode();
+}
+
+bool advanceBuffer(Hwc2TestLayer* testLayer)
+{
+ if (testLayer->advanceComposition())
+ return true;
+ return testLayer->advanceBufferArea();
+}
+
+bool advanceColor(Hwc2TestLayer* testLayer)
+{
+ /* Color depends on blend mode so advance blend mode last so color is not
+ * force to update as often */
+ if (testLayer->advancePlaneAlpha())
+ return true;
+ if (testLayer->advanceColor())
+ return true;
+ return testLayer->advanceBlendMode();
+}
+
+bool advanceComposition(Hwc2TestLayer* testLayer)
+{
+ return testLayer->advanceComposition();
+}
+
+bool advanceCursorPosition(Hwc2TestLayer* testLayer)
+{
+ return testLayer->advanceCursorPosition();
+}
+
+bool advanceDataspace(Hwc2TestLayer* testLayer)
+{
+ return testLayer->advanceDataspace();
+}
+
+bool advanceDisplayFrame(Hwc2TestLayer* testLayer)
+{
+ return testLayer->advanceDisplayFrame();
+}
+
+bool advancePlaneAlpha(Hwc2TestLayer* testLayer)
+{
+ return testLayer->advancePlaneAlpha();
+}
+
+bool advanceSourceCrop(Hwc2TestLayer* testLayer)
+{
+ if (testLayer->advanceSourceCrop())
+ return true;
+ return testLayer->advanceBufferArea();
+}
+
+bool advanceSurfaceDamage(Hwc2TestLayer* testLayer)
+{
+ if (testLayer->advanceSurfaceDamage())
+ return true;
+ return testLayer->advanceBufferArea();
+}
+
+bool advanceTransform(Hwc2TestLayer* testLayer)
+{
+ return testLayer->advanceTransform();
+}
+
+bool advanceVisibleRegions(Hwc2TestLayers* testLayers)
+{
+ return testLayers->advanceVisibleRegions();
+}
+
+bool advanceClientTargetSupport(
+ Hwc2TestClientTargetSupport* testClientTargetSupport)
+{
+ return testClientTargetSupport->advance();
+}
+
+static const std::array<hwc2_function_descriptor_t, 42> requiredFunctions = {{
+ HWC2_FUNCTION_ACCEPT_DISPLAY_CHANGES,
+ HWC2_FUNCTION_CREATE_LAYER,
+ HWC2_FUNCTION_CREATE_VIRTUAL_DISPLAY,
+ HWC2_FUNCTION_DESTROY_LAYER,
+ HWC2_FUNCTION_DESTROY_VIRTUAL_DISPLAY,
+ HWC2_FUNCTION_DUMP,
+ HWC2_FUNCTION_GET_ACTIVE_CONFIG,
+ HWC2_FUNCTION_GET_CHANGED_COMPOSITION_TYPES,
+ HWC2_FUNCTION_GET_CLIENT_TARGET_SUPPORT,
+ HWC2_FUNCTION_GET_COLOR_MODES,
+ HWC2_FUNCTION_GET_DISPLAY_ATTRIBUTE,
+ HWC2_FUNCTION_GET_DISPLAY_CONFIGS,
+ HWC2_FUNCTION_GET_DISPLAY_NAME,
+ HWC2_FUNCTION_GET_DISPLAY_REQUESTS,
+ HWC2_FUNCTION_GET_DISPLAY_TYPE,
+ HWC2_FUNCTION_GET_DOZE_SUPPORT,
+ HWC2_FUNCTION_GET_HDR_CAPABILITIES,
+ HWC2_FUNCTION_GET_MAX_VIRTUAL_DISPLAY_COUNT,
+ HWC2_FUNCTION_GET_RELEASE_FENCES,
+ HWC2_FUNCTION_PRESENT_DISPLAY,
+ HWC2_FUNCTION_REGISTER_CALLBACK,
+ HWC2_FUNCTION_SET_ACTIVE_CONFIG,
+ HWC2_FUNCTION_SET_CLIENT_TARGET,
+ HWC2_FUNCTION_SET_COLOR_MODE,
+ HWC2_FUNCTION_SET_COLOR_TRANSFORM,
+ HWC2_FUNCTION_SET_CURSOR_POSITION,
+ HWC2_FUNCTION_SET_LAYER_BLEND_MODE,
+ HWC2_FUNCTION_SET_LAYER_BUFFER,
+ HWC2_FUNCTION_SET_LAYER_COLOR,
+ HWC2_FUNCTION_SET_LAYER_COMPOSITION_TYPE,
+ HWC2_FUNCTION_SET_LAYER_DATASPACE,
+ HWC2_FUNCTION_SET_LAYER_DISPLAY_FRAME,
+ HWC2_FUNCTION_SET_LAYER_PLANE_ALPHA,
+ HWC2_FUNCTION_SET_LAYER_SOURCE_CROP,
+ HWC2_FUNCTION_SET_LAYER_SURFACE_DAMAGE,
+ HWC2_FUNCTION_SET_LAYER_TRANSFORM,
+ HWC2_FUNCTION_SET_LAYER_VISIBLE_REGION,
+ HWC2_FUNCTION_SET_LAYER_Z_ORDER,
+ HWC2_FUNCTION_SET_OUTPUT_BUFFER,
+ HWC2_FUNCTION_SET_POWER_MODE,
+ HWC2_FUNCTION_SET_VSYNC_ENABLED,
+ HWC2_FUNCTION_VALIDATE_DISPLAY,
+}};
+
+/* TESTCASE: Tests that the HWC2 supports all required functions. */
+TEST_F(Hwc2Test, GET_FUNCTION)
+{
+ for (hwc2_function_descriptor_t descriptor : requiredFunctions) {
+ hwc2_function_pointer_t pfn = getFunction(descriptor);
+ EXPECT_TRUE(pfn) << "failed to get function "
+ << getFunctionDescriptorName(descriptor);
+ }
+}
+
+/* TESTCASE: Tests that the HWC2 fails to retrieve and invalid function. */
+TEST_F(Hwc2Test, GET_FUNCTION_invalid_function)
+{
+ hwc2_function_pointer_t pfn = getFunction(HWC2_FUNCTION_INVALID);
+ EXPECT_FALSE(pfn) << "failed to get invalid function";
+}
+
+/* TESTCASE: Tests that the HWC2 does not return an invalid capability. */
+TEST_F(Hwc2Test, GET_CAPABILITIES)
+{
+ std::vector<hwc2_capability_t> capabilities;
+
+ getCapabilities(&capabilities);
+
+ EXPECT_EQ(std::count(capabilities.begin(), capabilities.end(),
+ HWC2_CAPABILITY_INVALID), 0);
+}
+
+static const std::array<hwc2_callback_descriptor_t, 3> callbackDescriptors = {{
+ HWC2_CALLBACK_HOTPLUG,
+ HWC2_CALLBACK_REFRESH,
+ HWC2_CALLBACK_VSYNC,
+}};
+
+/* TESTCASE: Tests that the HWC2 can successfully register all required
+ * callback functions. */
+TEST_F(Hwc2Test, REGISTER_CALLBACK)
+{
+ hwc2_callback_data_t data = reinterpret_cast<hwc2_callback_data_t>(
+ const_cast<char*>("data"));
+
+ for (auto descriptor : callbackDescriptors) {
+ ASSERT_NO_FATAL_FAILURE(registerCallback(descriptor, data,
+ []() { return; }));
+ }
+}
+
+/* TESTCASE: Test that the HWC2 fails to register invalid callbacks. */
+TEST_F(Hwc2Test, REGISTER_CALLBACK_bad_parameter)
+{
+ hwc2_callback_data_t data = reinterpret_cast<hwc2_callback_data_t>(
+ const_cast<char*>("data"));
+ hwc2_error_t err = HWC2_ERROR_NONE;
+
+ ASSERT_NO_FATAL_FAILURE(registerCallback(HWC2_CALLBACK_INVALID, data,
+ []() { return; }, &err));
+ EXPECT_EQ(err, HWC2_ERROR_BAD_PARAMETER) << "returned wrong error code";
+}
+
+/* TESTCASE: Tests that the HWC2 can register a callback with null data. */
+TEST_F(Hwc2Test, REGISTER_CALLBACK_null_data)
+{
+ hwc2_callback_data_t data = nullptr;
+
+ for (auto descriptor : callbackDescriptors) {
+ ASSERT_NO_FATAL_FAILURE(registerCallback(descriptor, data,
+ []() { return; }));
+ }
+}
+
+/* TESTCASE: Tests that the HWC2 returns the correct display type for each
+ * physical display. */
+TEST_F(Hwc2Test, GET_DISPLAY_TYPE)
+{
+ for (auto display : mDisplays) {
+ hwc2_display_type_t type;
+
+ ASSERT_NO_FATAL_FAILURE(getDisplayType(display, &type));
+ EXPECT_EQ(type, HWC2_DISPLAY_TYPE_PHYSICAL) << "failed to return"
+ " correct display type";
+ }
+}
+
+/* TESTCASE: Tests that the HWC2 returns an error when the display type of a bad
+ * display is requested. */
+TEST_F(Hwc2Test, GET_DISPLAY_TYPE_bad_display)
+{
+ hwc2_display_t display;
+ hwc2_display_type_t type;
+ hwc2_error_t err = HWC2_ERROR_NONE;
+
+ ASSERT_NO_FATAL_FAILURE(getBadDisplay(&display));
+
+ ASSERT_NO_FATAL_FAILURE(getDisplayType(display, &type, &err));
+ EXPECT_EQ(err, HWC2_ERROR_BAD_DISPLAY) << "returned wrong error code";
+}
+
+/* TESTCASE: Tests that the HWC2 can create and destroy layers. */
+TEST_F(Hwc2Test, CREATE_DESTROY_LAYER)
+{
+ for (auto display : mDisplays) {
+ hwc2_layer_t layer;
+
+ ASSERT_NO_FATAL_FAILURE(createLayer(display, &layer));
+
+ ASSERT_NO_FATAL_FAILURE(destroyLayer(display, layer));
+ }
+}
+
+/* TESTCASE: Tests that the HWC2 cannot create a layer for a bad display */
+TEST_F(Hwc2Test, CREATE_LAYER_bad_display)
+{
+ hwc2_display_t display;
+ hwc2_layer_t layer;
+ hwc2_error_t err = HWC2_ERROR_NONE;
+
+ ASSERT_NO_FATAL_FAILURE(getBadDisplay(&display));
+
+ ASSERT_NO_FATAL_FAILURE(createLayer(display, &layer, &err));
+ EXPECT_EQ(err, HWC2_ERROR_BAD_DISPLAY) << "returned wrong error code";
+}
+
+/* TESTCASE: Tests that the HWC2 will either support a large number of resources
+ * or will return no resources. */
+TEST_F(Hwc2Test, CREATE_LAYER_no_resources)
+{
+ const size_t layerCnt = 1000;
+
+ for (auto display : mDisplays) {
+ std::vector<hwc2_layer_t> layers;
+
+ ASSERT_NO_FATAL_FAILURE(createLayers(display, &layers, layerCnt));
+
+ ASSERT_NO_FATAL_FAILURE(destroyLayers(display, std::move(layers)));
+ }
+}
+
+/* TESTCASE: Tests that the HWC2 cannot destroy a layer for a bad display */
+TEST_F(Hwc2Test, DESTROY_LAYER_bad_display)
+{
+ hwc2_display_t badDisplay;
+
+ ASSERT_NO_FATAL_FAILURE(getBadDisplay(&badDisplay));
+
+ for (auto display : mDisplays) {
+ hwc2_layer_t layer = 0;
+ hwc2_error_t err = HWC2_ERROR_NONE;
+
+ ASSERT_NO_FATAL_FAILURE(destroyLayer(badDisplay, layer, &err));
+ EXPECT_EQ(err, HWC2_ERROR_BAD_DISPLAY) << "returned wrong error code";
+
+ ASSERT_NO_FATAL_FAILURE(createLayer(display, &layer));
+
+ ASSERT_NO_FATAL_FAILURE(destroyLayer(badDisplay, layer, &err));
+ EXPECT_EQ(err, HWC2_ERROR_BAD_DISPLAY) << "returned wrong error code";
+
+ ASSERT_NO_FATAL_FAILURE(destroyLayer(display, layer));
+ }
+}
+
+/* TESTCASE: Tests that the HWC2 cannot destory a bad layer */
+TEST_F(Hwc2Test, DESTROY_LAYER_bad_layer)
+{
+ for (auto display : mDisplays) {
+ hwc2_layer_t layer;
+ hwc2_error_t err = HWC2_ERROR_NONE;
+
+ ASSERT_NO_FATAL_FAILURE(destroyLayer(display, UINT64_MAX / 2, &err));
+ EXPECT_EQ(err, HWC2_ERROR_BAD_LAYER) << "returned wrong error code";
+
+ ASSERT_NO_FATAL_FAILURE(destroyLayer(display, 0, &err));
+ EXPECT_EQ(err, HWC2_ERROR_BAD_LAYER) << "returned wrong error code";
+
+ ASSERT_NO_FATAL_FAILURE(destroyLayer(display, UINT64_MAX - 1, &err));
+ EXPECT_EQ(err, HWC2_ERROR_BAD_LAYER) << "returned wrong error code";
+
+ ASSERT_NO_FATAL_FAILURE(destroyLayer(display, 1, &err));
+ EXPECT_EQ(err, HWC2_ERROR_BAD_LAYER) << "returned wrong error code";
+
+ ASSERT_NO_FATAL_FAILURE(destroyLayer(display, UINT64_MAX, &err));
+ EXPECT_EQ(err, HWC2_ERROR_BAD_LAYER) << "returned wrong error code";
+
+ ASSERT_NO_FATAL_FAILURE(createLayer(display, &layer));
+
+ ASSERT_NO_FATAL_FAILURE(destroyLayer(display, layer + 1, &err));
+ EXPECT_EQ(err, HWC2_ERROR_BAD_LAYER) << "returned wrong error code";
+
+ ASSERT_NO_FATAL_FAILURE(destroyLayer(display, layer));
+
+ ASSERT_NO_FATAL_FAILURE(destroyLayer(display, layer, &err));
+ EXPECT_EQ(err, HWC2_ERROR_BAD_LAYER) << "returned wrong error code";
+ }
+}
+
+static const std::array<hwc2_attribute_t, 2> requiredAttributes = {{
+ HWC2_ATTRIBUTE_WIDTH,
+ HWC2_ATTRIBUTE_HEIGHT,
+}};
+
+static const std::array<hwc2_attribute_t, 3> optionalAttributes = {{
+ HWC2_ATTRIBUTE_VSYNC_PERIOD,
+ HWC2_ATTRIBUTE_DPI_X,
+ HWC2_ATTRIBUTE_DPI_Y,
+}};
+
+/* TESTCASE: Tests that the HWC2 can return display attributes for a valid
+ * config. */
+TEST_F(Hwc2Test, GET_DISPLAY_ATTRIBUTE)
+{
+ for (auto display : mDisplays) {
+ std::vector<hwc2_config_t> configs;
+
+ ASSERT_NO_FATAL_FAILURE(getDisplayConfigs(display, &configs));
+
+ for (auto config : configs) {
+ int32_t value;
+
+ for (auto attribute : requiredAttributes) {
+ ASSERT_NO_FATAL_FAILURE(getDisplayAttribute(display, config,
+ attribute, &value));
+ EXPECT_GE(value, 0) << "missing required attribute "
+ << getAttributeName(attribute) << " for config "
+ << config;
+ }
+ for (auto attribute : optionalAttributes) {
+ ASSERT_NO_FATAL_FAILURE(getDisplayAttribute(display, config,
+ attribute, &value));
+ }
+ }
+ }
+}
+
+/* TESTCASE: Tests that the HWC2 will return a value of -1 for an invalid
+ * attribute */
+TEST_F(Hwc2Test, GET_DISPLAY_ATTRIBUTE_invalid_attribute)
+{
+ const hwc2_attribute_t attribute = HWC2_ATTRIBUTE_INVALID;
+
+ for (auto display : mDisplays) {
+ std::vector<hwc2_config_t> configs;
+
+ ASSERT_NO_FATAL_FAILURE(getDisplayConfigs(display, &configs));
+
+ for (auto config : configs) {
+ int32_t value;
+ hwc2_error_t err = HWC2_ERROR_NONE;
+
+ ASSERT_NO_FATAL_FAILURE(getDisplayAttribute(display, config,
+ attribute, &value, &err));
+ EXPECT_EQ(value, -1) << "failed to return -1 for an invalid"
+ " attribute for config " << config;
+ }
+ }
+}
+
+/* TESTCASE: Tests that the HWC2 will fail to get attributes for a bad display */
+TEST_F(Hwc2Test, GET_DISPLAY_ATTRIBUTE_bad_display)
+{
+ hwc2_display_t display;
+ const hwc2_config_t config = 0;
+ int32_t value;
+ hwc2_error_t err = HWC2_ERROR_NONE;
+
+ ASSERT_NO_FATAL_FAILURE(getBadDisplay(&display));
+
+ for (auto attribute : requiredAttributes) {
+ ASSERT_NO_FATAL_FAILURE(getDisplayAttribute(display, config, attribute,
+ &value, &err));
+ EXPECT_EQ(err, HWC2_ERROR_BAD_DISPLAY) << "returned wrong error code";
+ }
+
+ for (auto attribute : optionalAttributes) {
+ ASSERT_NO_FATAL_FAILURE(getDisplayAttribute(display, config, attribute,
+ &value, &err));
+ EXPECT_EQ(err, HWC2_ERROR_BAD_DISPLAY) << "returned wrong error code";
+ }
+}
+
+/* TESTCASE: Tests that the HWC2 will fail to get attributes for a bad config */
+TEST_F(Hwc2Test, GET_DISPLAY_ATTRIBUTE_bad_config)
+{
+ for (auto display : mDisplays) {
+ hwc2_config_t config;
+ int32_t value;
+ hwc2_error_t err = HWC2_ERROR_NONE;
+
+ ASSERT_NO_FATAL_FAILURE(getInvalidConfig(display, &config));
+
+ for (auto attribute : requiredAttributes) {
+ ASSERT_NO_FATAL_FAILURE(getDisplayAttribute(display, config,
+ attribute, &value, &err));
+ EXPECT_EQ(err, HWC2_ERROR_BAD_CONFIG) << "returned wrong error code";
+ }
+
+ for (auto attribute : optionalAttributes) {
+ ASSERT_NO_FATAL_FAILURE(getDisplayAttribute(display, config,
+ attribute, &value, &err));
+ EXPECT_EQ(err, HWC2_ERROR_BAD_CONFIG) << "returned wrong error code";
+ }
+ }
+}
+
+/* TESTCASE: Tests that the HWC2 will get display configs for active displays */
+TEST_F(Hwc2Test, GET_DISPLAY_CONFIGS)
+{
+ for (auto display : mDisplays) {
+ std::vector<hwc2_config_t> configs;
+
+ ASSERT_NO_FATAL_FAILURE(getDisplayConfigs(display, &configs));
+ }
+}
+
+/* TESTCASE: Tests that the HWC2 will not get display configs for bad displays */
+TEST_F(Hwc2Test, GET_DISPLAY_CONFIGS_bad_display)
+{
+ hwc2_display_t display;
+ std::vector<hwc2_config_t> configs;
+ hwc2_error_t err = HWC2_ERROR_NONE;
+
+ ASSERT_NO_FATAL_FAILURE(getBadDisplay(&display));
+
+ ASSERT_NO_FATAL_FAILURE(getDisplayConfigs(display, &configs, &err));
+
+ EXPECT_EQ(err, HWC2_ERROR_BAD_DISPLAY) << "returned wrong error code";
+ EXPECT_TRUE(configs.empty()) << "returned configs for bad display";
+}
+
+/* TESTCASE: Tests that the HWC2 will return the same config list multiple
+ * times in a row. */
+TEST_F(Hwc2Test, GET_DISPLAY_CONFIGS_same)
+{
+ for (auto display : mDisplays) {
+ std::vector<hwc2_config_t> configs1, configs2;
+
+ ASSERT_NO_FATAL_FAILURE(getDisplayConfigs(display, &configs1));
+ ASSERT_NO_FATAL_FAILURE(getDisplayConfigs(display, &configs2));
+
+ EXPECT_TRUE(std::is_permutation(configs1.begin(), configs1.end(),
+ configs2.begin())) << "returned two different config sets";
+ }
+}
+
+/* TESTCASE: Tests that the HWC2 does not return duplicate display configs */
+TEST_F(Hwc2Test, GET_DISPLAY_CONFIGS_duplicate)
+{
+ for (auto display : mDisplays) {
+ std::vector<hwc2_config_t> configs;
+
+ ASSERT_NO_FATAL_FAILURE(getDisplayConfigs(display, &configs));
+
+ std::unordered_set<hwc2_config_t> configsSet(configs.begin(),
+ configs.end());
+ EXPECT_EQ(configs.size(), configsSet.size()) << "returned duplicate"
+ " configs";
+ }
+}
+
+/* TESTCASE: Tests that the HWC2 returns the active config for a display */
+TEST_F(Hwc2Test, GET_ACTIVE_CONFIG)
+{
+ for (auto display : mDisplays) {
+ std::vector<hwc2_config_t> configs;
+
+ ASSERT_NO_FATAL_FAILURE(getDisplayConfigs(display, &configs));
+
+ for (auto config : configs) {
+ hwc2_config_t activeConfig;
+
+ ASSERT_NO_FATAL_FAILURE(setActiveConfig(display, config));
+ ASSERT_NO_FATAL_FAILURE(getActiveConfig(display, &activeConfig));
+
+ EXPECT_EQ(activeConfig, config) << "failed to get active config";
+ }
+ }
+}
+
+/* TESTCASE: Tests that the HWC2 does not return an active config for a bad
+ * display. */
+TEST_F(Hwc2Test, GET_ACTIVE_CONFIG_bad_display)
+{
+ hwc2_display_t display;
+ hwc2_config_t activeConfig;
+ hwc2_error_t err = HWC2_ERROR_NONE;
+
+ ASSERT_NO_FATAL_FAILURE(getBadDisplay(&display));
+
+ ASSERT_NO_FATAL_FAILURE(getActiveConfig(display, &activeConfig, &err));
+
+ EXPECT_EQ(err, HWC2_ERROR_BAD_DISPLAY) << "returned wrong error code";
+}
+
+/* TESTCASE: Tests that the HWC2 either begins with a valid active config
+ * or returns an error when getActiveConfig is called. */
+TEST_F(Hwc2Test, GET_ACTIVE_CONFIG_bad_config)
+{
+ for (auto display : mDisplays) {
+ std::vector<hwc2_config_t> configs;
+ hwc2_config_t activeConfig;
+ hwc2_error_t err = HWC2_ERROR_NONE;
+
+ ASSERT_NO_FATAL_FAILURE(getDisplayConfigs(display, &configs));
+
+ if (configs.empty())
+ return;
+
+ ASSERT_NO_FATAL_FAILURE(getActiveConfig(display, &activeConfig, &err));
+ if (err == HWC2_ERROR_NONE) {
+ EXPECT_NE(std::count(configs.begin(), configs.end(),
+ activeConfig), 0) << "active config is not found in "
+ " configs for display";
+ } else {
+ EXPECT_EQ(err, HWC2_ERROR_BAD_CONFIG) << "returned wrong error code";
+ }
+ }
+}
+
+/* TESTCASE: Tests that the HWC2 can set every display config as an active
+ * config */
+TEST_F(Hwc2Test, SET_ACTIVE_CONFIG)
+{
+ for (auto display : mDisplays) {
+ std::vector<hwc2_config_t> configs;
+
+ ASSERT_NO_FATAL_FAILURE(getDisplayConfigs(display, &configs));
+
+ for (auto config : configs) {
+ EXPECT_NO_FATAL_FAILURE(setActiveConfig(display, config));
+ }
+ }
+}
+
+/* TESTCASE: Tests that the HWC2 cannot set an active config for a bad display */
+TEST_F(Hwc2Test, SET_ACTIVE_CONFIG_bad_display)
+{
+ hwc2_display_t display;
+ const hwc2_config_t config = 0;
+ hwc2_error_t err = HWC2_ERROR_NONE;
+
+ ASSERT_NO_FATAL_FAILURE(getBadDisplay(&display));
+
+ ASSERT_NO_FATAL_FAILURE(setActiveConfig(display, config, &err));
+ EXPECT_EQ(err, HWC2_ERROR_BAD_DISPLAY) << "returned wrong error code";
+}
+
+/* TESTCASE: Tests that the HWC2 cannot set an invalid active config */
+TEST_F(Hwc2Test, SET_ACTIVE_CONFIG_bad_config)
+{
+ for (auto display : mDisplays) {
+ hwc2_config_t config;
+ hwc2_error_t err = HWC2_ERROR_NONE;
+
+ ASSERT_NO_FATAL_FAILURE(getInvalidConfig(display, &config));
+
+ ASSERT_NO_FATAL_FAILURE(setActiveConfig(display, config, &err));
+ EXPECT_EQ(err, HWC2_ERROR_BAD_CONFIG) << "returned wrong error code";
+ }
+}
+
+/* TESTCASE: Tests that the HWC2 returns a valid value for getDozeSupport. */
+TEST_F(Hwc2Test, GET_DOZE_SUPPORT)
+{
+ for (auto display : mDisplays) {
+ int32_t support = -1;
+
+ ASSERT_NO_FATAL_FAILURE(getDozeSupport(display, &support));
+
+ EXPECT_TRUE(support == 0 || support == 1) << "invalid doze support value";
+ }
+}
+
+/* TESTCASE: Tests that the HWC2 cannot get doze support for a bad display. */
+TEST_F(Hwc2Test, GET_DOZE_SUPPORT_bad_display)
+{
+ hwc2_display_t display;
+ int32_t support = -1;
+ hwc2_error_t err = HWC2_ERROR_NONE;
+
+ ASSERT_NO_FATAL_FAILURE(getBadDisplay(&display));
+
+ ASSERT_NO_FATAL_FAILURE(getDozeSupport(display, &support, &err));
+
+ EXPECT_EQ(err, HWC2_ERROR_BAD_DISPLAY) << "returned wrong error code";
+}
+
+/* TESTCASE: Tests that the HWC2 can set all supported power modes */
+TEST_F(Hwc2Test, SET_POWER_MODE)
+{
+ for (auto display : mDisplays) {
+ ASSERT_NO_FATAL_FAILURE(setPowerMode(display, HWC2_POWER_MODE_ON));
+ ASSERT_NO_FATAL_FAILURE(setPowerMode(display, HWC2_POWER_MODE_OFF));
+
+ int32_t support = -1;
+ ASSERT_NO_FATAL_FAILURE(getDozeSupport(display, &support));
+ if (support != 1)
+ return;
+
+ ASSERT_NO_FATAL_FAILURE(setPowerMode(display, HWC2_POWER_MODE_DOZE));
+ ASSERT_NO_FATAL_FAILURE(setPowerMode(display,
+ HWC2_POWER_MODE_DOZE_SUSPEND));
+
+ ASSERT_NO_FATAL_FAILURE(setPowerMode(display, HWC2_POWER_MODE_OFF));
+ }
+}
+
+/* TESTCASE: Tests that the HWC2 cannot set a power mode for a bad display. */
+TEST_F(Hwc2Test, SET_POWER_MODE_bad_display)
+{
+ hwc2_display_t display;
+ hwc2_error_t err = HWC2_ERROR_NONE;
+
+ ASSERT_NO_FATAL_FAILURE(getBadDisplay(&display));
+
+ ASSERT_NO_FATAL_FAILURE(setPowerMode(display, HWC2_POWER_MODE_ON, &err));
+ EXPECT_EQ(err, HWC2_ERROR_BAD_DISPLAY) << "returned wrong error code";
+
+ ASSERT_NO_FATAL_FAILURE(setPowerMode(display, HWC2_POWER_MODE_OFF, &err));
+ EXPECT_EQ(err, HWC2_ERROR_BAD_DISPLAY) << "returned wrong error code";
+
+ int32_t support = -1;
+ ASSERT_NO_FATAL_FAILURE(getDozeSupport(display, &support, &err));
+ if (support != 1)
+ return;
+
+ ASSERT_NO_FATAL_FAILURE(setPowerMode(display, HWC2_POWER_MODE_DOZE, &err));
+ EXPECT_EQ(err, HWC2_ERROR_BAD_DISPLAY) << "returned wrong error code";
+
+ ASSERT_NO_FATAL_FAILURE(setPowerMode(display, HWC2_POWER_MODE_DOZE_SUSPEND,
+ &err));
+ EXPECT_EQ(err, HWC2_ERROR_BAD_DISPLAY) << "returned wrong error code";
+}
+
+/* TESTCASE: Tests that the HWC2 cannot set an invalid power mode value. */
+TEST_F(Hwc2Test, SET_POWER_MODE_bad_parameter)
+{
+ for (auto display : mDisplays) {
+ hwc2_power_mode_t mode = static_cast<hwc2_power_mode_t>(
+ HWC2_POWER_MODE_DOZE_SUSPEND + 1);
+ hwc2_error_t err = HWC2_ERROR_NONE;
+
+ ASSERT_NO_FATAL_FAILURE(setPowerMode(display, mode, &err));
+ EXPECT_EQ(err, HWC2_ERROR_BAD_PARAMETER) << "returned wrong error code "
+ << mode;
+ }
+}
+
+/* TESTCASE: Tests that the HWC2 will return unsupported if it does not support
+ * an optional power mode. */
+TEST_F(Hwc2Test, SET_POWER_MODE_unsupported)
+{
+ for (auto display : mDisplays) {
+ int32_t support = -1;
+ hwc2_error_t err = HWC2_ERROR_NONE;
+
+ ASSERT_NO_FATAL_FAILURE(getDozeSupport(display, &support, &err));
+ if (support == 1)
+ return;
+
+ ASSERT_EQ(support, 0) << "invalid doze support value";
+
+ ASSERT_NO_FATAL_FAILURE(setPowerMode(display, HWC2_POWER_MODE_DOZE,
+ &err));
+ EXPECT_EQ(err, HWC2_ERROR_UNSUPPORTED) << "returned wrong error code";
+
+ ASSERT_NO_FATAL_FAILURE(setPowerMode(display,
+ HWC2_POWER_MODE_DOZE_SUSPEND, &err));
+ EXPECT_EQ(err, HWC2_ERROR_UNSUPPORTED) << "returned wrong error code";
+ }
+}
+
+/* TESTCASE: Tests that the HWC2 can set the same power mode multiple times. */
+TEST_F(Hwc2Test, SET_POWER_MODE_stress)
+{
+ for (auto display : mDisplays) {
+ ASSERT_NO_FATAL_FAILURE(setPowerMode(display, HWC2_POWER_MODE_OFF));
+ ASSERT_NO_FATAL_FAILURE(setPowerMode(display, HWC2_POWER_MODE_OFF));
+
+ ASSERT_NO_FATAL_FAILURE(setPowerMode(display, HWC2_POWER_MODE_ON));
+ ASSERT_NO_FATAL_FAILURE(setPowerMode(display, HWC2_POWER_MODE_ON));
+
+ ASSERT_NO_FATAL_FAILURE(setPowerMode(display, HWC2_POWER_MODE_OFF));
+ ASSERT_NO_FATAL_FAILURE(setPowerMode(display, HWC2_POWER_MODE_OFF));
+
+ int32_t support = -1;
+ ASSERT_NO_FATAL_FAILURE(getDozeSupport(display, &support));
+ if (support != 1)
+ return;
+
+ ASSERT_NO_FATAL_FAILURE(setPowerMode(display, HWC2_POWER_MODE_DOZE));
+ ASSERT_NO_FATAL_FAILURE(setPowerMode(display, HWC2_POWER_MODE_DOZE));
+
+ ASSERT_NO_FATAL_FAILURE(setPowerMode(display,
+ HWC2_POWER_MODE_DOZE_SUSPEND));
+ ASSERT_NO_FATAL_FAILURE(setPowerMode(display,
+ HWC2_POWER_MODE_DOZE_SUSPEND));
+
+ ASSERT_NO_FATAL_FAILURE(setPowerMode(display, HWC2_POWER_MODE_OFF));
+ }
+}
+
+/* TESTCASE: Tests that the HWC2 can enable and disable vsync on active
+ * displays */
+TEST_F(Hwc2Test, SET_VSYNC_ENABLED)
+{
+ for (auto display : mDisplays) {
+ hwc2_callback_data_t data = reinterpret_cast<hwc2_callback_data_t>(
+ const_cast<char*>("data"));
+
+ ASSERT_NO_FATAL_FAILURE(setPowerMode(display, HWC2_POWER_MODE_ON));
+
+ ASSERT_NO_FATAL_FAILURE(registerCallback(HWC2_CALLBACK_VSYNC, data,
+ []() { return; }));
+
+ ASSERT_NO_FATAL_FAILURE(setVsyncEnabled(display, HWC2_VSYNC_ENABLE));
+
+ ASSERT_NO_FATAL_FAILURE(setVsyncEnabled(display, HWC2_VSYNC_DISABLE));
+
+ ASSERT_NO_FATAL_FAILURE(setPowerMode(display, HWC2_POWER_MODE_OFF));
+ }
+}
+
+/* TESTCASE: Tests that the HWC2 issues a valid vsync callback. */
+TEST_F(Hwc2Test, SET_VSYNC_ENABLED_callback)
+{
+ for (auto display : mDisplays) {
+ hwc2_display_t receivedDisplay;
+ int64_t receivedTimestamp;
+
+ ASSERT_NO_FATAL_FAILURE(setPowerMode(display, HWC2_POWER_MODE_ON));
+
+ ASSERT_NO_FATAL_FAILURE(enableVsync(display));
+
+ ASSERT_NO_FATAL_FAILURE(waitForVsync(&receivedDisplay,
+ &receivedTimestamp));
+
+ EXPECT_EQ(receivedDisplay, display) << "failed to get correct display";
+ EXPECT_GE(receivedTimestamp, 0) << "failed to get valid timestamp";
+
+ ASSERT_NO_FATAL_FAILURE(disableVsync(display));
+
+ ASSERT_NO_FATAL_FAILURE(setPowerMode(display, HWC2_POWER_MODE_OFF));
+ }
+}
+
+/* TESTCASE: Tests that the HWC2 cannot enable a vsync for a bad display */
+TEST_F(Hwc2Test, SET_VSYNC_ENABLED_bad_display)
+{
+ hwc2_display_t display;
+ hwc2_callback_data_t data = reinterpret_cast<hwc2_callback_data_t>(
+ const_cast<char*>("data"));
+ hwc2_error_t err = HWC2_ERROR_NONE;
+
+ ASSERT_NO_FATAL_FAILURE(getBadDisplay(&display));
+
+ ASSERT_NO_FATAL_FAILURE(registerCallback(HWC2_CALLBACK_VSYNC, data,
+ []() { return; }));
+
+ ASSERT_NO_FATAL_FAILURE(setVsyncEnabled(display, HWC2_VSYNC_ENABLE, &err));
+ EXPECT_EQ(err, HWC2_ERROR_BAD_DISPLAY) << "returned wrong error code";
+
+ ASSERT_NO_FATAL_FAILURE(setVsyncEnabled(display, HWC2_VSYNC_DISABLE, &err));
+ EXPECT_EQ(err, HWC2_ERROR_BAD_DISPLAY) << "returned wrong error code";
+}
+
+/* TESTCASE: Tests that the HWC2 cannot enable an invalid vsync value */
+TEST_F(Hwc2Test, SET_VSYNC_ENABLED_bad_parameter)
+{
+ for (auto display : mDisplays) {
+ hwc2_callback_data_t data = reinterpret_cast<hwc2_callback_data_t>(
+ const_cast<char*>("data"));
+ hwc2_error_t err = HWC2_ERROR_NONE;
+
+ ASSERT_NO_FATAL_FAILURE(setPowerMode(display, HWC2_POWER_MODE_ON));
+
+ ASSERT_NO_FATAL_FAILURE(registerCallback(HWC2_CALLBACK_VSYNC, data,
+ []() { return; }));
+
+ ASSERT_NO_FATAL_FAILURE(setVsyncEnabled(display, HWC2_VSYNC_INVALID,
+ &err));
+ EXPECT_EQ(err, HWC2_ERROR_BAD_PARAMETER) << "returned wrong error code";
+
+ ASSERT_NO_FATAL_FAILURE(setPowerMode(display, HWC2_POWER_MODE_OFF));
+ }
+}
+
+/* TESTCASE: Tests that the HWC2 can enable and disable a vsync value multiple
+ * times. */
+TEST_F(Hwc2Test, SET_VSYNC_ENABLED_stress)
+{
+ for (auto display : mDisplays) {
+ hwc2_callback_data_t data = reinterpret_cast<hwc2_callback_data_t>(
+ const_cast<char*>("data"));
+
+ ASSERT_NO_FATAL_FAILURE(setPowerMode(display, HWC2_POWER_MODE_ON));
+
+ ASSERT_NO_FATAL_FAILURE(registerCallback(HWC2_CALLBACK_VSYNC, data,
+ []() { return; }));
+
+ ASSERT_NO_FATAL_FAILURE(setVsyncEnabled(display, HWC2_VSYNC_DISABLE));
+
+ ASSERT_NO_FATAL_FAILURE(setVsyncEnabled(display, HWC2_VSYNC_ENABLE));
+ ASSERT_NO_FATAL_FAILURE(setVsyncEnabled(display, HWC2_VSYNC_ENABLE));
+
+ ASSERT_NO_FATAL_FAILURE(setVsyncEnabled(display, HWC2_VSYNC_DISABLE));
+ ASSERT_NO_FATAL_FAILURE(setVsyncEnabled(display, HWC2_VSYNC_DISABLE));
+
+ ASSERT_NO_FATAL_FAILURE(setPowerMode(display, HWC2_POWER_MODE_OFF));
+ }
+}
+
+/* TESTCASE: Tests that the HWC2 can set a vsync enable value when the display
+ * is off and no callback is registered. */
+TEST_F(Hwc2Test, SET_VSYNC_ENABLED_no_callback_no_power)
+{
+ const uint secs = 1;
+
+ for (auto display : mDisplays) {
+ ASSERT_NO_FATAL_FAILURE(setVsyncEnabled(display, HWC2_VSYNC_ENABLE));
+
+ sleep(secs);
+
+ ASSERT_NO_FATAL_FAILURE(setVsyncEnabled(display, HWC2_VSYNC_DISABLE));
+ }
+}
+
+/* TESTCASE: Tests that the HWC2 can set a vsync enable value when no callback
+ * is registered. */
+TEST_F(Hwc2Test, SET_VSYNC_ENABLED_no_callback)
+{
+ const uint secs = 1;
+
+ for (auto display : mDisplays) {
+ ASSERT_NO_FATAL_FAILURE(setPowerMode(display, HWC2_POWER_MODE_ON));
+
+ ASSERT_NO_FATAL_FAILURE(setVsyncEnabled(display, HWC2_VSYNC_ENABLE));
+
+ sleep(secs);
+
+ ASSERT_NO_FATAL_FAILURE(setVsyncEnabled(display, HWC2_VSYNC_DISABLE));
+
+ ASSERT_NO_FATAL_FAILURE(setPowerMode(display, HWC2_POWER_MODE_OFF));
+ }
+}
+
+/* TESTCASE: Tests that the HWC2 returns a display name for each display */
+TEST_F(Hwc2Test, GET_DISPLAY_NAME)
+{
+ for (auto display : mDisplays) {
+ std::string name;
+
+ ASSERT_NO_FATAL_FAILURE(getDisplayName(display, &name));
+ }
+}
+
+/* TESTCASE: Tests that the HWC2 does not return a display name for a bad
+ * display */
+TEST_F(Hwc2Test, GET_DISPLAY_NAME_bad_display)
+{
+ hwc2_display_t display;
+ std::string name;
+ hwc2_error_t err = HWC2_ERROR_NONE;
+
+ ASSERT_NO_FATAL_FAILURE(getBadDisplay(&display));
+
+ ASSERT_NO_FATAL_FAILURE(getDisplayName(display, &name, &err));
+ EXPECT_EQ(err, HWC2_ERROR_BAD_DISPLAY) << "returned wrong error code";
+}
+
+/* TESTCASE: Tests that the HWC2 can set basic composition types. */
+TEST_F(Hwc2Test, SET_LAYER_COMPOSITION_TYPE)
+{
+ ASSERT_NO_FATAL_FAILURE(setLayerProperty(Hwc2TestCoverage::Complete,
+ setComposition, advanceComposition));
+}
+
+/* TESTCASE: Tests that the HWC2 can update a basic composition type on a
+ * layer. */
+TEST_F(Hwc2Test, SET_LAYER_COMPOSITION_TYPE_update)
+{
+ ASSERT_NO_FATAL_FAILURE(setLayerPropertyUpdate(Hwc2TestCoverage::Complete,
+ setComposition, advanceComposition));
+}
+
+/* TESTCASE: Tests that the HWC2 cannot set a composition type for a bad layer */
+TEST_F(Hwc2Test, SET_LAYER_COMPOSITION_TYPE_bad_layer)
+{
+ ASSERT_NO_FATAL_FAILURE(setLayerPropertyBadLayer(Hwc2TestCoverage::Default,
+ setComposition));
+}
+
+/* TESTCASE: Tests that the HWC2 cannot set a bad composition type */
+TEST_F(Hwc2Test, SET_LAYER_COMPOSITION_TYPE_bad_parameter)
+{
+ ASSERT_NO_FATAL_FAILURE(setLayerPropertyBadParameter(
+ [] (Hwc2Test* test, hwc2_display_t display, hwc2_layer_t layer,
+ hwc2_error_t* outErr) {
+
+ ASSERT_NO_FATAL_FAILURE(test->setLayerCompositionType(display,
+ layer, HWC2_COMPOSITION_INVALID, outErr));
+ }
+ ));
+}
+
+/* TESTCASE: Tests that the HWC2 can set the cursor position of a layer. */
+TEST_F(Hwc2Test, SET_CURSOR_POSITION)
+{
+ ASSERT_NO_FATAL_FAILURE(setLayerProperty(Hwc2TestCoverage::Complete,
+ ::setCursorPosition, advanceCursorPosition));
+}
+
+/* TESTCASE: Tests that the HWC2 can update the cursor position of a layer. */
+TEST_F(Hwc2Test, SET_CURSOR_POSITION_update)
+{
+ ASSERT_NO_FATAL_FAILURE(setLayerPropertyUpdate(Hwc2TestCoverage::Complete,
+ ::setCursorPosition, advanceCursorPosition));
+}
+
+/* TESTCASE: Tests that the HWC2 can set the cursor position of a layer when the
+ * composition type has not been set to HWC2_COMPOSITION_CURSOR. */
+TEST_F(Hwc2Test, SET_CURSOR_POSITION_composition_type_unset)
+{
+ ASSERT_NO_FATAL_FAILURE(setLayerProperty(Hwc2TestCoverage::Complete,
+ [] (Hwc2Test* test, hwc2_display_t display, hwc2_layer_t layer,
+ Hwc2TestLayer* testLayer, hwc2_error_t* outErr) {
+
+ const hwc_rect_t cursorPosition = testLayer->getCursorPosition();
+ EXPECT_NO_FATAL_FAILURE(test->setCursorPosition(display, layer,
+ cursorPosition.left, cursorPosition.top, outErr));
+ },
+
+ advanceCursorPosition));
+}
+
+/* TESTCASE: Tests that the HWC2 cannot set the cursor position of a bad
+ * display. */
+TEST_F(Hwc2Test, SET_CURSOR_POSITION_bad_display)
+{
+ hwc2_display_t display;
+ hwc2_layer_t layer = 0;
+ int32_t x = 0, y = 0;
+ hwc2_error_t err = HWC2_ERROR_NONE;
+
+ ASSERT_NO_FATAL_FAILURE(getBadDisplay(&display));
+
+ ASSERT_NO_FATAL_FAILURE(setCursorPosition(display, layer, x, y, &err));
+ EXPECT_EQ(err, HWC2_ERROR_BAD_DISPLAY) << "returned wrong error code";
+}
+
+/* TESTCASE: Tests that the HWC2 cannot set the cursor position of a bad layer. */
+TEST_F(Hwc2Test, SET_CURSOR_POSITION_bad_layer)
+{
+ ASSERT_NO_FATAL_FAILURE(setLayerPropertyBadLayer(Hwc2TestCoverage::Default,
+ [] (Hwc2Test* test, hwc2_display_t display, hwc2_layer_t badLayer,
+ Hwc2TestLayer* testLayer, hwc2_error_t* outErr) {
+
+ const hwc_rect_t cursorPosition = testLayer->getCursorPosition();
+ EXPECT_NO_FATAL_FAILURE(test->setCursorPosition(display,
+ badLayer, cursorPosition.left, cursorPosition.top,
+ outErr));
+ }
+ ));
+}
+
+/* TESTCASE: Tests that the HWC2 can set a blend mode value of a layer. */
+TEST_F(Hwc2Test, SET_LAYER_BLEND_MODE)
+{
+ ASSERT_NO_FATAL_FAILURE(setLayerProperty(Hwc2TestCoverage::Complete,
+ setBlendMode, advanceBlendMode));
+}
+
+/* TESTCASE: Tests that the HWC2 can update a blend mode value of a layer. */
+TEST_F(Hwc2Test, SET_LAYER_BLEND_MODE_update)
+{
+ ASSERT_NO_FATAL_FAILURE(setLayerPropertyUpdate(Hwc2TestCoverage::Complete,
+ setBlendMode, advanceBlendMode));
+}
+
+/* TESTCASE: Tests that the HWC2 cannot set a blend mode for a bad layer. */
+TEST_F(Hwc2Test, SET_LAYER_BLEND_MODE_bad_layer)
+{
+ ASSERT_NO_FATAL_FAILURE(setLayerPropertyBadLayer(Hwc2TestCoverage::Default,
+ setBlendMode));
+}
+
+/* TESTCASE: Tests that the HWC2 cannot set an invalid blend mode. */
+TEST_F(Hwc2Test, SET_LAYER_BLEND_MODE_bad_parameter)
+{
+ ASSERT_NO_FATAL_FAILURE(setLayerPropertyBadParameter(
+ [] (Hwc2Test* test, hwc2_display_t display, hwc2_layer_t layer,
+ hwc2_error_t* outErr) {
+
+ ASSERT_NO_FATAL_FAILURE(test->setLayerBlendMode(display,
+ layer, HWC2_BLEND_MODE_INVALID, outErr));
+ }
+ ));
+}
+
+/* TESTCASE: Tests that the HWC2 can set the buffer of a layer. */
+TEST_F(Hwc2Test, SET_LAYER_BUFFER)
+{
+ ASSERT_NO_FATAL_FAILURE(setLayerProperty(Hwc2TestCoverage::Complete,
+ setBuffer, advanceBuffer));
+}
+
+/* TESTCASE: Tests that the HWC2 can update the buffer of a layer. */
+TEST_F(Hwc2Test, SET_LAYER_BUFFER_update)
+{
+ ASSERT_NO_FATAL_FAILURE(setLayerPropertyUpdate(Hwc2TestCoverage::Complete,
+ setBuffer, advanceBuffer));
+}
+
+/* TESTCASE: Tests that the HWC2 cannot set the buffer of a bad layer. */
+TEST_F(Hwc2Test, SET_LAYER_BUFFER_bad_layer)
+{
+ ASSERT_NO_FATAL_FAILURE(setLayerPropertyBadLayer(Hwc2TestCoverage::Default,
+ [] (Hwc2Test* test, hwc2_display_t display, hwc2_layer_t badLayer,
+ Hwc2TestLayer* testLayer, hwc2_error_t* outErr) {
+
+ buffer_handle_t handle = nullptr;
+ android::base::unique_fd acquireFence;
+
+ /* If there is not available buffer for the given buffer
+ * properties, it should not fail this test case */
+ if (testLayer->getBuffer(&handle, &acquireFence) == 0) {
+ *outErr = HWC2_ERROR_BAD_LAYER;
+ return;
+ }
+
+ ASSERT_NO_FATAL_FAILURE(test->setLayerBuffer(display, badLayer,
+ handle, acquireFence, outErr));
+ }
+ ));
+}
+
+/* TESTCASE: Tests that the HWC2 can set an invalid buffer for a layer. */
+TEST_F(Hwc2Test, SET_LAYER_BUFFER_bad_parameter)
+{
+ ASSERT_NO_FATAL_FAILURE(setLayerPropertyBadParameter(
+ [] (Hwc2Test* test, hwc2_display_t display, hwc2_layer_t layer,
+ hwc2_error_t* outErr) {
+
+ buffer_handle_t handle = nullptr;
+ int32_t acquireFence = -1;
+
+ ASSERT_NO_FATAL_FAILURE(test->setLayerBuffer(display, layer,
+ handle, acquireFence, outErr));
+ }
+ ));
+}
+
+/* TESTCASE: Tests that the HWC2 can set the color of a layer. */
+TEST_F(Hwc2Test, SET_LAYER_COLOR)
+{
+ ASSERT_NO_FATAL_FAILURE(setLayerProperty(Hwc2TestCoverage::Complete,
+ setColor, advanceColor));
+}
+
+/* TESTCASE: Tests that the HWC2 can update the color of a layer. */
+TEST_F(Hwc2Test, SET_LAYER_COLOR_update)
+{
+ ASSERT_NO_FATAL_FAILURE(setLayerPropertyUpdate(Hwc2TestCoverage::Complete,
+ setColor, advanceColor));
+}
+
+/* TESTCASE: Tests that the HWC2 can set the color of a layer when the
+ * composition type has not been set to HWC2_COMPOSITION_SOLID_COLOR. */
+TEST_F(Hwc2Test, SET_LAYER_COLOR_composition_type_unset)
+{
+ ASSERT_NO_FATAL_FAILURE(setLayerProperty(Hwc2TestCoverage::Basic,
+ [] (Hwc2Test* test, hwc2_display_t display, hwc2_layer_t layer,
+ Hwc2TestLayer* testLayer, hwc2_error_t* outErr) {
+
+ EXPECT_NO_FATAL_FAILURE(test->setLayerColor(display, layer,
+ testLayer->getColor(), outErr));
+ },
+
+ advanceColor));
+}
+
+/* TESTCASE: Tests that the HWC2 cannot set the color of a bad layer. */
+TEST_F(Hwc2Test, SET_LAYER_COLOR_bad_layer)
+{
+ ASSERT_NO_FATAL_FAILURE(setLayerPropertyBadLayer(Hwc2TestCoverage::Default,
+ [] (Hwc2Test* test, hwc2_display_t display, hwc2_layer_t badLayer,
+ Hwc2TestLayer* testLayer, hwc2_error_t* outErr) {
+
+ EXPECT_NO_FATAL_FAILURE(test->setLayerColor(display, badLayer,
+ testLayer->getColor(), outErr));
+ }
+ ));
+}
+
+/* TESTCASE: Tests that the HWC2 can set the dataspace of a layer. */
+TEST_F(Hwc2Test, SET_LAYER_DATASPACE)
+{
+ ASSERT_NO_FATAL_FAILURE(setLayerProperty(Hwc2TestCoverage::Complete,
+ setDataspace, advanceDataspace));
+}
+
+/* TESTCASE: Tests that the HWC2 can update the dataspace of a layer. */
+TEST_F(Hwc2Test, SET_LAYER_DATASPACE_update)
+{
+ ASSERT_NO_FATAL_FAILURE(setLayerPropertyUpdate(Hwc2TestCoverage::Complete,
+ setDataspace, advanceDataspace));
+}
+
+/* TESTCASE: Tests that the HWC2 cannot set a dataspace for a bad layer. */
+TEST_F(Hwc2Test, SET_LAYER_DATASPACE_bad_layer)
+{
+ ASSERT_NO_FATAL_FAILURE(setLayerPropertyBadLayer(Hwc2TestCoverage::Default,
+ setDataspace));
+}
+
+/* TESTCASE: Tests that the HWC2 can set the display frame of a layer. */
+TEST_F(Hwc2Test, SET_LAYER_DISPLAY_FRAME)
+{
+ ASSERT_NO_FATAL_FAILURE(setLayerProperty(Hwc2TestCoverage::Complete,
+ setDisplayFrame, advanceDisplayFrame));
+}
+
+/* TESTCASE: Tests that the HWC2 can update the display frame of a layer. */
+TEST_F(Hwc2Test, SET_LAYER_DISPLAY_FRAME_update)
+{
+ ASSERT_NO_FATAL_FAILURE(setLayerPropertyUpdate(Hwc2TestCoverage::Complete,
+ setDisplayFrame, advanceDisplayFrame));
+}
+
+/* TESTCASE: Tests that the HWC2 cannot set the display frame of a bad layer. */
+TEST_F(Hwc2Test, SET_LAYER_DISPLAY_FRAME_bad_layer)
+{
+ ASSERT_NO_FATAL_FAILURE(setLayerPropertyBadLayer(Hwc2TestCoverage::Default,
+ setDisplayFrame));
+}
+
+/* TESTCASE: Tests that the HWC2 can set the plane alpha of a layer. */
+TEST_F(Hwc2Test, SET_LAYER_PLANE_ALPHA)
+{
+ ASSERT_NO_FATAL_FAILURE(setLayerProperty(Hwc2TestCoverage::Complete,
+ setPlaneAlpha, advancePlaneAlpha));
+}
+
+/* TESTCASE: Tests that the HWC2 can update the plane alpha of a layer. */
+TEST_F(Hwc2Test, SET_LAYER_PLANE_ALPHA_update)
+{
+ ASSERT_NO_FATAL_FAILURE(setLayerPropertyUpdate(Hwc2TestCoverage::Complete,
+ setPlaneAlpha, advancePlaneAlpha));
+}
+
+/* TESTCASE: Tests that the HWC2 cannot set a plane alpha for a bad layer. */
+TEST_F(Hwc2Test, SET_LAYER_PLANE_ALPHA_bad_layer)
+{
+ ASSERT_NO_FATAL_FAILURE(setLayerPropertyBadLayer(Hwc2TestCoverage::Default,
+ [] (Hwc2Test* test, hwc2_display_t display, hwc2_layer_t badLayer,
+ Hwc2TestLayer* testLayer, hwc2_error_t *outErr) {
+
+ EXPECT_NO_FATAL_FAILURE(test->setLayerPlaneAlpha(display,
+ badLayer, testLayer->getPlaneAlpha(), outErr));
+ }
+ ));
+}
+
+/* TESTCASE: Tests that the HWC2 can set the source crop of a layer. */
+TEST_F(Hwc2Test, SET_LAYER_SOURCE_CROP)
+{
+ ASSERT_NO_FATAL_FAILURE(setLayerProperty(Hwc2TestCoverage::Complete,
+ setSourceCrop, advanceSourceCrop));
+}
+
+/* TESTCASE: Tests that the HWC2 can update the source crop of a layer. */
+TEST_F(Hwc2Test, SET_LAYER_SOURCE_CROP_update)
+{
+ ASSERT_NO_FATAL_FAILURE(setLayerPropertyUpdate(Hwc2TestCoverage::Complete,
+ setSourceCrop, advanceSourceCrop));
+}
+
+/* TESTCASE: Tests that the HWC2 cannot set the source crop of a bad layer. */
+TEST_F(Hwc2Test, SET_LAYER_SOURCE_CROP_bad_layer)
+{
+ ASSERT_NO_FATAL_FAILURE(setLayerPropertyBadLayer(Hwc2TestCoverage::Default,
+ setSourceCrop));
+}
+
+/* TESTCASE: Tests that the HWC2 can set the surface damage of a layer. */
+TEST_F(Hwc2Test, SET_LAYER_SURFACE_DAMAGE)
+{
+ ASSERT_NO_FATAL_FAILURE(setLayerProperty(Hwc2TestCoverage::Complete,
+ setSurfaceDamage, advanceSurfaceDamage));
+}
+
+/* TESTCASE: Tests that the HWC2 can update the surface damage of a layer. */
+TEST_F(Hwc2Test, SET_LAYER_SURFACE_DAMAGE_update)
+{
+ ASSERT_NO_FATAL_FAILURE(setLayerPropertyUpdate(Hwc2TestCoverage::Complete,
+ setSurfaceDamage, advanceSurfaceDamage));
+}
+
+/* TESTCASE: Tests that the HWC2 cannot set the surface damage of a bad layer. */
+TEST_F(Hwc2Test, SET_LAYER_SURFACE_DAMAGE_bad_layer)
+{
+ ASSERT_NO_FATAL_FAILURE(setLayerPropertyBadLayer(Hwc2TestCoverage::Default,
+ setSurfaceDamage));
+}
+
+/* TESTCASE: Tests that the HWC2 can set the transform value of a layer. */
+TEST_F(Hwc2Test, SET_LAYER_TRANSFORM)
+{
+ ASSERT_NO_FATAL_FAILURE(setLayerProperty(Hwc2TestCoverage::Complete,
+ setTransform, advanceTransform));
+}
+
+/* TESTCASE: Tests that the HWC2 can update the transform value of a layer. */
+TEST_F(Hwc2Test, SET_LAYER_TRANSFORM_update)
+{
+ ASSERT_NO_FATAL_FAILURE(setLayerPropertyUpdate(Hwc2TestCoverage::Complete,
+ setTransform, advanceTransform));
+}
+
+/* TESTCASE: Tests that the HWC2 cannot set the transform for a bad layer. */
+TEST_F(Hwc2Test, SET_LAYER_TRANSFORM_bad_layer)
+{
+ ASSERT_NO_FATAL_FAILURE(setLayerPropertyBadLayer(Hwc2TestCoverage::Default,
+ setTransform));
+}
+
+/* TESTCASE: Tests that the HWC2 can set the visible region of a layer. */
+TEST_F(Hwc2Test, SET_LAYER_VISIBLE_REGION)
+{
+ ASSERT_NO_FATAL_FAILURE(setLayerProperties(Hwc2TestCoverage::Basic, 5,
+ [] (Hwc2Test* test, hwc2_display_t display, hwc2_layer_t layer,
+ Hwc2TestLayers* testLayers) {
+
+ EXPECT_NO_FATAL_FAILURE(test->setLayerVisibleRegion(display,
+ layer, testLayers->getVisibleRegion(layer)));
+ },
+
+ advanceVisibleRegions));
+}
+
+/* TESTCASE: Tests that the HWC2 cannot set the visible region of a bad layer. */
+TEST_F(Hwc2Test, SET_LAYER_VISIBLE_REGION_bad_layer)
+{
+ ASSERT_NO_FATAL_FAILURE(setLayerPropertyBadLayer(Hwc2TestCoverage::Default,
+ setVisibleRegion));
+}
+
+/* TESTCASE: Tests that the HWC2 can set the z order of a layer. */
+TEST_F(Hwc2Test, SET_LAYER_Z_ORDER)
+{
+ ASSERT_NO_FATAL_FAILURE(setLayerProperties(Hwc2TestCoverage::Complete, 10,
+ [] (Hwc2Test* test, hwc2_display_t display, hwc2_layer_t layer,
+ Hwc2TestLayers* testLayers) {
+
+ EXPECT_NO_FATAL_FAILURE(test->setLayerZOrder(display, layer,
+ testLayers->getZOrder(layer)));
+ },
+
+ /* TestLayer z orders are set during the construction of TestLayers
+ * and cannot be updated. There is no need (or ability) to cycle
+ * through additional z order configurations. */
+ [] (Hwc2TestLayers* /*testLayers*/) {
+ return false;
+ }
+ ));
+}
+
+/* TESTCASE: Tests that the HWC2 can update the z order of a layer. */
+TEST_F(Hwc2Test, SET_LAYER_Z_ORDER_update)
+{
+ const std::vector<uint32_t> zOrders = { static_cast<uint32_t>(0),
+ static_cast<uint32_t>(1), static_cast<uint32_t>(UINT32_MAX / 4),
+ static_cast<uint32_t>(UINT32_MAX / 2),
+ static_cast<uint32_t>(UINT32_MAX) };
+
+ for (auto display : mDisplays) {
+ std::vector<hwc2_config_t> configs;
+
+ ASSERT_NO_FATAL_FAILURE(getDisplayConfigs(display, &configs));
+
+ for (auto config : configs) {
+ hwc2_layer_t layer;
+
+ ASSERT_NO_FATAL_FAILURE(setActiveConfig(display, config));
+
+ ASSERT_NO_FATAL_FAILURE(createLayer(display, &layer));
+
+ for (uint32_t zOrder : zOrders) {
+ EXPECT_NO_FATAL_FAILURE(setLayerZOrder(display, layer, zOrder));
+ }
+
+ ASSERT_NO_FATAL_FAILURE(destroyLayer(display, layer));
+ }
+ }
+}
+
+/* TESTCASE: Tests that the HWC2 cannot set the z order of a bad layer. */
+TEST_F(Hwc2Test, SET_LAYER_Z_ORDER_bad_layer)
+{
+ ASSERT_NO_FATAL_FAILURE(setLayerPropertyBadLayer(Hwc2TestCoverage::Default,
+ setZOrder));
+}
+
+/* TESTCASE: Tests that the HWC2 can display a layer with basic property
+ * coverage */
+TEST_F(Hwc2Test, VALIDATE_DISPLAY_basic)
+{
+ ASSERT_NO_FATAL_FAILURE(displayLayers(Hwc2TestCoverage::Basic, 1,
+ [] (Hwc2Test* test, hwc2_display_t display,
+ const std::vector<hwc2_layer_t>& layers,
+ Hwc2TestLayers* /*testLayers*/) {
+
+ uint32_t numTypes, numRequests;
+ bool hasChanges = false;
+
+ EXPECT_NO_FATAL_FAILURE(test->validateDisplay(display, &numTypes,
+ &numRequests, &hasChanges));
+ if (hasChanges)
+ EXPECT_LE(numTypes, static_cast<uint32_t>(layers.size()))
+ << "wrong number of requests";
+ }
+ ));
+}
+
+/* TESTCASE: Tests that the HWC2 can display 5 layers with default coverage. */
+TEST_F(Hwc2Test, VALIDATE_DISPLAY_default_5)
+{
+ ASSERT_NO_FATAL_FAILURE(displayLayers(Hwc2TestCoverage::Default, 5,
+ [] (Hwc2Test* test, hwc2_display_t display,
+ const std::vector<hwc2_layer_t>& layers,
+ Hwc2TestLayers* /*testLayers*/) {
+
+ uint32_t numTypes, numRequests;
+ bool hasChanges = false;
+
+ EXPECT_NO_FATAL_FAILURE(test->validateDisplay(display, &numTypes,
+ &numRequests, &hasChanges));
+ if (hasChanges)
+ EXPECT_LE(numTypes, static_cast<uint32_t>(layers.size()))
+ << "wrong number of requests";
+ }
+ ));
+}
+
+/* TESTCASE: Tests that the HWC2 cannot validate a bad display */
+TEST_F(Hwc2Test, VALIDATE_DISPLAY_bad_display)
+{
+ hwc2_display_t display;
+ uint32_t numTypes, numRequests;
+ hwc2_error_t err = HWC2_ERROR_NONE;
+
+ ASSERT_NO_FATAL_FAILURE(getBadDisplay(&display));
+
+ ASSERT_NO_FATAL_FAILURE(validateDisplay(display, &numTypes, &numRequests,
+ &err));
+ EXPECT_EQ(err, HWC2_ERROR_BAD_DISPLAY) << "returned wrong error code";
+}
+
+/* TESTCASE: Tests that the HWC2 can get display requests after validating a
+ * basic layer. */
+TEST_F(Hwc2Test, GET_DISPLAY_REQUESTS_basic)
+{
+ ASSERT_NO_FATAL_FAILURE(displayLayers(Hwc2TestCoverage::Basic, 1,
+ [] (Hwc2Test* test, hwc2_display_t display,
+ const std::vector<hwc2_layer_t>& layers,
+ Hwc2TestLayers* /*testLayers*/) {
+
+ uint32_t numTypes, numRequests;
+ bool hasChanges = false;
+
+ ASSERT_NO_FATAL_FAILURE(test->validateDisplay(display, &numTypes,
+ &numRequests, &hasChanges));
+ if (hasChanges)
+ EXPECT_LE(numTypes, layers.size())
+ << "wrong number of requests";
+
+ EXPECT_NO_FATAL_FAILURE(test->handleRequests(display, layers,
+ numRequests));
+ }
+ ));
+}
+
+/* TESTCASE: Tests that the HWC2 cannot get display requests from a bad display */
+TEST_F(Hwc2Test, GET_DISPLAY_REQUESTS_bad_display)
+{
+ hwc2_display_t display;
+ hwc2_display_request_t displayRequests;
+ std::vector<hwc2_layer_t> layers;
+ std::vector<hwc2_layer_request_t> layerRequests;
+ hwc2_error_t err = HWC2_ERROR_NONE;
+
+ ASSERT_NO_FATAL_FAILURE(getBadDisplay(&display));
+
+ EXPECT_NO_FATAL_FAILURE(getDisplayRequests(display, &displayRequests,
+ &layers, &layerRequests, &err));
+ EXPECT_EQ(err, HWC2_ERROR_BAD_DISPLAY) << "returned wrong error code";
+}
+
+/* TESTCASE: Tests that the HWC2 cannot get display requests from an non
+ * validated display. */
+TEST_F(Hwc2Test, GET_DISPLAY_REQUESTS_not_validated)
+{
+ ASSERT_NO_FATAL_FAILURE(displayNonValidatedLayers(5,
+ [] (Hwc2Test* test, hwc2_display_t display,
+ std::vector<hwc2_layer_t>* layers) {
+
+ hwc2_display_request_t displayRequests;
+ std::vector<hwc2_layer_request_t> layerRequests;
+ hwc2_error_t err = HWC2_ERROR_NONE;
+
+ ASSERT_NO_FATAL_FAILURE(test->getDisplayRequests(display,
+ &displayRequests, layers, &layerRequests, &err));
+ EXPECT_EQ(err, HWC2_ERROR_NOT_VALIDATED)
+ << "returned wrong error code";
+ }
+ ));
+}
+
+/* TESTCASE: Tests that the HWC2 can get changed composition types after
+ * validating a basic layer. */
+TEST_F(Hwc2Test, GET_CHANGED_COMPOSITION_TYPES_basic)
+{
+ ASSERT_NO_FATAL_FAILURE(displayLayers(Hwc2TestCoverage::Basic, 1,
+ [] (Hwc2Test* test, hwc2_display_t display,
+ const std::vector<hwc2_layer_t>& layers,
+ Hwc2TestLayers* testLayers) {
+
+ uint32_t numTypes, numRequests;
+ bool hasChanges = false;
+
+ ASSERT_NO_FATAL_FAILURE(test->validateDisplay(display, &numTypes,
+ &numRequests, &hasChanges));
+ if (hasChanges)
+ EXPECT_LE(numTypes, layers.size())
+ << "wrong number of requests";
+
+ EXPECT_NO_FATAL_FAILURE(test->handleCompositionChanges(display,
+ *testLayers, layers, numTypes));
+ }
+ ));
+}
+
+/* TESTCASE: Tests that the HWC2 cannot get changed composition types from a bad
+ * display */
+TEST_F(Hwc2Test, GET_CHANGED_COMPOSITION_TYPES_bad_display)
+{
+ hwc2_display_t display;
+ std::vector<hwc2_layer_t> layers;
+ std::vector<hwc2_composition_t> types;
+ hwc2_error_t err = HWC2_ERROR_NONE;
+
+ ASSERT_NO_FATAL_FAILURE(getBadDisplay(&display));
+
+ EXPECT_NO_FATAL_FAILURE(getChangedCompositionTypes(display, &layers,
+ &types, &err));
+ EXPECT_EQ(err, HWC2_ERROR_BAD_DISPLAY) << "returned wrong error code";
+}
+
+/* TESTCASE: Tests that the HWC2 cannot get changed composition types from an non
+ * validated display. */
+TEST_F(Hwc2Test, GET_CHANGED_COMPOSITION_TYPES_not_validated)
+{
+ ASSERT_NO_FATAL_FAILURE(displayNonValidatedLayers(5,
+ [] (Hwc2Test* test, hwc2_display_t display,
+ std::vector<hwc2_layer_t>* layers) {
+
+ std::vector<hwc2_composition_t> types;
+ hwc2_error_t err = HWC2_ERROR_NONE;
+
+ ASSERT_NO_FATAL_FAILURE(test->getChangedCompositionTypes(
+ display, layers, &types, &err));
+ EXPECT_EQ(err, HWC2_ERROR_NOT_VALIDATED)
+ << "returned wrong error code";
+ }
+ ));
+}
+
+/* TESTCASE: Tests that the HWC2 can accept display changes after validating a
+ * basic layer. */
+TEST_F(Hwc2Test, ACCEPT_DISPLAY_CHANGES_basic)
+{
+ ASSERT_NO_FATAL_FAILURE(displayLayers(Hwc2TestCoverage::Basic, 1,
+ [] (Hwc2Test* test, hwc2_display_t display,
+ const std::vector<hwc2_layer_t>& layers,
+ Hwc2TestLayers* testLayers) {
+
+ uint32_t numTypes, numRequests;
+ bool hasChanges = false;
+
+ ASSERT_NO_FATAL_FAILURE(test->validateDisplay(display, &numTypes,
+ &numRequests, &hasChanges));
+ if (hasChanges)
+ EXPECT_LE(numTypes, layers.size())
+ << "wrong number of requests";
+
+ ASSERT_NO_FATAL_FAILURE(test->handleCompositionChanges(display,
+ *testLayers, layers, numTypes));
+
+ EXPECT_NO_FATAL_FAILURE(test->acceptDisplayChanges(display));
+ }
+ ));
+}
+
+/* TESTCASE: Tests that the HWC2 cannot accept display changes from a bad
+ * display */
+TEST_F(Hwc2Test, ACCEPT_DISPLAY_CHANGES_bad_display)
+{
+ hwc2_display_t display;
+ hwc2_error_t err = HWC2_ERROR_NONE;
+
+ ASSERT_NO_FATAL_FAILURE(getBadDisplay(&display));
+
+ EXPECT_NO_FATAL_FAILURE(acceptDisplayChanges(display, &err));
+ EXPECT_EQ(err, HWC2_ERROR_BAD_DISPLAY) << "returned wrong error code";
+}
+
+/* TESTCASE: Tests that the HWC2 cannot accept display changes from an non
+ * validated display. */
+TEST_F(Hwc2Test, ACCEPT_DISPLAY_CHANGES_not_validated)
+{
+ ASSERT_NO_FATAL_FAILURE(displayNonValidatedLayers(5,
+ [] (Hwc2Test* test, hwc2_display_t display,
+ std::vector<hwc2_layer_t>* /*layers*/) {
+
+ hwc2_error_t err = HWC2_ERROR_NONE;
+
+ ASSERT_NO_FATAL_FAILURE(test->acceptDisplayChanges(display, &err));
+ EXPECT_EQ(err, HWC2_ERROR_NOT_VALIDATED)
+ << "returned wrong error code";
+ }
+ ));
+}
+
+/* TESTCASE: Tests that the HWC2 supports client target with required values */
+TEST_F(Hwc2Test, GET_CLIENT_TARGET_SUPPORT)
+{
+ ASSERT_NO_FATAL_FAILURE(setClientTargetSupport(Hwc2TestCoverage::Default,
+ [] (Hwc2Test* test, hwc2_display_t display,
+ const Hwc2TestClientTargetSupport& testClientTargetSupport) {
+
+ const Area bufferArea = testClientTargetSupport.getBufferArea();
+ const android_pixel_format_t format = HAL_PIXEL_FORMAT_RGBA_8888;
+
+ ASSERT_NO_FATAL_FAILURE(test->getClientTargetSupport(display,
+ bufferArea.width, bufferArea.height, format,
+ testClientTargetSupport.getDataspace()));
+ },
+
+ advanceClientTargetSupport));
+}
+
+/* TESTCASE: Tests that the HWC2 cannot get client target support for a bad
+ * display. */
+TEST_F(Hwc2Test, GET_CLIENT_TARGET_SUPPORT_bad_display)
+{
+ ASSERT_NO_FATAL_FAILURE(setClientTargetSupport(Hwc2TestCoverage::Default,
+ [] (Hwc2Test* test, hwc2_display_t /*display*/,
+ const Hwc2TestClientTargetSupport& testClientTargetSupport) {
+
+ const Area bufferArea = testClientTargetSupport.getBufferArea();
+ const android_pixel_format_t format = HAL_PIXEL_FORMAT_RGBA_8888;
+ hwc2_display_t badDisplay;
+ hwc2_error_t err = HWC2_ERROR_NONE;
+
+ ASSERT_NO_FATAL_FAILURE(test->getBadDisplay(&badDisplay));
+
+ ASSERT_NO_FATAL_FAILURE(test->getClientTargetSupport(badDisplay,
+ bufferArea.width, bufferArea.height, format,
+ testClientTargetSupport.getDataspace(), &err));
+ EXPECT_EQ(err, HWC2_ERROR_BAD_DISPLAY) << "returned wrong error code";
+ },
+
+ advanceClientTargetSupport));
+}
+
+/* TESTCASE: Tests that the HWC2 either supports or returns error unsupported
+ * for a variety of client target values. */
+TEST_F(Hwc2Test, GET_CLIENT_TARGET_SUPPORT_unsupported)
+{
+ ASSERT_NO_FATAL_FAILURE(setClientTargetSupport(Hwc2TestCoverage::Complete,
+ [] (Hwc2Test* test, hwc2_display_t display,
+ const Hwc2TestClientTargetSupport& testClientTargetSupport) {
+
+ const Area bufferArea = testClientTargetSupport.getBufferArea();
+ const android_pixel_format_t format = HAL_PIXEL_FORMAT_RGBA_8888;
+ hwc2_error_t err = HWC2_ERROR_NONE;
+
+ ASSERT_NO_FATAL_FAILURE(test->getClientTargetSupport(display,
+ bufferArea.width, bufferArea.height, format,
+ testClientTargetSupport.getDataspace(), &err));
+ EXPECT_TRUE(err == HWC2_ERROR_NONE
+ || err == HWC2_ERROR_UNSUPPORTED)
+ << "returned wrong error code";
+ },
+
+ advanceClientTargetSupport));
+}
+
+/* TESTCASE: Tests that the HWC2 can set a client target buffer for a basic
+ * layer. */
+TEST_F(Hwc2Test, SET_CLIENT_TARGET_basic)
+{
+ const android_dataspace_t dataspace = HAL_DATASPACE_UNKNOWN;
+ const hwc_region_t damage = { };
+ const size_t layerCnt = 1;
+
+ for (auto display : mDisplays) {
+ std::vector<hwc2_config_t> configs;
+
+ ASSERT_NO_FATAL_FAILURE(setPowerMode(display, HWC2_POWER_MODE_ON));
+
+ ASSERT_NO_FATAL_FAILURE(getDisplayConfigs(display, &configs));
+
+ for (auto config : configs) {
+ Area displayArea;
+ std::vector<hwc2_layer_t> layers;
+
+ ASSERT_NO_FATAL_FAILURE(setActiveConfig(display, config));
+ ASSERT_NO_FATAL_FAILURE(getActiveDisplayArea(display, &displayArea));
+
+ ASSERT_NO_FATAL_FAILURE(createLayers(display, &layers, layerCnt));
+ Hwc2TestLayers testLayers(layers, Hwc2TestCoverage::Basic,
+ displayArea);
+
+ if (!testLayers.optimizeLayouts())
+ continue;
+
+ Hwc2TestClientTarget testClientTarget;
+
+ do {
+ std::set<hwc2_layer_t> clientLayers;
+ std::set<hwc2_layer_t> clearLayers;
+ uint32_t numTypes, numRequests;
+ bool hasChanges, skip;
+ bool flipClientTarget;
+ buffer_handle_t handle;
+ int32_t acquireFence;
+
+ ASSERT_NO_FATAL_FAILURE(setLayerProperties(display, layers,
+ &testLayers, &skip));
+ if (skip)
+ continue;
+
+ ASSERT_NO_FATAL_FAILURE(validateDisplay(display, &numTypes,
+ &numRequests, &hasChanges));
+ if (hasChanges)
+ EXPECT_LE(numTypes, layers.size())
+ << "wrong number of requests";
+
+ ASSERT_NO_FATAL_FAILURE(handleCompositionChanges(display,
+ testLayers, layers, numTypes, &clientLayers));
+ ASSERT_NO_FATAL_FAILURE(handleRequests(display, layers,
+ numRequests, &clearLayers, &flipClientTarget));
+ ASSERT_EQ(testClientTarget.getBuffer(testLayers, clientLayers,
+ clearLayers, flipClientTarget, displayArea, &handle,
+ &acquireFence), 0);
+ EXPECT_NO_FATAL_FAILURE(setClientTarget(display, handle,
+ acquireFence, dataspace, damage));
+
+ if (acquireFence >= 0)
+ close(acquireFence);
+
+ } while (testLayers.advance());
+
+ ASSERT_NO_FATAL_FAILURE(destroyLayers(display, std::move(layers)));
+ }
+
+ ASSERT_NO_FATAL_FAILURE(setPowerMode(display, HWC2_POWER_MODE_OFF));
+ }
+}
+
+/* TESTCASE: Tests that the HWC2 cannot set a client target for a bad display. */
+TEST_F(Hwc2Test, SET_CLIENT_TARGET_bad_display)
+{
+ hwc2_display_t display;
+ std::vector<hwc2_layer_t> layers;
+ const Area displayArea = {0, 0};
+ Hwc2TestLayers testLayers(layers, Hwc2TestCoverage::Default, displayArea);
+ std::set<hwc2_layer_t> clientLayers;
+ std::set<hwc2_layer_t> flipClientTargetLayers;
+ bool flipClientTarget = true;
+ const android_dataspace_t dataspace = HAL_DATASPACE_UNKNOWN;
+ const hwc_region_t damage = { };
+ buffer_handle_t handle;
+ int32_t acquireFence;
+ hwc2_error_t err = HWC2_ERROR_NONE;
+
+ ASSERT_NO_FATAL_FAILURE(getBadDisplay(&display));
+
+ Hwc2TestClientTarget testClientTarget;
+
+ ASSERT_EQ(testClientTarget.getBuffer(testLayers, clientLayers,
+ flipClientTargetLayers, flipClientTarget, displayArea, &handle,
+ &acquireFence), 0);
+
+ EXPECT_NO_FATAL_FAILURE(setClientTarget(display, handle, acquireFence,
+ dataspace, damage, &err));
+
+ if (acquireFence >= 0)
+ close(acquireFence);
+
+ EXPECT_EQ(err, HWC2_ERROR_BAD_DISPLAY) << "returned wrong error code";
+}
+
+/* TESTCASE: Tests that the HWC2 can present 1 default layer. */
+TEST_F(Hwc2Test, PRESENT_DISPLAY_default_1)
+{
+ const size_t layerCnt = 1;
+ Hwc2TestCoverage coverage = Hwc2TestCoverage::Default;
+ std::unordered_map<Hwc2TestPropertyName, Hwc2TestCoverage> exceptions;
+ bool optimize = false;
+
+ ASSERT_NO_FATAL_FAILURE(presentDisplays(layerCnt, coverage, exceptions,
+ optimize));
+}
+
+/* TESTCASE: Tests that the HWC2 can present 2 default layers. */
+TEST_F(Hwc2Test, PRESENT_DISPLAY_default_2)
+{
+ const size_t layerCnt = 2;
+ Hwc2TestCoverage coverage = Hwc2TestCoverage::Default;
+ std::unordered_map<Hwc2TestPropertyName, Hwc2TestCoverage> exceptions;
+ bool optimize = false;
+
+ ASSERT_NO_FATAL_FAILURE(presentDisplays(layerCnt, coverage, exceptions,
+ optimize));
+}
+
+/* TESTCASE: Tests that the HWC2 can present 3 default layers. */
+TEST_F(Hwc2Test, PRESENT_DISPLAY_default_3)
+{
+ const size_t layerCnt = 3;
+ Hwc2TestCoverage coverage = Hwc2TestCoverage::Default;
+ std::unordered_map<Hwc2TestPropertyName, Hwc2TestCoverage> exceptions;
+ bool optimize = false;
+
+ ASSERT_NO_FATAL_FAILURE(presentDisplays(layerCnt, coverage, exceptions,
+ optimize));
+}
+
+/* TESTCASE: Tests that the HWC2 can present 4 default layers. */
+TEST_F(Hwc2Test, PRESENT_DISPLAY_default_4)
+{
+ const size_t layerCnt = 4;
+ Hwc2TestCoverage coverage = Hwc2TestCoverage::Default;
+ std::unordered_map<Hwc2TestPropertyName, Hwc2TestCoverage> exceptions;
+ bool optimize = false;
+
+ ASSERT_NO_FATAL_FAILURE(presentDisplays(layerCnt, coverage, exceptions,
+ optimize));
+}
+
+/* TESTCASE: Tests that the HWC2 can present 5 default layers. */
+TEST_F(Hwc2Test, PRESENT_DISPLAY_default_5)
+{
+ const size_t layerCnt = 5;
+ Hwc2TestCoverage coverage = Hwc2TestCoverage::Default;
+ std::unordered_map<Hwc2TestPropertyName, Hwc2TestCoverage> exceptions;
+ bool optimize = false;
+
+ ASSERT_NO_FATAL_FAILURE(presentDisplays(layerCnt, coverage, exceptions,
+ optimize));
+}
+
+/* TESTCASE: Tests that the HWC2 can present 6 default layers. */
+TEST_F(Hwc2Test, PRESENT_DISPLAY_default_6)
+{
+ const size_t layerCnt = 6;
+ Hwc2TestCoverage coverage = Hwc2TestCoverage::Default;
+ std::unordered_map<Hwc2TestPropertyName, Hwc2TestCoverage> exceptions;
+ bool optimize = false;
+
+ ASSERT_NO_FATAL_FAILURE(presentDisplays(layerCnt, coverage, exceptions,
+ optimize));
+}
+
+/* TESTCASE: Tests that the HWC2 can present 1 layer with complete coverage of
+ * blend mode. */
+TEST_F(Hwc2Test, PRESENT_DISPLAY_blend_mode_1)
+{
+ const size_t layerCnt = 1;
+ Hwc2TestCoverage coverage = Hwc2TestCoverage::Default;
+ std::unordered_map<Hwc2TestPropertyName, Hwc2TestCoverage> exceptions =
+ {{Hwc2TestPropertyName::BlendMode, Hwc2TestCoverage::Complete},
+ {Hwc2TestPropertyName::Transform, Hwc2TestCoverage::Basic},
+ {Hwc2TestPropertyName::PlaneAlpha, Hwc2TestCoverage::Basic}};
+ bool optimize = false;
+
+ ASSERT_NO_FATAL_FAILURE(presentDisplays(layerCnt, coverage, exceptions,
+ optimize));
+}
+
+/* TESTCASE: Tests that the HWC2 can present 2 layers with complete coverage of
+ * blend mode. */
+TEST_F(Hwc2Test, PRESENT_DISPLAY_blend_mode_2)
+{
+ const size_t layerCnt = 2;
+ Hwc2TestCoverage coverage = Hwc2TestCoverage::Default;
+ std::unordered_map<Hwc2TestPropertyName, Hwc2TestCoverage> exceptions =
+ {{Hwc2TestPropertyName::BlendMode, Hwc2TestCoverage::Complete},
+ {Hwc2TestPropertyName::PlaneAlpha, Hwc2TestCoverage::Basic}};
+ bool optimize = false;
+
+ ASSERT_NO_FATAL_FAILURE(presentDisplays(layerCnt, coverage, exceptions,
+ optimize));
+}
+
+/* TESTCASE: Tests that the HWC2 can present 1 layer with complete coverage of
+ * buffer. */
+TEST_F(Hwc2Test, PRESENT_DISPLAY_buffer_1)
+{
+ const size_t layerCnt = 1;
+ Hwc2TestCoverage coverage = Hwc2TestCoverage::Default;
+ std::unordered_map<Hwc2TestPropertyName, Hwc2TestCoverage> exceptions =
+ {{Hwc2TestPropertyName::BufferArea, Hwc2TestCoverage::Complete}};
+ bool optimize = true;
+
+ ASSERT_NO_FATAL_FAILURE(presentDisplays(layerCnt, coverage, exceptions,
+ optimize));
+}
+
+/* TESTCASE: Tests that the HWC2 can present 1 layer with complete coverage of
+ * color. */
+TEST_F(Hwc2Test, PRESENT_DISPLAY_color_1)
+{
+ const size_t layerCnt = 1;
+ Hwc2TestCoverage coverage = Hwc2TestCoverage::Default;
+ std::unordered_map<Hwc2TestPropertyName, Hwc2TestCoverage> exceptions =
+ {{Hwc2TestPropertyName::Composition, Hwc2TestCoverage::Complete},
+ {Hwc2TestPropertyName::Color, Hwc2TestCoverage::Complete}};
+ bool optimize = true;
+
+ ASSERT_NO_FATAL_FAILURE(presentDisplays(layerCnt, coverage, exceptions,
+ optimize));
+}
+
+/* TESTCASE: Tests that the HWC2 can present 2 layers with complete coverage of
+ * color. */
+TEST_F(Hwc2Test, PRESENT_DISPLAY_color_2)
+{
+ const size_t layerCnt = 2;
+ Hwc2TestCoverage coverage = Hwc2TestCoverage::Default;
+ std::unordered_map<Hwc2TestPropertyName, Hwc2TestCoverage> exceptions =
+ {{Hwc2TestPropertyName::Composition, Hwc2TestCoverage::Complete},
+ {Hwc2TestPropertyName::BlendMode, Hwc2TestCoverage::Basic},
+ {Hwc2TestPropertyName::PlaneAlpha, Hwc2TestCoverage::Basic},
+ {Hwc2TestPropertyName::Color, Hwc2TestCoverage::Basic}};
+ bool optimize = true;
+
+ ASSERT_NO_FATAL_FAILURE(presentDisplays(layerCnt, coverage, exceptions,
+ optimize));
+}
+
+/* TESTCASE: Tests that the HWC2 can present 1 layer with complete coverage of
+ * composition. */
+TEST_F(Hwc2Test, PRESENT_DISPLAY_composition_1)
+{
+ const size_t layerCnt = 1;
+ Hwc2TestCoverage coverage = Hwc2TestCoverage::Default;
+ std::unordered_map<Hwc2TestPropertyName, Hwc2TestCoverage> exceptions =
+ {{Hwc2TestPropertyName::Composition, Hwc2TestCoverage::Complete}};
+ bool optimize = true;
+
+ ASSERT_NO_FATAL_FAILURE(presentDisplays(layerCnt, coverage, exceptions,
+ optimize));
+}
+
+/* TESTCASE: Tests that the HWC2 can present 1 layer with complete coverage of
+ * cursor. */
+TEST_F(Hwc2Test, PRESENT_DISPLAY_cursor_1)
+{
+ const size_t layerCnt = 1;
+ Hwc2TestCoverage coverage = Hwc2TestCoverage::Default;
+ std::unordered_map<Hwc2TestPropertyName, Hwc2TestCoverage> exceptions =
+ {{Hwc2TestPropertyName::Composition, Hwc2TestCoverage::Complete},
+ {Hwc2TestPropertyName::CursorPosition, Hwc2TestCoverage::Complete}};
+ bool optimize = true;
+
+ ASSERT_NO_FATAL_FAILURE(presentDisplays(layerCnt, coverage, exceptions,
+ optimize));
+}
+
+/* TESTCASE: Tests that the HWC2 can present 2 layers with complete coverage of
+ * cursor. */
+TEST_F(Hwc2Test, PRESENT_DISPLAY_cursor_2)
+{
+ const size_t layerCnt = 2;
+ Hwc2TestCoverage coverage = Hwc2TestCoverage::Default;
+ std::unordered_map<Hwc2TestPropertyName, Hwc2TestCoverage> exceptions =
+ {{Hwc2TestPropertyName::Composition, Hwc2TestCoverage::Complete},
+ {Hwc2TestPropertyName::CursorPosition, Hwc2TestCoverage::Complete},
+ {Hwc2TestPropertyName::DisplayFrame, Hwc2TestCoverage::Basic}};
+ bool optimize = true;
+
+ ASSERT_NO_FATAL_FAILURE(presentDisplays(layerCnt, coverage, exceptions,
+ optimize));
+}
+
+/* TESTCASE: Tests that the HWC2 can present 1 layer with complete coverage of
+ * dataspace. */
+TEST_F(Hwc2Test, PRESENT_DISPLAY_dataspace_1)
+{
+ const size_t layerCnt = 1;
+ Hwc2TestCoverage coverage = Hwc2TestCoverage::Default;
+ std::unordered_map<Hwc2TestPropertyName, Hwc2TestCoverage> exceptions =
+ {{Hwc2TestPropertyName::Dataspace, Hwc2TestCoverage::Complete}};
+ bool optimize = true;
+
+ ASSERT_NO_FATAL_FAILURE(presentDisplays(layerCnt, coverage, exceptions,
+ optimize));
+}
+
+/* TESTCASE: Tests that the HWC2 can present 1 layer with complete coverage of
+ * display frame. */
+TEST_F(Hwc2Test, PRESENT_DISPLAY_display_frame_1)
+{
+ const size_t layerCnt = 1;
+ Hwc2TestCoverage coverage = Hwc2TestCoverage::Default;
+ std::unordered_map<Hwc2TestPropertyName, Hwc2TestCoverage> exceptions =
+ {{Hwc2TestPropertyName::DisplayFrame, Hwc2TestCoverage::Complete}};
+ bool optimize = true;
+
+ ASSERT_NO_FATAL_FAILURE(presentDisplays(layerCnt, coverage, exceptions,
+ optimize));
+}
+
+/* TESTCASE: Tests that the HWC2 can present 2 layers with complete coverage of
+ * display frame. */
+TEST_F(Hwc2Test, PRESENT_DISPLAY_display_frame_2)
+{
+ const size_t layerCnt = 2;
+ Hwc2TestCoverage coverage = Hwc2TestCoverage::Default;
+ std::unordered_map<Hwc2TestPropertyName, Hwc2TestCoverage> exceptions =
+ {{Hwc2TestPropertyName::DisplayFrame, Hwc2TestCoverage::Complete}};
+ bool optimize = true;
+
+ ASSERT_NO_FATAL_FAILURE(presentDisplays(layerCnt, coverage, exceptions,
+ optimize));
+}
+
+/* TESTCASE: Tests that the HWC2 can present 3 layers with complete coverage of
+ * display frame. */
+TEST_F(Hwc2Test, PRESENT_DISPLAY_display_frame_3)
+{
+ const size_t layerCnt = 3;
+ Hwc2TestCoverage coverage = Hwc2TestCoverage::Default;
+ std::unordered_map<Hwc2TestPropertyName, Hwc2TestCoverage> exceptions =
+ {{Hwc2TestPropertyName::DisplayFrame, Hwc2TestCoverage::Complete}};
+ bool optimize = true;
+
+ ASSERT_NO_FATAL_FAILURE(presentDisplays(layerCnt, coverage, exceptions,
+ optimize));
+}
+
+/* TESTCASE: Tests that the HWC2 can present 4 layers with complete coverage of
+ * display frame. */
+TEST_F(Hwc2Test, PRESENT_DISPLAY_display_frame_4)
+{
+ const size_t layerCnt = 4;
+ Hwc2TestCoverage coverage = Hwc2TestCoverage::Default;
+ std::unordered_map<Hwc2TestPropertyName, Hwc2TestCoverage> exceptions =
+ {{Hwc2TestPropertyName::DisplayFrame, Hwc2TestCoverage::Complete}};
+ bool optimize = true;
+
+ ASSERT_NO_FATAL_FAILURE(presentDisplays(layerCnt, coverage, exceptions,
+ optimize));
+}
+
+/* TESTCASE: Tests that the HWC2 can present 1 layer with complete coverage of
+ * plane alpha. */
+TEST_F(Hwc2Test, PRESENT_DISPLAY_plane_alpha_1)
+{
+ const size_t layerCnt = 1;
+ Hwc2TestCoverage coverage = Hwc2TestCoverage::Default;
+ std::unordered_map<Hwc2TestPropertyName, Hwc2TestCoverage> exceptions =
+ {{Hwc2TestPropertyName::BlendMode, Hwc2TestCoverage::Basic},
+ {Hwc2TestPropertyName::PlaneAlpha, Hwc2TestCoverage::Complete}};
+ bool optimize = false;
+
+ ASSERT_NO_FATAL_FAILURE(presentDisplays(layerCnt, coverage, exceptions,
+ optimize));
+}
+
+/* TESTCASE: Tests that the HWC2 can present 2 layers with complete coverage of
+ * plane alpha. */
+TEST_F(Hwc2Test, PRESENT_DISPLAY_plane_alpha_2)
+{
+ const size_t layerCnt = 2;
+ Hwc2TestCoverage coverage = Hwc2TestCoverage::Default;
+ std::unordered_map<Hwc2TestPropertyName, Hwc2TestCoverage> exceptions =
+ {{Hwc2TestPropertyName::BlendMode, Hwc2TestCoverage::Basic},
+ {Hwc2TestPropertyName::PlaneAlpha, Hwc2TestCoverage::Complete}};
+ bool optimize = false;
+
+ ASSERT_NO_FATAL_FAILURE(presentDisplays(layerCnt, coverage, exceptions,
+ optimize));
+}
+
+/* TESTCASE: Tests that the HWC2 can present 1 layer with complete coverage of
+ * source crop. */
+TEST_F(Hwc2Test, PRESENT_DISPLAY_source_crop_1)
+{
+ const size_t layerCnt = 1;
+ Hwc2TestCoverage coverage = Hwc2TestCoverage::Default;
+ std::unordered_map<Hwc2TestPropertyName, Hwc2TestCoverage> exceptions =
+ {{Hwc2TestPropertyName::DisplayFrame, Hwc2TestCoverage::Complete},
+ {Hwc2TestPropertyName::SourceCrop, Hwc2TestCoverage::Complete}};
+ bool optimize = true;
+
+ ASSERT_NO_FATAL_FAILURE(presentDisplays(layerCnt, coverage, exceptions,
+ optimize));
+}
+
+/* TESTCASE: Tests that the HWC2 can present 2 layers with complete coverage of
+ * source crop. */
+TEST_F(Hwc2Test, PRESENT_DISPLAY_source_crop_2)
+{
+ const size_t layerCnt = 2;
+ Hwc2TestCoverage coverage = Hwc2TestCoverage::Default;
+ std::unordered_map<Hwc2TestPropertyName, Hwc2TestCoverage> exceptions =
+ {{Hwc2TestPropertyName::DisplayFrame, Hwc2TestCoverage::Complete},
+ {Hwc2TestPropertyName::SourceCrop, Hwc2TestCoverage::Complete}};
+ bool optimize = true;
+
+ ASSERT_NO_FATAL_FAILURE(presentDisplays(layerCnt, coverage, exceptions,
+ optimize));
+}
+
+
+/* TESTCASE: Tests that the HWC2 can present 1 layer with complete coverage of
+ * surface damage. */
+TEST_F(Hwc2Test, PRESENT_DISPLAY_surface_damage_1)
+{
+ const size_t layerCnt = 1;
+ Hwc2TestCoverage coverage = Hwc2TestCoverage::Default;
+ std::unordered_map<Hwc2TestPropertyName, Hwc2TestCoverage> exceptions =
+ {{Hwc2TestPropertyName::SurfaceDamage, Hwc2TestCoverage::Complete}};
+ bool optimize = true;
+
+ ASSERT_NO_FATAL_FAILURE(presentDisplays(layerCnt, coverage, exceptions,
+ optimize));
+}
+
+/* TESTCASE: Tests that the HWC2 can present 1 layer with complete coverage of
+ * transform. */
+TEST_F(Hwc2Test, PRESENT_DISPLAY_transform_1)
+{
+ const size_t layerCnt = 1;
+ Hwc2TestCoverage coverage = Hwc2TestCoverage::Default;
+ std::unordered_map<Hwc2TestPropertyName, Hwc2TestCoverage> exceptions =
+ {{Hwc2TestPropertyName::Transform, Hwc2TestCoverage::Complete}};
+ bool optimize = true;
+
+ ASSERT_NO_FATAL_FAILURE(presentDisplays(layerCnt, coverage, exceptions,
+ optimize));
+}
+
+/* TESTCASE: Tests that the HWC2 can present 2 layers with complete coverage of
+ * transform. */
+TEST_F(Hwc2Test, PRESENT_DISPLAY_transform_2)
+{
+ const size_t layerCnt = 2;
+ Hwc2TestCoverage coverage = Hwc2TestCoverage::Default;
+ std::unordered_map<Hwc2TestPropertyName, Hwc2TestCoverage> exceptions =
+ {{Hwc2TestPropertyName::Transform, Hwc2TestCoverage::Complete},
+ {Hwc2TestPropertyName::DisplayFrame, Hwc2TestCoverage::Basic}};
+ bool optimize = true;
+
+ ASSERT_NO_FATAL_FAILURE(presentDisplays(layerCnt, coverage, exceptions,
+ optimize));
+}
+
+/* TESTCASE: Tests that the HWC2 can present 1 layer with complete coverage of
+ * basic. */
+TEST_F(Hwc2Test, PRESENT_DISPLAY_basic_1)
+{
+ const size_t layerCnt = 1;
+ Hwc2TestCoverage coverage = Hwc2TestCoverage::Basic;
+ std::unordered_map<Hwc2TestPropertyName, Hwc2TestCoverage> exceptions;
+ bool optimize = true;
+
+ ASSERT_NO_FATAL_FAILURE(presentDisplays(layerCnt, coverage, exceptions,
+ optimize));
+}
+
+/* TESTCASE: Tests that the HWC2 cannot present a bad display. */
+TEST_F(Hwc2Test, PRESENT_DISPLAY_bad_display)
+{
+ hwc2_display_t display;
+ int32_t presentFence;
+ hwc2_error_t err = HWC2_ERROR_NONE;
+
+ ASSERT_NO_FATAL_FAILURE(getBadDisplay(&display));
+
+ ASSERT_NO_FATAL_FAILURE(presentDisplay(display, &presentFence, &err));
+ EXPECT_EQ(err, HWC2_ERROR_BAD_DISPLAY) << "returned wrong error code";
+}
+
+/* TESTCASE: Tests that the HWC2 cannot present an unvalidated display. */
+TEST_F(Hwc2Test, PRESENT_DISPLAY_not_validated)
+{
+ ASSERT_NO_FATAL_FAILURE(displayLayers(Hwc2TestCoverage::Default, 1,
+ [] (Hwc2Test* test, hwc2_display_t display,
+ const std::vector<hwc2_layer_t>& /*layers*/,
+ Hwc2TestLayers* /*testLayers*/) {
+
+ int32_t presentFence;
+ hwc2_error_t err = HWC2_ERROR_NONE;
+
+ ASSERT_NO_FATAL_FAILURE(test->setPowerMode(display,
+ HWC2_POWER_MODE_ON));
+ ASSERT_NO_FATAL_FAILURE(test->enableVsync(display));
+
+ ASSERT_NO_FATAL_FAILURE(test->waitForVsync());
+
+ ASSERT_NO_FATAL_FAILURE(test->presentDisplay(display,
+ &presentFence, &err));
+ EXPECT_EQ(err, HWC2_ERROR_NOT_VALIDATED)
+ << "returned wrong error code";
+
+ ASSERT_NO_FATAL_FAILURE(test->disableVsync(display));
+ ASSERT_NO_FATAL_FAILURE(test->setPowerMode(display,
+ HWC2_POWER_MODE_OFF));
+ }
+ ));
+}
+
+/* TESTCASE: Tests that the HWC2 cannot get release fences from a bad display. */
+TEST_F(Hwc2Test, GET_RELEASE_FENCES_bad_display)
+{
+ hwc2_display_t display;
+ std::vector<hwc2_layer_t> layers;
+ std::vector<int32_t> fences;
+ hwc2_error_t err = HWC2_ERROR_NONE;
+
+ ASSERT_NO_FATAL_FAILURE(getBadDisplay(&display));
+
+ ASSERT_NO_FATAL_FAILURE(getReleaseFences(display, &layers, &fences, &err));
+ EXPECT_EQ(err, HWC2_ERROR_BAD_DISPLAY) << "returned wrong error code";
+}
+
+static const std::array<android_color_mode, 9> androidColorModes = {{
+ HAL_COLOR_MODE_NATIVE,
+ HAL_COLOR_MODE_STANDARD_BT601_625,
+ HAL_COLOR_MODE_STANDARD_BT601_625_UNADJUSTED,
+ HAL_COLOR_MODE_STANDARD_BT601_525,
+ HAL_COLOR_MODE_STANDARD_BT601_525_UNADJUSTED,
+ HAL_COLOR_MODE_STANDARD_BT709,
+ HAL_COLOR_MODE_DCI_P3,
+ HAL_COLOR_MODE_SRGB,
+ HAL_COLOR_MODE_ADOBE_RGB,
+}};
+
+/* TESTCASE: Tests that the HWC2 can get the color modes for a display. The
+ * display must support HAL_COLOR_MODE_NATIVE */
+TEST_F(Hwc2Test, GET_COLOR_MODES)
+{
+ ASSERT_NO_FATAL_FAILURE(setActiveDisplayConfig(
+ [] (Hwc2Test* test, hwc2_display_t display) {
+
+ std::vector<android_color_mode_t> colorModes;
+
+ ASSERT_NO_FATAL_FAILURE(test->getColorModes(display,
+ &colorModes));
+
+ EXPECT_NE(std::count(colorModes.begin(), colorModes.end(),
+ HAL_COLOR_MODE_NATIVE), 0) << "all displays"
+ " must support HAL_COLOR_MODE_NATIVE";
+ }
+ ));
+}
+
+/* TESTCASE: Tests that the HWC2 cannot get color modes from a bad display. */
+TEST_F(Hwc2Test, GET_COLOR_MODES_bad_display)
+{
+ hwc2_display_t display;
+ std::vector<android_color_mode_t> colorModes;
+ hwc2_error_t err = HWC2_ERROR_NONE;
+
+ ASSERT_NO_FATAL_FAILURE(getBadDisplay(&display));
+
+ ASSERT_NO_FATAL_FAILURE(getColorModes(display, &colorModes, &err));
+ EXPECT_EQ(err, HWC2_ERROR_BAD_DISPLAY) << "returned wrong error code";
+}
+
+/* TESTCASE: Tests that the HWC2 can set the required color mode on a display. */
+TEST_F(Hwc2Test, SET_COLOR_MODES)
+{
+ ASSERT_NO_FATAL_FAILURE(setActiveDisplayConfig(
+ [] (Hwc2Test* test, hwc2_display_t display) {
+
+ const android_color_mode_t colorMode = HAL_COLOR_MODE_NATIVE;
+
+ EXPECT_NO_FATAL_FAILURE(test->setColorMode(display, colorMode));
+ }
+ ));
+}
+
+/* TESTCASE: Tests that the HWC2 cannot set a color mode on a bad display. */
+TEST_F(Hwc2Test, SET_COLOR_MODES_bad_display)
+{
+ hwc2_display_t display;
+ const android_color_mode_t colorMode = HAL_COLOR_MODE_NATIVE;
+ hwc2_error_t err = HWC2_ERROR_NONE;
+
+ ASSERT_NO_FATAL_FAILURE(getBadDisplay(&display));
+
+ ASSERT_NO_FATAL_FAILURE(setColorMode(display, colorMode, &err));
+ EXPECT_EQ(err, HWC2_ERROR_BAD_DISPLAY) << "returned wrong error code";
+}
+
+/* TESTCASE: Tests that the HWC2 cannot set an invalid color mode. */
+TEST_F(Hwc2Test, SET_COLOR_MODES_bad_parameter)
+{
+ ASSERT_NO_FATAL_FAILURE(setActiveDisplayConfig(
+ [] (Hwc2Test* test, hwc2_display_t display) {
+
+ const android_color_mode_t colorMode =
+ static_cast<android_color_mode_t>(-1);
+ hwc2_error_t err = HWC2_ERROR_NONE;
+
+ ASSERT_NO_FATAL_FAILURE(test->setColorMode(display, colorMode,
+ &err));
+ EXPECT_EQ(err, HWC2_ERROR_BAD_PARAMETER)
+ << "returned wrong error code";
+ }
+ ));
+}
+
+/* TESTCASE: Tests that the HWC2 either supports or returns error unsupported
+ * for all valid color modes. */
+TEST_F(Hwc2Test, SET_COLOR_MODES_unsupported)
+{
+ ASSERT_NO_FATAL_FAILURE(setActiveDisplayConfig(
+ [] (Hwc2Test* test, hwc2_display_t display) {
+
+ for (auto colorMode : androidColorModes) {
+ hwc2_error_t err = HWC2_ERROR_NONE;
+
+ ASSERT_NO_FATAL_FAILURE(test->setColorMode(display,
+ colorMode, &err));
+
+ EXPECT_TRUE(err == HWC2_ERROR_NONE
+ || err == HWC2_ERROR_UNSUPPORTED)
+ << "returned wrong error code";
+ }
+ }
+ ));
+}
+
+/* TESTCASE: Tests that the HWC2 gets the HDR capabilities for a display and
+ * test if they are valid. */
+TEST_F(Hwc2Test, GET_HDR_CAPABILITIES)
+{
+ ASSERT_NO_FATAL_FAILURE(setActiveDisplayConfig(
+ [] (Hwc2Test* test, hwc2_display_t display) {
+
+ std::vector<android_hdr_t> hdrCapabilities;
+ float maxLuminance, maxAverageLuminance, minLuminance;
+
+ EXPECT_NO_FATAL_FAILURE(test->getHdrCapabilities(display,
+ &hdrCapabilities, &maxLuminance, &maxAverageLuminance,
+ &minLuminance));
+
+ if (hdrCapabilities.empty())
+ return;
+
+ EXPECT_GE(maxLuminance, maxAverageLuminance);
+ EXPECT_GE(maxAverageLuminance, minLuminance);
+ }
+ ));
+}
+
+/* TESTCASE: Tests that the HWC2 cannot get hdr capabilities from a bad display */
+TEST_F(Hwc2Test, GET_HDR_CAPABILITIES_bad_display)
+{
+ hwc2_display_t display;
+ std::vector<android_hdr_t> hdrCapabilities;
+ float maxLuminance, maxAverageLuminance, minLuminance;
+ hwc2_error_t err = HWC2_ERROR_NONE;
+
+ ASSERT_NO_FATAL_FAILURE(getBadDisplay(&display));
+
+ ASSERT_NO_FATAL_FAILURE(getHdrCapabilities(display, &hdrCapabilities,
+ &maxLuminance, &maxAverageLuminance, &minLuminance, &err));
+ EXPECT_EQ(err, HWC2_ERROR_BAD_DISPLAY) << "returned wrong error code";
+}
+
+static const std::array<float, 16> identityMatrix = {{
+ 1.0, 0.0, 0.0, 0.0,
+ 0.0, 1.0, 0.0, 0.0,
+ 0.0, 0.0, 1.0, 0.0,
+ 0.0, 0.0, 0.0, 1.0,
+}};
+
+/* Values for the color transform matrices were precomputed using the source code
+ * in surfaceflinger/Effects/Daltonizer.cpp. */
+
+static const std::array<const std::array<float, 16>, 5> exampleMatrices = {{
+ identityMatrix,
+ /* Converts RGB color to the XYZ space */
+ {{ 0.4124, 0.2126, 0.0193, 0,
+ 0.3576, 0.7152, 0.1192, 0,
+ 0.1805, 0.0722, 0.9505, 0,
+ 0 , 0 , 0 , 1 }},
+ /* Protanomaly */
+ {{ 0.068493, 0.931506, 0, 0,
+ 0.068493, 0.931507, 0, 0,
+ 0.013626, -0.013626, 1, 0,
+ 0, 0, 0, 1 }},
+ /* Deuteranomaly */
+ {{ 0.288299, 0.711701, 0, 0,
+ 0.052709, 0.947291, 0, 0,
+ -0.257912, 0.257912, 1, 0,
+ 0, 0, 0, 1 }},
+ /* Tritanomaly */
+ {{ 1, -0.805712, 0.805712, 0,
+ 0, 0.378838, 0.621162, 0,
+ 0, 0.104823, 0.895177, 0,
+ 0, 0, 0, 1 }},
+}};
+
+/* TESTCASE: Tests that the HWC2 can set the identity color transform */
+TEST_F(Hwc2Test, SET_COLOR_TRANSFORM)
+{
+ ASSERT_NO_FATAL_FAILURE(setActiveDisplayConfig(
+ [] (Hwc2Test* test, hwc2_display_t display) {
+
+ EXPECT_NO_FATAL_FAILURE(test->setColorTransform(display,
+ identityMatrix, HAL_COLOR_TRANSFORM_IDENTITY));
+ }
+ ));
+}
+
+/* TESTCASE: Tests that the HWC2 cannot set the color transform for a bad
+ * display. */
+TEST_F(Hwc2Test, SET_COLOR_TRANSFORM_bad_display)
+{
+ hwc2_display_t display;
+ hwc2_error_t err = HWC2_ERROR_NONE;
+
+ ASSERT_NO_FATAL_FAILURE(getBadDisplay(&display));
+
+ ASSERT_NO_FATAL_FAILURE(setColorTransform(display, identityMatrix,
+ HAL_COLOR_TRANSFORM_IDENTITY, &err));
+ EXPECT_EQ(err, HWC2_ERROR_BAD_DISPLAY) << "returned wrong error code";
+}
+
+/* TESTCASE: Tests that the HWC2 cannot set an invalid color transform. */
+TEST_F(Hwc2Test, SET_COLOR_TRANSFORM_bad_parameter)
+{
+ ASSERT_NO_FATAL_FAILURE(setActiveDisplayConfig(
+ [] (Hwc2Test* test, hwc2_display_t display) {
+
+ const android_color_transform_t hint =
+ static_cast<android_color_transform_t>(-1);
+ hwc2_error_t err = HWC2_ERROR_NONE;
+
+ ASSERT_NO_FATAL_FAILURE(test->setColorTransform(display,
+ identityMatrix, hint, &err));
+ EXPECT_EQ(err, HWC2_ERROR_BAD_PARAMETER)
+ << "returned wrong error code";
+ }
+ ));
+}
+
+/* TESTCASE: Tests that the HWC2 can set an arbitrary color matrix. */
+TEST_F(Hwc2Test, SET_COLOR_TRANSFORM_arbitrary_matrix)
+{
+ ASSERT_NO_FATAL_FAILURE(setActiveDisplayConfig(
+ [] (Hwc2Test* test, hwc2_display_t display) {
+
+ const android_color_transform_t hint =
+ HAL_COLOR_TRANSFORM_ARBITRARY_MATRIX;
+
+ for (const std::array<float, 16>& matrix : exampleMatrices) {
+ EXPECT_NO_FATAL_FAILURE(test->setColorTransform(display,
+ matrix, hint));
+ }
+ }
+ ));
+}
+
+/* TESTCASE: Tests that the HWC2 create an destory virtual displays. */
+TEST_F(Hwc2Test, CREATE_DESTROY_VIRTUAL_DISPLAY)
+{
+ ASSERT_NO_FATAL_FAILURE(createVirtualDisplay(Hwc2TestCoverage::Complete,
+ [] (Hwc2Test* /*test*/, hwc2_display_t /*display*/,
+ Hwc2TestVirtualDisplay* /*testVirtualDisplay*/) { }));
+}
+
+/* TESTCASE: Tests that the HWC2 can create and destroy multiple virtual
+ * displays. */
+TEST_F(Hwc2Test, CREATE_DESTROY_VIRTUAL_DISPLAY_multiple)
+{
+ Hwc2TestVirtualDisplay testVirtualDisplay(Hwc2TestCoverage::Complete);
+ std::vector<hwc2_display_t> displays;
+
+ do {
+ const UnsignedArea& dimension =
+ testVirtualDisplay.getDisplayDimension();
+ android_pixel_format_t desiredFormat = HAL_PIXEL_FORMAT_RGBA_8888;
+ hwc2_display_t display;
+ hwc2_error_t err = HWC2_ERROR_NONE;
+
+ ASSERT_NO_FATAL_FAILURE(createVirtualDisplay(dimension.width,
+ dimension.height, &desiredFormat, &display, &err));
+
+ EXPECT_TRUE(err == HWC2_ERROR_NONE || err == HWC2_ERROR_NO_RESOURCES
+ || err == HWC2_ERROR_UNSUPPORTED) << "returned wrong error code";
+ EXPECT_GE(desiredFormat, 0) << "invalid format";
+
+ if (err == HWC2_ERROR_NONE)
+ displays.push_back(display);
+
+ } while (testVirtualDisplay.advance());
+
+ for (hwc2_display_t display : displays) {
+ EXPECT_NO_FATAL_FAILURE(destroyVirtualDisplay(display));
+ }
+}
+
+/* TESTCASE: Tests that the HWC2 cannot destroy a bad virtual displays. */
+TEST_F(Hwc2Test, DESTROY_VIRTUAL_DISPLAY_bad_display)
+{
+ hwc2_display_t display;
+ hwc2_error_t err = HWC2_ERROR_NONE;
+
+ ASSERT_NO_FATAL_FAILURE(getBadDisplay(&display));
+
+ ASSERT_NO_FATAL_FAILURE(destroyVirtualDisplay(display, &err));
+ EXPECT_EQ(err, HWC2_ERROR_BAD_DISPLAY) << "returned wrong error code";
+}
+
+/* TESTCASE: Tests that the HWC2 cannot destroy a physical display. */
+TEST_F(Hwc2Test, DESTROY_VIRTUAL_DISPLAY_bad_parameter)
+{
+ hwc2_display_t display = HWC_DISPLAY_PRIMARY;
+ hwc2_error_t err = HWC2_ERROR_NONE;
+
+ ASSERT_NO_FATAL_FAILURE(destroyVirtualDisplay(display, &err));
+ EXPECT_EQ(err, HWC2_ERROR_BAD_PARAMETER) << "returned wrong error code";
+}
+
+/* TESTCASE: Tests that the HWC2 can get the max virtual display count. */
+TEST_F(Hwc2Test, GET_MAX_VIRTUAL_DISPLAY_COUNT)
+{
+ uint32_t maxCnt;
+
+ ASSERT_NO_FATAL_FAILURE(getMaxVirtualDisplayCount(&maxCnt));
+}
+
+/* TESTCASE: Tests that the HWC2 returns the same max virtual display count for
+ * each call. */
+TEST_F(Hwc2Test, GET_MAX_VIRTUAL_DISPLAY_COUNT_duplicate)
+{
+ uint32_t maxCnt1, maxCnt2;
+
+ ASSERT_NO_FATAL_FAILURE(getMaxVirtualDisplayCount(&maxCnt1));
+ ASSERT_NO_FATAL_FAILURE(getMaxVirtualDisplayCount(&maxCnt2));
+
+ EXPECT_EQ(maxCnt1, maxCnt2) << "returned two different max virtual display"
+ " counts";
+}
+
+/* TESTCASE: Tests that the HWC2 can create the max number of virtual displays
+ * that it reports. */
+TEST_F(Hwc2Test, GET_MAX_VIRTUAL_DISPLAY_COUNT_create_max)
+{
+ std::vector<hwc2_display_t> displays;
+ uint32_t maxCnt;
+
+ ASSERT_NO_FATAL_FAILURE(getMaxVirtualDisplayCount(&maxCnt));
+
+ while (displays.size() < maxCnt) {
+ uint32_t width = 1920, height = 1080;
+ android_pixel_format_t desiredFormat = HAL_PIXEL_FORMAT_RGBA_8888;
+ hwc2_display_t display;
+ hwc2_error_t err = HWC2_ERROR_NONE;
+
+ ASSERT_NO_FATAL_FAILURE(createVirtualDisplay(width, height,
+ &desiredFormat, &display, &err));
+
+ EXPECT_TRUE(err == HWC2_ERROR_NONE || err == HWC2_ERROR_UNSUPPORTED)
+ << "returned wrong error code";
+ if (err != HWC2_ERROR_NONE)
+ break;
+
+ displays.push_back(display);
+ }
+
+ for (hwc2_display_t display : displays) {
+ EXPECT_NO_FATAL_FAILURE(destroyVirtualDisplay(display));
+ }
+}
+
+/* TESTCASE: Tests that the HWC2 can set an output buffer for a virtual
+ * display. */
+TEST_F(Hwc2Test, SET_OUTPUT_BUFFER)
+{
+ ASSERT_NO_FATAL_FAILURE(createVirtualDisplay(Hwc2TestCoverage::Complete,
+ [] (Hwc2Test* test, hwc2_display_t display,
+ Hwc2TestVirtualDisplay* testVirtualDisplay) {
+
+ buffer_handle_t handle;
+ android::base::unique_fd acquireFence;
+
+ if (testVirtualDisplay->getBuffer(&handle, &acquireFence) >= 0)
+ EXPECT_NO_FATAL_FAILURE(test->setOutputBuffer(display,
+ handle, acquireFence));
+ }));
+}
+
+/* TESTCASE: Tests that the HWC2 cannot set an output buffer for a bad display */
+TEST_F(Hwc2Test, SET_OUTPUT_BUFFER_bad_display)
+{
+ ASSERT_NO_FATAL_FAILURE(createVirtualDisplay(Hwc2TestCoverage::Default,
+ [] (Hwc2Test* test, hwc2_display_t /*display*/,
+ Hwc2TestVirtualDisplay* testVirtualDisplay) {
+
+ hwc2_display_t badDisplay;
+ buffer_handle_t handle;
+ android::base::unique_fd acquireFence;
+ hwc2_error_t err = HWC2_ERROR_NONE;
+
+ ASSERT_NO_FATAL_FAILURE(test->getBadDisplay(&badDisplay));
+
+ if (testVirtualDisplay->getBuffer(&handle, &acquireFence) < 0)
+ return;
+
+ ASSERT_NO_FATAL_FAILURE(test->setOutputBuffer(badDisplay,
+ handle, acquireFence, &err));
+ EXPECT_TRUE(err == HWC2_ERROR_BAD_DISPLAY)
+ << "returned wrong error code";
+ }));
+}
+
+/* TESTCASE: Tests that the HWC2 cannot set an invalid output buffer. */
+TEST_F(Hwc2Test, SET_OUTPUT_BUFFER_bad_parameter)
+{
+ ASSERT_NO_FATAL_FAILURE(createVirtualDisplay(Hwc2TestCoverage::Default,
+ [] (Hwc2Test* test, hwc2_display_t display,
+ Hwc2TestVirtualDisplay* /*testVirtualDisplay*/) {
+
+ const buffer_handle_t handle = nullptr;
+ uint32_t releaseFence = -1;
+ hwc2_error_t err = HWC2_ERROR_NONE;
+
+ ASSERT_NO_FATAL_FAILURE(test->setOutputBuffer(display, handle,
+ releaseFence, &err));
+ EXPECT_EQ(err, HWC2_ERROR_BAD_PARAMETER)
+ << "returned wrong error code";
+ }));
+}
+
+/* TESTCASE: Tests that the HWC2 cannot set an output buffer for non virtual
+ * display */
+TEST_F(Hwc2Test, SET_OUTPUT_BUFFER_unsupported)
+{
+ for (auto display : mDisplays) {
+ Hwc2TestVirtualDisplay testVirtualDisplay(Hwc2TestCoverage::Complete);
+
+ do {
+ buffer_handle_t handle;
+ android::base::unique_fd acquireFence;
+ hwc2_error_t err = HWC2_ERROR_NONE;
+
+ if (testVirtualDisplay.getBuffer(&handle, &acquireFence) < 0)
+ continue;
+
+ ASSERT_NO_FATAL_FAILURE(setOutputBuffer(display, handle,
+ acquireFence, &err));
+ EXPECT_EQ(err, HWC2_ERROR_UNSUPPORTED) << "returned wrong error code";
+
+ } while (testVirtualDisplay.advance());
+ }
+}
+
+/* TESTCASE: Tests that the HWC2 can dump debug information. */
+TEST_F(Hwc2Test, DUMP)
+{
+ std::string buffer;
+
+ ASSERT_NO_FATAL_FAILURE(dump(&buffer));
+}
diff --git a/services/surfaceflinger/tests/hwc2/Hwc2TestBuffer.cpp b/services/surfaceflinger/tests/hwc2/Hwc2TestBuffer.cpp
new file mode 100644
index 0000000..a59f388
--- /dev/null
+++ b/services/surfaceflinger/tests/hwc2/Hwc2TestBuffer.cpp
@@ -0,0 +1,692 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <mutex>
+#include <array>
+#include <sstream>
+#include <algorithm>
+
+#include <gui/Surface.h>
+#include <gui/BufferItemConsumer.h>
+#include <gui/GraphicBufferAlloc.h>
+
+#include <ui/GraphicBuffer.h>
+#include <ui/vec4.h>
+
+#include <GLES3/gl3.h>
+
+#include "Hwc2TestBuffer.h"
+#include "Hwc2TestLayers.h"
+
+using namespace android;
+
+/* Returns a fence from egl */
+typedef void (*FenceCallback)(int32_t fence, void* callbackArgs);
+
+/* Returns fence to fence generator */
+static void setFence(int32_t fence, void* fenceGenerator);
+
+
+/* Used to receive the surfaces and fences from egl. The egl buffers are thrown
+ * away. The fences are sent to the requester via a callback */
+class Hwc2TestSurfaceManager {
+public:
+ /* Listens for a new frame, detaches the buffer and returns the fence
+ * through saved callback. */
+ class BufferListener : public ConsumerBase::FrameAvailableListener {
+ public:
+ BufferListener(sp<IGraphicBufferConsumer> consumer,
+ FenceCallback callback, void* callbackArgs)
+ : mConsumer(consumer),
+ mCallback(callback),
+ mCallbackArgs(callbackArgs) { }
+
+ void onFrameAvailable(const BufferItem& /*item*/)
+ {
+ BufferItem item;
+
+ if (mConsumer->acquireBuffer(&item, 0))
+ return;
+ if (mConsumer->detachBuffer(item.mSlot))
+ return;
+
+ mCallback(item.mFence->dup(), mCallbackArgs);
+ }
+
+ private:
+ sp<IGraphicBufferConsumer> mConsumer;
+ FenceCallback mCallback;
+ void* mCallbackArgs;
+ };
+
+ /* Creates a buffer listener that waits on a new frame from the buffer
+ * queue. */
+ void initialize(const Area& bufferArea, android_pixel_format_t format,
+ FenceCallback callback, void* callbackArgs)
+ {
+ sp<IGraphicBufferProducer> producer;
+ sp<IGraphicBufferConsumer> consumer;
+ BufferQueue::createBufferQueue(&producer, &consumer);
+
+ consumer->setDefaultBufferSize(bufferArea.width, bufferArea.height);
+ consumer->setDefaultBufferFormat(format);
+
+ mBufferItemConsumer = new BufferItemConsumer(consumer, 0);
+
+ mListener = new BufferListener(consumer, callback, callbackArgs);
+ mBufferItemConsumer->setFrameAvailableListener(mListener);
+
+ mSurface = new Surface(producer, true);
+ }
+
+ /* Used by Egl manager. The surface is never displayed. */
+ sp<Surface> getSurface() const
+ {
+ return mSurface;
+ }
+
+private:
+ sp<BufferItemConsumer> mBufferItemConsumer;
+ sp<BufferListener> mListener;
+ /* Used by Egl manager. The surface is never displayed */
+ sp<Surface> mSurface;
+};
+
+
+/* Used to generate valid fences. It is not possible to create a dummy sync
+ * fence for testing. Egl can generate buffers along with a valid fence.
+ * The buffer cannot be guaranteed to be the same format across all devices so
+ * a CPU filled buffer is used instead. The Egl fence is used along with the
+ * CPU filled buffer. */
+class Hwc2TestEglManager {
+public:
+ Hwc2TestEglManager()
+ : mEglDisplay(EGL_NO_DISPLAY),
+ mEglSurface(EGL_NO_SURFACE),
+ mEglContext(EGL_NO_CONTEXT) { }
+
+ ~Hwc2TestEglManager()
+ {
+ cleanup();
+ }
+
+ int initialize(sp<Surface> surface)
+ {
+ mSurface = surface;
+
+ mEglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
+ if (mEglDisplay == EGL_NO_DISPLAY) return false;
+
+ EGLint major;
+ EGLint minor;
+ if (!eglInitialize(mEglDisplay, &major, &minor)) {
+ ALOGW("Could not initialize EGL");
+ return false;
+ }
+
+ /* We're going to use a 1x1 pbuffer surface later on
+ * The configuration distance doesn't really matter for what we're
+ * trying to do */
+ EGLint configAttrs[] = {
+ EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
+ EGL_RED_SIZE, 8,
+ EGL_GREEN_SIZE, 8,
+ EGL_BLUE_SIZE, 8,
+ EGL_ALPHA_SIZE, 0,
+ EGL_DEPTH_SIZE, 24,
+ EGL_STENCIL_SIZE, 0,
+ EGL_NONE
+ };
+
+ EGLConfig configs[1];
+ EGLint configCnt;
+ if (!eglChooseConfig(mEglDisplay, configAttrs, configs, 1,
+ &configCnt)) {
+ ALOGW("Could not select EGL configuration");
+ eglReleaseThread();
+ eglTerminate(mEglDisplay);
+ return false;
+ }
+
+ if (configCnt <= 0) {
+ ALOGW("Could not find EGL configuration");
+ eglReleaseThread();
+ eglTerminate(mEglDisplay);
+ return false;
+ }
+
+ /* These objects are initialized below but the default "null" values are
+ * used to cleanup properly at any point in the initialization sequence */
+ EGLint attrs[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE };
+ mEglContext = eglCreateContext(mEglDisplay, configs[0], EGL_NO_CONTEXT,
+ attrs);
+ if (mEglContext == EGL_NO_CONTEXT) {
+ ALOGW("Could not create EGL context");
+ cleanup();
+ return false;
+ }
+
+ EGLint surfaceAttrs[] = { EGL_NONE };
+ mEglSurface = eglCreateWindowSurface(mEglDisplay, configs[0],
+ mSurface.get(), surfaceAttrs);
+ if (mEglSurface == EGL_NO_SURFACE) {
+ ALOGW("Could not create EGL surface");
+ cleanup();
+ return false;
+ }
+
+ if (!eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, mEglContext)) {
+ ALOGW("Could not change current EGL context");
+ cleanup();
+ return false;
+ }
+
+ return true;
+ }
+
+ void makeCurrent() const
+ {
+ eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, mEglContext);
+ }
+
+ void present() const
+ {
+ eglSwapBuffers(mEglDisplay, mEglSurface);
+ }
+
+private:
+ void cleanup()
+ {
+ if (mEglDisplay == EGL_NO_DISPLAY)
+ return;
+ if (mEglSurface != EGL_NO_SURFACE)
+ eglDestroySurface(mEglDisplay, mEglSurface);
+ if (mEglContext != EGL_NO_CONTEXT)
+ eglDestroyContext(mEglDisplay, mEglContext);
+
+ eglMakeCurrent(mEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE,
+ EGL_NO_CONTEXT);
+ eglReleaseThread();
+ eglTerminate(mEglDisplay);
+ }
+
+ sp<Surface> mSurface;
+ EGLDisplay mEglDisplay;
+ EGLSurface mEglSurface;
+ EGLContext mEglContext;
+};
+
+
+static const std::array<vec2, 4> triangles = {{
+ { 1.0f, 1.0f },
+ { -1.0f, 1.0f },
+ { 1.0f, -1.0f },
+ { -1.0f, -1.0f },
+}};
+
+class Hwc2TestFenceGenerator {
+public:
+
+ Hwc2TestFenceGenerator()
+ {
+ mSurfaceManager.initialize({1, 1}, HAL_PIXEL_FORMAT_RGBA_8888,
+ setFence, this);
+
+ if (!mEglManager.initialize(mSurfaceManager.getSurface()))
+ return;
+
+ mEglManager.makeCurrent();
+
+ glClearColor(0.0, 0.0, 0.0, 1.0);
+ glEnableVertexAttribArray(0);
+ }
+
+ ~Hwc2TestFenceGenerator()
+ {
+ if (mFence >= 0)
+ close(mFence);
+ mFence = -1;
+
+ mEglManager.makeCurrent();
+ }
+
+ /* It is not possible to simply generate a fence. The easiest way is to
+ * generate a buffer using egl and use the associated fence. The buffer
+ * cannot be guaranteed to be a certain format across all devices using this
+ * method. Instead the buffer is generated using the CPU */
+ int32_t get()
+ {
+ if (mFence >= 0) {
+ return dup(mFence);
+ }
+
+ std::unique_lock<std::mutex> lock(mMutex);
+
+ /* If the pending is still set to false and times out, we cannot recover.
+ * Set an error and return */
+ while (mPending != false) {
+ if (mCv.wait_for(lock, std::chrono::seconds(2)) == std::cv_status::timeout)
+ return -ETIME;
+ }
+
+ /* Generate a fence. The fence will be returned through the setFence
+ * callback */
+ mEglManager.makeCurrent();
+
+ glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, triangles.data());
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ mEglManager.present();
+
+ /* Wait for the setFence callback */
+ while (mPending != true) {
+ if (mCv.wait_for(lock, std::chrono::seconds(2)) == std::cv_status::timeout)
+ return -ETIME;
+ }
+
+ mPending = false;
+
+ return dup(mFence);
+ }
+
+ /* Callback that sets the fence */
+ void set(int32_t fence)
+ {
+ mFence = fence;
+ mPending = true;
+
+ mCv.notify_all();
+ }
+
+private:
+
+ Hwc2TestSurfaceManager mSurfaceManager;
+ Hwc2TestEglManager mEglManager;
+
+ std::mutex mMutex;
+ std::condition_variable mCv;
+
+ int32_t mFence = -1;
+ bool mPending = false;
+};
+
+
+static void setFence(int32_t fence, void* fenceGenerator)
+{
+ static_cast<Hwc2TestFenceGenerator*>(fenceGenerator)->set(fence);
+}
+
+
+/* Sets the pixel of a buffer given the location, format, stride and color.
+ * Currently only supports RGBA_8888 */
+static void setColor(int32_t x, int32_t y,
+ android_pixel_format_t format, uint32_t stride, uint8_t* img, uint8_t r,
+ uint8_t g, uint8_t b, uint8_t a)
+{
+ switch (format) {
+ case HAL_PIXEL_FORMAT_RGBA_8888:
+ img[(y * stride + x) * 4 + 0] = r;
+ img[(y * stride + x) * 4 + 1] = g;
+ img[(y * stride + x) * 4 + 2] = b;
+ img[(y * stride + x) * 4 + 3] = a;
+ break;
+ default:
+ break;
+ }
+}
+
+Hwc2TestBuffer::Hwc2TestBuffer()
+ : mFenceGenerator(new Hwc2TestFenceGenerator()) { }
+
+Hwc2TestBuffer::~Hwc2TestBuffer() = default;
+
+/* When the buffer changes sizes, save the new size and invalidate the current
+ * buffer */
+void Hwc2TestBuffer::updateBufferArea(const Area& bufferArea)
+{
+ if (mBufferArea.width == bufferArea.width
+ && mBufferArea.height == bufferArea.height)
+ return;
+
+ mBufferArea.width = bufferArea.width;
+ mBufferArea.height = bufferArea.height;
+
+ mValidBuffer = false;
+}
+
+/* Returns a valid buffer handle and fence. The handle is filled using the CPU
+ * to ensure the correct format across all devices. The fence is created using
+ * egl. */
+int Hwc2TestBuffer::get(buffer_handle_t* outHandle, int32_t* outFence)
+{
+ if (mBufferArea.width == -1 || mBufferArea.height == -1)
+ return -EINVAL;
+
+ /* If the current buffer is valid, the previous buffer can be reused.
+ * Otherwise, create new buffer */
+ if (!mValidBuffer) {
+ int ret = generateBuffer();
+ if (ret)
+ return ret;
+ }
+
+ *outFence = mFenceGenerator->get();
+ *outHandle = mHandle;
+
+ mValidBuffer = true;
+
+ return 0;
+}
+
+/* CPU fills a buffer to guarantee the correct buffer format across all
+ * devices */
+int Hwc2TestBuffer::generateBuffer()
+{
+ int ret;
+
+ /* Create new graphic buffer with correct dimensions */
+ mGraphicBuffer = mGraphicBufferAlloc.createGraphicBuffer(
+ mBufferArea.width, mBufferArea.height, mFormat,
+ GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_HW_RENDER,
+ "hwc2_test_buffer", &ret);
+ if (ret)
+ return ret;
+
+ /* Locks the buffer for writing */
+ uint8_t* img;
+ mGraphicBuffer->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&img));
+
+ uint32_t stride = mGraphicBuffer->getStride();
+
+ /* Iterate from the top row of the buffer to the bottom row */
+ for (int32_t y = 0; y < mBufferArea.height; y++) {
+
+ /* Will be used as R, G and B values for pixel colors */
+ uint8_t max = 255;
+ uint8_t min = 0;
+
+ /* Divide the rows into 3 sections. The first section will contain
+ * the lighest colors. The last section will contain the darkest
+ * colors. */
+ if (y < mBufferArea.height * 1.0 / 3.0) {
+ min = 255 / 2;
+ } else if (y >= mBufferArea.height * 2.0 / 3.0) {
+ max = 255 / 2;
+ }
+
+ /* Divide the columns into 3 sections. The first section is red,
+ * the second is green and the third is blue */
+ int32_t x = 0;
+ for (; x < mBufferArea.width / 3; x++) {
+ setColor(x, y, mFormat, stride, img, max, min, min, 255);
+ }
+
+ for (; x < mBufferArea.width * 2 / 3; x++) {
+ setColor(x, y, mFormat, stride, img, min, max, min, 255);
+ }
+
+ for (; x < mBufferArea.width; x++) {
+ setColor(x, y, mFormat, stride, img, min, min, max, 255);
+ }
+ }
+
+ /* Unlock the buffer for reading */
+ mGraphicBuffer->unlock();
+
+ mHandle = mGraphicBuffer->handle;
+
+ return 0;
+}
+
+
+Hwc2TestClientTargetBuffer::Hwc2TestClientTargetBuffer()
+ : mFenceGenerator(new Hwc2TestFenceGenerator()) { }
+
+Hwc2TestClientTargetBuffer::~Hwc2TestClientTargetBuffer() { }
+
+/* Generates a client target buffer using the layers assigned for client
+ * composition. Takes into account the individual layer properties such as
+ * transform, blend mode, source crop, etc. */
+int Hwc2TestClientTargetBuffer::get(buffer_handle_t* outHandle,
+ int32_t* outFence, const Area& bufferArea,
+ const Hwc2TestLayers* testLayers,
+ const std::set<hwc2_layer_t>* clientLayers,
+ const std::set<hwc2_layer_t>* clearLayers)
+{
+ int err;
+
+ /* Create new graphic buffer with updated size */
+ mGraphicBuffer = mGraphicBufferAlloc.createGraphicBuffer(bufferArea.width,
+ bufferArea.height, mFormat,
+ GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_HW_RENDER,
+ "hwc2_test_buffer", &err);
+ if (err)
+ return err;
+
+ uint8_t* img;
+ mGraphicBuffer->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&img));
+
+ uint32_t stride = mGraphicBuffer->getStride();
+
+ float bWDiv3 = bufferArea.width / 3;
+ float bW2Div3 = bufferArea.width * 2 / 3;
+ float bHDiv3 = bufferArea.height / 3;
+ float bH2Div3 = bufferArea.height * 2 / 3;
+
+ /* Cycle through every pixel in the buffer and determine what color it
+ * should be. */
+ for (int32_t y = 0; y < bufferArea.height; y++) {
+ for (int32_t x = 0; x < bufferArea.width; x++) {
+
+ uint8_t r = 0, g = 0, b = 0;
+ float a = 0.0f;
+
+ /* Cycle through each client layer from back to front and
+ * update the pixel color. */
+ for (auto layer = clientLayers->rbegin();
+ layer != clientLayers->rend(); ++layer) {
+
+ const hwc_rect_t df = testLayers->getDisplayFrame(*layer);
+
+ float dfL = df.left;
+ float dfT = df.top;
+ float dfR = df.right;
+ float dfB = df.bottom;
+
+ /* If the pixel location falls outside of the layer display
+ * frame, skip the layer. */
+ if (x < dfL || x >= dfR || y < dfT || y >= dfB)
+ continue;
+
+ /* If the device has requested the layer be clear, clear
+ * the pixel and continue. */
+ if (clearLayers->count(*layer) != 0) {
+ r = 0;
+ g = 0;
+ b = 0;
+ a = 0.0f;
+ continue;
+ }
+
+ float planeAlpha = testLayers->getPlaneAlpha(*layer);
+
+ /* If the layer is a solid color, fill the color and
+ * continue. */
+ if (testLayers->getComposition(*layer)
+ == HWC2_COMPOSITION_SOLID_COLOR) {
+ const auto color = testLayers->getColor(*layer);
+ r = color.r;
+ g = color.g;
+ b = color.b;
+ a = color.a * planeAlpha;
+ continue;
+ }
+
+ float xPos = x;
+ float yPos = y;
+
+ hwc_transform_t transform = testLayers->getTransform(*layer);
+
+ float dfW = dfR - dfL;
+ float dfH = dfB - dfT;
+
+ /* If a layer has a transform, find which location on the
+ * layer will end up in the current pixel location. We
+ * can calculate the color of the current pixel using that
+ * location. */
+ if (transform > 0) {
+ /* Change origin to be the center of the layer. */
+ xPos = xPos - dfL - dfW / 2.0;
+ yPos = yPos - dfT - dfH / 2.0;
+
+ /* Flip Horizontal by reflecting across the y axis. */
+ if (transform & HWC_TRANSFORM_FLIP_H)
+ xPos = -xPos;
+
+ /* Flip vertical by reflecting across the x axis. */
+ if (transform & HWC_TRANSFORM_FLIP_V)
+ yPos = -yPos;
+
+ /* Rotate 90 by using a basic linear algebra rotation
+ * and scaling the result so the display frame remains
+ * the same. For example, a buffer of size 100x50 should
+ * rotate 90 degress but remain the same dimension
+ * (100x50) at the end of the transformation. */
+ if (transform & HWC_TRANSFORM_ROT_90) {
+ float tmp = xPos;
+ xPos = -yPos * dfW / dfH;
+ yPos = tmp * dfH / dfW;
+ }
+
+ /* Change origin back to the top left corner of the
+ * layer. */
+ xPos = xPos + dfL + dfW / 2.0;
+ yPos = yPos + dfT + dfH / 2.0;
+ }
+
+ hwc_frect_t sc = testLayers->getSourceCrop(*layer);
+ float scL = sc.left, scT = sc.top;
+
+ float dfWDivScW = dfW / (sc.right - scL);
+ float dfHDivScH = dfH / (sc.bottom - scT);
+
+ float max = 255, min = 0;
+
+ /* Choose the pixel color. Similar to generateBuffer,
+ * each layer will be divided into 3x3 colors. Because
+ * both the source crop and display frame must be taken into
+ * account, the formulas are more complicated.
+ *
+ * If the source crop and display frame were not taken into
+ * account, we would simply divide the buffer into three
+ * sections by height. Each section would get one color.
+ * For example the formula for the first section would be:
+ *
+ * if (yPos < bufferArea.height / 3)
+ * //Select first section color
+ *
+ * However the pixel color is chosen based on the source
+ * crop and displayed based on the display frame.
+ *
+ * If the display frame top was 0 and the source crop height
+ * and display frame height were the same. The only factor
+ * would be the source crop top. To calculate the new
+ * section boundary, the section boundary would be moved up
+ * by the height of the source crop top. The formula would
+ * be:
+ * if (yPos < (bufferArea.height / 3 - sourceCrop.top)
+ * //Select first section color
+ *
+ * If the display frame top could also vary but source crop
+ * and display frame heights were the same, the formula
+ * would be:
+ * if (yPos < (bufferArea.height / 3 - sourceCrop.top
+ * + displayFrameTop)
+ * //Select first section color
+ *
+ * If the heights were not the same, the conversion between
+ * the source crop and display frame dimensions must be
+ * taken into account. The formula would be:
+ * if (yPos < ((bufferArea.height / 3) - sourceCrop.top)
+ * * displayFrameHeight / sourceCropHeight
+ * + displayFrameTop)
+ * //Select first section color
+ */
+ if (yPos < ((bHDiv3) - scT) * dfHDivScH + dfT) {
+ min = 255 / 2;
+ } else if (yPos >= ((bH2Div3) - scT) * dfHDivScH + dfT) {
+ max = 255 / 2;
+ }
+
+ uint8_t rCur = min, gCur = min, bCur = min;
+ float aCur = 1.0f;
+
+ /* This further divides the color sections from 3 to 3x3.
+ * The math behind it follows the same logic as the previous
+ * comment */
+ if (xPos < ((bWDiv3) - scL) * (dfWDivScW) + dfL) {
+ rCur = max;
+ } else if (xPos < ((bW2Div3) - scL) * (dfWDivScW) + dfL) {
+ gCur = max;
+ } else {
+ bCur = max;
+ }
+
+
+ /* Blend the pixel color with the previous layers' pixel
+ * colors using the plane alpha and blend mode. The final
+ * pixel color is chosen using the plane alpha and blend
+ * mode formulas found in hwcomposer2.h */
+ hwc2_blend_mode_t blendMode = testLayers->getBlendMode(*layer);
+
+ if (blendMode == HWC2_BLEND_MODE_PREMULTIPLIED) {
+ rCur *= planeAlpha;
+ gCur *= planeAlpha;
+ bCur *= planeAlpha;
+ }
+
+ aCur *= planeAlpha;
+
+ if (blendMode == HWC2_BLEND_MODE_PREMULTIPLIED) {
+ r = rCur + r * (1.0 - aCur);
+ g = gCur + g * (1.0 - aCur);
+ b = bCur + b * (1.0 - aCur);
+ a = aCur + a * (1.0 - aCur);
+ } else if (blendMode == HWC2_BLEND_MODE_COVERAGE) {
+ r = rCur * aCur + r * (1.0 - aCur);
+ g = gCur * aCur + g * (1.0 - aCur);
+ b = bCur * aCur + b * (1.0 - aCur);
+ a = aCur * aCur + a * (1.0 - aCur);
+ } else {
+ r = rCur;
+ g = gCur;
+ b = bCur;
+ a = aCur;
+ }
+ }
+
+ /* Set the pixel color */
+ setColor(x, y, mFormat, stride, img, r, g, b, a * 255);
+ }
+ }
+
+ mGraphicBuffer->unlock();
+
+ *outFence = mFenceGenerator->get();
+ *outHandle = mGraphicBuffer->handle;
+
+ return 0;
+}
diff --git a/services/surfaceflinger/tests/hwc2/Hwc2TestBuffer.h b/services/surfaceflinger/tests/hwc2/Hwc2TestBuffer.h
new file mode 100644
index 0000000..ca60940
--- /dev/null
+++ b/services/surfaceflinger/tests/hwc2/Hwc2TestBuffer.h
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _HWC2_TEST_BUFFER_H
+#define _HWC2_TEST_BUFFER_H
+
+#include <android-base/unique_fd.h>
+#include <set>
+
+#include <hardware/hwcomposer2.h>
+
+#include <gui/GraphicBufferAlloc.h>
+#include <ui/GraphicBuffer.h>
+
+#include "Hwc2TestProperties.h"
+
+class Hwc2TestFenceGenerator;
+class Hwc2TestLayers;
+
+class Hwc2TestBuffer {
+public:
+ Hwc2TestBuffer();
+ ~Hwc2TestBuffer();
+
+ void updateBufferArea(const Area& bufferArea);
+
+ int get(buffer_handle_t* outHandle, int32_t* outFence);
+
+protected:
+ int generateBuffer();
+
+ android::GraphicBufferAlloc mGraphicBufferAlloc;
+ android::sp<android::GraphicBuffer> mGraphicBuffer;
+
+ std::unique_ptr<Hwc2TestFenceGenerator> mFenceGenerator;
+
+ Area mBufferArea = {-1, -1};
+ const android_pixel_format_t mFormat = HAL_PIXEL_FORMAT_RGBA_8888;
+
+ bool mValidBuffer = false;
+ buffer_handle_t mHandle = nullptr;
+};
+
+
+class Hwc2TestClientTargetBuffer {
+public:
+ Hwc2TestClientTargetBuffer();
+ ~Hwc2TestClientTargetBuffer();
+
+ int get(buffer_handle_t* outHandle, int32_t* outFence,
+ const Area& bufferArea, const Hwc2TestLayers* testLayers,
+ const std::set<hwc2_layer_t>* clientLayers,
+ const std::set<hwc2_layer_t>* clearLayers);
+
+protected:
+ android::GraphicBufferAlloc mGraphicBufferAlloc;
+ android::sp<android::GraphicBuffer> mGraphicBuffer;
+
+ std::unique_ptr<Hwc2TestFenceGenerator> mFenceGenerator;
+
+ const android_pixel_format_t mFormat = HAL_PIXEL_FORMAT_RGBA_8888;
+};
+
+#endif /* ifndef _HWC2_TEST_BUFFER_H */
diff --git a/services/surfaceflinger/tests/hwc2/Hwc2TestClientTarget.cpp b/services/surfaceflinger/tests/hwc2/Hwc2TestClientTarget.cpp
new file mode 100644
index 0000000..6925492
--- /dev/null
+++ b/services/surfaceflinger/tests/hwc2/Hwc2TestClientTarget.cpp
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <sstream>
+
+#include <ui/Rect.h>
+
+#include "Hwc2TestClientTarget.h"
+
+int Hwc2TestClientTarget::getBuffer(const Hwc2TestLayers& testLayers,
+ const std::set<hwc2_layer_t>& clientLayers,
+ const std::set<hwc2_layer_t>& clearLayers, bool flipClientTarget,
+ const Area& displayArea, buffer_handle_t* outHandle,
+ int32_t* outAcquireFence)
+{
+ if (!flipClientTarget) {
+ bool needsClientTarget = false;
+
+ for (auto clientLayer : clientLayers) {
+ if (testLayers.getVisibleRegion(clientLayer).numRects > 0) {
+ needsClientTarget = true;
+ break;
+ }
+ }
+
+ if (!needsClientTarget) {
+ *outHandle = nullptr;
+ *outAcquireFence = -1;
+ return 0;
+ }
+ }
+
+ return mBuffer.get(outHandle, outAcquireFence, displayArea,
+ &testLayers, &clientLayers, &clearLayers);
+}
+
+
+Hwc2TestClientTargetSupport::Hwc2TestClientTargetSupport(
+ Hwc2TestCoverage coverage, const Area& displayArea)
+ : mBufferArea(coverage, displayArea),
+ mDataspace(coverage),
+ mSurfaceDamage(coverage)
+{
+ mBufferArea.setDependent(&mSurfaceDamage);
+}
+
+std::string Hwc2TestClientTargetSupport::dump() const
+{
+ std::stringstream dmp;
+
+ dmp << "client target: \n";
+
+ for (auto property : properties) {
+ dmp << property->dump();
+ }
+
+ return dmp.str();
+}
+
+void Hwc2TestClientTargetSupport::reset()
+{
+ for (auto property : properties) {
+ property->reset();
+ }
+}
+
+bool Hwc2TestClientTargetSupport::advance()
+{
+ for (auto property : properties) {
+ if (property->advance())
+ return true;
+ }
+ return false;
+}
+
+Area Hwc2TestClientTargetSupport::getBufferArea() const
+{
+ return mBufferArea.get();
+}
+
+android_dataspace_t Hwc2TestClientTargetSupport::getDataspace() const
+{
+ return mDataspace.get();
+}
+
+const hwc_region_t Hwc2TestClientTargetSupport::getSurfaceDamage() const
+{
+ return mSurfaceDamage.get();
+}
diff --git a/services/surfaceflinger/tests/hwc2/Hwc2TestClientTarget.h b/services/surfaceflinger/tests/hwc2/Hwc2TestClientTarget.h
new file mode 100644
index 0000000..3b47978
--- /dev/null
+++ b/services/surfaceflinger/tests/hwc2/Hwc2TestClientTarget.h
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _HWC2_TEST_CLIENT_TARGET_H
+#define _HWC2_TEST_CLIENT_TARGET_H
+
+#include <set>
+
+#define HWC2_INCLUDE_STRINGIFICATION
+#define HWC2_USE_CPP11
+#include <hardware/hwcomposer2.h>
+#undef HWC2_INCLUDE_STRINGIFICATION
+#undef HWC2_USE_CPP11
+
+#include "Hwc2TestProperties.h"
+#include "Hwc2TestLayers.h"
+
+/* Generates client target buffers from client composition layers */
+class Hwc2TestClientTarget {
+public:
+ int getBuffer(const Hwc2TestLayers& layers,
+ const std::set<hwc2_layer_t>& clientLayers,
+ const std::set<hwc2_layer_t>& clearLayers,
+ bool clearClientTarget, const Area& displayArea,
+ buffer_handle_t* outHandle, int32_t* outAcquireFence);
+
+private:
+ Hwc2TestClientTargetBuffer mBuffer;
+};
+
+/* Generates valid client targets to test which ones the device will support */
+class Hwc2TestClientTargetSupport {
+public:
+ Hwc2TestClientTargetSupport(Hwc2TestCoverage coverage,
+ const Area& displayArea);
+
+ std::string dump() const;
+
+ void reset();
+ bool advance();
+
+ Area getBufferArea() const;
+ android_dataspace_t getDataspace() const;
+ const hwc_region_t getSurfaceDamage() const;
+
+private:
+ std::array<Hwc2TestContainer*, 3> properties = {{
+ &mDataspace, &mSurfaceDamage, &mBufferArea
+ }};
+
+ Hwc2TestBufferArea mBufferArea;
+ Hwc2TestDataspace mDataspace;
+ Hwc2TestSurfaceDamage mSurfaceDamage;
+};
+
+#endif /* ifndef _HWC2_TEST_CLIENT_TARGET_H */
diff --git a/services/surfaceflinger/tests/hwc2/Hwc2TestLayer.cpp b/services/surfaceflinger/tests/hwc2/Hwc2TestLayer.cpp
new file mode 100644
index 0000000..937fce2
--- /dev/null
+++ b/services/surfaceflinger/tests/hwc2/Hwc2TestLayer.cpp
@@ -0,0 +1,249 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <sstream>
+
+#include "Hwc2TestLayer.h"
+
+Hwc2TestCoverage getCoverage(Hwc2TestPropertyName property,
+ Hwc2TestCoverage coverage, const std::unordered_map<Hwc2TestPropertyName,
+ Hwc2TestCoverage>& coverageExceptions) {
+ auto exception = coverageExceptions.find(property);
+ return (exception != coverageExceptions.end())? exception->second : coverage;
+}
+
+Hwc2TestLayer::Hwc2TestLayer(Hwc2TestCoverage coverage,
+ const Area& displayArea)
+ : Hwc2TestLayer(coverage, displayArea,
+ std::unordered_map<Hwc2TestPropertyName, Hwc2TestCoverage>()) { }
+
+Hwc2TestLayer::Hwc2TestLayer(Hwc2TestCoverage coverage,
+ const Area& displayArea, const std::unordered_map<Hwc2TestPropertyName,
+ Hwc2TestCoverage>& coverageExceptions)
+ : mBlendMode(getCoverage(Hwc2TestPropertyName::BlendMode, coverage,
+ coverageExceptions)),
+ mBufferArea(getCoverage(Hwc2TestPropertyName::BufferArea, coverage,
+ coverageExceptions), displayArea),
+ mColor(getCoverage(Hwc2TestPropertyName::Color, coverage,
+ coverageExceptions)),
+ mComposition(getCoverage(Hwc2TestPropertyName::Composition, coverage,
+ coverageExceptions)),
+ mDataspace(getCoverage(Hwc2TestPropertyName::Dataspace, coverage,
+ coverageExceptions)),
+ mDisplayFrame(getCoverage(Hwc2TestPropertyName::DisplayFrame, coverage,
+ coverageExceptions), displayArea),
+ mPlaneAlpha(getCoverage(Hwc2TestPropertyName::PlaneAlpha, coverage,
+ coverageExceptions)),
+ mSourceCrop(getCoverage(Hwc2TestPropertyName::SourceCrop, coverage,
+ coverageExceptions)),
+ mSurfaceDamage(getCoverage(Hwc2TestPropertyName::SurfaceDamage, coverage,
+ coverageExceptions)),
+ mTransform(getCoverage(Hwc2TestPropertyName::Transform, coverage,
+ coverageExceptions))
+{
+ mBufferArea.setDependent(&mBuffer);
+ mBufferArea.setDependent(&mSourceCrop);
+ mBufferArea.setDependent(&mSurfaceDamage);
+ mBlendMode.setDependent(&mColor);
+}
+
+std::string Hwc2TestLayer::dump() const
+{
+ std::stringstream dmp;
+
+ dmp << "layer: \n";
+
+ for (auto property : mProperties) {
+ dmp << property->dump();
+ }
+
+ dmp << mVisibleRegion.dump();
+ dmp << "\tz order: " << mZOrder << "\n";
+
+ return dmp.str();
+}
+
+int Hwc2TestLayer::getBuffer(buffer_handle_t* outHandle,
+ android::base::unique_fd* outAcquireFence)
+{
+ int32_t acquireFence;
+ int ret = mBuffer.get(outHandle, &acquireFence);
+ outAcquireFence->reset(acquireFence);
+ return ret;
+}
+
+int Hwc2TestLayer::getBuffer(buffer_handle_t* outHandle,
+ int32_t* outAcquireFence)
+{
+ return mBuffer.get(outHandle, outAcquireFence);
+}
+
+void Hwc2TestLayer::setZOrder(uint32_t zOrder)
+{
+ mZOrder = zOrder;
+}
+
+void Hwc2TestLayer::setVisibleRegion(const android::Region& region)
+{
+ return mVisibleRegion.set(region);
+}
+
+void Hwc2TestLayer::reset()
+{
+ mVisibleRegion.release();
+
+ for (auto property : mProperties) {
+ property->reset();
+ }
+}
+
+bool Hwc2TestLayer::advance()
+{
+ for (auto property : mProperties) {
+ if (property->isSupported(mComposition.get()))
+ if (property->advance())
+ return true;
+ }
+ return false;
+}
+
+hwc2_blend_mode_t Hwc2TestLayer::getBlendMode() const
+{
+ return mBlendMode.get();
+}
+
+Area Hwc2TestLayer::getBufferArea() const
+{
+ return mBufferArea.get();
+}
+
+hwc_color_t Hwc2TestLayer::getColor() const
+{
+ return mColor.get();
+}
+
+hwc2_composition_t Hwc2TestLayer::getComposition() const
+{
+ return mComposition.get();
+}
+
+/* The cursor position corresponds to {displayFrame.left, displayFrame.top} */
+hwc_rect_t Hwc2TestLayer::getCursorPosition() const
+{
+ return mDisplayFrame.get();
+}
+
+android_dataspace_t Hwc2TestLayer::getDataspace() const
+{
+ return mDataspace.get();
+}
+
+hwc_rect_t Hwc2TestLayer::getDisplayFrame() const
+{
+ return mDisplayFrame.get();
+}
+
+float Hwc2TestLayer::getPlaneAlpha() const
+{
+ return mPlaneAlpha.get();
+}
+
+hwc_frect_t Hwc2TestLayer::getSourceCrop() const
+{
+ return mSourceCrop.get();
+}
+
+hwc_region_t Hwc2TestLayer::getSurfaceDamage() const
+{
+ return mSurfaceDamage.get();
+}
+
+hwc_transform_t Hwc2TestLayer::getTransform() const
+{
+ return mTransform.get();
+}
+
+hwc_region_t Hwc2TestLayer::getVisibleRegion() const
+{
+ return mVisibleRegion.get();
+}
+
+uint32_t Hwc2TestLayer::getZOrder() const
+{
+ return mZOrder;
+}
+
+bool Hwc2TestLayer::advanceBlendMode()
+{
+ return mBlendMode.advance();
+}
+
+bool Hwc2TestLayer::advanceBufferArea()
+{
+ return mBufferArea.advance();
+}
+
+bool Hwc2TestLayer::advanceColor()
+{
+ return mColor.advance();
+}
+
+bool Hwc2TestLayer::advanceComposition()
+{
+ return mComposition.advance();
+}
+
+bool Hwc2TestLayer::advanceCursorPosition()
+{
+ return mDisplayFrame.advance();
+}
+
+bool Hwc2TestLayer::advanceDataspace()
+{
+ return mDataspace.advance();
+}
+
+bool Hwc2TestLayer::advanceDisplayFrame()
+{
+ return mDisplayFrame.advance();
+}
+
+bool Hwc2TestLayer::advancePlaneAlpha()
+{
+ return mPlaneAlpha.advance();
+}
+
+bool Hwc2TestLayer::advanceSourceCrop()
+{
+ return mSourceCrop.advance();
+}
+
+bool Hwc2TestLayer::advanceSurfaceDamage()
+{
+ return mSurfaceDamage.advance();
+}
+
+bool Hwc2TestLayer::advanceTransform()
+{
+ return mTransform.advance();
+}
+
+bool Hwc2TestLayer::advanceVisibleRegion()
+{
+ if (mPlaneAlpha.advance())
+ return true;
+ return mDisplayFrame.advance();
+}
diff --git a/services/surfaceflinger/tests/hwc2/Hwc2TestLayer.h b/services/surfaceflinger/tests/hwc2/Hwc2TestLayer.h
new file mode 100644
index 0000000..0e7dd22
--- /dev/null
+++ b/services/surfaceflinger/tests/hwc2/Hwc2TestLayer.h
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _HWC2_TEST_LAYER_H
+#define _HWC2_TEST_LAYER_H
+
+#include <android-base/unique_fd.h>
+#include <unordered_map>
+
+#include "Hwc2TestBuffer.h"
+#include "Hwc2TestProperties.h"
+
+#define HWC2_INCLUDE_STRINGIFICATION
+#define HWC2_USE_CPP11
+#include <hardware/hwcomposer2.h>
+#undef HWC2_INCLUDE_STRINGIFICATION
+#undef HWC2_USE_CPP11
+
+class Hwc2TestLayer {
+public:
+ Hwc2TestLayer(Hwc2TestCoverage coverage, const Area& displayArea);
+
+ Hwc2TestLayer(Hwc2TestCoverage coverage, const Area& displayArea,
+ const std::unordered_map<Hwc2TestPropertyName,
+ Hwc2TestCoverage>& coverage_exceptions);
+
+ std::string dump() const;
+
+ int getBuffer(buffer_handle_t* outHandle,
+ android::base::unique_fd* outAcquireFence);
+ int getBuffer(buffer_handle_t* outHandle, int32_t* outAcquireFence);
+
+ void setZOrder(uint32_t zOrder);
+ void setVisibleRegion(const android::Region& region);
+
+ void reset();
+ bool advance();
+
+ hwc2_blend_mode_t getBlendMode() const;
+ Area getBufferArea() const;
+ hwc_color_t getColor() const;
+ hwc2_composition_t getComposition() const;
+ hwc_rect_t getCursorPosition() const;
+ android_dataspace_t getDataspace() const;
+ hwc_rect_t getDisplayFrame() const;
+ float getPlaneAlpha() const;
+ hwc_frect_t getSourceCrop() const;
+ hwc_region_t getSurfaceDamage() const;
+ hwc_transform_t getTransform() const;
+ hwc_region_t getVisibleRegion() const;
+ uint32_t getZOrder() const;
+
+ bool advanceBlendMode();
+ bool advanceBufferArea();
+ bool advanceColor();
+ bool advanceComposition();
+ bool advanceCursorPosition();
+ bool advanceDataspace();
+ bool advanceDisplayFrame();
+ bool advancePlaneAlpha();
+ bool advanceSourceCrop();
+ bool advanceSurfaceDamage();
+ bool advanceTransform();
+ bool advanceVisibleRegion();
+
+private:
+ std::array<Hwc2TestContainer*, 10> mProperties = {{
+ &mTransform, &mColor, &mDataspace, &mPlaneAlpha, &mSourceCrop,
+ &mSurfaceDamage, &mBlendMode, &mBufferArea, &mDisplayFrame,
+ &mComposition
+ }};
+
+ Hwc2TestBuffer mBuffer;
+
+ Hwc2TestBlendMode mBlendMode;
+ Hwc2TestBufferArea mBufferArea;
+ Hwc2TestColor mColor;
+ Hwc2TestComposition mComposition;
+ Hwc2TestDataspace mDataspace;
+ Hwc2TestDisplayFrame mDisplayFrame;
+ Hwc2TestPlaneAlpha mPlaneAlpha;
+ Hwc2TestSourceCrop mSourceCrop;
+ Hwc2TestSurfaceDamage mSurfaceDamage;
+ Hwc2TestTransform mTransform;
+ Hwc2TestVisibleRegion mVisibleRegion;
+
+ uint32_t mZOrder = UINT32_MAX;
+};
+
+#endif /* ifndef _HWC2_TEST_LAYER_H */
diff --git a/services/surfaceflinger/tests/hwc2/Hwc2TestLayers.cpp b/services/surfaceflinger/tests/hwc2/Hwc2TestLayers.cpp
new file mode 100644
index 0000000..495ef79
--- /dev/null
+++ b/services/surfaceflinger/tests/hwc2/Hwc2TestLayers.cpp
@@ -0,0 +1,281 @@
+/* * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <sstream>
+#include <gtest/gtest.h>
+
+#include "Hwc2TestLayers.h"
+
+Hwc2TestLayers::Hwc2TestLayers(const std::vector<hwc2_layer_t>& layers,
+ Hwc2TestCoverage coverage, const Area& displayArea)
+ : Hwc2TestLayers(layers, coverage, displayArea,
+ std::unordered_map<Hwc2TestPropertyName, Hwc2TestCoverage>()) { }
+
+Hwc2TestLayers::Hwc2TestLayers(const std::vector<hwc2_layer_t>& layers,
+ Hwc2TestCoverage coverage, const Area& displayArea,
+ const std::unordered_map<Hwc2TestPropertyName,
+ Hwc2TestCoverage>& coverageExceptions)
+ : mDisplayArea(displayArea)
+{
+ for (auto layer : layers) {
+ mTestLayers.emplace(std::piecewise_construct,
+ std::forward_as_tuple(layer),
+ std::forward_as_tuple(coverage, displayArea, coverageExceptions));
+ }
+
+ /* Iterate over the layers in order and assign z orders in the same order.
+ * This allows us to iterate over z orders in the same way when computing
+ * visible regions */
+ uint32_t nextZOrder = layers.size();
+
+ for (auto& testLayer : mTestLayers) {
+ testLayer.second.setZOrder(nextZOrder--);
+ }
+
+ setVisibleRegions();
+}
+
+std::string Hwc2TestLayers::dump() const
+{
+ std::stringstream dmp;
+ for (auto& testLayer : mTestLayers) {
+ dmp << testLayer.second.dump();
+ }
+ return dmp.str();
+}
+
+void Hwc2TestLayers::reset()
+{
+ for (auto& testLayer : mTestLayers) {
+ testLayer.second.reset();
+ }
+
+ setVisibleRegions();
+}
+
+bool Hwc2TestLayers::advance()
+{
+ auto itr = mTestLayers.begin();
+ bool optimized;
+
+ while (itr != mTestLayers.end()) {
+ if (itr->second.advance()) {
+ optimized = setVisibleRegions();
+ if (!mOptimize || optimized)
+ return true;
+ itr = mTestLayers.begin();
+ } else {
+ itr->second.reset();
+ ++itr;
+ }
+ }
+ return false;
+}
+
+bool Hwc2TestLayers::advanceVisibleRegions()
+{
+ auto itr = mTestLayers.begin();
+ bool optimized;
+
+ while (itr != mTestLayers.end()) {
+ if (itr->second.advanceVisibleRegion()) {
+ optimized = setVisibleRegions();
+ if (!mOptimize || optimized)
+ return true;
+ itr = mTestLayers.begin();
+ } else {
+ itr->second.reset();
+ ++itr;
+ }
+ }
+ return false;
+}
+
+/* Removes layouts that do not cover the entire display.
+ * Also removes layouts where a layer is completely blocked from view.
+ */
+bool Hwc2TestLayers::optimizeLayouts()
+{
+ mOptimize = true;
+
+ if (setVisibleRegions())
+ return true;
+ return advance();
+}
+
+bool Hwc2TestLayers::contains(hwc2_layer_t layer) const
+{
+ return mTestLayers.count(layer) != 0;
+}
+
+int Hwc2TestLayers::getBuffer(hwc2_layer_t layer, buffer_handle_t* outHandle,
+ int32_t* outAcquireFence)
+{
+ if (mTestLayers.count(layer) == 0) {
+ []() { GTEST_FAIL(); }();
+ }
+ return mTestLayers.at(layer).getBuffer(outHandle, outAcquireFence);
+}
+
+hwc2_blend_mode_t Hwc2TestLayers::getBlendMode(hwc2_layer_t layer) const
+{
+ if (mTestLayers.count(layer) == 0) {
+ []() { GTEST_FAIL(); }();
+ }
+ return mTestLayers.at(layer).getBlendMode();
+}
+
+Area Hwc2TestLayers::getBufferArea(hwc2_layer_t layer) const
+{
+ auto testLayer = mTestLayers.find(layer);
+ if (testLayer == mTestLayers.end())
+ [] () { GTEST_FAIL(); }();
+ return testLayer->second.getBufferArea();
+}
+
+hwc_color_t Hwc2TestLayers::getColor(hwc2_layer_t layer) const
+{
+ if (mTestLayers.count(layer) == 0) {
+ []() { GTEST_FAIL(); }();
+ }
+ return mTestLayers.at(layer).getColor();
+}
+
+hwc2_composition_t Hwc2TestLayers::getComposition(hwc2_layer_t layer) const
+{
+ if (mTestLayers.count(layer) == 0) {
+ []() { GTEST_FAIL(); }();
+ }
+ return mTestLayers.at(layer).getComposition();
+}
+
+hwc_rect_t Hwc2TestLayers::getCursorPosition(hwc2_layer_t layer) const
+{
+ if (mTestLayers.count(layer) == 0) {
+ []() { GTEST_FAIL(); }();
+ }
+ return mTestLayers.at(layer).getCursorPosition();
+}
+
+android_dataspace_t Hwc2TestLayers::getDataspace(hwc2_layer_t layer) const
+{
+ if (mTestLayers.count(layer) == 0) {
+ []() { GTEST_FAIL(); }();
+ }
+ return mTestLayers.at(layer).getDataspace();
+}
+
+hwc_rect_t Hwc2TestLayers::getDisplayFrame(hwc2_layer_t layer) const
+{
+ if (mTestLayers.count(layer) == 0) {
+ []() { GTEST_FAIL(); }();
+ }
+ return mTestLayers.at(layer).getDisplayFrame();
+}
+
+float Hwc2TestLayers::getPlaneAlpha(hwc2_layer_t layer) const
+{
+ if (mTestLayers.count(layer) == 0) {
+ []() { GTEST_FAIL(); }();
+ }
+ return mTestLayers.at(layer).getPlaneAlpha();
+}
+
+hwc_frect_t Hwc2TestLayers::getSourceCrop(hwc2_layer_t layer) const
+{
+ if (mTestLayers.count(layer) == 0) {
+ []() { GTEST_FAIL(); }();
+ }
+ return mTestLayers.at(layer).getSourceCrop();
+}
+
+hwc_region_t Hwc2TestLayers::getSurfaceDamage(hwc2_layer_t layer) const
+{
+ if (mTestLayers.count(layer) == 0) {
+ []() { GTEST_FAIL(); }();
+ }
+ return mTestLayers.at(layer).getSurfaceDamage();
+}
+
+hwc_transform_t Hwc2TestLayers::getTransform(hwc2_layer_t layer) const
+{
+ if (mTestLayers.count(layer) == 0) {
+ []() { GTEST_FAIL(); }();
+ }
+ return mTestLayers.at(layer).getTransform();
+}
+
+hwc_region_t Hwc2TestLayers::getVisibleRegion(hwc2_layer_t layer) const
+{
+ if (mTestLayers.count(layer) == 0) {
+ []() { GTEST_FAIL(); }();
+ }
+ return mTestLayers.at(layer).getVisibleRegion();
+}
+
+uint32_t Hwc2TestLayers::getZOrder(hwc2_layer_t layer) const
+{
+ if (mTestLayers.count(layer) == 0) {
+ []() { GTEST_FAIL(); }();
+ }
+ return mTestLayers.at(layer).getZOrder();
+}
+
+/* Sets the visible regions for a display. Returns false if the layers do not
+ * cover the entire display or if a layer is not visible */
+bool Hwc2TestLayers::setVisibleRegions()
+{
+ /* The region of the display that is covered by layers above the current
+ * layer */
+ android::Region aboveOpaqueLayers;
+
+ bool optimized = true;
+
+ /* Iterate over test layers from max z order to min z order. */
+ for (auto& testLayer : mTestLayers) {
+ android::Region visibleRegion;
+
+ /* Set the visible region of this layer */
+ const hwc_rect_t displayFrame = testLayer.second.getDisplayFrame();
+
+ visibleRegion.set(android::Rect(displayFrame.left, displayFrame.top,
+ displayFrame.right, displayFrame.bottom));
+
+ /* Remove the area covered by opaque layers above this layer
+ * from this layer's visible region */
+ visibleRegion.subtractSelf(aboveOpaqueLayers);
+
+ testLayer.second.setVisibleRegion(visibleRegion);
+
+ /* If a layer is not visible, return false */
+ if (visibleRegion.isEmpty())
+ optimized = false;
+
+ /* If this layer is opaque, store the region it covers */
+ if (testLayer.second.getPlaneAlpha() == 1.0f)
+ aboveOpaqueLayers.orSelf(visibleRegion);
+ }
+
+ /* If the opaque region does not cover the entire display return false */
+ if (!aboveOpaqueLayers.isRect())
+ return false;
+
+ const auto rect = aboveOpaqueLayers.begin();
+ if (rect->left != 0 || rect->top != 0 || rect->right != mDisplayArea.width
+ || rect->bottom != mDisplayArea.height)
+ return false;
+
+ return optimized;
+}
diff --git a/services/surfaceflinger/tests/hwc2/Hwc2TestLayers.h b/services/surfaceflinger/tests/hwc2/Hwc2TestLayers.h
new file mode 100644
index 0000000..d95a91f
--- /dev/null
+++ b/services/surfaceflinger/tests/hwc2/Hwc2TestLayers.h
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _HWC2_TEST_LAYERS_H
+#define _HWC2_TEST_LAYERS_H
+
+#include <map>
+
+#define HWC2_INCLUDE_STRINGIFICATION
+#define HWC2_USE_CPP11
+#include <hardware/hwcomposer2.h>
+#undef HWC2_INCLUDE_STRINGIFICATION
+#undef HWC2_USE_CPP11
+
+#include "Hwc2TestProperties.h"
+#include "Hwc2TestLayer.h"
+
+class Hwc2TestLayers {
+public:
+ Hwc2TestLayers(const std::vector<hwc2_layer_t>& layers,
+ Hwc2TestCoverage coverage, const Area& displayArea);
+
+ Hwc2TestLayers(const std::vector<hwc2_layer_t>& layers,
+ Hwc2TestCoverage coverage, const Area& displayArea,
+ const std::unordered_map<Hwc2TestPropertyName,
+ Hwc2TestCoverage>& coverageExceptions);
+
+ std::string dump() const;
+
+ void reset();
+
+ bool advance();
+ bool advanceVisibleRegions();
+
+ /* Test cases with multiple layers and property values can take quite some
+ * time to run. A significant amount of time can be spent on test cases
+ * where one layer is changing property values but is not visible. To
+ * decrease runtime, this function can be called. Removes layouts where a
+ * layer is completely blocked from view. It also removes layouts that do
+ * not cover the entire display.*/
+ bool optimizeLayouts();
+
+ bool contains(hwc2_layer_t layer) const;
+
+ int getBuffer(hwc2_layer_t layer, buffer_handle_t* outHandle,
+ int32_t* outAcquireFence);
+
+ hwc2_blend_mode_t getBlendMode(hwc2_layer_t layer) const;
+ Area getBufferArea(hwc2_layer_t layer) const;
+ hwc_color_t getColor(hwc2_layer_t layer) const;
+ hwc2_composition_t getComposition(hwc2_layer_t layer) const;
+ hwc_rect_t getCursorPosition(hwc2_layer_t layer) const;
+ android_dataspace_t getDataspace(hwc2_layer_t layer) const;
+ hwc_rect_t getDisplayFrame(hwc2_layer_t layer) const;
+ android_pixel_format_t getFormat(hwc2_layer_t layer) const;
+ float getPlaneAlpha(hwc2_layer_t layer) const;
+ hwc_frect_t getSourceCrop(hwc2_layer_t layer) const;
+ hwc_region_t getSurfaceDamage(hwc2_layer_t layer) const;
+ hwc_transform_t getTransform(hwc2_layer_t layer) const;
+ hwc_region_t getVisibleRegion(hwc2_layer_t layer) const;
+ uint32_t getZOrder(hwc2_layer_t layer) const;
+
+private:
+ bool setVisibleRegions();
+
+ std::map<hwc2_layer_t, Hwc2TestLayer> mTestLayers;
+
+ Area mDisplayArea;
+
+ bool mOptimize = false;
+};
+
+#endif /* ifndef _HWC2_TEST_LAYERS_H */
diff --git a/services/surfaceflinger/tests/hwc2/Hwc2TestProperties.cpp b/services/surfaceflinger/tests/hwc2/Hwc2TestProperties.cpp
new file mode 100644
index 0000000..b5522de
--- /dev/null
+++ b/services/surfaceflinger/tests/hwc2/Hwc2TestProperties.cpp
@@ -0,0 +1,782 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <sstream>
+#include <cutils/log.h>
+#include <ui/Rect.h>
+
+#define HWC2_INCLUDE_STRINGIFICATION
+#define HWC2_USE_CPP11
+#include <hardware/hwcomposer2.h>
+#undef HWC2_INCLUDE_STRINGIFICATION
+#undef HWC2_USE_CPP11
+
+#include "Hwc2TestBuffer.h"
+#include "Hwc2TestProperties.h"
+
+Hwc2TestBufferArea::Hwc2TestBufferArea(Hwc2TestCoverage coverage,
+ const Area& displayArea)
+ : Hwc2TestProperty(mBufferAreas, mCompositionSupport),
+ mScalars((coverage == Hwc2TestCoverage::Complete)? mCompleteScalars:
+ (coverage == Hwc2TestCoverage::Basic)? mBasicScalars:
+ mDefaultScalars),
+ mDisplayArea(displayArea)
+{
+ update();
+}
+
+std::string Hwc2TestBufferArea::dump() const
+{
+ std::stringstream dmp;
+ const Area& curr = get();
+ dmp << "\tbuffer area: width " << curr.width << ", height " << curr.height
+ << "\n";
+ return dmp.str();
+}
+
+void Hwc2TestBufferArea::setDependent(Hwc2TestBuffer* buffer)
+{
+ mBuffer = buffer;
+ if (buffer) {
+ buffer->updateBufferArea(get());
+ }
+}
+
+void Hwc2TestBufferArea::setDependent(Hwc2TestSourceCrop* sourceCrop)
+{
+ mSourceCrop = sourceCrop;
+ if (mSourceCrop) {
+ mSourceCrop->updateBufferArea(get());
+ }
+}
+
+void Hwc2TestBufferArea::setDependent(Hwc2TestSurfaceDamage* surfaceDamage)
+{
+ mSurfaceDamage = surfaceDamage;
+ if (mSurfaceDamage) {
+ mSurfaceDamage->updateBufferArea(get());
+ }
+}
+
+void Hwc2TestBufferArea::update()
+{
+ mBufferAreas.clear();
+
+ if (mDisplayArea.width == 0 && mDisplayArea.height == 0) {
+ mBufferAreas.push_back({0, 0});
+ return;
+ }
+
+ for (auto scalar : mScalars) {
+ mBufferAreas.push_back({static_cast<int32_t>(scalar * mDisplayArea.width),
+ static_cast<int32_t>(scalar * mDisplayArea.height)});
+ }
+
+ updateDependents();
+}
+
+void Hwc2TestBufferArea::updateDependents()
+{
+ const Area& curr = get();
+
+ if (mBuffer)
+ mBuffer->updateBufferArea(curr);
+ if (mSourceCrop)
+ mSourceCrop->updateBufferArea(curr);
+ if (mSurfaceDamage)
+ mSurfaceDamage->updateBufferArea(curr);
+}
+
+const std::vector<float> Hwc2TestBufferArea::mDefaultScalars = {
+ 1.0f,
+};
+
+const std::vector<float> Hwc2TestBufferArea::mBasicScalars = {
+ 1.0f, 0.5f,
+};
+
+const std::vector<float> Hwc2TestBufferArea::mCompleteScalars = {
+ 1.0f, 0.75f, 0.5f
+};
+
+
+Hwc2TestBlendMode::Hwc2TestBlendMode(Hwc2TestCoverage coverage)
+ : Hwc2TestProperty(coverage, mCompleteBlendModes, mBasicBlendModes,
+ mDefaultBlendModes, mCompositionSupport) { }
+
+std::string Hwc2TestBlendMode::dump() const
+{
+ std::stringstream dmp;
+ dmp << "\tblend mode: " << getBlendModeName(get()) << "\n";
+ return dmp.str();
+}
+
+void Hwc2TestBlendMode::setDependent(Hwc2TestColor* color)
+{
+ mColor = color;
+ updateDependents();
+}
+
+void Hwc2TestBlendMode::updateDependents()
+{
+ if (mColor)
+ mColor->updateBlendMode(get());
+}
+
+const std::vector<hwc2_blend_mode_t> Hwc2TestBlendMode::mDefaultBlendModes = {
+ HWC2_BLEND_MODE_NONE,
+};
+
+const std::vector<hwc2_blend_mode_t> Hwc2TestBlendMode::mBasicBlendModes = {
+ HWC2_BLEND_MODE_NONE,
+ HWC2_BLEND_MODE_PREMULTIPLIED,
+};
+
+const std::vector<hwc2_blend_mode_t> Hwc2TestBlendMode::mCompleteBlendModes = {
+ HWC2_BLEND_MODE_NONE,
+ HWC2_BLEND_MODE_PREMULTIPLIED,
+ HWC2_BLEND_MODE_COVERAGE,
+};
+
+
+Hwc2TestColor::Hwc2TestColor(Hwc2TestCoverage coverage,
+ hwc2_blend_mode_t blendMode)
+ : Hwc2TestProperty(mColors, mCompositionSupport),
+ mBaseColors((coverage == Hwc2TestCoverage::Complete)? mCompleteBaseColors:
+ (coverage == Hwc2TestCoverage::Basic)? mBasicBaseColors:
+ mDefaultBaseColors),
+ mBlendMode(blendMode)
+{
+ update();
+}
+
+std::string Hwc2TestColor::dump() const
+{
+ std::stringstream dmp;
+ const hwc_color_t& color = get();
+ dmp << "\tcolor: r " << std::to_string(color.r) << ", g "
+ << std::to_string(color.g) << ", b " << std::to_string(color.b)
+ << ", a " << std::to_string(color.a) << "\n";
+ return dmp.str();
+}
+
+void Hwc2TestColor::updateBlendMode(hwc2_blend_mode_t blendMode)
+{
+ mBlendMode = blendMode;
+ update();
+}
+
+void Hwc2TestColor::update()
+{
+ if (mBlendMode != HWC2_BLEND_MODE_PREMULTIPLIED) {
+ mColors = mBaseColors;
+ return;
+ }
+
+ mColors.clear();
+
+ for (const hwc_color_t& baseColor : mBaseColors) {
+ if (baseColor.a >= baseColor.r && baseColor.a >= baseColor.g
+ && baseColor.a >= baseColor.b) {
+ mColors.push_back(baseColor);
+ }
+ }
+
+}
+
+const std::vector<hwc_color_t> Hwc2TestColor::mDefaultBaseColors = {
+ {UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX},
+};
+
+const std::vector<hwc_color_t> Hwc2TestColor::mBasicBaseColors = {
+ {UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX},
+ { 0, 0, 0, 0},
+};
+
+const std::vector<hwc_color_t> Hwc2TestColor::mCompleteBaseColors = {
+ {UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX},
+ {UINT8_MAX, UINT8_MAX, UINT8_MAX, 0},
+ {UINT8_MAX, UINT8_MAX, 0, UINT8_MAX},
+ {UINT8_MAX, UINT8_MAX, 0, 0},
+ {UINT8_MAX, 0, UINT8_MAX, UINT8_MAX},
+ {UINT8_MAX, 0, UINT8_MAX, 0},
+ {UINT8_MAX, 0, 0, UINT8_MAX},
+ {UINT8_MAX, 0, 0, 0},
+ { 0, UINT8_MAX, UINT8_MAX, UINT8_MAX},
+ { 0, UINT8_MAX, UINT8_MAX, 0},
+ { 0, UINT8_MAX, 0, UINT8_MAX},
+ { 0, UINT8_MAX, 0, 0},
+ { 0, 0, UINT8_MAX, UINT8_MAX},
+ { 0, 0, UINT8_MAX, 0},
+ { 0, 0, 0, UINT8_MAX},
+ { 0, 0, 0, 0},
+};
+
+
+Hwc2TestComposition::Hwc2TestComposition(Hwc2TestCoverage coverage)
+ : Hwc2TestProperty(coverage, mCompleteCompositions, mBasicCompositions,
+ mDefaultCompositions, mCompositionSupport) { }
+
+std::string Hwc2TestComposition::dump() const
+{
+ std::stringstream dmp;
+ dmp << "\tcomposition: " << getCompositionName(get()) << "\n";
+ return dmp.str();
+}
+
+const std::vector<hwc2_composition_t> Hwc2TestComposition::mDefaultCompositions = {
+ HWC2_COMPOSITION_DEVICE,
+};
+
+const std::vector<hwc2_composition_t> Hwc2TestComposition::mBasicCompositions = {
+ HWC2_COMPOSITION_CLIENT,
+ HWC2_COMPOSITION_DEVICE,
+};
+
+const std::vector<hwc2_composition_t> Hwc2TestComposition::mCompleteCompositions = {
+ HWC2_COMPOSITION_CLIENT,
+ HWC2_COMPOSITION_DEVICE,
+ HWC2_COMPOSITION_SOLID_COLOR,
+ HWC2_COMPOSITION_CURSOR,
+ HWC2_COMPOSITION_SIDEBAND,
+};
+
+
+Hwc2TestDataspace::Hwc2TestDataspace(Hwc2TestCoverage coverage)
+ : Hwc2TestProperty(coverage, completeDataspaces, basicDataspaces,
+ defaultDataspaces, mCompositionSupport) { }
+
+std::string Hwc2TestDataspace::dump() const
+{
+ std::stringstream dmp;
+ dmp << "\tdataspace: " << get() << "\n";
+ return dmp.str();
+}
+
+const std::vector<android_dataspace_t> Hwc2TestDataspace::defaultDataspaces = {
+ HAL_DATASPACE_UNKNOWN,
+};
+
+const std::vector<android_dataspace_t> Hwc2TestDataspace::basicDataspaces = {
+ HAL_DATASPACE_UNKNOWN,
+ HAL_DATASPACE_V0_SRGB,
+};
+
+const std::vector<android_dataspace_t> Hwc2TestDataspace::completeDataspaces = {
+ HAL_DATASPACE_UNKNOWN,
+ HAL_DATASPACE_ARBITRARY,
+ HAL_DATASPACE_STANDARD_SHIFT,
+ HAL_DATASPACE_STANDARD_MASK,
+ HAL_DATASPACE_STANDARD_UNSPECIFIED,
+ HAL_DATASPACE_STANDARD_BT709,
+ HAL_DATASPACE_STANDARD_BT601_625,
+ HAL_DATASPACE_STANDARD_BT601_625_UNADJUSTED,
+ HAL_DATASPACE_STANDARD_BT601_525,
+ HAL_DATASPACE_STANDARD_BT601_525_UNADJUSTED,
+ HAL_DATASPACE_STANDARD_BT2020,
+ HAL_DATASPACE_STANDARD_BT2020_CONSTANT_LUMINANCE,
+ HAL_DATASPACE_STANDARD_BT470M,
+ HAL_DATASPACE_STANDARD_FILM,
+ HAL_DATASPACE_TRANSFER_SHIFT,
+ HAL_DATASPACE_TRANSFER_MASK,
+ HAL_DATASPACE_TRANSFER_UNSPECIFIED,
+ HAL_DATASPACE_TRANSFER_LINEAR,
+ HAL_DATASPACE_TRANSFER_SRGB,
+ HAL_DATASPACE_TRANSFER_SMPTE_170M,
+ HAL_DATASPACE_TRANSFER_GAMMA2_2,
+ HAL_DATASPACE_TRANSFER_GAMMA2_8,
+ HAL_DATASPACE_TRANSFER_ST2084,
+ HAL_DATASPACE_TRANSFER_HLG,
+ HAL_DATASPACE_RANGE_SHIFT,
+ HAL_DATASPACE_RANGE_MASK,
+ HAL_DATASPACE_RANGE_UNSPECIFIED,
+ HAL_DATASPACE_RANGE_FULL,
+ HAL_DATASPACE_RANGE_LIMITED,
+ HAL_DATASPACE_SRGB_LINEAR,
+ HAL_DATASPACE_V0_SRGB_LINEAR,
+ HAL_DATASPACE_SRGB,
+ HAL_DATASPACE_V0_SRGB,
+ HAL_DATASPACE_JFIF,
+ HAL_DATASPACE_V0_JFIF,
+ HAL_DATASPACE_BT601_625,
+ HAL_DATASPACE_V0_BT601_625,
+ HAL_DATASPACE_BT601_525,
+ HAL_DATASPACE_V0_BT601_525,
+ HAL_DATASPACE_BT709,
+ HAL_DATASPACE_V0_BT709,
+ HAL_DATASPACE_DEPTH,
+};
+
+
+Hwc2TestDisplayDimension::Hwc2TestDisplayDimension(Hwc2TestCoverage coverage)
+ : Hwc2TestProperty(
+ (coverage == Hwc2TestCoverage::Complete)? mCompleteDisplayDimensions:
+ (coverage == Hwc2TestCoverage::Basic)? mBasicDisplayDimensions:
+ mDefaultDisplayDimensions, mCompositionSupport) { }
+
+std::string Hwc2TestDisplayDimension::dump() const
+{
+ std::stringstream dmp;
+ const UnsignedArea& curr = get();
+ dmp << "\tdisplay dimension: " << curr.width<< " x " << curr.height<< "\n";
+ return dmp.str();
+}
+
+void Hwc2TestDisplayDimension::setDependent(Hwc2TestBuffer* buffer)
+{
+ mBuffer = buffer;
+ updateDependents();
+}
+
+void Hwc2TestDisplayDimension::updateDependents()
+{
+ const UnsignedArea& curr = get();
+
+ if (mBuffer)
+ mBuffer->updateBufferArea({static_cast<int32_t>(curr.width),
+ static_cast<int32_t>(curr.height)});
+}
+
+const std::vector<UnsignedArea>
+ Hwc2TestDisplayDimension::mDefaultDisplayDimensions = {
+ {1920, 1080},
+};
+
+const std::vector<UnsignedArea>
+ Hwc2TestDisplayDimension::mBasicDisplayDimensions = {
+ {640, 480},
+ {1280, 720},
+ {1920, 1080},
+ {1920, 1200},
+};
+
+const std::vector<UnsignedArea>
+ Hwc2TestDisplayDimension::mCompleteDisplayDimensions = {
+ {320, 240},
+ {480, 320},
+ {640, 480},
+ {1280, 720},
+ {1920, 1080},
+ {1920, 1200},
+ {2560, 1440},
+ {2560, 1600},
+ {3840, 2160},
+ {4096, 2160},
+};
+
+
+Hwc2TestDisplayFrame::Hwc2TestDisplayFrame(Hwc2TestCoverage coverage,
+ const Area& displayArea)
+ : Hwc2TestProperty(mDisplayFrames, mCompositionSupport),
+ mFrectScalars((coverage == Hwc2TestCoverage::Complete)? mCompleteFrectScalars:
+ (coverage == Hwc2TestCoverage::Basic)? mBasicFrectScalars:
+ mDefaultFrectScalars),
+ mDisplayArea(displayArea)
+{
+ update();
+}
+
+std::string Hwc2TestDisplayFrame::dump() const
+{
+ std::stringstream dmp;
+ const hwc_rect_t& displayFrame = get();
+ dmp << "\tdisplay frame: left " << displayFrame.left << ", top "
+ << displayFrame.top << ", right " << displayFrame.right
+ << ", bottom " << displayFrame.bottom << "\n";
+ return dmp.str();
+}
+
+void Hwc2TestDisplayFrame::update()
+{
+ mDisplayFrames.clear();
+
+ if (mDisplayArea.width == 0 && mDisplayArea.height == 0) {
+ mDisplayFrames.push_back({0, 0, 0, 0});
+ return;
+ }
+
+ for (const auto& frectScalar : mFrectScalars) {
+ mDisplayFrames.push_back({
+ static_cast<int>(frectScalar.left * mDisplayArea.width),
+ static_cast<int>(frectScalar.top * mDisplayArea.height),
+ static_cast<int>(frectScalar.right * mDisplayArea.width),
+ static_cast<int>(frectScalar.bottom * mDisplayArea.height)});
+ }
+}
+
+const std::vector<hwc_frect_t> Hwc2TestDisplayFrame::mDefaultFrectScalars = {
+ {0.0, 0.0, 1.0, 1.0},
+};
+
+const std::vector<hwc_frect_t> Hwc2TestDisplayFrame::mBasicFrectScalars = {
+ {0.0, 0.0, 1.0, 1.0},
+ {0.0, 0.0, 1.0, 0.05},
+ {0.0, 0.95, 1.0, 1.0},
+};
+
+const std::vector<hwc_frect_t> Hwc2TestDisplayFrame::mCompleteFrectScalars = {
+ {0.0, 0.0, 1.0, 1.0},
+ {0.0, 0.05, 1.0, 0.95},
+ {0.0, 0.05, 1.0, 1.0},
+ {0.0, 0.0, 1.0, 0.05},
+ {0.0, 0.95, 1.0, 1.0},
+ {0.25, 0.0, 0.75, 0.35},
+ {0.25, 0.25, 0.75, 0.75},
+};
+
+
+Hwc2TestPlaneAlpha::Hwc2TestPlaneAlpha(Hwc2TestCoverage coverage)
+ : Hwc2TestProperty(coverage, mCompletePlaneAlphas, mBasicPlaneAlphas,
+ mDefaultPlaneAlphas, mCompositionSupport) { }
+
+std::string Hwc2TestPlaneAlpha::dump() const
+{
+ std::stringstream dmp;
+ dmp << "\tplane alpha: " << get() << "\n";
+ return dmp.str();
+}
+
+const std::vector<float> Hwc2TestPlaneAlpha::mDefaultPlaneAlphas = {
+ 1.0f,
+};
+
+const std::vector<float> Hwc2TestPlaneAlpha::mBasicPlaneAlphas = {
+ 1.0f, 0.0f,
+};
+
+const std::vector<float> Hwc2TestPlaneAlpha::mCompletePlaneAlphas = {
+ 1.0f, 0.75f, 0.5f, 0.25f, 0.0f,
+};
+
+
+Hwc2TestSourceCrop::Hwc2TestSourceCrop(Hwc2TestCoverage coverage,
+ const Area& bufferArea)
+ : Hwc2TestProperty(mSourceCrops, mCompositionSupport),
+ mFrectScalars((coverage == Hwc2TestCoverage::Complete)? mCompleteFrectScalars:
+ (coverage == Hwc2TestCoverage::Basic)? mBasicFrectScalars:
+ mDefaultFrectScalars),
+ mBufferArea(bufferArea)
+{
+ update();
+}
+
+std::string Hwc2TestSourceCrop::dump() const
+{
+ std::stringstream dmp;
+ const hwc_frect_t& sourceCrop = get();
+ dmp << "\tsource crop: left " << sourceCrop.left << ", top "
+ << sourceCrop.top << ", right " << sourceCrop.right << ", bottom "
+ << sourceCrop.bottom << "\n";
+ return dmp.str();
+}
+
+void Hwc2TestSourceCrop::updateBufferArea(const Area& bufferArea)
+{
+ mBufferArea = bufferArea;
+ update();
+}
+
+void Hwc2TestSourceCrop::update()
+{
+ mSourceCrops.clear();
+
+ if (mBufferArea.width == 0 && mBufferArea.height == 0) {
+ mSourceCrops.push_back({0, 0, 0, 0});
+ return;
+ }
+
+ for (const auto& frectScalar : mFrectScalars) {
+ mSourceCrops.push_back({
+ frectScalar.left * mBufferArea.width,
+ frectScalar.top * mBufferArea.height,
+ frectScalar.right * mBufferArea.width,
+ frectScalar.bottom * mBufferArea.height});
+ }
+}
+
+const std::vector<hwc_frect_t> Hwc2TestSourceCrop::mDefaultFrectScalars = {
+ {0.0, 0.0, 1.0, 1.0},
+};
+
+const std::vector<hwc_frect_t> Hwc2TestSourceCrop::mBasicFrectScalars = {
+ {0.0, 0.0, 1.0, 1.0},
+ {0.0, 0.0, 0.5, 0.5},
+ {0.5, 0.5, 1.0, 1.0},
+};
+
+const std::vector<hwc_frect_t> Hwc2TestSourceCrop::mCompleteFrectScalars = {
+ {0.0, 0.0, 1.0, 1.0},
+ {0.0, 0.0, 0.5, 0.5},
+ {0.5, 0.5, 1.0, 1.0},
+ {0.0, 0.0, 0.25, 0.25},
+ {0.25, 0.25, 0.75, 0.75},
+};
+
+
+Hwc2TestSurfaceDamage::Hwc2TestSurfaceDamage(Hwc2TestCoverage coverage)
+ : Hwc2TestProperty(mSurfaceDamages, mCompositionSupport),
+ mRegionScalars((coverage == Hwc2TestCoverage::Complete)? mCompleteRegionScalars:
+ (coverage == Hwc2TestCoverage::Basic)? mBasicRegionScalars:
+ mDefaultRegionScalars)
+{
+ update();
+}
+
+Hwc2TestSurfaceDamage::~Hwc2TestSurfaceDamage()
+{
+ freeSurfaceDamages();
+}
+
+std::string Hwc2TestSurfaceDamage::dump() const
+{
+ std::stringstream dmp;
+
+ const hwc_region_t& curr = get();
+ dmp << "\tsurface damage: region count " << curr.numRects << "\n";
+ for (size_t i = 0; i < curr.numRects; i++) {
+ const hwc_rect_t& rect = curr.rects[i];
+ dmp << "\t\trect: left " << rect.left << ", top " << rect.top
+ << ", right " << rect.right << ", bottom " << rect.bottom << "\n";
+ }
+
+ return dmp.str();
+}
+
+void Hwc2TestSurfaceDamage::updateBufferArea(const Area& bufferArea)
+{
+ mBufferArea = bufferArea;
+ update();
+}
+
+void Hwc2TestSurfaceDamage::update()
+{
+ freeSurfaceDamages();
+
+ if (mBufferArea.width == 0 && mBufferArea.height == 0) {
+ mSurfaceDamages.push_back({0, nullptr});
+ return;
+ }
+
+ hwc_region_t damage;
+
+ for (const auto& regionScalar : mRegionScalars) {
+ damage.numRects = regionScalar.size();
+
+ if (damage.numRects > 0) {
+ hwc_rect_t* rects = new hwc_rect_t[damage.numRects];
+ if (!rects) {
+ ALOGW("failed to allocate new hwc_rect_t array");
+ continue;
+ }
+
+ for (size_t i = 0; i < damage.numRects; i++) {
+ rects[i].left = regionScalar[i].left * mBufferArea.width;
+ rects[i].top = regionScalar[i].top * mBufferArea.height;
+ rects[i].right = regionScalar[i].right * mBufferArea.width;
+ rects[i].bottom = regionScalar[i].bottom * mBufferArea.height;
+ }
+
+ damage.rects = static_cast<hwc_rect_t const*>(rects);
+ } else {
+ damage.rects = nullptr;
+ }
+
+ mSurfaceDamages.push_back(damage);
+ }
+}
+
+void Hwc2TestSurfaceDamage::freeSurfaceDamages()
+{
+ for (const auto& surfaceDamage : mSurfaceDamages) {
+ if (surfaceDamage.numRects > 0 && surfaceDamage.rects)
+ delete[] surfaceDamage.rects;
+ }
+ mSurfaceDamages.clear();
+}
+
+const std::vector<std::vector<hwc_frect_t>> Hwc2TestSurfaceDamage::mDefaultRegionScalars = {
+ {{}},
+};
+
+const std::vector<std::vector<hwc_frect_t>> Hwc2TestSurfaceDamage::mBasicRegionScalars = {
+ {{}},
+ {{0.0, 0.0, 1.0, 1.0}},
+};
+
+const std::vector<std::vector<hwc_frect_t>> Hwc2TestSurfaceDamage::mCompleteRegionScalars = {
+ {{}},
+ {{0.0, 0.0, 1.0, 1.0}},
+ {{0.0, 0.0, 0.5, 0.5}, {0.5, 0.5, 1.0, 1.0}},
+};
+
+
+Hwc2TestTransform::Hwc2TestTransform(Hwc2TestCoverage coverage)
+ : Hwc2TestProperty(coverage, mCompleteTransforms, mBasicTransforms,
+ mDefaultTransforms, mCompositionSupport) { }
+
+std::string Hwc2TestTransform::dump() const
+{
+ std::stringstream dmp;
+ dmp << "\ttransform: " << getTransformName(get()) << "\n";
+ return dmp.str();
+}
+
+const std::vector<hwc_transform_t> Hwc2TestTransform::mDefaultTransforms = {
+ static_cast<hwc_transform_t>(0),
+};
+
+const std::vector<hwc_transform_t> Hwc2TestTransform::mBasicTransforms = {
+ static_cast<hwc_transform_t>(0),
+ HWC_TRANSFORM_FLIP_H,
+ HWC_TRANSFORM_FLIP_V,
+ HWC_TRANSFORM_ROT_90,
+};
+
+const std::vector<hwc_transform_t> Hwc2TestTransform::mCompleteTransforms = {
+ static_cast<hwc_transform_t>(0),
+ HWC_TRANSFORM_FLIP_H,
+ HWC_TRANSFORM_FLIP_V,
+ HWC_TRANSFORM_ROT_90,
+ HWC_TRANSFORM_ROT_180,
+ HWC_TRANSFORM_ROT_270,
+ HWC_TRANSFORM_FLIP_H_ROT_90,
+ HWC_TRANSFORM_FLIP_V_ROT_90,
+};
+
+
+Hwc2TestVisibleRegion::~Hwc2TestVisibleRegion()
+{
+ release();
+}
+
+std::string Hwc2TestVisibleRegion::dump() const
+{
+ std::stringstream dmp;
+
+ const hwc_region_t& curr = get();
+ dmp << "\tvisible region: region count " << curr.numRects << "\n";
+ for (size_t i = 0; i < curr.numRects; i++) {
+ const hwc_rect_t& rect = curr.rects[i];
+ dmp << "\t\trect: left " << rect.left << ", top " << rect.top
+ << ", right " << rect.right << ", bottom " << rect.bottom << "\n";
+ }
+
+ return dmp.str();
+}
+
+void Hwc2TestVisibleRegion::set(const android::Region& visibleRegion)
+{
+ release();
+
+ size_t size = 0;
+ const android::Rect* rects = visibleRegion.getArray(&size);
+
+ mVisibleRegion.numRects = size;
+ mVisibleRegion.rects = nullptr;
+
+ if (size > 0) {
+ hwc_rect_t* hwcRects = new hwc_rect_t[size];
+ for (size_t i = 0; i < size; i++) {
+ hwcRects[i].left = rects[i].left;
+ hwcRects[i].top = rects[i].top;
+ hwcRects[i].right = rects[i].right;
+ hwcRects[i].bottom = rects[i].bottom;
+ }
+ mVisibleRegion.rects = hwcRects;
+ }
+}
+
+hwc_region_t Hwc2TestVisibleRegion::get() const
+{
+ return mVisibleRegion;
+}
+
+void Hwc2TestVisibleRegion::release()
+{
+ if (mVisibleRegion.numRects > 0 && mVisibleRegion.rects)
+ delete[] mVisibleRegion.rects;
+ mVisibleRegion.rects = nullptr;
+ mVisibleRegion.numRects = 0;
+}
+
+/* Identifies which layer properties are supported by each composition type.
+ * hwc2_composition_t values range from:
+ * HWC2_COMPOSITION_INVALID = 0,
+ * HWC2_COMPOSITION_CLIENT = 1,
+ * HWC2_COMPOSITION_DEVICE = 2,
+ * HWC2_COMPOSITION_SOLID_COLOR = 3,
+ * HWC2_COMPOSITION_CURSOR = 4,
+ * HWC2_COMPOSITION_SIDEBAND = 5,
+ *
+ * Each property array can be indexed by a hwc2_composition_t value.
+ * By using an array instead of a more complex data structure, runtimes for
+ * some test cases showed a noticeable improvement.
+ */
+
+/* INVALID CLIENT DEVICE COLOR CURSOR SIDEBAND */
+const std::array<bool, 6> Hwc2TestBufferArea::mCompositionSupport = {{
+ false, true, true, false, true, true,
+}};
+
+/* INVALID CLIENT DEVICE COLOR CURSOR SIDEBAND */
+const std::array<bool, 6> Hwc2TestBlendMode::mCompositionSupport = {{
+ false, true, true, false, true, true,
+}};
+
+/* INVALID CLIENT DEVICE COLOR CURSOR SIDEBAND */
+const std::array<bool, 6> Hwc2TestColor::mCompositionSupport = {{
+ false, false, false, true, false, false,
+}};
+
+/* INVALID CLIENT DEVICE COLOR CURSOR SIDEBAND */
+const std::array<bool, 6> Hwc2TestComposition::mCompositionSupport = {{
+ false, true, true, true, true, true,
+}};
+
+/* INVALID CLIENT DEVICE COLOR CURSOR SIDEBAND */
+const std::array<bool, 6> Hwc2TestDataspace::mCompositionSupport = {{
+ false, true, true, true, true, false,
+}};
+
+/* INVALID CLIENT DEVICE COLOR CURSOR SIDEBAND */
+const std::array<bool, 6> Hwc2TestDisplayDimension::mCompositionSupport = {{
+ false, true, true, true, true, true,
+}};
+
+/* INVALID CLIENT DEVICE COLOR CURSOR SIDEBAND */
+const std::array<bool, 6> Hwc2TestDisplayFrame::mCompositionSupport = {{
+ false, true, true, true, false, true,
+}};
+
+/* INVALID CLIENT DEVICE COLOR CURSOR SIDEBAND */
+const std::array<bool, 6> Hwc2TestPlaneAlpha::mCompositionSupport = {{
+ false, true, true, true, true, true,
+}};
+
+/* INVALID CLIENT DEVICE COLOR CURSOR SIDEBAND */
+const std::array<bool, 6> Hwc2TestSourceCrop::mCompositionSupport = {{
+ false, true, true, false, true, false,
+}};
+
+/* INVALID CLIENT DEVICE COLOR CURSOR SIDEBAND */
+const std::array<bool, 6> Hwc2TestSurfaceDamage::mCompositionSupport = {{
+ false, false, true, false, true, false,
+}};
+
+/* INVALID CLIENT DEVICE COLOR CURSOR SIDEBAND */
+const std::array<bool, 6> Hwc2TestTransform::mCompositionSupport = {{
+ false, true, true, false, true, true,
+}};
diff --git a/services/surfaceflinger/tests/hwc2/Hwc2TestProperties.h b/services/surfaceflinger/tests/hwc2/Hwc2TestProperties.h
new file mode 100644
index 0000000..c2029ab
--- /dev/null
+++ b/services/surfaceflinger/tests/hwc2/Hwc2TestProperties.h
@@ -0,0 +1,384 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _HWC2_TEST_PROPERTIES_H
+#define _HWC2_TEST_PROPERTIES_H
+
+#include <array>
+#include <vector>
+
+#include <ui/Region.h>
+
+#define HWC2_INCLUDE_STRINGIFICATION
+#define HWC2_USE_CPP11
+#include <hardware/hwcomposer2.h>
+#undef HWC2_INCLUDE_STRINGIFICATION
+#undef HWC2_USE_CPP11
+
+enum class Hwc2TestCoverage {
+ Default = 0,
+ Basic,
+ Complete,
+};
+
+enum class Hwc2TestPropertyName {
+ BlendMode = 1,
+ BufferArea,
+ Color,
+ Composition,
+ CursorPosition,
+ Dataspace,
+ DisplayFrame,
+ PlaneAlpha,
+ SourceCrop,
+ SurfaceDamage,
+ Transform,
+};
+
+typedef struct {
+ int32_t width;
+ int32_t height;
+} Area;
+
+
+typedef struct {
+ uint32_t width;
+ uint32_t height;
+} UnsignedArea;
+
+
+class Hwc2TestContainer {
+public:
+ virtual ~Hwc2TestContainer() = default;
+
+ /* Resets the container */
+ virtual void reset() = 0;
+
+ /* Attempts to advance to the next valid value. Returns true if one can be
+ * found */
+ virtual bool advance() = 0;
+
+ virtual std::string dump() const = 0;
+
+ /* Returns true if the container supports the given composition type */
+ virtual bool isSupported(hwc2_composition_t composition) = 0;
+};
+
+
+template <class T>
+class Hwc2TestProperty : public Hwc2TestContainer {
+public:
+ Hwc2TestProperty(Hwc2TestCoverage coverage,
+ const std::vector<T>& completeList, const std::vector<T>& basicList,
+ const std::vector<T>& defaultList,
+ const std::array<bool, 6>& compositionSupport)
+ : Hwc2TestProperty((coverage == Hwc2TestCoverage::Complete)? completeList:
+ (coverage == Hwc2TestCoverage::Basic)? basicList : defaultList,
+ compositionSupport) { }
+
+ Hwc2TestProperty(const std::vector<T>& list,
+ const std::array<bool, 6>& compositionSupport)
+ : mList(list),
+ mCompositionSupport(compositionSupport) { }
+
+ void reset() override
+ {
+ mListIdx = 0;
+ }
+
+ bool advance() override
+ {
+ if (mListIdx + 1 < mList.size()) {
+ mListIdx++;
+ updateDependents();
+ return true;
+ }
+ reset();
+ updateDependents();
+ return false;
+ }
+
+ T get() const
+ {
+ return mList.at(mListIdx);
+ }
+
+ virtual bool isSupported(hwc2_composition_t composition)
+ {
+ return mCompositionSupport.at(composition);
+ }
+
+protected:
+ /* If a derived class has dependents, override this function */
+ virtual void updateDependents() { }
+
+ const std::vector<T>& mList;
+ size_t mListIdx = 0;
+
+ const std::array<bool, 6>& mCompositionSupport;
+};
+
+class Hwc2TestBuffer;
+class Hwc2TestSourceCrop;
+class Hwc2TestSurfaceDamage;
+
+class Hwc2TestBufferArea : public Hwc2TestProperty<Area> {
+public:
+ Hwc2TestBufferArea(Hwc2TestCoverage coverage, const Area& displayArea);
+
+ std::string dump() const override;
+
+ void setDependent(Hwc2TestBuffer* buffer);
+ void setDependent(Hwc2TestSourceCrop* sourceCrop);
+ void setDependent(Hwc2TestSurfaceDamage* surfaceDamage);
+
+protected:
+ void update();
+ void updateDependents() override;
+
+ const std::vector<float>& mScalars;
+ static const std::vector<float> mDefaultScalars;
+ static const std::vector<float> mBasicScalars;
+ static const std::vector<float> mCompleteScalars;
+
+ Area mDisplayArea;
+
+ Hwc2TestBuffer* mBuffer = nullptr;
+ Hwc2TestSourceCrop* mSourceCrop = nullptr;
+ Hwc2TestSurfaceDamage* mSurfaceDamage = nullptr;
+
+ std::vector<Area> mBufferAreas;
+
+ static const std::array<bool, 6> mCompositionSupport;
+};
+
+
+class Hwc2TestColor;
+
+class Hwc2TestBlendMode : public Hwc2TestProperty<hwc2_blend_mode_t> {
+public:
+ Hwc2TestBlendMode(Hwc2TestCoverage coverage);
+
+ std::string dump() const override;
+
+ void setDependent(Hwc2TestColor* color);
+
+protected:
+ void updateDependents() override;
+
+ Hwc2TestColor* mColor = nullptr;
+
+ static const std::vector<hwc2_blend_mode_t> mDefaultBlendModes;
+ static const std::vector<hwc2_blend_mode_t> mBasicBlendModes;
+ static const std::vector<hwc2_blend_mode_t> mCompleteBlendModes;
+
+ static const std::array<bool, 6> mCompositionSupport;
+};
+
+
+class Hwc2TestColor : public Hwc2TestProperty<hwc_color_t> {
+public:
+ Hwc2TestColor(Hwc2TestCoverage coverage,
+ hwc2_blend_mode_t blendMode = HWC2_BLEND_MODE_NONE);
+
+ std::string dump() const override;
+
+ void updateBlendMode(hwc2_blend_mode_t blendMode);
+
+protected:
+ void update();
+
+ std::vector<hwc_color_t> mBaseColors;
+ static const std::vector<hwc_color_t> mDefaultBaseColors;
+ static const std::vector<hwc_color_t> mBasicBaseColors;
+ static const std::vector<hwc_color_t> mCompleteBaseColors;
+
+ hwc2_blend_mode_t mBlendMode;
+
+ std::vector<hwc_color_t> mColors;
+
+ static const std::array<bool, 6> mCompositionSupport;
+};
+
+
+class Hwc2TestComposition : public Hwc2TestProperty<hwc2_composition_t> {
+public:
+ Hwc2TestComposition(Hwc2TestCoverage coverage);
+
+ std::string dump() const override;
+
+protected:
+ static const std::vector<hwc2_composition_t> mDefaultCompositions;
+ static const std::vector<hwc2_composition_t> mBasicCompositions;
+ static const std::vector<hwc2_composition_t> mCompleteCompositions;
+
+ static const std::array<bool, 6> mCompositionSupport;
+};
+
+
+class Hwc2TestDataspace : public Hwc2TestProperty<android_dataspace_t> {
+public:
+ Hwc2TestDataspace(Hwc2TestCoverage coverage);
+
+ std::string dump() const override;
+
+protected:
+ static const std::vector<android_dataspace_t> defaultDataspaces;
+ static const std::vector<android_dataspace_t> basicDataspaces;
+ static const std::vector<android_dataspace_t> completeDataspaces;
+
+ static const std::array<bool, 6> mCompositionSupport;
+};
+
+
+class Hwc2TestDisplayDimension : public Hwc2TestProperty<UnsignedArea> {
+public:
+ Hwc2TestDisplayDimension(Hwc2TestCoverage coverage);
+
+ std::string dump() const;
+
+ void setDependent(Hwc2TestBuffer* buffer);
+
+private:
+ void updateDependents();
+
+ Hwc2TestBuffer* mBuffer;
+
+ static const std::vector<UnsignedArea> mDefaultDisplayDimensions;
+ static const std::vector<UnsignedArea> mBasicDisplayDimensions;
+ static const std::vector<UnsignedArea> mCompleteDisplayDimensions;
+
+ static const std::array<bool, 6> mCompositionSupport;
+};
+
+
+class Hwc2TestDisplayFrame : public Hwc2TestProperty<hwc_rect_t> {
+public:
+ Hwc2TestDisplayFrame(Hwc2TestCoverage coverage, const Area& displayArea);
+
+ std::string dump() const override;
+
+protected:
+ void update();
+
+ const std::vector<hwc_frect_t>& mFrectScalars;
+ const static std::vector<hwc_frect_t> mDefaultFrectScalars;
+ const static std::vector<hwc_frect_t> mBasicFrectScalars;
+ const static std::vector<hwc_frect_t> mCompleteFrectScalars;
+
+ Area mDisplayArea;
+
+ std::vector<hwc_rect_t> mDisplayFrames;
+
+ static const std::array<bool, 6> mCompositionSupport;
+};
+
+
+class Hwc2TestPlaneAlpha : public Hwc2TestProperty<float> {
+public:
+ Hwc2TestPlaneAlpha(Hwc2TestCoverage coverage);
+
+ std::string dump() const override;
+
+protected:
+ static const std::vector<float> mDefaultPlaneAlphas;
+ static const std::vector<float> mBasicPlaneAlphas;
+ static const std::vector<float> mCompletePlaneAlphas;
+
+ static const std::array<bool, 6> mCompositionSupport;
+};
+
+
+class Hwc2TestSourceCrop : public Hwc2TestProperty<hwc_frect_t> {
+public:
+ Hwc2TestSourceCrop(Hwc2TestCoverage coverage, const Area& bufferArea = {0, 0});
+
+ std::string dump() const override;
+
+ void updateBufferArea(const Area& bufferArea);
+
+protected:
+ void update();
+
+ const std::vector<hwc_frect_t>& mFrectScalars;
+ const static std::vector<hwc_frect_t> mDefaultFrectScalars;
+ const static std::vector<hwc_frect_t> mBasicFrectScalars;
+ const static std::vector<hwc_frect_t> mCompleteFrectScalars;
+
+ Area mBufferArea;
+
+ std::vector<hwc_frect_t> mSourceCrops;
+
+ static const std::array<bool, 6> mCompositionSupport;
+};
+
+
+class Hwc2TestSurfaceDamage : public Hwc2TestProperty<hwc_region_t> {
+public:
+ Hwc2TestSurfaceDamage(Hwc2TestCoverage coverage);
+ ~Hwc2TestSurfaceDamage();
+
+ std::string dump() const override;
+
+ void updateBufferArea(const Area& bufferArea);
+
+protected:
+ void update();
+ void freeSurfaceDamages();
+
+ const std::vector<std::vector<hwc_frect_t>> &mRegionScalars;
+ const static std::vector<std::vector<hwc_frect_t>> mDefaultRegionScalars;
+ const static std::vector<std::vector<hwc_frect_t>> mBasicRegionScalars;
+ const static std::vector<std::vector<hwc_frect_t>> mCompleteRegionScalars;
+
+ Area mBufferArea = {0, 0};
+
+ std::vector<hwc_region_t> mSurfaceDamages;
+
+ static const std::array<bool, 6> mCompositionSupport;
+};
+
+
+class Hwc2TestTransform : public Hwc2TestProperty<hwc_transform_t> {
+public:
+ Hwc2TestTransform(Hwc2TestCoverage coverage);
+
+ std::string dump() const override;
+
+protected:
+ static const std::vector<hwc_transform_t> mDefaultTransforms;
+ static const std::vector<hwc_transform_t> mBasicTransforms;
+ static const std::vector<hwc_transform_t> mCompleteTransforms;
+
+ static const std::array<bool, 6> mCompositionSupport;
+};
+
+
+class Hwc2TestVisibleRegion {
+public:
+ ~Hwc2TestVisibleRegion();
+
+ std::string dump() const;
+
+ void set(const android::Region& visibleRegion);
+ hwc_region_t get() const;
+ void release();
+
+protected:
+ hwc_region_t mVisibleRegion = {0, nullptr};
+};
+
+#endif /* ifndef _HWC2_TEST_PROPERTIES_H */
diff --git a/services/surfaceflinger/tests/hwc2/Hwc2TestVirtualDisplay.cpp b/services/surfaceflinger/tests/hwc2/Hwc2TestVirtualDisplay.cpp
new file mode 100644
index 0000000..d0fbc0b
--- /dev/null
+++ b/services/surfaceflinger/tests/hwc2/Hwc2TestVirtualDisplay.cpp
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <sstream>
+
+#include "Hwc2TestVirtualDisplay.h"
+
+Hwc2TestVirtualDisplay::Hwc2TestVirtualDisplay(
+ Hwc2TestCoverage coverage)
+ : mDisplayDimension(coverage)
+{
+ mDisplayDimension.setDependent(&mBuffer);
+}
+
+std::string Hwc2TestVirtualDisplay::dump() const
+{
+ std::stringstream dmp;
+
+ dmp << "virtual display: \n";
+
+ mDisplayDimension.dump();
+
+ return dmp.str();
+}
+
+int Hwc2TestVirtualDisplay::getBuffer(buffer_handle_t* outHandle,
+ android::base::unique_fd* outAcquireFence)
+{
+ int32_t acquireFence;
+ int ret = mBuffer.get(outHandle, &acquireFence);
+ outAcquireFence->reset(acquireFence);
+ return ret;
+}
+
+void Hwc2TestVirtualDisplay::reset()
+{
+ return mDisplayDimension.reset();
+}
+
+bool Hwc2TestVirtualDisplay::advance()
+{
+ return mDisplayDimension.advance();
+}
+
+UnsignedArea Hwc2TestVirtualDisplay::getDisplayDimension() const
+{
+ return mDisplayDimension.get();
+}
diff --git a/services/surfaceflinger/tests/hwc2/Hwc2TestVirtualDisplay.h b/services/surfaceflinger/tests/hwc2/Hwc2TestVirtualDisplay.h
new file mode 100644
index 0000000..09420ef
--- /dev/null
+++ b/services/surfaceflinger/tests/hwc2/Hwc2TestVirtualDisplay.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _HWC2_TEST_VIRTUAL_DISPLAY_H
+#define _HWC2_TEST_VIRTUAL_DISPLAY_H
+
+#include "Hwc2TestBuffer.h"
+#include "Hwc2TestProperties.h"
+
+#define HWC2_INCLUDE_STRINGIFICATION
+#define HWC2_USE_CPP11
+#include <hardware/hwcomposer2.h>
+#undef HWC2_INCLUDE_STRINGIFICATION
+#undef HWC2_USE_CPP11
+
+class Hwc2TestVirtualDisplay {
+public:
+ Hwc2TestVirtualDisplay(Hwc2TestCoverage coverage);
+
+ std::string dump() const;
+
+ int getBuffer(buffer_handle_t* outHandle,
+ android::base::unique_fd* outAcquireFence);
+
+ void reset();
+ bool advance();
+
+ UnsignedArea getDisplayDimension() const;
+
+private:
+ Hwc2TestBuffer mBuffer;
+
+ Hwc2TestDisplayDimension mDisplayDimension;
+};
+
+#endif /* ifndef _HWC2_TEST_VIRTUAL_DISPLAY_H */
diff --git a/services/vr/sensord/Android.mk b/services/vr/sensord/Android.mk
index e213bd6..f86664e 100644
--- a/services/vr/sensord/Android.mk
+++ b/services/vr/sensord/Android.mk
@@ -14,6 +14,8 @@
LOCAL_PATH := $(call my-dir)
+SENSORD_EXTEND ?= libsensordextensionstub
+
sourceFiles := \
pose_service.cpp \
sensord.cpp \
@@ -42,6 +44,7 @@
liblog \
libhardware \
libutils \
+ $(SENSORD_EXTEND) \
cFlags := -DLOG_TAG=\"sensord\" \
-DTRACE=0
@@ -67,3 +70,8 @@
LOCAL_SRC_FILES := test/poselatencytest.cpp
LOCAL_MODULE := poselatencytest
include $(BUILD_EXECUTABLE)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := libsensordextensionstub
+LOCAL_SRC_FILES := sensord_extension.cpp
+include $(BUILD_SHARED_LIBRARY)
diff --git a/services/vr/sensord/sensord.cpp b/services/vr/sensord/sensord.cpp
index 0a75318..db39152 100644
--- a/services/vr/sensord/sensord.cpp
+++ b/services/vr/sensord/sensord.cpp
@@ -14,6 +14,7 @@
#include "sensor_ndk_thread.h"
#include "sensor_service.h"
#include "sensor_thread.h"
+#include "sensord_extension.h"
using android::dvr::PoseService;
using android::dvr::SensorHalThread;
@@ -22,10 +23,13 @@
using android::dvr::SensorThread;
using android::pdx::Service;
using android::pdx::ServiceDispatcher;
+using android::dvr::SensordExtension;
int main(int, char**) {
ALOGI("Starting up...");
+ SensordExtension::run();
+
// We need to be able to create endpoints with full perms.
umask(0000);
diff --git a/services/vr/sensord/sensord_extension.cpp b/services/vr/sensord/sensord_extension.cpp
new file mode 100644
index 0000000..6cd7db3
--- /dev/null
+++ b/services/vr/sensord/sensord_extension.cpp
@@ -0,0 +1,4 @@
+#include "sensord_extension.h"
+
+void android::dvr::SensordExtension::run() {
+}
diff --git a/services/vr/sensord/sensord_extension.h b/services/vr/sensord/sensord_extension.h
new file mode 100644
index 0000000..e553eed
--- /dev/null
+++ b/services/vr/sensord/sensord_extension.h
@@ -0,0 +1,16 @@
+#ifndef ANDROID_DVR_SENSORD_EXTENSION_H_
+#define ANDROID_DVR_SENSORD_EXTENSION_H_
+
+namespace android {
+namespace dvr {
+
+// Allows sensord to be extended with additional code.
+class SensordExtension {
+ public:
+ static void run();
+};
+
+} // namespace dvr
+} // namespace android
+
+#endif // ANDROID_DVR_SENSORD_EXTENSION_H_
diff --git a/services/vr/virtual_touchpad/Android.mk b/services/vr/virtual_touchpad/Android.mk
index b78eb99..88b2dd9 100644
--- a/services/vr/virtual_touchpad/Android.mk
+++ b/services/vr/virtual_touchpad/Android.mk
@@ -9,7 +9,8 @@
VirtualTouchpadEvdev.cpp
shared_libs := \
- libbase
+ libbase \
+ libutils
include $(CLEAR_VARS)
LOCAL_SRC_FILES := $(src)
@@ -24,21 +25,23 @@
# Touchpad unit tests.
-test_src_files := \
- tests/VirtualTouchpad_test.cpp
-
-static_libs := \
+test_static_libs := \
libbase \
libcutils \
- libutils \
libvirtualtouchpad
+test_shared_libs := \
+ libutils
+
+test_src_files := \
+ tests/VirtualTouchpad_test.cpp
+
$(foreach file,$(test_src_files), \
$(eval include $(CLEAR_VARS)) \
$(eval LOCAL_SRC_FILES := $(file)) \
$(eval LOCAL_C_INCLUDES := $(LOCAL_PATH)/include) \
- $(eval LOCAL_STATIC_LIBRARIES := $(static_libs)) \
- $(eval LOCAL_SHARED_LIBRARIES := $(shared_libs)) \
+ $(eval LOCAL_STATIC_LIBRARIES := $(test_static_libs)) \
+ $(eval LOCAL_SHARED_LIBRARIES := $(test_shared_libs)) \
$(eval LOCAL_CPPFLAGS += -std=c++11) \
$(eval LOCAL_LDLIBS := -llog) \
$(eval LOCAL_MODULE := $(notdir $(file:%.cpp=%))) \
@@ -70,7 +73,7 @@
LOCAL_STATIC_LIBRARIES := $(static_libs)
LOCAL_SHARED_LIBRARIES := $(shared_libs)
LOCAL_CPPFLAGS += -std=c++11
-LOCAL_CFLAGS += -DLOG_TAG=\"VrVirtualTouchpad\"
+LOCAL_CFLAGS += -DLOG_TAG=\"VrVirtualTouchpad\" -DSELINUX_ACCESS_CONTROL
LOCAL_LDLIBS := -llog
LOCAL_MODULE := virtual_touchpad
LOCAL_MODULE_TAGS := optional
diff --git a/services/vr/virtual_touchpad/EvdevInjector.cpp b/services/vr/virtual_touchpad/EvdevInjector.cpp
index d8a1dfa..b4c0a52 100644
--- a/services/vr/virtual_touchpad/EvdevInjector.cpp
+++ b/services/vr/virtual_touchpad/EvdevInjector.cpp
@@ -307,5 +307,11 @@
return 0;
}
+void EvdevInjector::dumpInternal(String8& result) {
+ result.append("[injector]\n");
+ result.appendFormat("state = %d\n", static_cast<int>(state_));
+ result.appendFormat("error = %d\n\n", error_);
+}
+
} // namespace dvr
} // namespace android
diff --git a/services/vr/virtual_touchpad/EvdevInjector.h b/services/vr/virtual_touchpad/EvdevInjector.h
index 1b1c4da..c69dbef 100644
--- a/services/vr/virtual_touchpad/EvdevInjector.h
+++ b/services/vr/virtual_touchpad/EvdevInjector.h
@@ -3,6 +3,7 @@
#include <android-base/unique_fd.h>
#include <linux/uinput.h>
+#include <utils/String8.h>
#include <cstdint>
#include <memory>
@@ -99,6 +100,8 @@
int SendMultiTouchXY(int32_t slot, int32_t id, int32_t x, int32_t y);
int SendMultiTouchLift(int32_t slot);
+ void dumpInternal(String8& result);
+
protected:
// Must be called only between construction and ConfigureBegin().
inline void SetUInputForTesting(UInput* uinput) { uinput_ = uinput; }
diff --git a/services/vr/virtual_touchpad/VirtualTouchpadClient.cpp b/services/vr/virtual_touchpad/VirtualTouchpadClient.cpp
index 175173f..782b19c 100644
--- a/services/vr/virtual_touchpad/VirtualTouchpadClient.cpp
+++ b/services/vr/virtual_touchpad/VirtualTouchpadClient.cpp
@@ -10,17 +10,49 @@
class VirtualTouchpadClientImpl : public VirtualTouchpadClient {
public:
- VirtualTouchpadClientImpl(sp<IVirtualTouchpadService> service)
- : service_(service) {}
- ~VirtualTouchpadClientImpl() override {}
+ VirtualTouchpadClientImpl() {}
+ ~VirtualTouchpadClientImpl() override {
+ if (service_ != nullptr) {
+ Detach();
+ }
+ }
- status_t Touch(int touchpad,
- float x, float y, float pressure) override {
+ status_t Attach() {
+ if (service_ != nullptr) {
+ return ALREADY_EXISTS;
+ }
+ sp<IServiceManager> sm = defaultServiceManager();
+ if (sm == nullptr) {
+ ALOGE("no service manager");
+ return NO_INIT;
+ }
+ sp<IVirtualTouchpadService> service =
+ interface_cast<IVirtualTouchpadService>(
+ sm->getService(IVirtualTouchpadService::SERVICE_NAME()));
+ if (service == nullptr) {
+ ALOGE("failed to get service");
+ return NAME_NOT_FOUND;
+ }
+ service_ = service;
+ return service_->attach().transactionError();
+ }
+
+ status_t Detach() {
+ if (service_ == nullptr) {
+ return NO_INIT;
+ }
+ status_t status = service_->detach().transactionError();
+ service_ = nullptr;
+ return status;
+ }
+
+ status_t Touch(int touchpad, float x, float y, float pressure) override {
if (service_ == nullptr) {
return NO_INIT;
}
return service_->touch(touchpad, x, y, pressure).transactionError();
}
+
status_t ButtonState(int touchpad, int buttons) override {
if (service_ == nullptr) {
return NO_INIT;
@@ -28,6 +60,12 @@
return service_->buttonState(touchpad, buttons).transactionError();
}
+ void dumpInternal(String8& result) override {
+ result.append("[virtual touchpad]\n");
+ result.appendFormat("connected = %s\n\n",
+ service_ != nullptr ? "true" : "false");
+ }
+
private:
sp<IVirtualTouchpadService> service_;
};
@@ -35,18 +73,7 @@
} // anonymous namespace
sp<VirtualTouchpad> VirtualTouchpadClient::Create() {
- sp<IServiceManager> sm = defaultServiceManager();
- if (sm == nullptr) {
- ALOGE("no service manager");
- return sp<VirtualTouchpad>();
- }
- sp<IVirtualTouchpadService> service = interface_cast<IVirtualTouchpadService>(
- sm->getService(IVirtualTouchpadService::SERVICE_NAME()));
- if (service == nullptr) {
- ALOGE("failed to get service");
- return sp<VirtualTouchpad>();
- }
- return new VirtualTouchpadClientImpl(service);
+ return new VirtualTouchpadClientImpl();
}
} // namespace dvr
diff --git a/services/vr/virtual_touchpad/VirtualTouchpadEvdev.cpp b/services/vr/virtual_touchpad/VirtualTouchpadEvdev.cpp
index f25a2ad..bc29408 100644
--- a/services/vr/virtual_touchpad/VirtualTouchpadEvdev.cpp
+++ b/services/vr/virtual_touchpad/VirtualTouchpadEvdev.cpp
@@ -32,15 +32,10 @@
sp<VirtualTouchpad> VirtualTouchpadEvdev::Create() {
VirtualTouchpadEvdev* const touchpad = new VirtualTouchpadEvdev();
- const status_t status = touchpad->Initialize();
- if (status) {
- ALOGE("initialization failed: %d", status);
- return sp<VirtualTouchpad>();
- }
return sp<VirtualTouchpad>(touchpad);
}
-int VirtualTouchpadEvdev::Initialize() {
+status_t VirtualTouchpadEvdev::Attach() {
if (!injector_) {
owned_injector_.reset(new EvdevInjector());
injector_ = owned_injector_.get();
@@ -56,9 +51,20 @@
return injector_->GetError();
}
+status_t VirtualTouchpadEvdev::Detach() {
+ injector_->Close();
+ injector_ = nullptr;
+ owned_injector_.reset();
+ last_device_x_ = INT32_MIN;
+ last_device_y_ = INT32_MIN;
+ touches_ = 0;
+ last_motion_event_buttons_ = 0;
+ return OK;
+}
+
int VirtualTouchpadEvdev::Touch(int touchpad, float x, float y,
float pressure) {
- (void)touchpad; // TODO(b/35992608) Support multiple virtual touchpad devices.
+ (void)touchpad; // TODO(b/35992608) Support multiple touchpad devices.
if ((x < 0.0f) || (x >= 1.0f) || (y < 0.0f) || (y >= 1.0f)) {
return EINVAL;
}
@@ -104,7 +110,7 @@
}
int VirtualTouchpadEvdev::ButtonState(int touchpad, int buttons) {
- (void)touchpad; // TODO(b/35992608) Support multiple virtual touchpad devices.
+ (void)touchpad; // TODO(b/35992608) Support multiple touchpad devices.
const int changes = last_motion_event_buttons_ ^ buttons;
if (!changes) {
return 0;
@@ -123,10 +129,26 @@
injector_->SendKey(BTN_BACK, (buttons & AMOTION_EVENT_BUTTON_BACK)
? EvdevInjector::KEY_PRESS
: EvdevInjector::KEY_RELEASE);
+ injector_->SendSynReport();
}
last_motion_event_buttons_ = buttons;
return injector_->GetError();
}
+void VirtualTouchpadEvdev::dumpInternal(String8& result) {
+ result.append("[virtual touchpad]\n");
+ if (!injector_) {
+ result.append("injector = none\n");
+ return;
+ }
+ result.appendFormat("injector = %s\n", owned_injector_ ? "normal" : "test");
+ result.appendFormat("touches = %d\n", touches_);
+ result.appendFormat("last_position = (%" PRId32 ", %" PRId32 ")\n",
+ last_device_x_, last_device_y_);
+ result.appendFormat("last_buttons = 0x%" PRIX32 "\n\n",
+ last_motion_event_buttons_);
+ injector_->dumpInternal(result);
+}
+
} // namespace dvr
} // namespace android
diff --git a/services/vr/virtual_touchpad/VirtualTouchpadEvdev.h b/services/vr/virtual_touchpad/VirtualTouchpadEvdev.h
index ec8006b..b158cec 100644
--- a/services/vr/virtual_touchpad/VirtualTouchpadEvdev.h
+++ b/services/vr/virtual_touchpad/VirtualTouchpadEvdev.h
@@ -18,15 +18,17 @@
static sp<VirtualTouchpad> Create();
// VirtualTouchpad implementation:
+ status_t Attach() override;
+ status_t Detach() override;
status_t Touch(int touchpad, float x, float y, float pressure) override;
status_t ButtonState(int touchpad, int buttons) override;
+ void dumpInternal(String8& result) override;
protected:
VirtualTouchpadEvdev() {}
~VirtualTouchpadEvdev() override {}
- status_t Initialize();
- // Must be called only between construction and Initialize().
+ // Must be called only between construction and Attach().
inline void SetEvdevInjectorForTesting(EvdevInjector* injector) {
injector_ = injector;
}
diff --git a/services/vr/virtual_touchpad/VirtualTouchpadService.cpp b/services/vr/virtual_touchpad/VirtualTouchpadService.cpp
index a1f281c..2e2f622 100644
--- a/services/vr/virtual_touchpad/VirtualTouchpadService.cpp
+++ b/services/vr/virtual_touchpad/VirtualTouchpadService.cpp
@@ -1,22 +1,136 @@
#include "VirtualTouchpadService.h"
+#include <inttypes.h>
+
+#include <binder/IPCThreadState.h>
+#include <binder/PermissionCache.h>
#include <binder/Status.h>
+#include <cutils/log.h>
#include <linux/input.h>
-#include <log/log.h>
+#include <private/android_filesystem_config.h>
#include <utils/Errors.h>
namespace android {
namespace dvr {
-binder::Status VirtualTouchpadService::touch(int touchpad,
- float x, float y, float pressure) {
- const status_t error = touchpad_->Touch(touchpad, x, y, pressure);
- return error ? binder::Status::fromStatusT(error) : binder::Status::ok();
+namespace {
+const String16 kDumpPermission("android.permission.DUMP");
+const String16 kTouchPermission("android.permission.RESTRICTED_VR_ACCESS");
+} // anonymous namespace
+
+VirtualTouchpadService::~VirtualTouchpadService() {
+ if (client_pid_) {
+ client_pid_ = 0;
+ touchpad_->Detach();
+ }
+}
+
+binder::Status VirtualTouchpadService::attach() {
+ pid_t pid;
+ if (!CheckTouchPermission(&pid)) {
+ return binder::Status::fromStatusT(PERMISSION_DENIED);
+ }
+ if (client_pid_ == pid) {
+ // The same client has called attach() twice with no intervening detach().
+ // This indicates a problem with the client, so return an error.
+ // However, since the client is already attached, any touchpad actions
+ // it takes will still work.
+ ALOGE("pid=%ld attached twice", static_cast<long>(pid));
+ return binder::Status::fromStatusT(ALREADY_EXISTS);
+ }
+ if (client_pid_ != 0) {
+ // Attach while another client is attached. This can happen if the client
+ // dies without cleaning up after itself, so move ownership to the current
+ // caller. If two actual clients have connected, the problem will be
+ // reported when the previous client performs any touchpad action.
+ ALOGE("pid=%ld replaces %ld", static_cast<long>(pid),
+ static_cast<long>(client_pid_));
+ }
+ client_pid_ = pid;
+ if (const status_t error = touchpad_->Attach()) {
+ return binder::Status::fromStatusT(error);
+ }
+ return binder::Status::ok();
+}
+
+binder::Status VirtualTouchpadService::detach() {
+ if (!CheckPermissions()) {
+ return binder::Status::fromStatusT(PERMISSION_DENIED);
+ }
+ client_pid_ = 0;
+ if (const status_t error = touchpad_->Detach()) {
+ return binder::Status::fromStatusT(error);
+ }
+ return binder::Status::ok();
+}
+
+binder::Status VirtualTouchpadService::touch(int touchpad, float x, float y,
+ float pressure) {
+ if (!CheckPermissions()) {
+ return binder::Status::fromStatusT(PERMISSION_DENIED);
+ }
+ if (const status_t error = touchpad_->Touch(touchpad, x, y, pressure)) {
+ return binder::Status::fromStatusT(error);
+ }
+ return binder::Status::ok();
}
binder::Status VirtualTouchpadService::buttonState(int touchpad, int buttons) {
- const status_t error = touchpad_->ButtonState(touchpad, buttons);
- return error ? binder::Status::fromStatusT(error) : binder::Status::ok();
+ if (!CheckPermissions()) {
+ return binder::Status::fromStatusT(PERMISSION_DENIED);
+ }
+ if (const status_t error = touchpad_->ButtonState(touchpad, buttons)) {
+ return binder::Status::fromStatusT(error);
+ }
+ return binder::Status::ok();
+}
+
+status_t VirtualTouchpadService::dump(
+ int fd, const Vector<String16>& args[[gnu::unused]]) {
+ String8 result;
+ const android::IPCThreadState* ipc = android::IPCThreadState::self();
+ const pid_t pid = ipc->getCallingPid();
+ const uid_t uid = ipc->getCallingUid();
+ if ((uid != AID_SHELL) &&
+ !PermissionCache::checkPermission(kDumpPermission, pid, uid)) {
+ result.appendFormat("Permission denial: can't dump " LOG_TAG
+ " from pid=%ld, uid=%ld\n",
+ static_cast<long>(pid), static_cast<long>(uid));
+ } else {
+ result.appendFormat("[service]\nclient_pid = %ld\n\n",
+ static_cast<long>(client_pid_));
+ touchpad_->dumpInternal(result);
+ }
+ write(fd, result.string(), result.size());
+ return OK;
+}
+
+bool VirtualTouchpadService::CheckPermissions() {
+ pid_t pid;
+ if (!CheckTouchPermission(&pid)) {
+ return false;
+ }
+ if (client_pid_ != pid) {
+ ALOGE("pid=%ld is not owner", static_cast<long>(pid));
+ return false;
+ }
+ return true;
+}
+
+bool VirtualTouchpadService::CheckTouchPermission(pid_t* out_pid) {
+ const android::IPCThreadState* ipc = android::IPCThreadState::self();
+ *out_pid = ipc->getCallingPid();
+#ifdef SELINUX_ACCESS_CONTROL
+ return true;
+#else
+ const uid_t uid = ipc->getCallingUid();
+ const bool permission = PermissionCache::checkPermission(kTouchPermission, *out_pid, uid);
+ if (!permission) {
+ ALOGE("permission denied to pid=%ld uid=%ld", static_cast<long>(*out_pid),
+ static_cast<long>(uid));
+ }
+ return permission;
+#endif
}
} // namespace dvr
diff --git a/services/vr/virtual_touchpad/VirtualTouchpadService.h b/services/vr/virtual_touchpad/VirtualTouchpadService.h
index 9b880b2..194d787 100644
--- a/services/vr/virtual_touchpad/VirtualTouchpadService.h
+++ b/services/vr/virtual_touchpad/VirtualTouchpadService.h
@@ -14,17 +14,28 @@
class VirtualTouchpadService : public BnVirtualTouchpadService {
public:
VirtualTouchpadService(sp<VirtualTouchpad> touchpad)
- : touchpad_(touchpad) {}
- ~VirtualTouchpadService() override {}
+ : touchpad_(touchpad), client_pid_(0) {}
+ ~VirtualTouchpadService() override;
protected:
// Implements IVirtualTouchpadService.
+ binder::Status attach() override;
+ binder::Status detach() override;
binder::Status touch(int touchpad, float x, float y, float pressure) override;
binder::Status buttonState(int touchpad, int buttons) override;
+ // Implements BBinder::dump().
+ status_t dump(int fd, const Vector<String16>& args) override;
+
private:
+ bool CheckPermissions();
+ bool CheckTouchPermission(pid_t* out_pid);
+
sp<VirtualTouchpad> touchpad_;
+ // Only one client at a time can use the virtual touchpad.
+ pid_t client_pid_;
+
VirtualTouchpadService(const VirtualTouchpadService&) = delete;
void operator=(const VirtualTouchpadService&) = delete;
};
diff --git a/services/vr/virtual_touchpad/aidl/android/dvr/VirtualTouchpadService.aidl b/services/vr/virtual_touchpad/aidl/android/dvr/VirtualTouchpadService.aidl
index 496c5e2..9cfb186 100644
--- a/services/vr/virtual_touchpad/aidl/android/dvr/VirtualTouchpadService.aidl
+++ b/services/vr/virtual_touchpad/aidl/android/dvr/VirtualTouchpadService.aidl
@@ -6,6 +6,16 @@
const String SERVICE_NAME = "virtual_touchpad";
/**
+ * Initialize the virtual touchpad.
+ */
+ void attach() = 0;
+
+ /**
+ * Shut down the virtual touchpad.
+ */
+ void detach() = 1;
+
+ /**
* Generate a simulated touch event.
*
* @param touchpad Selects touchpad.
@@ -15,7 +25,7 @@
*
* Position values in the range [0.0, 1.0) map to the screen.
*/
- void touch(int touchpad, float x, float y, float pressure);
+ void touch(int touchpad, float x, float y, float pressure) = 2;
/**
* Generate a simulated touchpad button state event.
@@ -23,5 +33,5 @@
* @param touchpad Selects touchpad.
* @param buttons A union of MotionEvent BUTTON_* values.
*/
- void buttonState(int touchpad, int buttons);
+ void buttonState(int touchpad, int buttons) = 3;
}
diff --git a/services/vr/virtual_touchpad/include/VirtualTouchpad.h b/services/vr/virtual_touchpad/include/VirtualTouchpad.h
index d24d121..b1ee700 100644
--- a/services/vr/virtual_touchpad/include/VirtualTouchpad.h
+++ b/services/vr/virtual_touchpad/include/VirtualTouchpad.h
@@ -3,6 +3,7 @@
#include <utils/Errors.h>
#include <utils/RefBase.h>
+#include <utils/String8.h>
#include <utils/StrongPointer.h>
namespace android {
@@ -21,10 +22,18 @@
// Implementations should provide this, and hide their constructors.
// For the user, switching implementations should be as simple as changing
// the class whose |Create()| is called.
+ // Implementations should be minimial; major resource allocation should
+ // be performed in Attach().
static sp<VirtualTouchpad> Create() {
return sp<VirtualTouchpad>();
}
+ // Initialize a virtual touchpad.
+ virtual status_t Attach() = 0;
+
+ // Shut down a virtual touchpad.
+ virtual status_t Detach() = 0;
+
// Generate a simulated touch event.
//
// @param touchpad Touchpad selector index.
@@ -49,6 +58,9 @@
//
virtual status_t ButtonState(int touchpad, int buttons) = 0;
+ // Report state for 'dumpsys'.
+ virtual void dumpInternal(String8& result) = 0;
+
protected:
VirtualTouchpad() {}
~VirtualTouchpad() override {}
diff --git a/services/vr/virtual_touchpad/include/VirtualTouchpadClient.h b/services/vr/virtual_touchpad/include/VirtualTouchpadClient.h
index dd9c265..471d9e0 100644
--- a/services/vr/virtual_touchpad/include/VirtualTouchpadClient.h
+++ b/services/vr/virtual_touchpad/include/VirtualTouchpadClient.h
@@ -13,8 +13,11 @@
public:
// VirtualTouchpad implementation:
static sp<VirtualTouchpad> Create();
+ status_t Attach() override;
+ status_t Detach() override;
status_t Touch(int touchpad, float x, float y, float pressure) override;
status_t ButtonState(int touchpad, int buttons) override;
+ void dumpInternal(String8& result) override;
protected:
VirtualTouchpadClient() {}
diff --git a/services/vr/virtual_touchpad/tests/VirtualTouchpad_test.cpp b/services/vr/virtual_touchpad/tests/VirtualTouchpad_test.cpp
index 469a2d0..b11a983 100644
--- a/services/vr/virtual_touchpad/tests/VirtualTouchpad_test.cpp
+++ b/services/vr/virtual_touchpad/tests/VirtualTouchpad_test.cpp
@@ -97,7 +97,6 @@
static sp<VirtualTouchpad> Create(EvdevInjectorForTesting& injector) {
VirtualTouchpadForTesting* const touchpad = new VirtualTouchpadForTesting();
touchpad->SetEvdevInjectorForTesting(&injector);
- touchpad->Initialize();
return sp<VirtualTouchpad>(touchpad);
}
};
@@ -123,6 +122,9 @@
EvdevInjectorForTesting injector(record);
sp<VirtualTouchpad> touchpad(VirtualTouchpadForTesting::Create(injector));
+ status_t touch_status = touchpad->Attach();
+ EXPECT_EQ(0, touch_status);
+
// Check some aspects of uinput_user_dev.
const uinput_user_dev* uidev = injector.GetUiDev();
for (int i = 0; i < ABS_CNT; ++i) {
@@ -151,6 +153,7 @@
// From ConfigureKey(BTN_TOUCH):
expect.IoctlSetInt(UI_SET_EVBIT, EV_KEY);
expect.IoctlSetInt(UI_SET_KEYBIT, BTN_TOUCH);
+ expect.IoctlSetInt(UI_SET_KEYBIT, BTN_BACK);
// From ConfigureEnd():
expect.Write(uidev, sizeof(uinput_user_dev));
expect.IoctlVoid(UI_DEV_CREATE);
@@ -158,7 +161,7 @@
expect.Reset();
record.Reset();
- int touch_status = touchpad->Touch(VirtualTouchpad::PRIMARY, 0, 0, 0);
+ touch_status = touchpad->Touch(VirtualTouchpad::PRIMARY, 0, 0, 0);
EXPECT_EQ(0, touch_status);
expect.WriteInputEvent(EV_ABS, ABS_MT_SLOT, 0);
expect.WriteInputEvent(EV_ABS, ABS_MT_TRACKING_ID, 0);
@@ -180,16 +183,22 @@
expect.Reset();
record.Reset();
- touch_status = touchpad->Touch(VirtualTouchpad::PRIMARY, 1.0f, 1.0f, 1.0f);
+ touch_status = touchpad->Touch(VirtualTouchpad::PRIMARY, 0.99f, 0.99f, 0.99f);
EXPECT_EQ(0, touch_status);
expect.WriteInputEvent(EV_ABS, ABS_MT_TRACKING_ID, 0);
- expect.WriteInputEvent(EV_ABS, ABS_MT_POSITION_X, width);
- expect.WriteInputEvent(EV_ABS, ABS_MT_POSITION_Y, height);
+ expect.WriteInputEvent(EV_ABS, ABS_MT_POSITION_X, 0.99f * width);
+ expect.WriteInputEvent(EV_ABS, ABS_MT_POSITION_Y, 0.99f * height);
expect.WriteInputEvent(EV_SYN, SYN_REPORT, 0);
EXPECT_EQ(expect.GetString(), record.GetString());
expect.Reset();
record.Reset();
+ touch_status = touchpad->Touch(VirtualTouchpad::PRIMARY, 1.0f, 1.0f, 1.0f);
+ EXPECT_EQ(EINVAL, touch_status);
+ EXPECT_EQ(expect.GetString(), record.GetString());
+
+ expect.Reset();
+ record.Reset();
touch_status =
touchpad->Touch(VirtualTouchpad::PRIMARY, 0.25f, 0.75f, -0.01f);
EXPECT_EQ(0, touch_status);
@@ -224,6 +233,10 @@
expect.Reset();
record.Reset();
+ touch_status = touchpad->Detach();
+ EXPECT_EQ(0, touch_status);
+ expect.Close();
+ EXPECT_EQ(expect.GetString(), record.GetString());
}
TEST_F(VirtualTouchpadTest, Badness) {
@@ -232,11 +245,14 @@
EvdevInjectorForTesting injector(record);
sp<VirtualTouchpad> touchpad(VirtualTouchpadForTesting::Create(injector));
+ status_t touch_status = touchpad->Attach();
+ EXPECT_EQ(0, touch_status);
+
// Touch off-screen should return an error,
// and should not result in any system calls.
expect.Reset();
record.Reset();
- status_t touch_status =
+ touch_status =
touchpad->Touch(VirtualTouchpad::PRIMARY, -0.25f, 0.75f, 1.0f);
EXPECT_NE(OK, touch_status);
touch_status =
@@ -256,6 +272,10 @@
AMOTION_EVENT_BUTTON_FORWARD);
EXPECT_NE(OK, touch_status);
EXPECT_EQ(expect.GetString(), record.GetString());
+
+ // Repeated attach is an error.
+ touch_status = touchpad->Attach();
+ EXPECT_NE(0, touch_status);
}
} // namespace dvr
diff --git a/services/vr/vr_window_manager/shell_view.cpp b/services/vr/vr_window_manager/shell_view.cpp
index fae1dd9..10588b7 100644
--- a/services/vr/vr_window_manager/shell_view.cpp
+++ b/services/vr/vr_window_manager/shell_view.cpp
@@ -250,8 +250,12 @@
translate_ = Eigen::Translation3f(0, 0, -2.5f);
- if (!InitializeTouch())
- ALOGE("Failed to initialize virtual touchpad");
+ virtual_touchpad_ = VirtualTouchpadClient::Create();
+ const status_t touchpad_status = virtual_touchpad_->Attach();
+ if (touchpad_status != OK) {
+ ALOGE("Failed to connect to virtual touchpad");
+ return touchpad_status;
+ }
surface_flinger_view_.reset(new SurfaceFlingerView);
if (!surface_flinger_view_->Initialize(this))
@@ -702,22 +706,10 @@
controller_mesh_->Draw();
}
-bool ShellView::InitializeTouch() {
- virtual_touchpad_ = VirtualTouchpadClient::Create();
- if (!virtual_touchpad_.get()) {
- ALOGE("Failed to connect to virtual touchpad");
- return false;
- }
- return true;
-}
-
void ShellView::Touch() {
if (!virtual_touchpad_.get()) {
ALOGE("missing virtual touchpad");
- // Try to reconnect; useful in development.
- if (!InitializeTouch()) {
- return;
- }
+ return;
}
const android::status_t status = virtual_touchpad_->Touch(
diff --git a/services/vr/vr_window_manager/shell_view.h b/services/vr/vr_window_manager/shell_view.h
index c477669..49456c6 100644
--- a/services/vr/vr_window_manager/shell_view.h
+++ b/services/vr/vr_window_manager/shell_view.h
@@ -58,7 +58,6 @@
bool test_ime);
bool IsImeHit(const vec3& view_location, const vec3& view_direction,
vec3 *hit_location);
- bool InitializeTouch();
void Touch();
bool OnTouchpadButton(bool down, int button);
diff --git a/services/vr/vr_window_manager/vr_window_manager_binder.cpp b/services/vr/vr_window_manager/vr_window_manager_binder.cpp
index c2138b7..bd3f3ee 100644
--- a/services/vr/vr_window_manager/vr_window_manager_binder.cpp
+++ b/services/vr/vr_window_manager/vr_window_manager_binder.cpp
@@ -16,7 +16,8 @@
namespace {
const String16 kDumpPermission("android.permission.DUMP");
-const String16 kSendMeControllerInputPermission("TODO"); // TODO(kpschoedel)
+const String16 kSendMeControllerInputPermission(
+ "android.permission.RESTRICTED_VR_ACCESS");
} // anonymous namespace
constexpr size_t AshmemControllerDataProvider::kRegionLength;
@@ -136,8 +137,8 @@
int fd, const Vector<String16>& args [[gnu::unused]]) {
String8 result;
const android::IPCThreadState* ipc = android::IPCThreadState::self();
- const int pid = ipc->getCallingPid();
- const int uid = ipc->getCallingUid();
+ const pid_t pid = ipc->getCallingPid();
+ const uid_t uid = ipc->getCallingUid();
if ((uid != AID_SHELL) &&
!PermissionCache::checkPermission(kDumpPermission, pid, uid)) {
result.appendFormat("Permission denial: can't dump " LOG_TAG
diff --git a/vulkan/api/platform.api b/vulkan/api/platform.api
index b82cbb4..eb0124d 100644
--- a/vulkan/api/platform.api
+++ b/vulkan/api/platform.api
@@ -50,4 +50,8 @@
@internal type void* HWND
@internal type void* HANDLE
@internal type u32 DWORD
+@internal type u16* LPCWSTR
@internal class SECURITY_ATTRIBUTES {}
+
+// VK_USE_PLATFORM_XLIB_XRANDR_EXT
+@internal type u64 RROutput
diff --git a/vulkan/api/vulkan.api b/vulkan/api/vulkan.api
index cfeeeef..b4708b0 100644
--- a/vulkan/api/vulkan.api
+++ b/vulkan/api/vulkan.api
@@ -28,7 +28,7 @@
// API version (major.minor.patch)
define VERSION_MAJOR 1
define VERSION_MINOR 0
-define VERSION_PATCH 38
+define VERSION_PATCH 43
// API limits
define VK_MAX_PHYSICAL_DEVICE_NAME_SIZE 256
@@ -37,6 +37,9 @@
define VK_MAX_DESCRIPTION_SIZE 256
define VK_MAX_MEMORY_TYPES 32
define VK_MAX_MEMORY_HEAPS 16 /// The maximum number of unique memory heaps, each of which supporting 1 or more memory types.
+define VK_MAX_DEVICE_GROUP_SIZE_KHX 32
+define VK_LUID_SIZE_KHX 8
+define VK_QUEUE_FAMILY_EXTERNAL_KHX -2
// API keywords
define VK_TRUE 1
@@ -70,7 +73,7 @@
@extension("VK_KHR_xcb_surface") define VK_KHR_XCB_SURFACE_NAME "VK_KHR_xcb_surface"
// 7
-@extension("VK_KHR_wayland_surface") define VK_KHR_WAYLAND_SURFACE_SPEC_VERSION 5
+@extension("VK_KHR_wayland_surface") define VK_KHR_WAYLAND_SURFACE_SPEC_VERSION 6
@extension("VK_KHR_wayland_surface") define VK_KHR_WAYLAND_SURFACE_NAME "VK_KHR_wayland_surface"
// 8
@@ -90,7 +93,7 @@
@extension("VK_ANDROID_native_buffer") define VK_ANDROID_NATIVE_BUFFER_NAME "VK_ANDROID_native_buffer"
// 12
-@extension("VK_EXT_debug_report") define VK_EXT_DEBUG_REPORT_SPEC_VERSION 4
+@extension("VK_EXT_debug_report") define VK_EXT_DEBUG_REPORT_SPEC_VERSION 5
@extension("VK_EXT_debug_report") define VK_EXT_DEBUG_REPORT_NAME "VK_EXT_debug_report"
// 13
@@ -118,7 +121,7 @@
@extension("VK_AMD_shader_explicit_vertex_parameter") define VK_AMD_SHADER_EXPLICIT_VERTEX_PARAMETER_EXTENSION_NAME "VK_AMD_shader_explicit_vertex_parameter"
// 23
-@extension("VK_EXT_debug_marker") define VK_EXT_DEBUG_MARKER_SPEC_VERSION 3
+@extension("VK_EXT_debug_marker") define VK_EXT_DEBUG_MARKER_SPEC_VERSION 4
@extension("VK_EXT_debug_marker") define VK_EXT_DEBUG_MARKER_NAME "VK_EXT_debug_marker"
// 26
@@ -149,6 +152,10 @@
@extension("VK_AMD_shader_ballot") define VK_AMD_SHADER_BALLOT_SPEC_VERSION 1
@extension("VK_AMD_shader_ballot") define VK_AMD_SHADER_BALLOT_EXTENSION_NAME "VK_AMD_shader_ballot"
+// 54
+@extension("VK_KHX_multiview") define VK_KHX_MULTIVIEW_SPEC_VERSION 1
+@extension("VK_KHX_multiview") define VK_KHX_MULTIVIEW_EXTENSION_NAME "VK_KHX_multiview"
+
// 56
@extension("VK_NV_external_memory_capabilities") define VK_NV_EXTERNAL_MEMORY_CAPABILITIES_SPEC_VERSION 1
@extension("VK_NV_external_memory_capabilities") define VK_NV_EXTERNAL_MEMORY_CAPABILITIES_EXTENSION_NAME "VK_NV_external_memory_capabilities"
@@ -169,21 +176,141 @@
@extension("VK_KHR_get_physical_device_properties2") define VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION 1
@extension("VK_KHR_get_physical_device_properties2") define VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME "VK_KHR_get_physical_device_properties2"
+// 61
+@extension("VK_KHX_device_group") define VK_KHX_DEVICE_GROUP_SPEC_VERSION 1
+@extension("VK_KHX_device_group") define VK_KHX_DEVICE_GROUP_EXTENSION_NAME "VK_KHX_device_group"
+
// 62
@extension("VK_EXT_validation_flags") define VK_EXT_VALIDATION_FLAGS_SPEC_VERSION 1
@extension("VK_EXT_validation_flags") define VK_EXT_VALIDATION_FLAGS_EXTENSION_NAME "VK_EXT_validation_flags"
+// 63
+@extension("VK_NN_vi_surface") define VK_NN_VI_SURFACE_SPEC_VERSION 1
+@extension("VK_NN_vi_surface") define VK_NN_VI_SURFACE_EXTENSION_NAME "VK_NN_vi_surface"
+
+// 64
+@extension("VK_KHR_shader_draw_parameters") define VK_KHR_SHADER_DRAW_PARAMETERS_SPEC_VERSION 1
+@extension("VK_KHR_shader_draw_parameters") define VK_KHR_SHADER_DRAW_PARAMETERS_EXTENSION_NAME "VK_KHR_shader_draw_parameters"
+
+// 65
+@extension("VK_EXT_shader_subgroup_ballot") define VK_EXT_SHADER_SUBGROUP_BALLOT_SPEC_VERSION 1
+@extension("VK_EXT_shader_subgroup_ballot") define VK_EXT_SHADER_SUBGROUP_BALLOT_EXTENSION_NAME "VK_EXT_shader_subgroup_ballot"
+
+// 66
+@extension("VK_EXT_shader_subgroup_vote") define VK_EXT_SHADER_SUBGROUP_VOTE_SPEC_VERSION 1
+@extension("VK_EXT_shader_subgroup_vote") define VK_EXT_SHADER_SUBGROUP_VOTE_EXTENSION_NAME "VK_EXT_shader_subgroup_vote"
+
+// 70
+@extension("VK_KHR_maintenance1") define VK_KHR_MAINTENANCE1_SPEC_VERSION 1
+@extension("VK_KHR_maintenance1") define VK_KHR_MAINTENANCE1_EXTENSION_NAME "VK_KHR_maintenance1"
+
+// 71
+@extension("VK_KHX_device_group_creation") define VK_KHX_DEVICE_GROUP_CREATION_SPEC_VERSION 1
+@extension("VK_KHX_device_group_creation") define VK_KHX_DEVICE_GROUP_CREATION_EXTENSION_NAME "VK_KHX_device_group_creation"
+
+// 72
+@extension("VK_KHX_external_memory_capabilities") define VK_KHX_EXTERNAL_MEMORY_CAPABILITIES_SPEC_VERSION 1
+@extension("VK_KHX_external_memory_capabilities") define VK_KHX_EXTERNAL_MEMORY_CAPABILITIES_EXTENSION_NAME "VK_KHX_external_memory_capabilities"
+
+// 73
+@extension("VK_KHX_external_memory") define VK_KHX_EXTERNAL_MEMORY_SPEC_VERSION 1
+@extension("VK_KHX_external_memory") define VK_KHX_EXTERNAL_MEMORY_EXTENSION_NAME "VK_KHX_external_memory"
+
+// 74
+@extension("VK_KHX_external_memory_win32") define VK_KHX_EXTERNAL_MEMORY_WIN32_SPEC_VERSION 1
+@extension("VK_KHX_external_memory_win32") define VK_KHX_EXTERNAL_MEMORY_WIN32_EXTENSION_NAME "VK_KHX_external_memory_win32"
+
+// 75
+@extension("VK_KHX_external_memory_fd") define VK_KHX_EXTERNAL_MEMORY_FD_SPEC_VERSION 1
+@extension("VK_KHX_external_memory_fd") define VK_KHX_EXTERNAL_MEMORY_FD_EXTENSION_NAME "VK_KHX_external_memory_fd"
+
+// 76
+@extension("VK_KHX_win32_keyed_mutex") define VK_KHX_WIN32_KEYED_MUTEX_SPEC_VERSION 1
+@extension("VK_KHX_win32_keyed_mutex") define VK_KHX_WIN32_KEYED_MUTEX_EXTENSION_NAME "VK_KHX_win32_keyed_mutex"
+
+// 77
+@extension("VK_KHX_external_semaphore_capabilities") define VK_KHX_EXTERNAL_SEMAPHORE_CAPABILITIES_SPEC_VERSION 1
+@extension("VK_KHX_external_semaphore_capabilities") define VK_KHX_EXTERNAL_SEMAPHORE_CAPABILITIES_EXTENSION_NAME "VK_KHX_external_semaphore_capabilities"
+
+// 78
+@extension("VK_KHX_external_semaphore") define VK_KHX_EXTERNAL_SEMAPHORE_SPEC_VERSION 1
+@extension("VK_KHX_external_semaphore") define VK_KHX_EXTERNAL_SEMAPHORE_EXTENSION_NAME "VK_KHX_external_semaphore"
+
+// 79
+@extension("VK_KHX_external_semaphore_win32") define VK_KHX_EXTERNAL_SEMAPHORE_WIN32_SPEC_VERSION 1
+@extension("VK_KHX_external_semaphore_win32") define VK_KHX_EXTERNAL_SEMAPHORE_WIN32_EXTENSION_NAME "VK_KHX_external_semaphore_win32"
+
+// 80
+@extension("VK_KHX_external_semaphore_fd") define VK_KHX_EXTERNAL_SEMAPHORE_FD_SPEC_VERSION 1
+@extension("VK_KHX_external_semaphore_fd") define VK_KHX_EXTERNAL_SEMAPHORE_FD_EXTENSION_NAME "VK_KHX_external_semaphore_fd"
+
+// 81
+@extension("VK_KHR_push_descriptor") define VK_KHR_PUSH_DESCRIPTOR_SPEC_VERSION 1
+@extension("VK_KHR_push_descriptor") define VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME "VK_KHR_push_descriptor"
+
// 85
@extension("VK_KHR_incremental_present") define VK_KHR_INCREMENTAL_PRESENT_SPEC_VERSION 1
@extension("VK_KHR_incremental_present") define VK_KHR_INCREMENTAL_PRESENT_NAME "VK_KHR_incremental_present"
+// 86
+@extension("VK_KHR_descriptor_update_template") define VK_KHR_DESCRIPTOR_UPDATE_TEMPLATE_SPEC_VERSION 1
+@extension("VK_KHR_descriptor_update_template") define VK_KHR_DESCRIPTOR_UPDATE_TEMPLATE_EXTENSION_NAME "VK_KHR_descriptor_update_template"
+
// 87
@extension("VK_NVX_device_generated_commands") define VK_NVX_DEVICE_GENERATED_COMMANDS_SPEC_VERSION 1
@extension("VK_NVX_device_generated_commands") define VK_NVX_DEVICE_GENERATED_COMMANDS_EXTENSION_NAME "VK_NVX_device_generated_commands"
+// 88
+@extension("VK_NV_clip_space_w_scaling") define VK_NV_CLIP_SPACE_W_SCALING_SPEC_VERSION 1
+@extension("VK_NV_clip_space_w_scaling") define VK_NV_CLIP_SPACE_W_SCALING_EXTENSION_NAME "VK_NV_clip_space_w_scaling"
+
+// 89
+@extension("VK_EXT_direct_mode_display") define VK_EXT_DIRECT_MODE_DISPLAY_SPEC_VERSION 1
+@extension("VK_EXT_direct_mode_display") define VK_EXT_DIRECT_MODE_DISPLAY_EXTENSION_NAME "VK_EXT_direct_mode_display"
+
+// 90
+@extension("VK_EXT_acquire_xlib_display") define VK_EXT_ACQUIRE_XLIB_DISPLAY_SPEC_VERSION 1
+@extension("VK_EXT_acquire_xlib_display") define VK_EXT_ACQUIRE_XLIB_DISPLAY_EXTENSION_NAME "VK_EXT_acquire_xlib_display"
+
+// 91
+@extension("VK_EXT_display_surface_counter") define VK_EXT_DISPLAY_SURFACE_COUNTER_SPEC_VERSION 1
+@extension("VK_EXT_display_surface_counter") define VK_EXT_DISPLAY_SURFACE_COUNTER_EXTENSION_NAME "VK_EXT_display_surface_counter"
+
+// 92
+@extension("VK_EXT_display_control") define VK_EXT_DISPLAY_CONTROL_SPEC_VERSION 1
+@extension("VK_EXT_display_control") define VK_EXT_DISPLAY_CONTROL_COUNTER_EXTENSION_NAME "VK_EXT_display_control"
+
// 93
@extension("VK_GOOGLE_display_timing") define VK_GOOGLE_DISPLAY_TIMING_SPEC_VERSION 1
-@extension("VK_GOOGLE_display_timing") define VK_GOOGLE_DISPLAY_TIMING_NAME "VK_GOOGLE_display_timing"
+@extension("VK_GOOGLE_display_timing") define VK_GOOGLE_DISPLAY_TIMING_EXTENSION_NAME "VK_GOOGLE_display_timing"
+
+// 95
+@extension("VK_NV_sample_mask_override_coverage") define VK_NV_SAMPLE_MASK_OVERRIDE_COVERAGE_SPEC_VERSION 1
+@extension("VK_NV_sample_mask_override_coverage") define VK_NV_SAMPLE_MASK_OVERRIDE_COVERAGE_EXTENSION_NAME "VK_NV_sample_mask_override_coverage"
+
+// 96
+@extension("VK_NV_geometry_shader_passthrough") define VK_NV_GEOMETRY_SHADER_PASSTHROUGH_SPEC_VERSION 1
+@extension("VK_NV_geometry_shader_passthrough") define VK_NV_GEOMETRY_SHADER_PASSTHROUGH_EXTENSION_NAME "VK_NV_geometry_shader_passthrough"
+
+// 97
+@extension("VK_NV_viewport_array2") define VK_NV_VIEWPORT_ARRAY2_SPEC_VERSION 1
+@extension("VK_NV_viewport_array2") define VK_NV_VIEWPORT_ARRAY2_EXTENSION_NAME "VK_NV_viewport_array2"
+
+// 98
+@extension("VK_NVX_multiview_per_view_attributes") define VK_NVX_MULTIVIEW_PER_VIEW_ATTRIBUTES_SPEC_VERSION 1
+@extension("VK_NVX_multiview_per_view_attributes") define VK_NVX_MULTIVIEW_PER_VIEW_ATTRIBUTES_EXTENSION_NAME "VK_NVX_multiview_per_view_attributes"
+
+// 99
+@extension("VK_NV_viewport_swizzle") define VK_NV_VIEWPORT_SWIZZLE_SPEC_VERSION 1
+@extension("VK_NV_viewport_swizzle") define VK_NV_VIEWPORT_SWIZZLE_EXTENSION_NAME "VK_NV_viewport_swizzle"
+
+// 100
+@extension("VK_EXT_discard_rectangles") define VK_EXT_DISCARD_RECTANGLES_SPEC_VERSION 1
+@extension("VK_EXT_discard_rectangles") define VK_EXT_DISCARD_RECTANGLES_EXTENSION_NAME "VK_EXT_discard_rectangles"
+
+// 105
+@extension("VK_EXT_swapchain_colorspace") define VK_EXT_SWAPCHAIN_COLORSPACE_SPEC_VERSION 1
+@extension("VK_EXT_swapchain_colorspace") define VK_EXT_SWAPCHAIN_COLORSPACE_COUNTER_EXTENSION_NAME "VK_EXT_swapchain_colorspace"
// 106
@extension("VK_EXT_hdr_metadata") define VK_EXT_HDR_METADATA_SPEC_VERSION 1
@@ -193,6 +320,14 @@
@extension("VK_KHR_shared_presentable_image") define VK_KHR_SHARED_PRESENTABLE_IMAGE_SPEC_VERSION 1
@extension("VK_KHR_shared_presentable_image") define VK_KHR_SHARED_PRESENTABLE_IMAGE_EXTENSION_NAME "VK_KHR_shared_presentable_image"
+// 123
+@extension("VK_MVK_ios_surface") define VK_MVK_IOS_SURFACE_SPEC_VERSION 1
+@extension("VK_MVK_ios_surface") define VK_MVK_IOS_SURFACE_EXTENSION_NAME "VK_MVK_ios_surface"
+
+// 124
+@extension("VK_MVK_macos_surface") define VK_MVK_MACOS_SURFACE_SPEC_VERSION 1
+@extension("VK_MVK_macos_surface") define VK_MVK_MACOS_SURFACE_EXTENSION_NAME "VK_MVK_macos_surface"
+
/////////////
// Types //
/////////////
@@ -231,15 +366,23 @@
@nonDispatchHandle type u64 VkRenderPass
@nonDispatchHandle type u64 VkPipelineCache
+// 1
@extension("VK_KHR_surface") @nonDispatchHandle type u64 VkSurfaceKHR
+// 2
@extension("VK_KHR_swapchain") @nonDispatchHandle type u64 VkSwapchainKHR
+// 3
@extension("VK_KHR_display") @nonDispatchHandle type u64 VkDisplayKHR
@extension("VK_KHR_display") @nonDispatchHandle type u64 VkDisplayModeKHR
+// 12
@extension("VK_EXT_debug_report") @nonDispatchHandle type u64 VkDebugReportCallbackEXT
+// 86
+@extension("VK_KHR_descriptor_update_template") @nonDispatchHandle type u64 VkDescriptorUpdateTemplateKHR
+
+// 87
@extension("VK_NVX_device_generated_commands") @nonDispatchHandle type u64 VkObjectTableNVX
@extension("VK_NVX_device_generated_commands") @nonDispatchHandle type u64 VkIndirectCommandsLayoutNVX
@@ -259,7 +402,7 @@
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL = 0x00000007, /// Optimal layout when image is used only as destination of transfer operations
VK_IMAGE_LAYOUT_PREINITIALIZED = 0x00000008, /// Initial layout used when the data is populated by the CPU
- //@extension("VK_KHR_swapchain")
+ //@extension("VK_KHR_swapchain") // 2
VK_IMAGE_LAYOUT_PRESENT_SRC_KHR = 1000001002,
//@extension("VK_KHR_shared_presentable_image")
@@ -375,7 +518,7 @@
VK_FILTER_NEAREST = 0x00000000,
VK_FILTER_LINEAR = 0x00000001,
- //@extension("VK_IMG_filter_cubic")
+ //@extension("VK_IMG_filter_cubic") // 16
VK_FILTER_CUBIC_IMG = 1000015000,
}
@@ -687,7 +830,7 @@
VK_FORMAT_ASTC_12x12_UNORM_BLOCK = 183,
VK_FORMAT_ASTC_12x12_SRGB_BLOCK = 184,
- //@extension("VK_IMG_format_pvrtc")
+ //@extension("VK_IMG_format_pvrtc") // 28
VK_FORMAT_PVRTC1_2BPP_UNORM_BLOCK_IMG = 1000054000,
VK_FORMAT_PVRTC1_4BPP_UNORM_BLOCK_IMG = 1000054001,
VK_FORMAT_PVRTC2_2BPP_UNORM_BLOCK_IMG = 1000054002,
@@ -750,74 +893,73 @@
VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFO = 47,
VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFO = 48,
- //@extension("VK_KHR_swapchain")
+ //@extension("VK_KHR_swapchain") // 2
VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR = 1000001000,
VK_STRUCTURE_TYPE_PRESENT_INFO_KHR = 1000001001,
- //@extension("VK_KHR_display")
+ //@extension("VK_KHR_display") // 3
VK_STRUCTURE_TYPE_DISPLAY_MODE_CREATE_INFO_KHR = 1000002000,
VK_STRUCTURE_TYPE_DISPLAY_SURFACE_CREATE_INFO_KHR = 1000002001,
- //@extension("VK_KHR_display_swapchain")
+ //@extension("VK_KHR_display_swapchain") // 4
VK_STRUCTURE_TYPE_DISPLAY_DISPLAY_PRESENT_INFO_KHR = 1000003000,
- //@extension("VK_KHR_xlib_surface")
+ //@extension("VK_KHR_xlib_surface") // 5
VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR = 1000004000,
- //@extension("VK_KHR_xcb_surface")
+ //@extension("VK_KHR_xcb_surface") // 6
VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR = 1000005000,
- //@extension("VK_KHR_wayland_surface")
+ //@extension("VK_KHR_wayland_surface") // 7
VK_STRUCTURE_TYPE_WAYLAND_SURFACE_CREATE_INFO_KHR = 1000006000,
- //@extension("VK_KHR_mir_surface")
+ //@extension("VK_KHR_mir_surface") // 8
VK_STRUCTURE_TYPE_MIR_SURFACE_CREATE_INFO_KHR = 1000007000,
- //@extension("VK_KHR_android_surface")
+ //@extension("VK_KHR_android_surface") // 9
VK_STRUCTURE_TYPE_ANDROID_SURFACE_CREATE_INFO_KHR = 1000008000,
- //@extension("VK_KHR_win32_surface")
+ //@extension("VK_KHR_win32_surface") // 10
VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR = 1000009000,
- //@extension("VK_KHR_incremental_present")
- VK_STRUCTURE_TYPE_PRESENT_REGIONS_KHR = 1000084000,
-
- //@extension("VK_ANDROID_native_buffer")
+ //@extension("VK_ANDROID_native_buffer") // 11
VK_STRUCTURE_TYPE_NATIVE_BUFFER_ANDROID = 1000010000,
VK_STRUCTURE_TYPE_SWAPCHAIN_IMAGE_CREATE_INFO_ANDROID = 1000010001,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRESENTATION_PROPERTIES_ANDROID = 1000010002,
- //@extension("VK_GOOGLE_display_timing")
- VK_STRUCTURE_TYPE_PRESENT_TIMES_INFO_GOOGLE = 1000092000,
-
- //@extension("VK_EXT_debug_report")
+ //@extension("VK_EXT_debug_report") // 12
VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT = 1000011000,
- //@extension("VK_AMD_rasterization_order")
+ //@extension("VK_AMD_rasterization_order") // 19
VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_RASTERIZATION_ORDER_AMD = 1000018000,
- //@extension("VK_EXT_debug_marker")
+ //@extension("VK_EXT_debug_marker") // 23
VK_STRUCTURE_TYPE_DEBUG_MARKER_OBJECT_NAME_INFO_EXT = 1000022000,
VK_STRUCTURE_TYPE_DEBUG_MARKER_OBJECT_TAG_INFO_EXT = 1000022001,
VK_STRUCTURE_TYPE_DEBUG_MARKER_MARKER_INFO_EXT = 1000022002,
- //@extension("VK_NV_dedicated_allocation")
+ //@extension("VK_NV_dedicated_allocation") // 27
VK_STRUCTURE_TYPE_DEDICATED_ALLOCATION_IMAGE_CREATE_INFO_NV = 1000026000,
VK_STRUCTURE_TYPE_DEDICATED_ALLOCATION_BUFFER_CREATE_INFO_NV = 1000026001,
VK_STRUCTURE_TYPE_DEDICATED_ALLOCATION_MEMORY_ALLOCATE_INFO_NV = 1000026002,
- //@extension("VK_NV_external_memory")
+ //@extension("VK_KHX_multiview") // 54
+ VK_STRUCTURE_TYPE_RENDER_PASS_MULTIVIEW_CREATE_INFO_KHX = 1000053000,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_FEATURES_KHX = 1000053001,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_PROPERTIES_KHX = 1000053002,
+
+ //@extension("VK_NV_external_memory") // 57
VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO_NV = 1000056000,
VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO_NV = 1000056001,
- //@extension("VK_NV_external_memory_win32")
+ //@extension("VK_NV_external_memory_win32") // 58
VK_STRUCTURE_TYPE_IMPORT_MEMORY_WIN32_HANDLE_INFO_NV = 1000057000,
VK_STRUCTURE_TYPE_EXPORT_MEMORY_WIN32_HANDLE_INFO_NV = 1000057001,
- //@extension("VK_NV_win32_keyed_mutex")
+ //@extension("VK_NV_win32_keyed_mutex") // 59
VK_STRUCTURE_TYPE_WIN32_KEYED_MUTEX_ACQUIRE_RELEASE_INFO_NV = 1000058000,
- //@extension("VK_KHR_get_physical_device_properties2")
+ //@extension("VK_KHR_get_physical_device_properties2") // 60
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2_KHR = 1000059000,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2_KHR = 1000059001,
VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR = 1000059002,
@@ -828,19 +970,123 @@
VK_STRUCTURE_TYPE_SPARSE_IMAGE_FORMAT_PROPERTIES_2_KHR = 1000059007,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SPARSE_IMAGE_FORMAT_INFO_2_KHR = 1000059008,
- //@extension("VK_EXT_validation_flags")
+ //@extension("VK_KHX_device_group") // 61
+ VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_FLAGS_INFO_KHX = 1000060000,
+ VK_STRUCTURE_TYPE_BIND_BUFFER_MEMORY_INFO_KHX = 1000060001,
+ VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_INFO_KHX = 1000060002,
+ VK_STRUCTURE_TYPE_DEVICE_GROUP_RENDER_PASS_BEGIN_INFO_KHX = 1000060003,
+ VK_STRUCTURE_TYPE_DEVICE_GROUP_COMMAND_BUFFER_BEGIN_INFO_KHX = 1000060004,
+ VK_STRUCTURE_TYPE_DEVICE_GROUP_SUBMIT_INFO_KHX = 1000060005,
+ VK_STRUCTURE_TYPE_DEVICE_GROUP_BIND_SPARSE_INFO_KHX = 1000060006,
+ VK_STRUCTURE_TYPE_DEVICE_GROUP_PRESENT_CAPABILITIES_KHX = 1000060007,
+ VK_STRUCTURE_TYPE_IMAGE_SWAPCHAIN_CREATE_INFO_KHX = 1000060008,
+ VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_SWAPCHAIN_INFO_KHX = 1000060009,
+ VK_STRUCTURE_TYPE_ACQUIRE_NEXT_IMAGE_INFO_KHX = 1000060010,
+ VK_STRUCTURE_TYPE_DEVICE_GROUP_PRESENT_INFO_KHX = 1000060011,
+ VK_STRUCTURE_TYPE_DEVICE_GROUP_SWAPCHAIN_CREATE_INFO_KHX = 1000060012,
+
+ //@extension("VK_EXT_validation_flags") // 62
VK_STRUCTURE_TYPE_VALIDATION_FLAGS_EXT = 1000061000,
- //@extension("VK_KHR_incremental_present")
+ //@extension("VK_NN_vi_surface") // 63
+ VK_STRUCTURE_TYPE_VI_SURFACE_CREATE_INFO_NN = 1000062000,
+
+ //@extension("VK_KHX_device_group_creation") // 71
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GROUP_PROPERTIES_KHX = 1000070000,
+ VK_STRUCTURE_TYPE_DEVICE_GROUP_DEVICE_CREATE_INFO_KHX = 1000070001,
+
+ //@extension("VK_KHX_external_memory_capabilities") // 72
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO_KHX = 1000071000,
+ VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES_KHX = 1000071001,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_BUFFER_INFO_KHX = 1000071002,
+ VK_STRUCTURE_TYPE_EXTERNAL_BUFFER_PROPERTIES_KHX = 1000071003,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ID_PROPERTIES_KHX = 1000071004,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2_KHX = 1000071005,
+ VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2_KHX = 1000071006,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2_KHX = 1000071007,
+
+ //@extension("VK_KHX_external_memory") // 73
+ VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_BUFFER_CREATE_INFO_KHX = 1000072000,
+ VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO_KHX = 1000072001,
+ VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO_KHX = 1000072002,
+
+ //@extension("VK_KHX_external_memory_win32") // 74
+ VK_STRUCTURE_TYPE_IMPORT_MEMORY_WIN32_HANDLE_INFO_KHX = 1000073000,
+ VK_STRUCTURE_TYPE_EXPORT_MEMORY_WIN32_HANDLE_INFO_KHX = 1000073001,
+ VK_STRUCTURE_TYPE_MEMORY_WIN32_HANDLE_PROPERTIES_KHX = 1000073002,
+
+ //@extension("VK_KHX_external_memory_fd") // 75
+ VK_STRUCTURE_TYPE_IMPORT_MEMORY_FD_INFO_KHX = 1000074000,
+ VK_STRUCTURE_TYPE_MEMORY_FD_PROPERTIES_KHX = 1000074001,
+
+ //@extension("VK_KHX_win32_keyed_mutex") // 76
+ VK_STRUCTURE_TYPE_WIN32_KEYED_MUTEX_ACQUIRE_RELEASE_INFO_KHX = 1000075000,
+
+ //@extension("VK_KHX_external_semaphore_capabilities") // 77
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_SEMAPHORE_INFO_KHX = 1000076000,
+ VK_STRUCTURE_TYPE_EXTERNAL_SEMAPHORE_PROPERTIES_KHX = 1000076001,
+
+ //@extension("VK_KHX_external_semaphore") // 78
+ VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_CREATE_INFO_KHX = 1000077000,
+
+ //@extension("VK_KHX_external_semaphore_win32") // 79
+ VK_STRUCTURE_TYPE_IMPORT_SEMAPHORE_WIN32_HANDLE_INFO_KHX = 1000078000,
+ VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_WIN32_HANDLE_INFO_KHX = 1000078001,
+ VK_STRUCTURE_TYPE_D3D12_FENCE_SUBMIT_INFO_KHX = 1000078002,
+
+ //@extension("VK_KHX_external_semaphore_fd") // 80
+ VK_STRUCTURE_TYPE_IMPORT_SEMAPHORE_FD_INFO_KHX = 1000079000,
+
+ //@extension("VK_KHR_push_descriptor") // 81
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PUSH_DESCRIPTOR_PROPERTIES_KHR = 1000080000,
+
+ //@extension("VK_KHR_incremental_present") // 85
VK_STRUCTURE_TYPE_PRESENT_REGIONS_KHR = 1000084000,
- //@extension("VK_NVX_device_generated_commands")
+ //@extension("VK_KHR_descriptor_update_template") // 86
+ VK_STRUCTURE_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_CREATE_INFO_KHR = 1000085000,
+
+ //@extension("VK_NVX_device_generated_commands") // 87
VK_STRUCTURE_TYPE_OBJECT_TABLE_CREATE_INFO_NVX = 1000086000,
VK_STRUCTURE_TYPE_INDIRECT_COMMANDS_LAYOUT_CREATE_INFO_NVX = 1000086001,
VK_STRUCTURE_TYPE_CMD_PROCESS_COMMANDS_INFO_NVX = 1000086002,
VK_STRUCTURE_TYPE_CMD_RESERVE_SPACE_FOR_COMMANDS_INFO_NVX = 1000086003,
VK_STRUCTURE_TYPE_DEVICE_GENERATED_COMMANDS_LIMITS_NVX = 1000086004,
VK_STRUCTURE_TYPE_DEVICE_GENERATED_COMMANDS_FEATURES_NVX = 1000086005,
+
+ //@extension("VK_NV_clip_space_w_scaling") // 88
+ VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_W_SCALING_STATE_CREATE_INFO_NV = 1000087000,
+
+ //@extension("VK_EXT_display_surface_counter") // 91
+ VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES2_EXT = 1000090000,
+
+ //@extension("VK_EXT_display_control") // 92
+ VK_STRUCTURE_TYPE_DISPLAY_POWER_INFO_EXT = 1000091000,
+ VK_STRUCTURE_TYPE_DEVICE_EVENT_INFO_EXT = 1000091001,
+ VK_STRUCTURE_TYPE_DISPLAY_EVENT_INFO_EXT = 1000091002,
+ VK_STRUCTURE_TYPE_SWAPCHAIN_COUNTER_CREATE_INFO_EXT = 1000091003,
+
+ //@extension("VK_GOOGLE_display_timing") // 93
+ VK_STRUCTURE_TYPE_PRESENT_TIMES_INFO_GOOGLE = 1000092000,
+
+ //@extension("VK_NVX_multiview_per_view_attributes") // 98
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_PER_VIEW_ATTRIBUTES_PROPERTIES_NVX = 1000097000,
+
+ //@extension("VK_NV_viewport_swizzle") // 99
+ VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_SWIZZLE_STATE_CREATE_INFO_NV = 1000098000,
+
+ //@extension("VK_EXT_discard_rectangles") // 100
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DISCARD_RECTANGLE_PROPERTIES_EXT = 1000099000,
+ VK_STRUCTURE_TYPE_PIPELINE_DISCARD_RECTANGLE_STATE_CREATE_INFO_EXT = 1000099001,
+
+ //@extension("VK_EXT_hdr_metadata") // 106
+ VK_STRUCTURE_TYPE_HDR_METADATA_EXT = 1000105000,
+
+ //@extension("VK_MVK_ios_surface") // 123
+ VK_STRUCTURE_TYPE_IOS_SURFACE_CREATE_INFO_MVK = 1000122000,
+
+ //@extension("VK_MVK_macos_surface") // 124
+ VK_STRUCTURE_TYPE_MACOS_SURFACE_CREATE_INFO_MVK = 1000123000,
}
enum VkSubpassContents {
@@ -863,7 +1109,7 @@
VK_EVENT_RESET = 4,
VK_INCOMPLETE = 5,
- //@extension("VK_KHR_swapchain")
+ //@extension("VK_KHR_swapchain") // 2
VK_SUBOPTIMAL_KHR = 1000001003,
// Error codes (negative values)
@@ -880,23 +1126,27 @@
VK_ERROR_FORMAT_NOT_SUPPORTED = 0xFFFFFFF5, // -11
VK_ERROR_FRAGMENTED_POOL = 0xFFFFFFF4, // -12
- //@extension("VK_KHR_surface")
+ //@extension("VK_KHR_surface") // 1
VK_ERROR_SURFACE_LOST_KHR = 0xC4653600, // -1000000000
+ VK_ERROR_NATIVE_WINDOW_IN_USE_KHR = 0xC46535FF, // -1000000001
- //@extension("VK_KHR_surface")
- VK_ERROR_NATIVE_WINDOW_IN_USE_KHR = 0xC46535FF, // -1000008001
-
- //@extension("VK_KHR_swapchain")
+ //@extension("VK_KHR_swapchain") // 2
VK_ERROR_OUT_OF_DATE_KHR = 0xC4653214, // -1000001004
- //@extension("VK_KHR_display_swapchain")
+ //@extension("VK_KHR_display_swapchain") // 4
VK_ERROR_INCOMPATIBLE_DISPLAY_KHR = 0xC4652A47, // -1000003001
- //@extension("VK_EXT_debug_report")
+ //@extension("VK_EXT_debug_report") // 12
VK_ERROR_VALIDATION_FAILED_EXT = 0xC4650B07, // -1000011001
- //@extension("VK_NV_glsl_shader")
+ //@extension("VK_NV_glsl_shader") // 13
VK_ERROR_INVALID_SHADER_NV = 0xC4650720, // -1000012000
+
+ //@extension("VK_KHR_maintenance1") // 70
+ VK_ERROR_OUT_OF_POOL_MEMORY_KHR = 0xC4642878, // -1000069000
+
+ //@extension("VK_KHX_external_memory") // 73
+ VK_ERROR_INVALID_EXTERNAL_HANDLE_KHX = 0xC4641CBD, // -1000072003
}
enum VkDynamicState {
@@ -909,23 +1159,31 @@
VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK = 0x00000006,
VK_DYNAMIC_STATE_STENCIL_WRITE_MASK = 0x00000007,
VK_DYNAMIC_STATE_STENCIL_REFERENCE = 0x00000008,
+
+ //@extension("VK_NV_clip_space_w_scaling") // 88
+ VK_DYNAMIC_STATE_VIEWPORT_W_SCALING_NV = 1000087000,
+
+ //@extension("VK_EXT_discard_rectangles") // 100
+ VK_DYNAMIC_STATE_DISCARD_RECTANGLE_EXT = 1000099000,
}
-@extension("VK_KHR_surface")
+@extension("VK_KHR_surface") // 1
enum VkPresentModeKHR {
VK_PRESENT_MODE_IMMEDIATE_KHR = 0x00000000,
VK_PRESENT_MODE_MAILBOX_KHR = 0x00000001,
VK_PRESENT_MODE_FIFO_KHR = 0x00000002,
VK_PRESENT_MODE_FIFO_RELAXED_KHR = 0x00000003,
+
//@extension("VK_KHR_shared_presentable_image")
- VK_PRESENT_MODE_SHARED_DEMAND_REFRESH_KHR = 1000111000,
- //@extension("VK_KHR_shared_presentable_image")
- VK_PRESENT_MODE_SHARED_CONTINUOUS_REFRESH_KHR = 1000111001,
+ VK_PRESENT_MODE_SHARED_DEMAND_REFRESH_KHR = 1000111000,
+ VK_PRESENT_MODE_SHARED_CONTINUOUS_REFRESH_KHR = 1000111001,
}
-@extension("VK_KHR_surface")
+@extension("VK_KHR_surface") // 1
enum VkColorSpaceKHR {
VK_COLORSPACE_SRGB_NONLINEAR_KHR = 0x00000000,
+
+ //@extension("VK_EXT_swapchain_colorspace")
VK_COLOR_SPACE_DISPLAY_P3_LINEAR_EXT = 1000104001,
VK_COLOR_SPACE_DISPLAY_P3_NONLINEAR_EXT = 1000104002,
VK_COLOR_SPACE_SCRGB_LINEAR_EXT = 1000104003,
@@ -940,7 +1198,7 @@
VK_COLOR_SPACE_ADOBERGB_NONLINEAR_EXT = 1000104012,
}
-@extension("VK_EXT_debug_report")
+@extension("VK_EXT_debug_report") // 12
enum VkDebugReportObjectTypeEXT {
VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT = 0,
VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT = 1,
@@ -977,24 +1235,30 @@
VK_DEBUG_REPORT_OBJECT_TYPE_INDIRECT_COMMANDS_LAYOUT_NVX_EXT = 32,
}
-@extension("VK_EXT_debug_report")
+@extension("VK_EXT_debug_report") // 12
enum VkDebugReportErrorEXT {
VK_DEBUG_REPORT_ERROR_NONE_EXT = 0,
VK_DEBUG_REPORT_ERROR_CALLBACK_REF_EXT = 1,
}
-@extension("VK_AMD_rasterization_order")
+@extension("VK_AMD_rasterization_order") // 19
enum VkRasterizationOrderAMD {
VK_RASTERIZATION_ORDER_STRICT_AMD = 0,
VK_RASTERIZATION_ORDER_RELAXED_AMD = 1,
}
-@extension("VK_EXT_validation_flags")
+@extension("VK_EXT_validation_flags") // 62
enum VkValidationCheckEXT {
VK_VALIDATION_CHECK_ALL_EXT = 0,
}
-@extension("VK_NVX_device_generated_commands")
+@extension("VK_KHR_descriptor_update_template") // 86
+enum VkDescriptorUpdateTemplateTypeKHR {
+ VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET_KHR = 0,
+ VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_PUSH_DESCRIPTORS_KHR = 1,
+}
+
+@extension("VK_NVX_device_generated_commands") // 87
enum VkIndirectCommandsTokenTypeNVX {
VK_INDIRECT_COMMANDS_TOKEN_PIPELINE_NVX = 0,
VK_INDIRECT_COMMANDS_TOKEN_DESCRIPTOR_SET_NVX = 1,
@@ -1006,7 +1270,7 @@
VK_INDIRECT_COMMANDS_TOKEN_DISPATCH_NVX = 7,
}
-@extension("VK_NVX_device_generated_commands")
+@extension("VK_NVX_device_generated_commands") // 87
enum VkObjectEntryTypeNVX {
VK_OBJECT_ENTRY_DESCRIPTOR_SET_NVX = 0,
VK_OBJECT_ENTRY_PIPELINE_NVX = 1,
@@ -1015,6 +1279,41 @@
VK_OBJECT_ENTRY_PUSH_CONSTANT_NVX = 4,
}
+@extension("VK_EXT_display_control") // 92
+enum VkDisplayPowerStateEXT {
+ VK_DISPLAY_POWER_STATE_OFF_EXT = 0,
+ VK_DISPLAY_POWER_STATE_SUSPEND_EXT = 1,
+ VK_DISPLAY_POWER_STATE_ON_EXT = 2,
+}
+
+@extension("VK_EXT_display_control") // 92
+enum VkDeviceEventTypeEXT {
+ VK_DEVICE_EVENT_TYPE_DISPLAY_HOTPLUG_EXT = 0,
+}
+
+@extension("VK_EXT_display_control") // 92
+enum VkDisplayEventTypeEXT {
+ VK_DISPLAY_EVENT_TYPE_FIRST_PIXEL_OUT_EXT = 0,
+}
+
+@extension("VK_NV_viewport_swizzle") // 99
+enum VkViewportCoordinateSwizzleNV {
+ VK_VIEWPORT_COORDINATE_SWIZZLE_POSITIVE_X_NV = 0,
+ VK_VIEWPORT_COORDINATE_SWIZZLE_NEGATIVE_X_NV = 1,
+ VK_VIEWPORT_COORDINATE_SWIZZLE_POSITIVE_Y_NV = 2,
+ VK_VIEWPORT_COORDINATE_SWIZZLE_NEGATIVE_Y_NV = 3,
+ VK_VIEWPORT_COORDINATE_SWIZZLE_POSITIVE_Z_NV = 4,
+ VK_VIEWPORT_COORDINATE_SWIZZLE_NEGATIVE_Z_NV = 5,
+ VK_VIEWPORT_COORDINATE_SWIZZLE_POSITIVE_W_NV = 6,
+ VK_VIEWPORT_COORDINATE_SWIZZLE_NEGATIVE_W_NV = 7,
+}
+
+@extension("VK_EXT_discard_rectangles") // 100
+enum VkDiscardRectangleModeEXT {
+ VK_DISCARD_RECTANGLE_MODE_INCLUSIVE_EXT = 0,
+ VK_DISCARD_RECTANGLE_MODE_EXCLUSIVE_EXT = 1,
+}
+
/////////////////
// Bitfields //
/////////////////
@@ -1042,6 +1341,9 @@
type VkFlags VkMemoryHeapFlags
bitfield VkMemoryHeapFlagBits {
VK_MEMORY_HEAP_DEVICE_LOCAL_BIT = 0x00000001,
+
+ //@extension("VK_KHX_device_group_creation") // 71
+ VK_MEMORY_HEAP_MULTI_INSTANCE_BIT_KHX = 0x00000002,
}
/// Access flags
@@ -1065,7 +1367,7 @@
VK_ACCESS_MEMORY_READ_BIT = 0x00008000,
VK_ACCESS_MEMORY_WRITE_BIT = 0x00010000,
- //@extension("VK_NVX_device_generated_commands")
+ //@extension("VK_NVX_device_generated_commands") // 87
VK_ACCESS_COMMAND_PROCESS_READ_BIT_NVX = 0x00020000,
VK_ACCESS_COMMAND_PROCESS_WRITE_BIT_NVX = 0x00040000,
}
@@ -1138,6 +1440,12 @@
VK_IMAGE_CREATE_SPARSE_ALIASED_BIT = 0x00000004, /// Image should support constent data access to physical memory blocks mapped into multiple locations of sparse images
VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT = 0x00000008, /// Allows image views to have different format than the base image
VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT = 0x00000010, /// Allows creating image views with cube type from the created image
+
+ //@extension("VK_KHR_maintenance1") // 70
+ VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT_KHR = 0x00000020,
+
+ //@extension("VK_KHX_device_group") // 61
+ VK_IMAGE_CREATE_BIND_SFR_BIT_KHX = 0x00000040,
}
/// Image view creation flags
@@ -1151,6 +1459,10 @@
VK_PIPELINE_CREATE_DISABLE_OPTIMIZATION_BIT = 0x00000001,
VK_PIPELINE_CREATE_ALLOW_DERIVATIVES_BIT = 0x00000002,
VK_PIPELINE_CREATE_DERIVATIVE_BIT = 0x00000004,
+
+ //@extension("VK_KHX_device_group") // 61
+ VK_PIPELINE_CREATE_VIEW_INDEX_FROM_DEVICE_INDEX_BIT_KHX = 0x00000008,
+ VK_PIPELINE_CREATE_DISPATCH_BASE_KHX = 0x00000010,
}
/// Color component flags
@@ -1190,8 +1502,12 @@
VK_FORMAT_FEATURE_BLIT_DST_BIT = 0x00000800, /// Format can be used as the destination image of blits with vkCommandBlitImage
VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT = 0x00001000,
- //@extension("VK_IMG_filter_cubic")
+ //@extension("VK_IMG_filter_cubic") // 16
VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_CUBIC_BIT_IMG = 0x00002000,
+
+ //@extension("VK_KHR_maintenance1") // 70
+ VK_FORMAT_FEATURE_TRANSFER_SRC_BIT_KHR = 0x00004000,
+ VK_FORMAT_FEATURE_TRANSFER_DST_BIT_KHR = 0x00008000,
}
/// Query control flags
@@ -1293,7 +1609,7 @@
VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT = 0x00008000, /// All stages of the graphics pipeline
VK_PIPELINE_STAGE_ALL_COMMANDS_BIT = 0x00010000, /// All graphics, compute, copy, and transition commands
- //@extension("VK_NVX_device_generated_commands")
+ //@extension("VK_NVX_device_generated_commands") // 87
VK_PIPELINE_STAGE_COMMAND_PROCESS_BIT_NVX = 0x00020000,
}
@@ -1306,6 +1622,9 @@
/// Subpass description flags
type VkFlags VkSubpassDescriptionFlags
bitfield VkSubpassDescriptionFlagBits {
+ //@extension("VK_NVX_multiview_per_view_attributes") // 98
+ VK_SUBPASS_DESCRIPTION_PER_VIEW_ATTRIBUTES_BIT_NVX = 0x00000001,
+ VK_SUBPASS_DESCRIPTION_PER_VIEW_POSITION_X_ONLY_BIT_NVX = 0x00000002,
}
/// Command pool creation flags
@@ -1381,8 +1700,10 @@
/// Descriptor set layout creation flags
type VkFlags VkDescriptorSetLayoutCreateFlags
-//bitfield VkDescriptorSetLayoutCreateFlagBits {
-//}
+bitfield VkDescriptorSetLayoutCreateFlagBits {
+ //@extension("VK_KHR_push_descriptor") // 81
+ VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR = 0x00000001,
+}
/// Pipeline vertex input state creation flags
type VkFlags VkPipelineVertexInputStateCreateFlags
@@ -1453,6 +1774,12 @@
type VkFlags VkDependencyFlags
bitfield VkDependencyFlagBits {
VK_DEPENDENCY_BY_REGION_BIT = 0x00000001,
+
+ //@extension("VK_KHX_multiview") // 54
+ VK_DEPENDENCY_VIEW_LOCAL_BIT_KHX = 0x00000002,
+
+ //@extension("VK_KHX_device_group") // 61
+ VK_DEPENDENCY_DEVICE_GROUP_BIT_KHX = 0x00000004,
}
/// Cull mode flags
@@ -1464,9 +1791,9 @@
VK_CULL_MODE_FRONT_AND_BACK = 0x00000003,
}
-@extension("VK_KHR_surface")
+@extension("VK_KHR_surface") // 1
type VkFlags VkSurfaceTransformFlagsKHR
-@extension("VK_KHR_surface")
+@extension("VK_KHR_surface") // 1
bitfield VkSurfaceTransformFlagBitsKHR {
VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR = 0x00000001,
VK_SURFACE_TRANSFORM_ROTATE_90_BIT_KHR = 0x00000002,
@@ -1479,9 +1806,9 @@
VK_SURFACE_TRANSFORM_INHERIT_BIT_KHR = 0x00000100,
}
-@extension("VK_KHR_surface")
+@extension("VK_KHR_surface") // 1
type VkFlags VkCompositeAlphaFlagsKHR
-@extension("VK_KHR_surface")
+@extension("VK_KHR_surface") // 1
bitfield VkCompositeAlphaFlagBitsKHR {
VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR = 0x00000001,
VK_COMPOSITE_ALPHA_PRE_MULTIPLIED_BIT_KHR = 0x00000002,
@@ -1489,15 +1816,17 @@
VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR = 0x00000008,
}
-@extension("VK_KHR_swapchain")
+@extension("VK_KHR_swapchain") // 2
type VkFlags VkSwapchainCreateFlagsKHR
-//@extension("VK_KHR_swapchain")
-//bitfield VkSwapchainCreateFlagBitsKHR {
-//}
+@extension("VK_KHR_swapchain") // 2
+bitfield VkSwapchainCreateFlagBitsKHR {
+ //@extension("VK_KHX_device_group") // 61
+ VK_SWAPCHAIN_CREATE_BIND_SFR_BIT_KHX = 0x00000001,
+}
-@extension("VK_KHR_display")
+@extension("VK_KHR_display") // 3
type VkFlags VkDisplayPlaneAlphaFlagsKHR
-@extension("VK_KHR_display")
+@extension("VK_KHR_display") // 3
bitfield VkDisplayPlaneAlphaFlagBitsKHR {
VK_DISPLAY_PLANE_ALPHA_OPAQUE_BIT_KHR = 0x00000001,
VK_DISPLAY_PLANE_ALPHA_GLOBAL_BIT_KHR = 0x00000002,
@@ -1505,64 +1834,64 @@
VK_DISPLAY_PLANE_ALPHA_PER_PIXEL_PREMULTIPLIED_BIT_KHR = 0x00000008,
}
-@extension("VK_KHR_display")
+@extension("VK_KHR_display") // 3
type VkFlags VkDisplaySurfaceCreateFlagsKHR
-//@extension("VK_KHR_display")
+//@extension("VK_KHR_display") // 3
//bitfield VkDisplaySurfaceCreateFlagBitsKHR {
//}
-@extension("VK_KHR_display")
+@extension("VK_KHR_display") // 3
type VkFlags VkDisplayModeCreateFlagsKHR
-//@extension("VK_KHR_display")
+//@extension("VK_KHR_display") // 3
//bitfield VkDisplayModeCreateFlagBitsKHR {
//}
-@extension("VK_KHR_xlib_surface")
+@extension("VK_KHR_xlib_surface") // 5
type VkFlags VkXlibSurfaceCreateFlagsKHR
-//@extension("VK_KHR_xlib_surface")
+//@extension("VK_KHR_xlib_surface") // 5
//bitfield VkXlibSurfaceCreateFlagBitsKHR {
//}
-@extension("VK_KHR_xcb_surface")
+@extension("VK_KHR_xcb_surface") // 6
type VkFlags VkXcbSurfaceCreateFlagsKHR
-//@extension("VK_KHR_xcb_surface")
+//@extension("VK_KHR_xcb_surface") // 6
//bitfield VkXcbSurfaceCreateFlagBitsKHR {
//}
-@extension("VK_KHR_wayland_surface")
+@extension("VK_KHR_wayland_surface") // 7
type VkFlags VkWaylandSurfaceCreateFlagsKHR
-//@extension("VK_KHR_wayland_surface")
+//@extension("VK_KHR_wayland_surface") // 7
//bitfield VkWaylandSurfaceCreateFlagBitsKHR {
//}
-@extension("VK_KHR_mir_surface")
+@extension("VK_KHR_mir_surface") // 8
type VkFlags VkMirSurfaceCreateFlagsKHR
-//@extension("VK_KHR_mir_surface")
+//@extension("VK_KHR_mir_surface") // 8
//bitfield VkMirSurfaceCreateFlagBitsKHR {
//}
-@extension("VK_KHR_android_surface")
+@extension("VK_KHR_android_surface") // 9
type VkFlags VkAndroidSurfaceCreateFlagsKHR
-//@extension("VK_KHR_android_surface")
+//@extension("VK_KHR_android_surface") // 9
//bitfield VkAndroidSurfaceCreateFlagBitsKHR {
//}
-@extension("VK_KHR_win32_surface")
+@extension("VK_KHR_win32_surface") // 10
type VkFlags VkWin32SurfaceCreateFlagsKHR
-//@extension("VK_KHR_win32_surface")
+//@extension("VK_KHR_win32_surface") // 10
//bitfield VkWin32SurfaceCreateFlagBitsKHR {
//}
-@extension("VK_ANDROID_native_buffer")
+@extension("VK_ANDROID_native_buffer") // 11
type VkFlags VkSwapchainImageUsageFlagsANDROID
-@extension("VK_ANDROID_native_buffer")
+@extension("VK_ANDROID_native_buffer") // 11
bitfield VkSwapchainImageUsageFlagBitsANDROID {
VK_SWAPCHAIN_IMAGE_USAGE_FLAGS_SHARED_BIT_ANDROID = 0x00000001,
}
-@extension("VK_EXT_debug_report")
+@extension("VK_EXT_debug_report") // 12
type VkFlags VkDebugReportFlagsEXT
-@extension("VK_EXT_debug_report")
+@extension("VK_EXT_debug_report") // 12
bitfield VkDebugReportFlagBitsEXT {
VK_DEBUG_REPORT_INFORMATION_BIT_EXT = 0x00000001,
VK_DEBUG_REPORT_WARNING_BIT_EXT = 0x00000002,
@@ -1571,9 +1900,9 @@
VK_DEBUG_REPORT_DEBUG_BIT_EXT = 0x00000010,
}
-@extension("VK_NV_external_memory_capabilities")
+@extension("VK_NV_external_memory_capabilities") // 56
type VkFlags VkExternalMemoryHandleTypeFlagsNV
-@extension("VK_NV_external_memory_capabilities")
+@extension("VK_NV_external_memory_capabilities") // 56
bitfield VkExternalMemoryHandleTypeFlagBitsNV {
VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT_NV = 0x00000001,
VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT_NV = 0x00000002,
@@ -1581,18 +1910,104 @@
VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_IMAGE_KMT_BIT_NV = 0x00000008,
}
-@extension("VK_NV_external_memory_capabilities")
+@extension("VK_NV_external_memory_capabilities") // 56
type VkFlags VkExternalMemoryFeatureFlagsNV
-@extension("VK_NV_external_memory_capabilities")
+@extension("VK_NV_external_memory_capabilities") // 56
bitfield VkExternalMemoryFeatureFlagBitsNV {
VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT_NV = 0x00000001,
VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT_NV = 0x00000002,
VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT_NV = 0x00000004,
}
-@extension("VK_NVX_device_generated_commands")
+@extension("VK_KHX_device_group") // 61
+type VkFlags VkPeerMemoryFeatureFlagsKHX
+@extension("VK_KHX_device_group") // 61
+bitfield VkPeerMemoryFeatureFlagBitsKHX {
+ VK_PEER_MEMORY_FEATURE_COPY_SRC_BIT_KHX = 0x00000001,
+ VK_PEER_MEMORY_FEATURE_COPY_DST_BIT_KHX = 0x00000002,
+ VK_PEER_MEMORY_FEATURE_GENERIC_SRC_BIT_KHX = 0x00000004,
+ VK_PEER_MEMORY_FEATURE_GENERIC_DST_BIT_KHX = 0x00000008,
+}
+
+@extension("VK_KHX_device_group") // 61
+type VkFlags VkMemoryAllocateFlagsKHX
+@extension("VK_KHX_device_group") // 61
+bitfield VkMemoryAllocateFlagBitsKHX {
+ VK_MEMORY_ALLOCATE_DEVICE_MASK_BIT_KHX = 0x00000001,
+}
+
+@extension("VK_KHX_device_group") // 61
+type VkFlags VkDeviceGroupPresentModeFlagsKHX
+@extension("VK_KHX_device_group") // 61
+bitfield VkDeviceGroupPresentModeFlagBitsKHX {
+ VK_DEVICE_GROUP_PRESENT_MODE_LOCAL_BIT_KHX = 0x00000001,
+ VK_DEVICE_GROUP_PRESENT_MODE_REMOTE_BIT_KHX = 0x00000002,
+ VK_DEVICE_GROUP_PRESENT_MODE_SUM_BIT_KHX = 0x00000004,
+ VK_DEVICE_GROUP_PRESENT_MODE_LOCAL_MULTI_DEVICE_BIT_KHX = 0x00000008,
+}
+
+@extension("VK_NN_vi_surface") // 63
+type VkFlags VkViSurfaceCreateFlagsNN
+//@extension("VK_NN_vi_surface") // 63
+//bitfield VkViSurfaceCreateFlagBitsNN {
+//}
+
+@extension("VK_KHR_maintenance1") // 70
+type VkFlags VkCommandPoolTrimFlagsKHR
+//@extension("VK_KHR_maintenance1") // 70
+//bitfield VkCommandPoolTrimFlagBitsKHR {
+//}
+
+@extension("VK_KHX_external_memory_capabilities") // 72
+type VkFlags VkExternalMemoryHandleTypeFlagsKHX
+@extension("VK_KHX_external_memory_capabilities") // 72
+bitfield VkExternalMemoryHandleTypeFlagBitsKHX {
+ VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT_KHX = 0x00000001,
+ VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT_KHX = 0x00000002,
+ VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT_KHX = 0x00000004,
+ VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_BIT_KHX = 0x00000008,
+ VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_KMT_BIT_KHX = 0x00000010,
+ VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_HEAP_BIT_KHX = 0x00000020,
+ VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_RESOURCE_BIT_KHX = 0x00000040,
+}
+
+@extension("VK_KHX_external_memory_capabilities") // 72
+type VkFlags VkExternalMemoryFeatureFlagsKHX
+@extension("VK_KHX_external_memory_capabilities") // 72
+bitfield VkExternalMemoryFeatureFlagBitsKHX {
+ VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT_KHX = 0x00000001,
+ VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT_KHX = 0x00000002,
+ VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT_KHX = 0x00000004,
+}
+
+@extension("VK_KHX_external_semaphore_capabilities") // 77
+type VkFlags VkExternalSemaphoreHandleTypeFlagsKHX
+@extension("VK_KHX_external_semaphore_capabilities") // 77
+bitfield VkExternalSemaphoreHandleTypeFlagBitsKHX {
+ VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT_KHX = 0x00000001
+ VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT_KHX = 0x00000002
+ VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT_KHX = 0x00000004
+ VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_D3D12_FENCE_BIT_KHX = 0x00000008
+ VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_FENCE_FD_BIT_KHX = 0x00000010
+}
+
+@extension("VK_KHX_external_semaphore_capabilities") // 77
+type VkFlags VkExternalSemaphoreFeatureFlagsKHX
+@extension("VK_KHX_external_semaphore_capabilities") // 77
+bitfield VkExternalSemaphoreFeatureFlagBitsKHX {
+ VK_EXTERNAL_SEMAPHORE_FEATURE_EXPORTABLE_BIT_KHX = 0x00000001,
+ VK_EXTERNAL_SEMAPHORE_FEATURE_IMPORTABLE_BIT_KHX = 0x00000002,
+}
+
+@extension("VK_KHR_descriptor_update_template") // 86
+type VkFlags VkDescriptorUpdateTemplateCreateFlagsKHR
+//@extension("VK_KHR_descriptor_update_template") // 86
+//bitfield VkDescriptorUpdateTemplateCreateFlagBitsKHR {
+//}
+
+@extension("VK_NVX_device_generated_commands") // 87
type VkFlags VkIndirectCommandsLayoutUsageFlagsNVX
-@extension("VK_NVX_device_generated_commands")
+@extension("VK_NVX_device_generated_commands") // 87
bitfield VkIndirectCommandsLayoutUsageFlagBitsNVX {
VK_INDIRECT_COMMANDS_LAYOUT_USAGE_UNORDERED_SEQUENCES_BIT_NVX = 0x00000001,
VK_INDIRECT_COMMANDS_LAYOUT_USAGE_SPARSE_SEQUENCES_BIT_NVX = 0x00000002,
@@ -1600,14 +2015,45 @@
VK_INDIRECT_COMMANDS_LAYOUT_USAGE_INDEXED_SEQUENCES_BIT_NVX = 0x00000008,
}
-@extension("VK_NVX_device_generated_commands")
+@extension("VK_NVX_device_generated_commands") // 87
type VkFlags VkObjectEntryUsageFlagsNVX
-@extension("VK_NVX_device_generated_commands")
+@extension("VK_NVX_device_generated_commands") // 87
bitfield VkObjectEntryUsageFlagBitsNVX {
VK_OBJECT_ENTRY_USAGE_GRAPHICS_BIT_NVX = 0x00000001,
VK_OBJECT_ENTRY_USAGE_COMPUTE_BIT_NVX = 0x00000002,
}
+@extension("VK_EXT_display_surface_counter") // 91
+type VkFlags VkSurfaceCounterFlagsEXT
+@extension("VK_EXT_display_surface_counter") // 91
+bitfield VkSurfaceCounterFlagBitsEXT {
+ VK_SURFACE_COUNTER_VBLANK_EXT = 0x00000001,
+}
+
+@extension("VK_NV_viewport_swizzle") // 99
+type VkFlags VkPipelineViewportSwizzleStateCreateFlagsNV
+//@extension("VK_NV_viewport_swizzle") // 99
+//bitfield VkPipelineViewportSwizzleStateCreateFlagBitsNV {
+//}
+
+@extension("VK_EXT_discard_rectangles") // 100
+type VkFlags VkPipelineDiscardRectangleStateCreateFlagsEXT
+//@extension("VK_EXT_discard_rectangles") // 100
+//bitfield VkPipelineDiscardRectangleStateCreateFlagBitsEXT {
+//}
+
+@extension("VK_MVK_ios_surface") // 123
+type VkFlags VkIOSSurfaceCreateFlagsMVK
+//@extension("VK_MVK_ios_surface") // 123
+//bitfield VkIOSSurfaceCreateFlagBitsMVK {
+//}
+
+@extension("VK_MVK_macos_surface") // 124
+type VkFlags VkMacOSSurfaceCreateFlagsMVK
+//@extension("VK_MVK_macos_surface") // 124
+//bitfield VkMacOSSurfaceCreateFlagBitsMVK {
+//}
+
//////////////////
// Structures //
//////////////////
@@ -2712,7 +3158,7 @@
u32 z
}
-@extension("VK_KHR_surface")
+@extension("VK_KHR_surface") // 1
class VkSurfaceCapabilitiesKHR {
u32 minImageCount
u32 maxImageCount
@@ -2726,13 +3172,13 @@
VkImageUsageFlags supportedUsageFlags
}
-@extension("VK_KHR_surface")
+@extension("VK_KHR_surface") // 1
class VkSurfaceFormatKHR {
VkFormat format
VkColorSpaceKHR colorSpace
}
-@extension("VK_KHR_swapchain")
+@extension("VK_KHR_swapchain") // 2
class VkSwapchainCreateInfoKHR {
VkStructureType sType
const void* pNext
@@ -2754,7 +3200,7 @@
VkSwapchainKHR oldSwapchain
}
-@extension("VK_KHR_swapchain")
+@extension("VK_KHR_swapchain") // 2
class VkPresentInfoKHR {
VkStructureType sType
const void* pNext
@@ -2766,7 +3212,7 @@
VkResult* pResults
}
-@extension("VK_KHR_display")
+@extension("VK_KHR_display") // 3
class VkDisplayPropertiesKHR {
VkDisplayKHR display
const char* displayName
@@ -2777,19 +3223,19 @@
VkBool32 persistentContent
}
-@extension("VK_KHR_display")
+@extension("VK_KHR_display") // 3
class VkDisplayModeParametersKHR {
VkExtent2D visibleRegion
u32 refreshRate
}
-@extension("VK_KHR_display")
+@extension("VK_KHR_display") // 3
class VkDisplayModePropertiesKHR {
VkDisplayModeKHR displayMode
VkDisplayModeParametersKHR parameters
}
-@extension("VK_KHR_display")
+@extension("VK_KHR_display") // 3
class VkDisplayModeCreateInfoKHR {
VkStructureType sType
const void* pNext
@@ -2797,13 +3243,13 @@
VkDisplayModeParametersKHR parameters
}
-@extension("VK_KHR_display")
+@extension("VK_KHR_display") // 3
class VkDisplayPlanePropertiesKHR {
VkDisplayKHR currentDisplay
u32 currentStackIndex
}
-@extension("VK_KHR_display")
+@extension("VK_KHR_display") // 3
class VkDisplayPlaneCapabilitiesKHR {
VkDisplayPlaneAlphaFlagsKHR supportedAlpha
VkOffset2D minSrcPosition
@@ -2816,7 +3262,7 @@
VkExtent2D maxDstExtent
}
-@extension("VK_KHR_display")
+@extension("VK_KHR_display") // 3
class VkDisplaySurfaceCreateInfoKHR {
VkStructureType sType
const void* pNext
@@ -2830,7 +3276,7 @@
VkExtent2D imageExtent
}
-@extension("VK_KHR_display_swapchain")
+@extension("VK_KHR_display_swapchain") // 4
class VkDisplayPresentInfoKHR {
VkStructureType sType
const void* pNext
@@ -2839,7 +3285,7 @@
VkBool32 persistent
}
-@extension("VK_KHR_xlib_surface")
+@extension("VK_KHR_xlib_surface") // 5
class VkXlibSurfaceCreateInfoKHR {
VkStructureType sType
const void* pNext
@@ -2848,7 +3294,7 @@
platform.Window window
}
-@extension("VK_KHR_xcb_surface")
+@extension("VK_KHR_xcb_surface") // 6
class VkXcbSurfaceCreateInfoKHR {
VkStructureType sType
const void* pNext
@@ -2857,7 +3303,7 @@
platform.xcb_window_t window
}
-@extension("VK_KHR_wayland_surface")
+@extension("VK_KHR_wayland_surface") // 7
class VkWaylandSurfaceCreateInfoKHR {
VkStructureType sType
const void* pNext
@@ -2866,7 +3312,7 @@
platform.wl_surface* surface
}
-@extension("VK_KHR_mir_surface")
+@extension("VK_KHR_mir_surface") // 8
class VkMirSurfaceCreateInfoKHR {
VkStructureType sType
const void* pNext
@@ -2875,7 +3321,7 @@
platform.MirSurface* mirSurface
}
-@extension("VK_KHR_android_surface")
+@extension("VK_KHR_android_surface") // 9
class VkAndroidSurfaceCreateInfoKHR {
VkStructureType sType
const void* pNext
@@ -2883,7 +3329,7 @@
platform.ANativeWindow* window
}
-@extension("VK_KHR_win32_surface")
+@extension("VK_KHR_win32_surface") // 10
class VkWin32SurfaceCreateInfoKHR {
VkStructureType sType
const void* pNext
@@ -2892,12 +3338,13 @@
platform.HWND hwnd
}
+@extension("VK_ANDROID_native_buffer") // 11
@internal class Gralloc1Usage {
u64 consumer
u64 producer
}
-@extension("VK_ANDROID_native_buffer")
+@extension("VK_ANDROID_native_buffer") // 11
class VkNativeBufferANDROID {
VkStructureType sType
const void* pNext
@@ -2908,50 +3355,21 @@
Gralloc1Usage usage2
}
-@extension("VK_ANDROID_native_buffer")
+@extension("VK_ANDROID_native_buffer") // 11
class VkSwapchainImageCreateInfoANDROID {
VkStructureType sType
const void* pNext
VkSwapchainImageUsageFlagsANDROID flags
}
-@extension("VK_ANDROID_native_buffer")
+@extension("VK_ANDROID_native_buffer") // 11
class VkPhysicalDevicePresentationPropertiesANDROID {
VkStructureType sType
void* pNext
VkBool32 sharedImage
}
-@extension("VK_GOOGLE_display_timing")
-class VkRefreshCycleDurationGOOGLE {
- u64 minRefreshDuration
- u64 maxRefreshDuration
-}
-
-@extension("VK_GOOGLE_display_timing")
-class VkPastPresentationTimingGOOGLE {
- u32 presentID
- u64 desiredPresentTime
- u64 actualPresentTime
- u64 earliestPresentTime
- u64 presentMargin
-}
-
-@extension("VK_GOOGLE_display_timing")
-class VkPresentTimeGOOGLE {
- u32 presentID
- u64 desiredPresentTime
-}
-
-@extension("VK_GOOGLE_display_timing")
-class VkPresentTimesInfoGOOGLE {
- VkStructureType sType
- const void* pNext
- u32 swapchainCount
- const VkPresentTimeGOOGLE* pTimes
-}
-
-@extension("VK_EXT_debug_report")
+@extension("VK_EXT_debug_report") // 12
class VkDebugReportCallbackCreateInfoEXT {
VkStructureType sType
const void* pNext
@@ -2960,14 +3378,14 @@
void* pUserData
}
-@extension("VK_AMD_rasterization_order")
+@extension("VK_AMD_rasterization_order") // 19
class VkPipelineRasterizationStateRasterizationOrderAMD {
VkStructureType sType
const void* pNext
VkRasterizationOrderAMD rasterizationOrder
}
-@extension("VK_EXT_debug_marker")
+@extension("VK_EXT_debug_marker") // 23
class VkDebugMarkerObjectNameInfoEXT {
VkStructureType sType
const void* pNext
@@ -2976,7 +3394,7 @@
const char* pObjectName
}
-@extension("VK_EXT_debug_marker")
+@extension("VK_EXT_debug_marker") // 23
class VkDebugMarkerObjectTagInfoEXT {
VkStructureType sType
const void* pNext
@@ -2987,7 +3405,7 @@
const void* pTag
}
-@extension("VK_EXT_debug_marker")
+@extension("VK_EXT_debug_marker") // 23
class VkDebugMarkerMarkerInfoEXT {
VkStructureType sType
const void* pNext
@@ -2995,21 +3413,21 @@
f32[4] color
}
-@extension("VK_NV_dedicated_allocation")
+@extension("VK_NV_dedicated_allocation") // 27
class VkDedicatedAllocationImageCreateInfoNV {
VkStructureType sType
const void* pNext
VkBool32 dedicatedAllocation
}
-@extension("VK_NV_dedicated_allocation")
+@extension("VK_NV_dedicated_allocation") // 27
class VkDedicatedAllocationBufferCreateInfoNV {
VkStructureType sType
const void* pNext
VkBool32 dedicatedAllocation
}
-@extension("VK_NV_dedicated_allocation")
+@extension("VK_NV_dedicated_allocation") // 27
class VkDedicatedAllocationMemoryAllocateInfoNV {
VkStructureType sType
const void* pNext
@@ -3017,7 +3435,36 @@
VkBuffer buffer
}
-@extension("VK_NV_external_memory_capabilities")
+@extension("VK_KHX_multiview") // 54
+class VkRenderPassMultiviewCreateInfoKHX {
+ VkStructureType sType
+ const void* pNext
+ u32 subpassCount
+ const u32* pViewMasks
+ u32 dependencyCount
+ const s32* pViewOffsets
+ u32 correlationMaskCount
+ const u32* pCorrelationMasks
+}
+
+@extension("VK_KHX_multiview") // 54
+class VkPhysicalDeviceMultiviewFeaturesKHX {
+ VkStructureType sType
+ void* pNext
+ VkBool32 multiview
+ VkBool32 multiviewGeometryShader
+ VkBool32 multiviewTessellationShader
+}
+
+@extension("VK_KHX_multiview") // 54
+class VkPhysicalDeviceMultiviewPropertiesKHX {
+ VkStructureType sType
+ void* pNext
+ u32 maxMultiviewViewCount
+ u32 maxMultiviewInstanceIndex
+}
+
+@extension("VK_NV_external_memory_capabilities") // 56
class VkExternalImageFormatPropertiesNV {
VkImageFormatProperties imageFormatProperties
VkExternalMemoryFeatureFlagsNV externalMemoryFeatures
@@ -3025,21 +3472,21 @@
VkExternalMemoryHandleTypeFlagsNV compatibleHandleTypes
}
-@extension("VK_NV_external_memory")
+@extension("VK_NV_external_memory") // 57
class VkExternalMemoryImageCreateInfoNV {
VkStructureType sType
const void* pNext
VkExternalMemoryHandleTypeFlagsNV handleTypes
}
-@extension("VK_NV_external_memory")
+@extension("VK_NV_external_memory") // 57
class VkExportMemoryAllocateInfoNV {
VkStructureType sType
const void* pNext
VkExternalMemoryHandleTypeFlagsNV handleTypes
}
-@extension("VK_NV_external_memory_win32")
+@extension("VK_NV_external_memory_win32") // 58
class VkImportMemoryWin32HandleInfoNV {
VkStructureType sType
const void* pNext
@@ -3047,7 +3494,7 @@
platform.HANDLE handle
}
-@extension("VK_NV_external_memory_win32")
+@extension("VK_NV_external_memory_win32") // 58
class VkExportMemoryWin32HandleInfoNV {
VkStructureType sType
const void* pNext
@@ -3055,7 +3502,7 @@
platform.DWORD dwAccess
}
-@extension("VK_NV_win32_keyed_mutex")
+@extension("VK_NV_win32_keyed_mutex") // 59
class VkWin32KeyedMutexAcquireReleaseInfoNV {
VkStructureType sType
const void* pNext
@@ -3068,35 +3515,35 @@
const u64* pReleaseKeys
}
-@extension("VK_KHR_get_physical_device_properties2")
+@extension("VK_KHR_get_physical_device_properties2") // 60
class VkPhysicalDeviceFeatures2KHR {
VkStructureType sType
void* pNext
VkPhysicalDeviceFeatures features
}
-@extension("VK_KHR_get_physical_device_properties2")
+@extension("VK_KHR_get_physical_device_properties2") // 60
class VkPhysicalDeviceProperties2KHR {
VkStructureType sType
void* pNext
VkPhysicalDeviceProperties properties
}
-@extension("VK_KHR_get_physical_device_properties2")
+@extension("VK_KHR_get_physical_device_properties2") // 60
class VkFormatProperties2KHR {
VkStructureType sType
void* pNext
VkFormatProperties formatProperties
}
-@extension("VK_KHR_get_physical_device_properties2")
+@extension("VK_KHR_get_physical_device_properties2") // 60
class VkImageFormatProperties2KHR {
VkStructureType sType
void* pNext
VkImageFormatProperties imageFormatProperties
}
-@extension("VK_KHR_get_physical_device_properties2")
+@extension("VK_KHR_get_physical_device_properties2") // 60
class VkPhysicalDeviceImageFormatInfo2KHR {
VkStructureType sType
const void* pNext
@@ -3107,28 +3554,28 @@
VkImageCreateFlags flags
}
-@extension("VK_KHR_get_physical_device_properties2")
+@extension("VK_KHR_get_physical_device_properties2") // 60
class VkQueueFamilyProperties2KHR {
VkStructureType sType
void* pNext
VkQueueFamilyProperties queueFamilyProperties
}
-@extension("VK_KHR_get_physical_device_properties2")
+@extension("VK_KHR_get_physical_device_properties2") // 60
class VkPhysicalDeviceMemoryProperties2KHR {
VkStructureType sType
void* pNext
VkPhysicalDeviceMemoryProperties memoryProperties
}
-@extension("VK_KHR_get_physical_device_properties2")
+@extension("VK_KHR_get_physical_device_properties2") // 60
class VkSparseImageFormatProperties2KHR {
VkStructureType sType
void* pNext
VkSparseImageFormatProperties properties
}
-@extension("VK_KHR_get_physical_device_properties2")
+@extension("VK_KHR_get_physical_device_properties2") // 60
class VkPhysicalDeviceSparseImageFormatInfo2KHR {
VkStructureType sType
const void* pNext
@@ -3139,7 +3586,125 @@
VkImageTiling tiling
}
-@extension("VK_EXT_validation_flags")
+@extension("VK_KHX_device_group") // 61
+class VkMemoryAllocateFlagsInfoKHX {
+ VkStructureType sType
+ const void* pNext
+ VkMemoryAllocateFlagsKHX flags
+ u32 deviceMask
+}
+
+@extension("VK_KHX_device_group") // 61
+class VkBindBufferMemoryInfoKHX {
+ VkStructureType sType
+ const void* pNext
+ VkBuffer buffer
+ VkDeviceMemory memory
+ VkDeviceSize memoryOffset
+ u32 deviceIndexCount
+ const u32* pDeviceIndices
+}
+
+@extension("VK_KHX_device_group") // 61
+class VkBindImageMemoryInfoKHX {
+ VkStructureType sType
+ const void* pNext
+ VkImage image
+ VkDeviceMemory memory
+ VkDeviceSize memoryOffset
+ u32 deviceIndexCount
+ const u32* pDeviceIndices
+ u32 SFRRectCount
+ const VkRect2D* pSFRRects
+}
+
+@extension("VK_KHX_device_group") // 61
+class VkDeviceGroupRenderPassBeginInfoKHX {
+ VkStructureType sType
+ const void* pNext
+ u32 deviceMask
+ u32 deviceRenderAreaCount
+ const VkRect2D* pDeviceRenderAreas
+}
+
+@extension("VK_KHX_device_group") // 61
+class VkDeviceGroupCommandBufferBeginInfoKHX {
+ VkStructureType sType
+ const void* pNext
+ u32 deviceMask
+}
+
+@extension("VK_KHX_device_group") // 61
+class VkDeviceGroupSubmitInfoKHX {
+ VkStructureType sType
+ const void* pNext
+ u32 waitSemaphoreCount
+ const u32* pWaitSemaphoreDeviceIndices
+ u32 commandBufferCount
+ const u32* pCommandBufferDeviceMasks
+ u32 signalSemaphoreCount
+ const u32* pSignalSemaphoreDeviceIndices
+}
+
+@extension("VK_KHX_device_group") // 61
+class VkDeviceGroupBindSparseInfoKHX {
+ VkStructureType sType
+ const void* pNext
+ u32 resourceDeviceIndex
+ u32 memoryDeviceIndex
+}
+
+@extension("VK_KHX_device_group") // 61
+class VkDeviceGroupPresentCapabilitiesKHX {
+ VkStructureType sType
+ const void* pNext
+ u32[VK_MAX_DEVICE_GROUP_SIZE_KHX] presentMask
+ VkDeviceGroupPresentModeFlagsKHX modes
+}
+
+@extension("VK_KHX_device_group") // 61
+class VkImageSwapchainCreateInfoKHX {
+ VkStructureType sType
+ const void* pNext
+ VkSwapchainKHR swapchain
+}
+
+@extension("VK_KHX_device_group") // 61
+class VkBindImageMemorySwapchainInfoKHX {
+ VkStructureType sType
+ const void* pNext
+ VkSwapchainKHR swapchain
+ u32 imageIndex
+}
+
+@extension("VK_KHX_device_group") // 61
+class VkAcquireNextImageInfoKHX {
+ VkStructureType sType
+ const void* pNext
+ VkSwapchainKHR swapchain
+ u64 timeout
+ VkSemaphore semaphore
+ VkFence fence
+ u32 deviceMask
+}
+
+@extension("VK_KHX_device_group") // 61
+class VkDeviceGroupPresentInfoKHX {
+ VkStructureType sType
+ const void* pNext
+ u32 swapchainCount
+ const u32* pDeviceMasks
+ VkDeviceGroupPresentModeFlagBitsKHX mode
+}
+
+@extension("VK_KHX_device_group") // 61
+class VkDeviceGroupSwapchainCreateInfoKHX {
+ VkStructureType sType
+ const void* pNext
+ VkDeviceGroupPresentModeFlagsKHX modes
+}
+
+@extension("VK_EXT_validation_flags") // 62
class VkValidationFlagsEXT {
VkStructureType sType
const void* pNext
@@ -3147,14 +3712,271 @@
VkValidationCheckEXT* pDisabledValidationChecks
}
-@extension("VK_NVX_device_generated_commands")
+@extension("VK_NN_vi_surface") // 63
+class VkViSurfaceCreateInfoNN {
+ VkStructureType sType
+ const void* pNext
+ VkViSurfaceCreateFlagsNN flags
+ void* window
+}
+
+@extension("VK_KHX_device_group_creation") // 71
+class VkPhysicalDeviceGroupPropertiesKHX {
+ VkStructureType sType
+ const void* pNext
+ u32 physicalDeviceCount
+ VkPhysicalDevice[VK_MAX_DEVICE_GROUP_SIZE_KHX] physicalDevices
+ VkBool32 subsetAllocation
+}
+
+@extension("VK_KHX_device_group_creation") // 71
+class VkDeviceGroupDeviceCreateInfoKHX {
+ VkStructureType sType
+ const void* pNext
+ u32 physicalDeviceCount
+ const VkPhysicalDevice* pPhysicalDevices
+}
+
+@extension("VK_KHX_external_memory_capabilities") // 72
+class VkExternalMemoryPropertiesKHX {
+ VkExternalMemoryFeatureFlagsKHX externalMemoryFeatures
+ VkExternalMemoryHandleTypeFlagsKHX exportFromImportedHandleTypes
+ VkExternalMemoryHandleTypeFlagsKHX compatibleHandleTypes
+}
+
+@extension("VK_KHX_external_memory_capabilities") // 72
+class VkPhysicalDeviceExternalImageFormatInfoKHX {
+ VkStructureType sType
+ const void* pNext
+ VkExternalMemoryHandleTypeFlagBitsKHX handleType
+}
+
+@extension("VK_KHX_external_memory_capabilities") // 72
+class VkExternalImageFormatPropertiesKHX {
+ VkStructureType sType
+ void* pNext
+ VkExternalMemoryPropertiesKHX externalMemoryProperties
+}
+
+@extension("VK_KHX_external_memory_capabilities") // 72
+class VkPhysicalDeviceExternalBufferInfoKHX {
+ VkStructureType sType
+ const void* pNext
+ VkBufferCreateFlags flags
+ VkBufferUsageFlags usage
+ VkExternalMemoryHandleTypeFlagBitsKHX handleType
+}
+
+@extension("VK_KHX_external_memory_capabilities") // 72
+class VkExternalBufferPropertiesKHX {
+ VkStructureType sType
+ void* pNext
+ VkExternalMemoryPropertiesKHX externalMemoryProperties
+}
+
+@extension("VK_KHX_external_memory_capabilities") // 72
+class VkPhysicalDeviceIDPropertiesKHX {
+ VkStructureType sType
+ void* pNext
+ u8[VK_UUID_SIZE] deviceUUID
+ u8[VK_UUID_SIZE] driverUUID
+ u8[VK_LUID_SIZE_KHX] deviceLUID
+ VkBool32 deviceLUIDValid
+}
+
+@extension("VK_KHX_external_memory") // 73
+class VkExternalMemoryImageCreateInfoKHX {
+ VkStructureType sType
+ const void* pNext
+ VkExternalMemoryHandleTypeFlagsKHX handleTypes
+}
+
+@extension("VK_KHX_external_memory") // 73
+class VkExternalMemoryBufferCreateInfoKHX {
+ VkStructureType sType
+ const void* pNext
+ VkExternalMemoryHandleTypeFlagsKHX handleTypes
+}
+
+@extension("VK_KHX_external_memory") // 73
+class VkExportMemoryAllocateInfoKHX {
+ VkStructureType sType
+ const void* pNext
+ VkExternalMemoryHandleTypeFlagsKHX handleTypes
+}
+
+@extension("VK_KHX_external_memory_win32") // 74
+class VkImportMemoryWin32HandleInfoKHX {
+ VkStructureType sType
+ const void* pNext
+ VkExternalMemoryHandleTypeFlagBitsKHX handleType
+ platform.HANDLE handle
+}
+
+@extension("VK_KHX_external_memory_win32") // 74
+class VkExportMemoryWin32HandleInfoKHX {
+ VkStructureType sType
+ const void* pNext
+ const platform.SECURITY_ATTRIBUTES* pAttributes
+ platform.DWORD dwAccess
+ platform.LPCWSTR name
+}
+
+@extension("VK_KHX_external_memory_win32") // 74
+class VkMemoryWin32HandlePropertiesKHX {
+ VkStructureType sType
+ void* pNext
+ u32 memoryTypeBits
+}
+
+@extension("VK_KHX_external_memory_fd") // 75
+class VkImportMemoryFdInfoKHX {
+ VkStructureType sType
+ const void* pNext
+ VkExternalMemoryHandleTypeFlagBitsKHX handleType
+ int fd
+}
+
+@extension("VK_KHX_external_memory_fd") // 75
+class VkMemoryFdPropertiesKHX {
+ VkStructureType sType
+ void* pNext
+ u32 memoryTypeBits
+}
+
+@extension("VK_KHX_win32_keyed_mutex") // 76
+class VkWin32KeyedMutexAcquireReleaseInfoKHX {
+ VkStructureType sType
+ const void* pNext
+ u32 acquireCount
+ const VkDeviceMemory* pAcquireSyncs
+ const u64* pAcquireKeys
+ const u32* pAcquireTimeouts
+ u32 releaseCount
+ const VkDeviceMemory* pReleaseSyncs
+ const u64* pReleaseKeys
+}
+
+@extension("VK_KHX_external_semaphore_capabilities") // 77
+class VkPhysicalDeviceExternalSemaphoreInfoKHX {
+ VkStructureType sType
+ const void* pNext
+ VkExternalSemaphoreHandleTypeFlagBitsKHX handleType
+}
+
+@extension("VK_KHX_external_semaphore_capabilities") // 77
+class VkExternalSemaphorePropertiesKHX {
+ VkStructureType sType
+ void* pNext
+ VkExternalSemaphoreHandleTypeFlagsKHX exportFromImportedHandleTypes
+ VkExternalSemaphoreHandleTypeFlagsKHX compatibleHandleTypes
+ VkExternalSemaphoreFeatureFlagsKHX externalSemaphoreFeatures
+}
+
+@extension("VK_KHX_external_semaphore") // 78
+class VkExportSemaphoreCreateInfoKHX {
+ VkStructureType sType
+ const void* pNext
+ VkExternalSemaphoreHandleTypeFlagsKHX handleTypes
+}
+
+@extension("VK_KHX_external_semaphore_win32") // 79
+class VkImportSemaphoreWin32HandleInfoKHX {
+ VkStructureType sType
+ const void* pNext
+ VkSemaphore semaphore
+ VkExternalSemaphoreHandleTypeFlagsKHX handleType
+ platform.HANDLE handle
+}
+
+@extension("VK_KHX_external_semaphore_win32") // 79
+class VkExportSemaphoreWin32HandleInfoKHX {
+ VkStructureType sType
+ const void* pNext
+ const platform.SECURITY_ATTRIBUTES* pAttributes
+ platform.DWORD dwAccess
+ platform.LPCWSTR name
+}
+
+@extension("VK_KHX_external_semaphore_win32") // 79
+class VkD3D12FenceSubmitInfoKHX {
+ VkStructureType sType
+ const void* pNext
+ u32 waitSemaphoreValuesCount
+ const u64* pWaitSemaphoreValues
+ u32 signalSemaphoreValuesCount
+ const u64* pSignalSemaphoreValues
+}
+
+@extension("VK_KHX_external_semaphore_fd") // 80
+class VkImportSemaphoreFdInfoKHX {
+ VkStructureType sType
+ const void* pNext
+ VkSemaphore semaphore
+ VkExternalSemaphoreHandleTypeFlagBitsKHX handleType
+ s32 fd
+}
+
+@extension("VK_KHR_push_descriptor") // 81
+class VkPhysicalDevicePushDescriptorPropertiesKHR {
+ VkStructureType sType
+ void* pNext
+ u32 maxPushDescriptors
+}
+
+@extension("VK_KHR_incremental_present") // 85
+class VkRectLayerKHR {
+ VkOffset2D offset
+ VkExtent2D extent
+ u32 layer
+}
+
+@extension("VK_KHR_incremental_present") // 85
+class VkPresentRegionKHR {
+ u32 rectangleCount
+ const VkRectLayerKHR* pRectangles
+}
+
+@extension("VK_KHR_incremental_present") // 85
+class VkPresentRegionsKHR {
+ VkStructureType sType
+ const void* pNext
+ u32 swapchainCount
+ const VkPresentRegionKHR* pRegions
+}
+
+@extension("VK_KHR_descriptor_update_template") // 86
+class VkDescriptorUpdateTemplateEntryKHR {
+ u32 dstBinding
+ u32 dstArrayElement
+ u32 descriptorCount
+ VkDescriptorType descriptorType
+ platform.size_t offset
+ platform.size_t stride
+}
+
+@extension("VK_KHR_descriptor_update_template") // 86
+class VkDescriptorUpdateTemplateCreateInfoKHR {
+ VkStructureType sType
+ void* pNext
+ VkDescriptorUpdateTemplateCreateFlagsKHR flags
+ u32 descriptorUpdateEntryCount
+ const VkDescriptorUpdateTemplateEntryKHR* pDescriptorUpdateEntries
+ VkDescriptorUpdateTemplateTypeKHR templateType
+ VkDescriptorSetLayout descriptorSetLayout
+ VkPipelineBindPoint pipelineBindPoint
+ VkPipelineLayout pipelineLayout
+ u32 set
+}
+
+@extension("VK_NVX_device_generated_commands") // 87
class VkDeviceGeneratedCommandsFeaturesNVX {
VkStructureType sType
const void* pNext
VkBool32 computeBindingPointSupport
}
-@extension("VK_NVX_device_generated_commands")
+@extension("VK_NVX_device_generated_commands") // 87
class VkDeviceGeneratedCommandsLimitsNVX {
VkStructureType sType
const void* pNext
@@ -3165,14 +3987,14 @@
u32 minCommandsTokenBufferOffsetAlignment
}
-@extension("VK_NVX_device_generated_commands")
+@extension("VK_NVX_device_generated_commands") // 87
class VkIndirectCommandsTokenNVX {
VkIndirectCommandsTokenTypeNVX tokenType
VkBuffer buffer
VkDeviceSize offset
}
-@extension("VK_NVX_device_generated_commands")
+@extension("VK_NVX_device_generated_commands") // 87
class VkIndirectCommandsLayoutTokenNVX {
VkIndirectCommandsTokenTypeNVX tokenType
u32 bindingUnit
@@ -3180,7 +4002,7 @@
u32 divisor
}
-@extension("VK_NVX_device_generated_commands")
+@extension("VK_NVX_device_generated_commands") // 87
class VkIndirectCommandsLayoutCreateInfoNVX {
VkStructureType sType
const void* pNext
@@ -3190,7 +4012,7 @@
const VkIndirectCommandsLayoutTokenNVX* pTokens
}
-@extension("VK_NVX_device_generated_commands")
+@extension("VK_NVX_device_generated_commands") // 87
class VkCmdProcessCommandsInfoNVX {
VkStructureType sType
const void* pNext
@@ -3206,7 +4028,7 @@
VkDeviceSize sequencesIndexOffset
}
-@extension("VK_NVX_device_generated_commands")
+@extension("VK_NVX_device_generated_commands") // 87
class VkCmdReserveSpaceForCommandsInfoNVX {
VkStructureType sType
const void* pNext
@@ -3215,7 +4037,7 @@
u32 maxSequencesCount
}
-@extension("VK_NVX_device_generated_commands")
+@extension("VK_NVX_device_generated_commands") // 87
class VkObjectTableCreateInfoNVX {
VkStructureType sType
const void* pNext
@@ -3230,20 +4052,20 @@
u32 maxPipelineLayouts
}
-@extension("VK_NVX_device_generated_commands")
+@extension("VK_NVX_device_generated_commands") // 87
class VkObjectTableEntryNVX {
VkObjectEntryTypeNVX type
VkObjectEntryUsageFlagsNVX flags
}
-@extension("VK_NVX_device_generated_commands")
+@extension("VK_NVX_device_generated_commands") // 87
class VkObjectTablePipelineEntryNVX {
VkObjectEntryTypeNVX type
VkObjectEntryUsageFlagsNVX flags
VkPipeline pipeline
}
-@extension("VK_NVX_device_generated_commands")
+@extension("VK_NVX_device_generated_commands") // 87
class VkObjectTableDescriptorSetEntryNVX {
VkObjectEntryTypeNVX type
VkObjectEntryUsageFlagsNVX flags
@@ -3251,21 +4073,22 @@
VkDescriptorSet descriptorSet
}
-@extension("VK_NVX_device_generated_commands")
+@extension("VK_NVX_device_generated_commands") // 87
class VkObjectTableVertexBufferEntryNVX {
VkObjectEntryTypeNVX type
VkObjectEntryUsageFlagsNVX flags
VkBuffer buffer
}
-@extension("VK_NVX_device_generated_commands")
+@extension("VK_NVX_device_generated_commands") // 87
class VkObjectTableIndexBufferEntryNVX {
VkObjectEntryTypeNVX type
VkObjectEntryUsageFlagsNVX flags
VkBuffer buffer
+ VkIndexType indexType
}
-@extension("VK_NVX_device_generated_commands")
+@extension("VK_NVX_device_generated_commands") // 87
class VkObjectTablePushConstantEntryNVX {
VkObjectEntryTypeNVX type
VkObjectEntryUsageFlagsNVX flags
@@ -3273,43 +4096,169 @@
VkShaderStageFlags stageFlags
}
-@extension("VK_KHR_incremental_present")
-class VkRectLayerKHR {
- VkOffset2D offset
- VkExtent2D extent
- u32 layer
+@extension("VK_NV_clip_space_w_scaling") // 88
+class VkViewportWScalingNV {
+ f32 xcoeff
+ f32 ycoeff
}
-@extension("VK_KHR_incremental_present")
-class VkPresentRegionKHR {
- u32 rectangleCount
- const VkRectLayerKHR* pRectangles
-}
-
-@extension("VK_KHR_incremental_present")
-class VkPresentRegionsKHR {
+@extension("VK_NV_clip_space_w_scaling") // 88
+class VkPipelineViewportWScalingStateCreateInfoNV {
VkStructureType sType
const void* pNext
- u32 swapchainCount
- const VkPresentRegionKHR* pRegions
+ VkBool32 viewportWScalingEnable
+ u32 viewportCount
+ const VkViewportWScalingNV* pViewportWScalings
}
-@extension("VK_EXT_hdr_metadata")
+@extension("VK_EXT_display_surface_counter") // 91
+class VkSurfaceCapabilities2EXT {
+ VkStructureType sType
+ void* pNext
+ u32 minImageCount
+ u32 maxImageCount
+ VkExtent2D currentExtent
+ VkExtent2D minImageExtent
+ VkExtent2D maxImageExtent
+ u32 maxImageArrayLayers
+ VkSurfaceTransformFlagsKHR supportedTransforms
+ VkSurfaceTransformFlagBitsKHR currentTransform
+ VkCompositeAlphaFlagsKHR supportedCompositeAlpha
+ VkImageUsageFlags supportedUsageFlags
+ VkSurfaceCounterFlagsEXT supportedSurfaceCounters
+}
+
+@extension("VK_EXT_display_control") // 92
+class VkDisplayPowerInfoEXT {
+ VkStructureType sType
+ const void* pNext
+ VkDisplayPowerStateEXT powerState
+}
+
+@extension("VK_EXT_display_control") // 92
+class VkDeviceEventInfoEXT {
+ VkStructureType sType
+ const void* pNext
+ VkDeviceEventTypeEXT deviceEvent
+}
+
+@extension("VK_EXT_display_control") // 92
+class VkDisplayEventInfoEXT {
+ VkStructureType sType
+ const void* pNext
+ VkDisplayEventTypeEXT displayEvent
+}
+
+@extension("VK_EXT_display_control") // 92
+class VkSwapchainCounterCreateInfoEXT {
+ VkStructureType sType
+ const void* pNext
+ VkSurfaceCounterFlagsEXT surfaceCounters
+}
+
+@extension("VK_GOOGLE_display_timing") // 93
+class VkRefreshCycleDurationGOOGLE {
+ u64 refreshDuration
+}
+
+@extension("VK_GOOGLE_display_timing") // 93
+class VkPastPresentationTimingGOOGLE {
+ u32 presentID
+ u64 desiredPresentTime
+ u64 actualPresentTime
+ u64 earliestPresentTime
+ u64 presentMargin
+}
+
+@extension("VK_GOOGLE_display_timing") // 93
+class VkPresentTimeGOOGLE {
+ u32 presentID
+ u64 desiredPresentTime
+}
+
+@extension("VK_GOOGLE_display_timing") // 93
+class VkPresentTimesInfoGOOGLE {
+ VkStructureType sType
+ const void* pNext
+ u32 swapchainCount
+ const VkPresentTimeGOOGLE* pTimes
+}
+
+@extension("VK_NVX_multiview_per_view_attributes") // 98
+class VkPhysicalDeviceMultiviewPerViewAttributesPropertiesNVX {
+ VkStructureType sType
+ void* pNext
+ VkBool32 perViewPositionAllComponents
+}
+
+@extension("VK_NV_viewport_swizzle") // 99
+class VkViewportSwizzleNV {
+ VkViewportCoordinateSwizzleNV x
+ VkViewportCoordinateSwizzleNV y
+ VkViewportCoordinateSwizzleNV z
+ VkViewportCoordinateSwizzleNV w
+}
+
+@extension("VK_NV_viewport_swizzle") // 99
+class VkPipelineViewportSwizzleStateCreateInfoNV {
+ VkStructureType sType
+ const void* pNext
+ VkPipelineViewportSwizzleStateCreateFlagsNV flags
+ u32 viewportCount
+ const VkViewportSwizzleNV* pViewportSwizzles
+}
+
+@extension("VK_EXT_discard_rectangles") // 100
+class VkPhysicalDeviceDiscardRectanglePropertiesEXT {
+ VkStructureType sType
+ const void* pNext
+ u32 maxDiscardRectangles
+}
+
+@extension("VK_EXT_discard_rectangles") // 100
+class VkPipelineDiscardRectangleStateCreateInfoEXT {
+ VkStructureType sType
+ const void* pNext
+ VkPipelineDiscardRectangleStateCreateFlagsEXT flags
+ VkDiscardRectangleModeEXT discardRectangleMode
+ u32 discardRectangleCount
+ const VkRect2D* pDiscardRectangles
+}
+
+@extension("VK_EXT_hdr_metadata") // 106
class VkXYColorEXT {
- f32 x
- f32 y
+ f32 x
+ f32 y
}
-@extension("VK_EXT_hdr_metadata")
+@extension("VK_EXT_hdr_metadata") // 106
class VkHdrMetadataEXT {
- VkXYColorEXT displayPrimaryRed
- VkXYColorEXT displayPrimaryGreen
- VkXYColorEXT displayPrimaryBlue
- VkXYColorEXT whitePoint
- f32 maxLuminance
- f32 minLuminance
- f32 maxContentLightLevel
- f32 maxFrameAverageLightLevel
+ VkStructureType sType
+ const void* pNext
+ VkXYColorEXT displayPrimaryRed
+ VkXYColorEXT displayPrimaryGreen
+ VkXYColorEXT displayPrimaryBlue
+ VkXYColorEXT whitePoint
+ f32 maxLuminance
+ f32 minLuminance
+ f32 maxContentLightLevel
+ f32 maxFrameAverageLightLevel
+}
+
+@extension("VK_MVK_ios_surface") // 123
+class VkIOSSurfaceCreateInfoMVK {
+ VkStructureType sType
+ const void* pNext
+ VkIOSSurfaceCreateFlagsMVK flags
+ const void* pView
+}
+
+@extension("VK_MVK_macos_surface") // 124
+class VkMacOSSurfaceCreateInfoMVK {
+ VkStructureType sType
+ const void* pNext
+ VkMacOSSurfaceCreateFlagsMVK flags
+ const void* pView
}
////////////////
@@ -5033,9 +5982,9 @@
@threadSafety("app")
cmd void vkCmdDispatch(
VkCommandBuffer commandBuffer,
- u32 x,
- u32 y,
- u32 z) {
+ u32 groupCountX,
+ u32 groupCountY,
+ u32 groupCountZ) {
commandBufferObject := GetCommandBuffer(commandBuffer)
commandBufferObject.queueFlags = AddQueueFlag(commandBufferObject.queueFlags, VK_QUEUE_COMPUTE_BIT)
@@ -5507,7 +6456,7 @@
}
}
-@extension("VK_KHR_surface")
+@extension("VK_KHR_surface") // 1
cmd void vkDestroySurfaceKHR(
VkInstance instance,
VkSurfaceKHR surface,
@@ -5519,7 +6468,7 @@
State.Surfaces[surface] = null
}
-@extension("VK_KHR_surface")
+@extension("VK_KHR_surface") // 1
cmd VkResult vkGetPhysicalDeviceSurfaceSupportKHR(
VkPhysicalDevice physicalDevice,
u32 queueFamilyIndex,
@@ -5530,7 +6479,7 @@
return ?
}
-@extension("VK_KHR_surface")
+@extension("VK_KHR_surface") // 1
cmd VkResult vkGetPhysicalDeviceSurfaceCapabilitiesKHR(
VkPhysicalDevice physicalDevice,
VkSurfaceKHR surface,
@@ -5543,7 +6492,7 @@
return ?
}
-@extension("VK_KHR_surface")
+@extension("VK_KHR_surface") // 1
cmd VkResult vkGetPhysicalDeviceSurfaceFormatsKHR(
VkPhysicalDevice physicalDevice,
VkSurfaceKHR surface,
@@ -5563,7 +6512,7 @@
return ?
}
-@extension("VK_KHR_surface")
+@extension("VK_KHR_surface") // 1
cmd VkResult vkGetPhysicalDeviceSurfacePresentModesKHR(
VkPhysicalDevice physicalDevice,
VkSurfaceKHR surface,
@@ -5583,7 +6532,7 @@
return ?
}
-@extension("VK_KHR_swapchain")
+@extension("VK_KHR_swapchain") // 2
cmd VkResult vkCreateSwapchainKHR(
VkDevice device,
const VkSwapchainCreateInfoKHR* pCreateInfo,
@@ -5599,7 +6548,7 @@
return ?
}
-@extension("VK_KHR_swapchain")
+@extension("VK_KHR_swapchain") // 2
cmd void vkDestroySwapchainKHR(
VkDevice device,
VkSwapchainKHR swapchain,
@@ -5611,7 +6560,7 @@
State.Swapchains[swapchain] = null
}
-@extension("VK_KHR_swapchain")
+@extension("VK_KHR_swapchain") // 2
cmd VkResult vkGetSwapchainImagesKHR(
VkDevice device,
VkSwapchainKHR swapchain,
@@ -5632,7 +6581,7 @@
return ?
}
-@extension("VK_KHR_swapchain")
+@extension("VK_KHR_swapchain") // 2
cmd VkResult vkAcquireNextImageKHR(
VkDevice device,
VkSwapchainKHR swapchain,
@@ -5649,7 +6598,7 @@
return ?
}
-@extension("VK_KHR_swapchain")
+@extension("VK_KHR_swapchain") // 2
cmd VkResult vkQueuePresentKHR(
VkQueue queue,
const VkPresentInfoKHR* pPresentInfo) {
@@ -5661,7 +6610,7 @@
return ?
}
-@extension("VK_KHR_display")
+@extension("VK_KHR_display") // 3
cmd VkResult vkGetPhysicalDeviceDisplayPropertiesKHR(
VkPhysicalDevice physicalDevice,
u32* pPropertyCount,
@@ -5670,7 +6619,7 @@
return ?
}
-@extension("VK_KHR_display")
+@extension("VK_KHR_display") // 3
cmd VkResult vkGetPhysicalDeviceDisplayPlanePropertiesKHR(
VkPhysicalDevice physicalDevice,
u32* pPropertyCount,
@@ -5679,7 +6628,7 @@
return ?
}
-@extension("VK_KHR_display")
+@extension("VK_KHR_display") // 3
cmd VkResult vkGetDisplayPlaneSupportedDisplaysKHR(
VkPhysicalDevice physicalDevice,
u32 planeIndex,
@@ -5689,7 +6638,7 @@
return ?
}
-@extension("VK_KHR_display")
+@extension("VK_KHR_display") // 3
cmd VkResult vkGetDisplayModePropertiesKHR(
VkPhysicalDevice physicalDevice,
VkDisplayKHR display,
@@ -5699,7 +6648,7 @@
return ?
}
-@extension("VK_KHR_display")
+@extension("VK_KHR_display") // 3
cmd VkResult vkCreateDisplayModeKHR(
VkPhysicalDevice physicalDevice,
VkDisplayKHR display,
@@ -5710,7 +6659,7 @@
return ?
}
-@extension("VK_KHR_display")
+@extension("VK_KHR_display") // 3
cmd VkResult vkGetDisplayPlaneCapabilitiesKHR(
VkPhysicalDevice physicalDevice,
VkDisplayModeKHR mode,
@@ -5720,7 +6669,7 @@
return ?
}
-@extension("VK_KHR_display")
+@extension("VK_KHR_display") // 3
cmd VkResult vkCreateDisplayPlaneSurfaceKHR(
VkInstance instance,
const VkDisplaySurfaceCreateInfoKHR* pCreateInfo,
@@ -5729,7 +6678,7 @@
return ?
}
-@extension("VK_KHR_display_swapchain")
+@extension("VK_KHR_display_swapchain") // 4
cmd VkResult vkCreateSharedSwapchainsKHR(
VkDevice device,
u32 swapchainCount,
@@ -5739,7 +6688,7 @@
return ?
}
-@extension("VK_KHR_xlib_surface")
+@extension("VK_KHR_xlib_surface") // 5
cmd VkResult vkCreateXlibSurfaceKHR(
VkInstance instance,
const VkXlibSurfaceCreateInfoKHR* pCreateInfo,
@@ -5749,7 +6698,7 @@
return ?
}
-@extension("VK_KHR_xlib_surface")
+@extension("VK_KHR_xlib_surface") // 5
cmd VkBool32 vkGetPhysicalDeviceXlibPresentationSupportKHR(
VkPhysicalDevice physicalDevice,
u32 queueFamilyIndex,
@@ -5759,7 +6708,7 @@
return ?
}
-@extension("VK_KHR_xcb_surface")
+@extension("VK_KHR_xcb_surface") // 6
cmd VkResult vkCreateXcbSurfaceKHR(
VkInstance instance,
const VkXcbSurfaceCreateInfoKHR* pCreateInfo,
@@ -5769,7 +6718,7 @@
return ?
}
-@extension("VK_KHR_xcb_surface")
+@extension("VK_KHR_xcb_surface") // 6
cmd VkBool32 vkGetPhysicalDeviceXcbPresentationSupportKHR(
VkPhysicalDevice physicalDevice,
u32 queueFamilyIndex,
@@ -5779,7 +6728,7 @@
return ?
}
-@extension("VK_KHR_wayland_surface")
+@extension("VK_KHR_wayland_surface") // 7
cmd VkResult vkCreateWaylandSurfaceKHR(
VkInstance instance,
const VkWaylandSurfaceCreateInfoKHR* pCreateInfo,
@@ -5789,7 +6738,7 @@
return ?
}
-@extension("VK_KHR_wayland_surface")
+@extension("VK_KHR_wayland_surface") // 7
cmd VkBool32 vkGetPhysicalDeviceWaylandPresentationSupportKHR(
VkPhysicalDevice physicalDevice,
u32 queueFamilyIndex,
@@ -5798,7 +6747,7 @@
return ?
}
-@extension("VK_KHR_mir_surface")
+@extension("VK_KHR_mir_surface") // 8
cmd VkResult vkCreateMirSurfaceKHR(
VkInstance instance,
const VkMirSurfaceCreateInfoKHR* pCreateInfo,
@@ -5808,7 +6757,7 @@
return ?
}
-@extension("VK_KHR_mir_surface")
+@extension("VK_KHR_mir_surface") // 8
cmd VkBool32 vkGetPhysicalDeviceMirPresentationSupportKHR(
VkPhysicalDevice physicalDevice,
u32 queueFamilyIndex,
@@ -5817,7 +6766,7 @@
return ?
}
-@extension("VK_KHR_android_surface")
+@extension("VK_KHR_android_surface") // 9
cmd VkResult vkCreateAndroidSurfaceKHR(
VkInstance instance,
const VkAndroidSurfaceCreateInfoKHR* pCreateInfo,
@@ -5827,7 +6776,7 @@
return ?
}
-@extension("VK_KHR_win32_surface")
+@extension("VK_KHR_win32_surface") // 10
cmd VkResult vkCreateWin32SurfaceKHR(
VkInstance instance,
const VkWin32SurfaceCreateInfoKHR* pCreateInfo,
@@ -5837,7 +6786,7 @@
return ?
}
-@extension("VK_KHR_win32_surface")
+@extension("VK_KHR_win32_surface") // 10
cmd VkResult vkGetPhysicalDeviceWin32PresentationSupportKHR(
VkPhysicalDevice physicalDevice,
u32 queueFamilyIndex) {
@@ -5845,7 +6794,7 @@
return ?
}
-@extension("VK_ANDROID_native_buffer")
+@extension("VK_ANDROID_native_buffer") // 11
@optional
cmd VkResult vkGetSwapchainGrallocUsageANDROID(
VkDevice device,
@@ -5855,7 +6804,7 @@
return ?
}
-@extension("VK_ANDROID_native_buffer")
+@extension("VK_ANDROID_native_buffer") // 11
@optional
cmd VkResult vkGetSwapchainGrallocUsage2ANDROID(
VkDevice device,
@@ -5867,7 +6816,7 @@
return ?
}
-@extension("VK_ANDROID_native_buffer")
+@extension("VK_ANDROID_native_buffer") // 11
cmd VkResult vkAcquireImageANDROID(
VkDevice device,
VkImage image,
@@ -5877,7 +6826,7 @@
return ?
}
-@extension("VK_ANDROID_native_buffer")
+@extension("VK_ANDROID_native_buffer") // 11
cmd VkResult vkQueueSignalReleaseImageANDROID(
VkQueue queue,
u32 waitSemaphoreCount,
@@ -5887,32 +6836,9 @@
return ?
}
-@extension("VK_GOOGLE_display_timing")
-cmd VkResult vkGetRefreshCycleDurationGOOGLE(
- VkDevice device,
- VkSwapchainKHR swapchain,
- VkRefreshCycleDurationGOOGLE* pDisplayTimingProperties) {
- deviceObject := GetDevice(device)
- swapchainObject := GetSwapchain(swapchain)
-
- displayTimingProperties := ?
- pDisplayTimingProperties[0] = displayTimingProperties
-
- return ?
-}
-
-@extension("VK_GOOGLE_display_timing")
-cmd VkResult vkGetPastPresentationTimingGOOGLE(
- VkDevice device,
- VkSwapchainKHR swapchain,
- u32* pPresentationTimingCount,
- VkPastPresentationTimingGOOGLE* pPresentationTimings) {
- return ?
-}
-
-@extension("VK_EXT_debug_report")
+@extension("VK_EXT_debug_report") // 12
@external type void* PFN_vkDebugReportCallbackEXT
-@extension("VK_EXT_debug_report")
+@extension("VK_EXT_debug_report") // 12
@pfn cmd VkBool32 vkDebugReportCallbackEXT(
VkDebugReportFlagsEXT flags,
VkDebugReportObjectTypeEXT objectType,
@@ -5925,7 +6851,7 @@
return ?
}
-@extension("VK_EXT_debug_report")
+@extension("VK_EXT_debug_report") // 12
cmd VkResult vkCreateDebugReportCallbackEXT(
VkInstance instance,
const VkDebugReportCallbackCreateInfoEXT* pCreateInfo,
@@ -5934,14 +6860,14 @@
return ?
}
-@extension("VK_EXT_debug_report")
+@extension("VK_EXT_debug_report") // 12
cmd void vkDestroyDebugReportCallbackEXT(
VkInstance instance,
VkDebugReportCallbackEXT callback,
const VkAllocationCallbacks* pAllocator) {
}
-@extension("VK_EXT_debug_report")
+@extension("VK_EXT_debug_report") // 12
cmd void vkDebugReportMessageEXT(
VkInstance instance,
VkDebugReportFlagsEXT flags,
@@ -5953,38 +6879,38 @@
const char* pMessage) {
}
-@extension("VK_EXT_debug_marker")
+@extension("VK_EXT_debug_marker") // 23
cmd VkResult vkDebugMarkerSetObjectTagEXT(
VkDevice device,
VkDebugMarkerObjectTagInfoEXT* pTagInfo) {
return ?
}
-@extension("VK_EXT_debug_marker")
+@extension("VK_EXT_debug_marker") // 23
cmd VkResult vkDebugMarkerSetObjectNameEXT(
VkDevice device,
VkDebugMarkerObjectNameInfoEXT* pNameInfo) {
return ?
}
-@extension("VK_EXT_debug_marker")
+@extension("VK_EXT_debug_marker") // 23
cmd void vkCmdDebugMarkerBeginEXT(
VkCommandBuffer commandBuffer,
VkDebugMarkerMarkerInfoEXT* pMarkerInfo) {
}
-@extension("VK_EXT_debug_marker")
+@extension("VK_EXT_debug_marker") // 23
cmd void vkCmdDebugMarkerEndEXT(
VkCommandBuffer commandBuffer) {
}
-@extension("VK_EXT_debug_marker")
+@extension("VK_EXT_debug_marker") // 23
cmd void vkCmdDebugMarkerInsertEXT(
VkCommandBuffer commandBuffer,
VkDebugMarkerMarkerInfoEXT* pMarkerInfo) {
}
-@extension("VK_AMD_draw_indirect_count")
+@extension("VK_AMD_draw_indirect_count") // 34
cmd void vkCmdDrawIndirectCountAMD(
VkCommandBuffer commandBuffer,
VkBuffer buffer,
@@ -5995,7 +6921,7 @@
u32 stride) {
}
-@extension("VK_AMD_draw_indirect_count")
+@extension("VK_AMD_draw_indirect_count") // 34
cmd void vkCmdDrawIndexedIndirectCountAMD(
VkCommandBuffer commandBuffer,
VkBuffer buffer,
@@ -6006,7 +6932,7 @@
u32 stride) {
}
-@extension("VK_NV_external_memory_capabilities")
+@extension("VK_NV_external_memory_capabilities") // 56
cmd VkResult vkGetPhysicalDeviceExternalImageFormatPropertiesNV(
VkPhysicalDevice physicalDevice,
VkFormat format,
@@ -6019,7 +6945,7 @@
return ?
}
-@extension("VK_NV_external_memory_win32")
+@extension("VK_NV_external_memory_win32") // 58
cmd VkResult vkGetMemoryWin32HandleNV(
VkDevice device,
VkDeviceMemory memory,
@@ -6028,26 +6954,26 @@
return ?
}
-@extension("VK_KHR_get_physical_device_properties2")
+@extension("VK_KHR_get_physical_device_properties2") // 60
cmd void vkGetPhysicalDeviceFeatures2KHR(
VkPhysicalDevice physicalDevice,
VkPhysicalDeviceFeatures2KHR* pFeatures) {
}
-@extension("VK_KHR_get_physical_device_properties2")
+@extension("VK_KHR_get_physical_device_properties2") // 60
cmd void vkGetPhysicalDeviceProperties2KHR(
VkPhysicalDevice physicalDevice,
VkPhysicalDeviceProperties2KHR* pProperties) {
}
-@extension("VK_KHR_get_physical_device_properties2")
+@extension("VK_KHR_get_physical_device_properties2") // 60
cmd void vkGetPhysicalDeviceFormatProperties2KHR(
VkPhysicalDevice physicalDevice,
VkFormat format,
VkFormatProperties2KHR* pFormatProperties) {
}
-@extension("VK_KHR_get_physical_device_properties2")
+@extension("VK_KHR_get_physical_device_properties2") // 60
cmd VkResult vkGetPhysicalDeviceImageFormatProperties2KHR(
VkPhysicalDevice physicalDevice,
const VkPhysicalDeviceImageFormatInfo2KHR* pImageFormatInfo,
@@ -6055,40 +6981,263 @@
return ?
}
-@extension("VK_KHR_get_physical_device_properties2")
+@extension("VK_KHR_get_physical_device_properties2") // 60
cmd void vkGetPhysicalDeviceQueueFamilyProperties2KHR(
VkPhysicalDevice physicalDevice,
u32* pQueueFamilyPropertyCount,
VkQueueFamilyProperties2KHR* pQueueFamilyProperties) {
}
-@extension("VK_KHR_get_physical_device_properties2")
+@extension("VK_KHR_get_physical_device_properties2") // 60
cmd void vkGetPhysicalDeviceMemoryProperties2KHR(
VkPhysicalDevice physicalDevice,
VkPhysicalDeviceMemoryProperties2KHR* pMemoryProperties) {
}
-@extension("VK_KHR_get_physical_device_properties2")
+@extension("VK_KHR_get_physical_device_properties2") // 60
cmd void vkGetPhysicalDeviceSparseImageFormatProperties2KHR(
- VkPhysicalDevice physicalDevice,
- const VkPhysicalDeviceSparseImageFormatInfo2KHR* pFormatInfo,
- u32* pPropertyCount,
- VkSparseImageFormatProperties2KHR* pProperties) {
+ VkPhysicalDevice physicalDevice,
+ const VkPhysicalDeviceSparseImageFormatInfo2KHR* pFormatInfo,
+ u32* pPropertyCount,
+ VkSparseImageFormatProperties2KHR* pProperties) {
}
-@extension("VK_NVX_device_generated_commands")
+@extension("VK_KHX_device_group") // 61
+cmd void vkGetDeviceGroupPeerMemoryFeaturesKHX(
+ VkDevice device,
+ u32 heapIndex,
+ u32 localDeviceIndex,
+ u32 remoteDeviceIndex,
+ VkPeerMemoryFeatureFlagsKHX* pPeerMemoryFeatures) {
+}
+
+@extension("VK_KHX_device_group") // 61
+cmd VkResult vkBindBufferMemory2KHX(
+ VkDevice device,
+ u32 bindInfoCount,
+ const VkBindBufferMemoryInfoKHX* pBindInfos) {
+ return ?
+}
+
+@extension("VK_KHX_device_group") // 61
+cmd VkResult vkBindImageMemory2KHX(
+ VkDevice device,
+ u32 bindInfoCount,
+ const VkBindImageMemoryInfoKHX* pBindInfos) {
+ return ?
+}
+
+@extension("VK_KHX_device_group") // 61
+cmd void vkCmdSetDeviceMaskKHX(
+ VkCommandBuffer commandBuffer,
+ u32 deviceMask) {
+}
+
+@extension("VK_KHX_device_group") // 61
+cmd VkResult vkGetDeviceGroupPresentCapabilitiesKHX(
+ VkDevice device,
+ VkDeviceGroupPresentCapabilitiesKHX* pDeviceGroupPresentCapabilities) {
+ return ?
+}
+
+@extension("VK_KHX_device_group") // 61
+cmd VkResult vkGetDeviceGroupSurfacePresentModesKHX(
+ VkDevice device,
+ VkSurfaceKHR surface,
+ VkDeviceGroupPresentModeFlagsKHX* pModes) {
+ return ?
+}
+
+@extension("VK_KHX_device_group") // 61
+cmd VkResult vkAcquireNextImage2KHX(
+ VkDevice device,
+ const VkAcquireNextImageInfoKHX* pAcquireInfo,
+ u32* pImageIndex) {
+ return ?
+}
+
+@extension("VK_KHX_device_group") // 61
+cmd void vkCmdDispatchBaseKHX(
+ VkCommandBuffer commandBuffer,
+ u32 baseGroupX,
+ u32 baseGroupY,
+ u32 baseGroupZ,
+ u32 groupCountX,
+ u32 groupCountY,
+ u32 groupCountZ) {
+}
+
+@extension("VK_KHX_device_group") // 61
+cmd VkResult vkGetPhysicalDevicePresentRectanglesKHX(
+ VkPhysicalDevice physicalDevice,
+ VkSurfaceKHR surface,
+ u32* pRectCount,
+ VkRect2D* pRects) {
+ return ?
+}
+
+@extension("VK_NN_vi_surface") // 63
+cmd VkResult vkCreateViSurfaceNN(
+ VkInstance instance,
+ const VkViSurfaceCreateInfoNN* pCreateInfo,
+ const VkAllocationCallbacks* pAllocator,
+ VkSurfaceKHR* pSurface) {
+ return ?
+}
+
+@extension("VK_KHR_maintenance1") // 70
+cmd void vkTrimCommandPoolKHR(
+ VkDevice device,
+ VkCommandPool commandPool,
+ VkCommandPoolTrimFlagsKHR flags) {
+}
+
+@extension("VK_KHX_device_group_creation") // 71
+cmd VkResult vkEnumeratePhysicalDeviceGroupsKHX(
+ VkInstance instance,
+ u32* pPhysicalDeviceGroupCount,
+ VkPhysicalDeviceGroupPropertiesKHX* pPhysicalDeviceGroupProperties) {
+ return ?
+}
+
+@extension("VK_KHX_external_memory_capabilities") // 72
+cmd void vkGetPhysicalDeviceExternalBufferPropertiesKHX(
+ VkPhysicalDevice physicalDevice,
+ const VkPhysicalDeviceExternalBufferInfoKHX* pExternalBufferInfo,
+ VkExternalBufferPropertiesKHX* pExternalBufferProperties) {
+}
+
+@extension("VK_KHX_external_memory_win32") // 74
+cmd VkResult vkGetMemoryWin32HandleKHX(
+ VkDevice device,
+ VkDeviceMemory memory,
+ VkExternalMemoryHandleTypeFlagBitsKHX handleType,
+ platform.HANDLE* pHandle) {
+ return ?
+}
+
+@extension("VK_KHX_external_memory_win32") // 74
+cmd VkResult vkGetMemoryWin32HandlePropertiesKHX(
+ VkDevice device,
+ VkExternalMemoryHandleTypeFlagBitsKHX handleType,
+ platform.HANDLE handle,
+ VkMemoryWin32HandlePropertiesKHX* pMemoryWin32HandleProperties) {
+ return ?
+}
+
+@extension("VK_KHX_external_memory_fd") // 75
+cmd VkResult vkGetMemoryFdKHX(
+ VkDevice device,
+ VkDeviceMemory memory,
+ VkExternalMemoryHandleTypeFlagBitsKHX handleType,
+ s32* pFd) {
+ return ?
+}
+
+@extension("VK_KHX_external_memory_fd") // 75
+cmd VkResult vkGetMemoryFdPropertiesKHX(
+ VkDevice device,
+ VkExternalMemoryHandleTypeFlagBitsKHX handleType,
+ s32 fd,
+ VkMemoryFdPropertiesKHX* pMemoryFdProperties) {
+ return ?
+}
+
+@extension("VK_KHX_external_semaphore_capabilities") // 77
+cmd void vkGetPhysicalDeviceExternalSemaphorePropertiesKHX(
+ VkPhysicalDevice physicalDevice,
+ const VkPhysicalDeviceExternalSemaphoreInfoKHX* pExternalSemaphoreInfo,
+ VkExternalSemaphorePropertiesKHX* pExternalSemaphoreProperties) {
+}
+
+@extension("VK_KHX_external_semaphore_win32") // 79
+cmd VkResult vkImportSemaphoreWin32HandleKHX(
+ VkDevice device,
+ const VkImportSemaphoreWin32HandleInfoKHX* pImportSemaphoreWin32HandleInfo) {
+ return ?
+}
+
+@extension("VK_KHX_external_semaphore_win32") // 79
+cmd VkResult vkGetSemaphoreWin32HandleKHX(
+ VkDevice device,
+ VkSemaphore semaphore,
+ VkExternalSemaphoreHandleTypeFlagBitsKHX handleType,
+ platform.HANDLE* pHandle) {
+ return ?
+}
+
+@extension("VK_KHX_external_semaphore_fd") // 80
+cmd VkResult vkImportSemaphoreFdKHX(
+ VkDevice device,
+ const VkImportSemaphoreFdInfoKHX* pImportSemaphoreFdInfo) {
+ return ?
+}
+
+@extension("VK_KHX_external_semaphore_fd") // 80
+cmd VkResult vkGetSemaphoreFdKHX(
+ VkDevice device,
+ VkSemaphore semaphore,
+ VkExternalSemaphoreHandleTypeFlagBitsKHX handleType,
+ s32* pFd) {
+ return ?
+}
+
+@extension("VK_KHR_push_descriptor") // 81
+cmd void vkCmdPushDescriptorSetKHR(
+ VkCommandBuffer commandBuffer,
+ VkPipelineBindPoint pipelineBindPoint,
+ VkPipelineLayout layout,
+ u32 set,
+ u32 descriptorWriteCount,
+ const VkWriteDescriptorSet* pDescriptorWrites) {
+}
+
+@extension("VK_KHR_descriptor_update_template") // 86
+cmd VkResult vkCreateDescriptorUpdateTemplateKHR(
+ VkDevice device,
+ const VkDescriptorUpdateTemplateCreateInfoKHR* pCreateInfo,
+ const VkAllocationCallbacks* pAllocator,
+ VkDescriptorUpdateTemplateKHR* pDescriptorUpdateTemplate) {
+ return ?
+}
+
+@extension("VK_KHR_descriptor_update_template") // 86
+cmd void vkDestroyDescriptorUpdateTemplateKHR(
+ VkDevice device,
+ VkDescriptorUpdateTemplateKHR descriptorUpdateTemplate,
+ const VkAllocationCallbacks* pAllocator) {
+}
+
+@extension("VK_KHR_descriptor_update_template") // 86
+cmd void vkUpdateDescriptorSetWithTemplateKHR(
+ VkDevice device,
+ VkDescriptorSet descriptorSet,
+ VkDescriptorUpdateTemplateKHR descriptorUpdateTemplate,
+ const void* pData) {
+}
+
+@extension("VK_KHR_descriptor_update_template") // 86
+cmd void vkCmdPushDescriptorSetWithTemplateKHR(
+ VkCommandBuffer commandBuffer,
+ VkDescriptorUpdateTemplateKHR descriptorUpdateTemplate,
+ VkPipelineLayout layout,
+ u32 set,
+ const void* pData) {
+}
+
+@extension("VK_NVX_device_generated_commands") // 87
cmd void vkCmdProcessCommandsNVX(
VkCommandBuffer commandBuffer,
const VkCmdProcessCommandsInfoNVX* pProcessCommandsInfo) {
}
-@extension("VK_NVX_device_generated_commands")
+@extension("VK_NVX_device_generated_commands") // 87
cmd void vkCmdReserveSpaceForCommandsNVX(
VkCommandBuffer commandBuffer,
const VkCmdReserveSpaceForCommandsInfoNVX* pReserveSpaceInfo) {
}
-@extension("VK_NVX_device_generated_commands")
+@extension("VK_NVX_device_generated_commands") // 87
cmd VkResult vkCreateIndirectCommandsLayoutNVX(
VkDevice device,
const VkIndirectCommandsLayoutCreateInfoNVX* pCreateInfo,
@@ -6097,14 +7246,14 @@
return ?
}
-@extension("VK_NVX_device_generated_commands")
+@extension("VK_NVX_device_generated_commands") // 87
cmd void vkDestroyIndirectCommandsLayoutNVX(
VkDevice device,
VkIndirectCommandsLayoutNVX indirectCommandsLayout,
const VkAllocationCallbacks* pAllocator) {
}
-@extension("VK_NVX_device_generated_commands")
+@extension("VK_NVX_device_generated_commands") // 87
cmd VkResult vkCreateObjectTableNVX(
VkDevice device,
const VkObjectTableCreateInfoNVX* pCreateInfo,
@@ -6113,14 +7262,14 @@
return ?
}
-@extension("VK_NVX_device_generated_commands")
+@extension("VK_NVX_device_generated_commands") // 87
cmd void vkDestroyObjectTableNVX(
VkDevice device,
VkObjectTableNVX objectTable,
const VkAllocationCallbacks* pAllocator) {
}
-@extension("VK_NVX_device_generated_commands")
+@extension("VK_NVX_device_generated_commands") // 87
cmd VkResult vkRegisterObjectsNVX(
VkDevice device,
VkObjectTableNVX objectTable,
@@ -6130,7 +7279,7 @@
return ?
}
-@extension("VK_NVX_device_generated_commands")
+@extension("VK_NVX_device_generated_commands") // 87
cmd VkResult vkUnregisterObjectsNVX(
VkDevice device,
VkObjectTableNVX objectTable,
@@ -6140,28 +7289,153 @@
return ?
}
-@extension("VK_NVX_device_generated_commands")
+@extension("VK_NVX_device_generated_commands") // 87
cmd void vkGetPhysicalDeviceGeneratedCommandsPropertiesNVX(
VkPhysicalDevice physicalDevice,
VkDeviceGeneratedCommandsFeaturesNVX* pFeatures,
VkDeviceGeneratedCommandsLimitsNVX* pLimits) {
}
-@extension("VK_EXT_hdr_metadata")
-cmd void vkSetHdrMetadataEXT(
- VkDevice device,
- u32 swapchainCount,
- const VkSwapchainKHR* pSwapchains,
- const VkHdrMetadataEXT* pMetadata) {
+@extension("VK_NV_clip_space_w_scaling") // 88
+cmd void vkCmdSetViewportWScalingNV(
+ VkCommandBuffer commandBuffer,
+ u32 firstViewport,
+ u32 viewportCount,
+ const VkViewportWScalingNV* pViewportWScalings) {
}
-@extension("VK_KHR_shared_presentable_image")
+@extension("VK_EXT_direct_mode_display") // 89
+cmd VkResult vkReleaseDisplayEXT(
+ VkPhysicalDevice physicalDevice,
+ VkDisplayKHR display) {
+ return ?
+}
+
+@extension("VK_EXT_acquire_xlib_display") // 90
+cmd VkResult vkAcquireXlibDisplayEXT(
+ VkPhysicalDevice physicalDevice,
+ platform.Display* dpy,
+ VkDisplayKHR display) {
+ return ?
+}
+
+@extension("VK_EXT_acquire_xlib_display") // 90
+cmd VkResult vkGetRandROutputDisplayEXT(
+ VkPhysicalDevice physicalDevice,
+ platform.Display* dpy,
+ platform.RROutput rrOutput,
+ VkDisplayKHR* pDisplay) {
+ return ?
+}
+
+@extension("VK_EXT_display_surface_counter") // 91
+cmd VkResult vkGetPhysicalDeviceSurfaceCapabilities2EXT(
+ VkPhysicalDevice physicalDevice,
+ VkSurfaceKHR surface,
+ VkSurfaceCapabilities2EXT* pSurfaceCapabilities) {
+ return ?
+}
+
+@extension("VK_EXT_display_control") // 92
+cmd VkResult vkDisplayPowerControlEXT(
+ VkDevice device,
+ VkDisplayKHR display,
+ const VkDisplayPowerInfoEXT* pDisplayPowerInfo) {
+ return ?
+}
+
+@extension("VK_EXT_display_control") // 92
+cmd VkResult vkRegisterDeviceEventEXT(
+ VkDevice device,
+ const VkDeviceEventInfoEXT* pDeviceEventInfo,
+ const VkAllocationCallbacks* pAllocator,
+ VkFence* pFence) {
+ return ?
+}
+
+@extension("VK_EXT_display_control") // 92
+cmd VkResult vkRegisterDisplayEventEXT(
+ VkDevice device,
+ VkDisplayKHR display,
+ const VkDisplayEventInfoEXT* pDisplayEventInfo,
+ const VkAllocationCallbacks* pAllocator,
+ VkFence* pFence) {
+ return ?
+}
+
+@extension("VK_EXT_display_control") // 92
+cmd VkResult vkGetSwapchainCounterEXT(
+ VkDevice device,
+ VkSwapchainKHR swapchain,
+ VkSurfaceCounterFlagBitsEXT counter,
+ u64* pCounterValue) {
+ return ?
+}
+
+@extension("VK_GOOGLE_display_timing") // 93
+cmd VkResult vkGetRefreshCycleDurationGOOGLE(
+ VkDevice device,
+ VkSwapchainKHR swapchain,
+ VkRefreshCycleDurationGOOGLE* pDisplayTimingProperties) {
+ deviceObject := GetDevice(device)
+ swapchainObject := GetSwapchain(swapchain)
+
+ displayTimingProperties := ?
+ pDisplayTimingProperties[0] = displayTimingProperties
+
+ return ?
+}
+
+@extension("VK_GOOGLE_display_timing") // 93
+cmd VkResult vkGetPastPresentationTimingGOOGLE(
+ VkDevice device,
+ VkSwapchainKHR swapchain,
+ u32* pPresentationTimingCount,
+ VkPastPresentationTimingGOOGLE* pPresentationTimings) {
+ return ?
+}
+
+@extension("VK_EXT_discard_rectangles") // 100
+cmd void vkCmdSetDiscardRectangleEXT(
+ VkCommandBuffer commandBuffer,
+ u32 firstDiscardRectangle,
+ u32 discardRectangleCount,
+ const VkRect2D* pDiscardRectangles) {
+}
+
+@extension("VK_EXT_hdr_metadata") // 106
+cmd void vkSetHdrMetadataEXT(
+ VkDevice device,
+ u32 swapchainCount,
+ const VkSwapchainKHR* pSwapchains,
+ const VkHdrMetadataEXT* pMetadata) {
+}
+
+@extension("VK_KHR_shared_presentable_image") // 112
cmd VkResult vkGetSwapchainStatusKHR(
VkDevice device,
VkSwapchainKHR swapchain) {
return ?
}
+@extension("VK_MVK_ios_surface") // 123
+cmd VkResult vkCreateIOSSurfaceMVK(
+ VkInstance instance,
+ const VkIOSSurfaceCreateInfoMVK* pCreateInfo,
+ const VkAllocationCallbacks* pAllocator,
+ VkSurfaceKHR* pSurface) {
+ return ?
+}
+
+@extension("VK_MVK_macos_surface") // 124
+cmd VkResult vkCreateMacOSSurfaceMVK(
+ VkInstance instance,
+ const VkMacOSSurfaceCreateInfoMVK* pCreateInfo,
+ const VkAllocationCallbacks* pAllocator,
+ VkSurfaceKHR* pSurface) {
+ return ?
+}
+
////////////////
// Validation //
////////////////
diff --git a/vulkan/include/vulkan/vk_platform.h b/vulkan/include/vulkan/vk_platform.h
index 2054447..6dc5eb5 100644
--- a/vulkan/include/vulkan/vk_platform.h
+++ b/vulkan/include/vulkan/vk_platform.h
@@ -2,7 +2,7 @@
// File: vk_platform.h
//
/*
-** Copyright (c) 2014-2015 The Khronos Group Inc.
+** Copyright (c) 2014-2017 The Khronos Group Inc.
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
diff --git a/vulkan/include/vulkan/vulkan.h b/vulkan/include/vulkan/vulkan.h
index 3c8ee1c..8bb5448 100644
--- a/vulkan/include/vulkan/vulkan.h
+++ b/vulkan/include/vulkan/vulkan.h
@@ -43,11 +43,11 @@
#define VK_VERSION_MINOR(version) (((uint32_t)(version) >> 12) & 0x3ff)
#define VK_VERSION_PATCH(version) ((uint32_t)(version) & 0xfff)
// Version of this file
-#define VK_HEADER_VERSION 38
+#define VK_HEADER_VERSION 43
#define VK_NULL_HANDLE 0
-
+
#define VK_DEFINE_HANDLE(object) typedef struct object##_T* object;
@@ -60,7 +60,7 @@
#define VK_DEFINE_NON_DISPATCHABLE_HANDLE(object) typedef uint64_t object;
#endif
#endif
-
+
typedef uint32_t VkFlags;
@@ -145,6 +145,8 @@
VK_ERROR_INCOMPATIBLE_DISPLAY_KHR = -1000003001,
VK_ERROR_VALIDATION_FAILED_EXT = -1000011001,
VK_ERROR_INVALID_SHADER_NV = -1000012000,
+ VK_ERROR_OUT_OF_POOL_MEMORY_KHR = -1000069000,
+ VK_ERROR_INVALID_EXTERNAL_HANDLE_KHX = -1000072003,
VK_RESULT_BEGIN_RANGE = VK_ERROR_FRAGMENTED_POOL,
VK_RESULT_END_RANGE = VK_INCOMPLETE,
VK_RESULT_RANGE_SIZE = (VK_INCOMPLETE - VK_ERROR_FRAGMENTED_POOL + 1),
@@ -220,6 +222,9 @@
VK_STRUCTURE_TYPE_DEDICATED_ALLOCATION_IMAGE_CREATE_INFO_NV = 1000026000,
VK_STRUCTURE_TYPE_DEDICATED_ALLOCATION_BUFFER_CREATE_INFO_NV = 1000026001,
VK_STRUCTURE_TYPE_DEDICATED_ALLOCATION_MEMORY_ALLOCATE_INFO_NV = 1000026002,
+ VK_STRUCTURE_TYPE_RENDER_PASS_MULTIVIEW_CREATE_INFO_KHX = 1000053000,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_FEATURES_KHX = 1000053001,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_PROPERTIES_KHX = 1000053002,
VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO_NV = 1000056000,
VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO_NV = 1000056001,
VK_STRUCTURE_TYPE_IMPORT_MEMORY_WIN32_HANDLE_INFO_NV = 1000057000,
@@ -234,15 +239,70 @@
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_PROPERTIES_2_KHR = 1000059006,
VK_STRUCTURE_TYPE_SPARSE_IMAGE_FORMAT_PROPERTIES_2_KHR = 1000059007,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SPARSE_IMAGE_FORMAT_INFO_2_KHR = 1000059008,
+ VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_FLAGS_INFO_KHX = 1000060000,
+ VK_STRUCTURE_TYPE_BIND_BUFFER_MEMORY_INFO_KHX = 1000060001,
+ VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_INFO_KHX = 1000060002,
+ VK_STRUCTURE_TYPE_DEVICE_GROUP_RENDER_PASS_BEGIN_INFO_KHX = 1000060003,
+ VK_STRUCTURE_TYPE_DEVICE_GROUP_COMMAND_BUFFER_BEGIN_INFO_KHX = 1000060004,
+ VK_STRUCTURE_TYPE_DEVICE_GROUP_SUBMIT_INFO_KHX = 1000060005,
+ VK_STRUCTURE_TYPE_DEVICE_GROUP_BIND_SPARSE_INFO_KHX = 1000060006,
+ VK_STRUCTURE_TYPE_DEVICE_GROUP_PRESENT_CAPABILITIES_KHX = 1000060007,
+ VK_STRUCTURE_TYPE_IMAGE_SWAPCHAIN_CREATE_INFO_KHX = 1000060008,
+ VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_SWAPCHAIN_INFO_KHX = 1000060009,
+ VK_STRUCTURE_TYPE_ACQUIRE_NEXT_IMAGE_INFO_KHX = 1000060010,
+ VK_STRUCTURE_TYPE_DEVICE_GROUP_PRESENT_INFO_KHX = 1000060011,
+ VK_STRUCTURE_TYPE_DEVICE_GROUP_SWAPCHAIN_CREATE_INFO_KHX = 1000060012,
VK_STRUCTURE_TYPE_VALIDATION_FLAGS_EXT = 1000061000,
+ VK_STRUCTURE_TYPE_VI_SURFACE_CREATE_INFO_NN = 1000062000,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GROUP_PROPERTIES_KHX = 1000070000,
+ VK_STRUCTURE_TYPE_DEVICE_GROUP_DEVICE_CREATE_INFO_KHX = 1000070001,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO_KHX = 1000071000,
+ VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES_KHX = 1000071001,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_BUFFER_INFO_KHX = 1000071002,
+ VK_STRUCTURE_TYPE_EXTERNAL_BUFFER_PROPERTIES_KHX = 1000071003,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ID_PROPERTIES_KHX = 1000071004,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2_KHX = 1000071005,
+ VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2_KHX = 1000071006,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2_KHX = 1000071007,
+ VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_BUFFER_CREATE_INFO_KHX = 1000072000,
+ VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO_KHX = 1000072001,
+ VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO_KHX = 1000072002,
+ VK_STRUCTURE_TYPE_IMPORT_MEMORY_WIN32_HANDLE_INFO_KHX = 1000073000,
+ VK_STRUCTURE_TYPE_EXPORT_MEMORY_WIN32_HANDLE_INFO_KHX = 1000073001,
+ VK_STRUCTURE_TYPE_MEMORY_WIN32_HANDLE_PROPERTIES_KHX = 1000073002,
+ VK_STRUCTURE_TYPE_IMPORT_MEMORY_FD_INFO_KHX = 1000074000,
+ VK_STRUCTURE_TYPE_MEMORY_FD_PROPERTIES_KHX = 1000074001,
+ VK_STRUCTURE_TYPE_WIN32_KEYED_MUTEX_ACQUIRE_RELEASE_INFO_KHX = 1000075000,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_SEMAPHORE_INFO_KHX = 1000076000,
+ VK_STRUCTURE_TYPE_EXTERNAL_SEMAPHORE_PROPERTIES_KHX = 1000076001,
+ VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_CREATE_INFO_KHX = 1000077000,
+ VK_STRUCTURE_TYPE_IMPORT_SEMAPHORE_WIN32_HANDLE_INFO_KHX = 1000078000,
+ VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_WIN32_HANDLE_INFO_KHX = 1000078001,
+ VK_STRUCTURE_TYPE_D3D12_FENCE_SUBMIT_INFO_KHX = 1000078002,
+ VK_STRUCTURE_TYPE_IMPORT_SEMAPHORE_FD_INFO_KHX = 1000079000,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PUSH_DESCRIPTOR_PROPERTIES_KHR = 1000080000,
VK_STRUCTURE_TYPE_PRESENT_REGIONS_KHR = 1000084000,
+ VK_STRUCTURE_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_CREATE_INFO_KHR = 1000085000,
VK_STRUCTURE_TYPE_OBJECT_TABLE_CREATE_INFO_NVX = 1000086000,
VK_STRUCTURE_TYPE_INDIRECT_COMMANDS_LAYOUT_CREATE_INFO_NVX = 1000086001,
VK_STRUCTURE_TYPE_CMD_PROCESS_COMMANDS_INFO_NVX = 1000086002,
VK_STRUCTURE_TYPE_CMD_RESERVE_SPACE_FOR_COMMANDS_INFO_NVX = 1000086003,
VK_STRUCTURE_TYPE_DEVICE_GENERATED_COMMANDS_LIMITS_NVX = 1000086004,
VK_STRUCTURE_TYPE_DEVICE_GENERATED_COMMANDS_FEATURES_NVX = 1000086005,
+ VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_W_SCALING_STATE_CREATE_INFO_NV = 1000087000,
+ VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES2_EXT = 1000090000,
+ VK_STRUCTURE_TYPE_DISPLAY_POWER_INFO_EXT = 1000091000,
+ VK_STRUCTURE_TYPE_DEVICE_EVENT_INFO_EXT = 1000091001,
+ VK_STRUCTURE_TYPE_DISPLAY_EVENT_INFO_EXT = 1000091002,
+ VK_STRUCTURE_TYPE_SWAPCHAIN_COUNTER_CREATE_INFO_EXT = 1000091003,
VK_STRUCTURE_TYPE_PRESENT_TIMES_INFO_GOOGLE = 1000092000,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_PER_VIEW_ATTRIBUTES_PROPERTIES_NVX = 1000097000,
+ VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_SWIZZLE_STATE_CREATE_INFO_NV = 1000098000,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DISCARD_RECTANGLE_PROPERTIES_EXT = 1000099000,
+ VK_STRUCTURE_TYPE_PIPELINE_DISCARD_RECTANGLE_STATE_CREATE_INFO_EXT = 1000099001,
+ VK_STRUCTURE_TYPE_HDR_METADATA_EXT = 1000105000,
+ VK_STRUCTURE_TYPE_IOS_SURFACE_CREATE_INFO_MVK = 1000122000,
+ VK_STRUCTURE_TYPE_MACOS_SURFACE_CREATE_INFO_MVK = 1000123000,
VK_STRUCTURE_TYPE_BEGIN_RANGE = VK_STRUCTURE_TYPE_APPLICATION_INFO,
VK_STRUCTURE_TYPE_END_RANGE = VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFO,
VK_STRUCTURE_TYPE_RANGE_SIZE = (VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFO - VK_STRUCTURE_TYPE_APPLICATION_INFO + 1),
@@ -712,6 +772,8 @@
VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK = 6,
VK_DYNAMIC_STATE_STENCIL_WRITE_MASK = 7,
VK_DYNAMIC_STATE_STENCIL_REFERENCE = 8,
+ VK_DYNAMIC_STATE_VIEWPORT_W_SCALING_NV = 1000087000,
+ VK_DYNAMIC_STATE_DISCARD_RECTANGLE_EXT = 1000099000,
VK_DYNAMIC_STATE_BEGIN_RANGE = VK_DYNAMIC_STATE_VIEWPORT,
VK_DYNAMIC_STATE_END_RANGE = VK_DYNAMIC_STATE_STENCIL_REFERENCE,
VK_DYNAMIC_STATE_RANGE_SIZE = (VK_DYNAMIC_STATE_STENCIL_REFERENCE - VK_DYNAMIC_STATE_VIEWPORT + 1),
@@ -852,6 +914,8 @@
VK_FORMAT_FEATURE_BLIT_DST_BIT = 0x00000800,
VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT = 0x00001000,
VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_CUBIC_BIT_IMG = 0x00002000,
+ VK_FORMAT_FEATURE_TRANSFER_SRC_BIT_KHR = 0x00004000,
+ VK_FORMAT_FEATURE_TRANSFER_DST_BIT_KHR = 0x00008000,
VK_FORMAT_FEATURE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
} VkFormatFeatureFlagBits;
typedef VkFlags VkFormatFeatureFlags;
@@ -875,6 +939,8 @@
VK_IMAGE_CREATE_SPARSE_ALIASED_BIT = 0x00000004,
VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT = 0x00000008,
VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT = 0x00000010,
+ VK_IMAGE_CREATE_BIND_SFR_BIT_KHX = 0x00000040,
+ VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT_KHR = 0x00000020,
VK_IMAGE_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
} VkImageCreateFlagBits;
typedef VkFlags VkImageCreateFlags;
@@ -912,6 +978,7 @@
typedef enum VkMemoryHeapFlagBits {
VK_MEMORY_HEAP_DEVICE_LOCAL_BIT = 0x00000001,
+ VK_MEMORY_HEAP_MULTI_INSTANCE_BIT_KHX = 0x00000002,
VK_MEMORY_HEAP_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
} VkMemoryHeapFlagBits;
typedef VkFlags VkMemoryHeapFlags;
@@ -1029,6 +1096,8 @@
VK_PIPELINE_CREATE_DISABLE_OPTIMIZATION_BIT = 0x00000001,
VK_PIPELINE_CREATE_ALLOW_DERIVATIVES_BIT = 0x00000002,
VK_PIPELINE_CREATE_DERIVATIVE_BIT = 0x00000004,
+ VK_PIPELINE_CREATE_VIEW_INDEX_FROM_DEVICE_INDEX_BIT_KHX = 0x00000008,
+ VK_PIPELINE_CREATE_DISPATCH_BASE_KHX = 0x00000010,
VK_PIPELINE_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
} VkPipelineCreateFlagBits;
typedef VkFlags VkPipelineCreateFlags;
@@ -1075,6 +1144,11 @@
typedef VkFlags VkPipelineLayoutCreateFlags;
typedef VkFlags VkShaderStageFlags;
typedef VkFlags VkSamplerCreateFlags;
+
+typedef enum VkDescriptorSetLayoutCreateFlagBits {
+ VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR = 0x00000001,
+ VK_DESCRIPTOR_SET_LAYOUT_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
+} VkDescriptorSetLayoutCreateFlagBits;
typedef VkFlags VkDescriptorSetLayoutCreateFlags;
typedef enum VkDescriptorPoolCreateFlagBits {
@@ -1091,6 +1165,12 @@
VK_ATTACHMENT_DESCRIPTION_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
} VkAttachmentDescriptionFlagBits;
typedef VkFlags VkAttachmentDescriptionFlags;
+
+typedef enum VkSubpassDescriptionFlagBits {
+ VK_SUBPASS_DESCRIPTION_PER_VIEW_ATTRIBUTES_BIT_NVX = 0x00000001,
+ VK_SUBPASS_DESCRIPTION_PER_VIEW_POSITION_X_ONLY_BIT_NVX = 0x00000002,
+ VK_SUBPASS_DESCRIPTION_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
+} VkSubpassDescriptionFlagBits;
typedef VkFlags VkSubpassDescriptionFlags;
typedef enum VkAccessFlagBits {
@@ -1119,6 +1199,8 @@
typedef enum VkDependencyFlagBits {
VK_DEPENDENCY_BY_REGION_BIT = 0x00000001,
+ VK_DEPENDENCY_VIEW_LOCAL_BIT_KHX = 0x00000002,
+ VK_DEPENDENCY_DEVICE_GROUP_BIT_KHX = 0x00000004,
VK_DEPENDENCY_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
} VkDependencyFlagBits;
typedef VkFlags VkDependencyFlags;
@@ -2381,7 +2463,7 @@
typedef void (VKAPI_PTR *PFN_vkCmdDrawIndexed)(VkCommandBuffer commandBuffer, uint32_t indexCount, uint32_t instanceCount, uint32_t firstIndex, int32_t vertexOffset, uint32_t firstInstance);
typedef void (VKAPI_PTR *PFN_vkCmdDrawIndirect)(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, uint32_t drawCount, uint32_t stride);
typedef void (VKAPI_PTR *PFN_vkCmdDrawIndexedIndirect)(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, uint32_t drawCount, uint32_t stride);
-typedef void (VKAPI_PTR *PFN_vkCmdDispatch)(VkCommandBuffer commandBuffer, uint32_t x, uint32_t y, uint32_t z);
+typedef void (VKAPI_PTR *PFN_vkCmdDispatch)(VkCommandBuffer commandBuffer, uint32_t groupCountX, uint32_t groupCountY, uint32_t groupCountZ);
typedef void (VKAPI_PTR *PFN_vkCmdDispatchIndirect)(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset);
typedef void (VKAPI_PTR *PFN_vkCmdCopyBuffer)(VkCommandBuffer commandBuffer, VkBuffer srcBuffer, VkBuffer dstBuffer, uint32_t regionCount, const VkBufferCopy* pRegions);
typedef void (VKAPI_PTR *PFN_vkCmdCopyImage)(VkCommandBuffer commandBuffer, VkImage srcImage, VkImageLayout srcImageLayout, VkImage dstImage, VkImageLayout dstImageLayout, uint32_t regionCount, const VkImageCopy* pRegions);
@@ -3017,9 +3099,9 @@
VKAPI_ATTR void VKAPI_CALL vkCmdDispatch(
VkCommandBuffer commandBuffer,
- uint32_t x,
- uint32_t y,
- uint32_t z);
+ uint32_t groupCountX,
+ uint32_t groupCountY,
+ uint32_t groupCountZ);
VKAPI_ATTR void VKAPI_CALL vkCmdDispatchIndirect(
VkCommandBuffer commandBuffer,
@@ -3335,6 +3417,11 @@
#define VK_KHR_SWAPCHAIN_SPEC_VERSION 68
#define VK_KHR_SWAPCHAIN_EXTENSION_NAME "VK_KHR_swapchain"
+
+typedef enum VkSwapchainCreateFlagBitsKHR {
+ VK_SWAPCHAIN_CREATE_BIND_SFR_BIT_KHX = 0x00000001,
+ VK_SWAPCHAIN_CREATE_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF
+} VkSwapchainCreateFlagBitsKHR;
typedef VkFlags VkSwapchainCreateFlagsKHR;
typedef struct VkSwapchainCreateInfoKHR {
@@ -3635,7 +3722,7 @@
#define VK_KHR_wayland_surface 1
#include <wayland-client.h>
-#define VK_KHR_WAYLAND_SURFACE_SPEC_VERSION 5
+#define VK_KHR_WAYLAND_SURFACE_SPEC_VERSION 6
#define VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME "VK_KHR_wayland_surface"
typedef VkFlags VkWaylandSurfaceCreateFlagsKHR;
@@ -3877,44 +3964,125 @@
VkSparseImageFormatProperties2KHR* pProperties);
#endif
-#define VK_KHR_incremental_present 1
-#define VK_KHR_INCREMENTAL_PRESENT_SPEC_VERSION 1
-#define VK_KHR_INCREMENTAL_PRESENT_EXTENSION_NAME "VK_KHR_incremental_present"
+#define VK_KHR_shader_draw_parameters 1
+#define VK_KHR_SHADER_DRAW_PARAMETERS_SPEC_VERSION 1
+#define VK_KHR_SHADER_DRAW_PARAMETERS_EXTENSION_NAME "VK_KHR_shader_draw_parameters"
-typedef struct VkRectLayerKHR {
- VkOffset2D offset;
- VkExtent2D extent;
- uint32_t layer;
-} VkRectLayerKHR;
-typedef struct VkPresentRegionKHR {
- uint32_t rectangleCount;
- const VkRectLayerKHR* pRectangles;
-} VkPresentRegionKHR;
+#define VK_KHR_maintenance1 1
+#define VK_KHR_MAINTENANCE1_SPEC_VERSION 1
+#define VK_KHR_MAINTENANCE1_EXTENSION_NAME "VK_KHR_maintenance1"
-typedef struct VkPresentRegionsKHR {
- VkStructureType sType;
- const void* pNext;
- uint32_t swapchainCount;
- const VkPresentRegionKHR* pRegions;
-} VkPresentRegionsKHR;
+typedef VkFlags VkCommandPoolTrimFlagsKHR;
-#define VK_KHR_shared_presentable_image 1
-#define VK_KHR_SHARED_PRESENTABLE_IMAGE_SPEC_VERSION 1
-#define VK_KHR_SHARED_PRESENTABLE_IMAGE_EXTENSION_NAME "VK_KHR_shared_presentable_image"
-
-typedef VkResult (VKAPI_PTR *PFN_vkGetSwapchainStatusKHR)(VkDevice device, VkSwapchainKHR swapchain);
+typedef void (VKAPI_PTR *PFN_vkTrimCommandPoolKHR)(VkDevice device, VkCommandPool commandPool, VkCommandPoolTrimFlagsKHR flags);
#ifndef VK_NO_PROTOTYPES
-VKAPI_ATTR VkResult VKAPI_CALL vkGetSwapchainStatusKHR(
+VKAPI_ATTR void VKAPI_CALL vkTrimCommandPoolKHR(
VkDevice device,
- VkSwapchainKHR swapchain);
+ VkCommandPool commandPool,
+ VkCommandPoolTrimFlagsKHR flags);
+#endif
+
+#define VK_KHR_push_descriptor 1
+#define VK_KHR_PUSH_DESCRIPTOR_SPEC_VERSION 1
+#define VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME "VK_KHR_push_descriptor"
+
+typedef struct VkPhysicalDevicePushDescriptorPropertiesKHR {
+ VkStructureType sType;
+ void* pNext;
+ uint32_t maxPushDescriptors;
+} VkPhysicalDevicePushDescriptorPropertiesKHR;
+
+
+typedef void (VKAPI_PTR *PFN_vkCmdPushDescriptorSetKHR)(VkCommandBuffer commandBuffer, VkPipelineBindPoint pipelineBindPoint, VkPipelineLayout layout, uint32_t set, uint32_t descriptorWriteCount, const VkWriteDescriptorSet* pDescriptorWrites);
+
+#ifndef VK_NO_PROTOTYPES
+VKAPI_ATTR void VKAPI_CALL vkCmdPushDescriptorSetKHR(
+ VkCommandBuffer commandBuffer,
+ VkPipelineBindPoint pipelineBindPoint,
+ VkPipelineLayout layout,
+ uint32_t set,
+ uint32_t descriptorWriteCount,
+ const VkWriteDescriptorSet* pDescriptorWrites);
+#endif
+
+#define VK_KHR_descriptor_update_template 1
+VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkDescriptorUpdateTemplateKHR)
+
+#define VK_KHR_DESCRIPTOR_UPDATE_TEMPLATE_SPEC_VERSION 1
+#define VK_KHR_DESCRIPTOR_UPDATE_TEMPLATE_EXTENSION_NAME "VK_KHR_descriptor_update_template"
+
+
+typedef enum VkDescriptorUpdateTemplateTypeKHR {
+ VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET_KHR = 0,
+ VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_PUSH_DESCRIPTORS_KHR = 1,
+ VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_BEGIN_RANGE_KHR = VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET_KHR,
+ VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_END_RANGE_KHR = VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_PUSH_DESCRIPTORS_KHR,
+ VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_RANGE_SIZE_KHR = (VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_PUSH_DESCRIPTORS_KHR - VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET_KHR + 1),
+ VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_MAX_ENUM_KHR = 0x7FFFFFFF
+} VkDescriptorUpdateTemplateTypeKHR;
+
+typedef VkFlags VkDescriptorUpdateTemplateCreateFlagsKHR;
+
+typedef struct VkDescriptorUpdateTemplateEntryKHR {
+ uint32_t dstBinding;
+ uint32_t dstArrayElement;
+ uint32_t descriptorCount;
+ VkDescriptorType descriptorType;
+ size_t offset;
+ size_t stride;
+} VkDescriptorUpdateTemplateEntryKHR;
+
+typedef struct VkDescriptorUpdateTemplateCreateInfoKHR {
+ VkStructureType sType;
+ void* pNext;
+ VkDescriptorUpdateTemplateCreateFlagsKHR flags;
+ uint32_t descriptorUpdateEntryCount;
+ const VkDescriptorUpdateTemplateEntryKHR* pDescriptorUpdateEntries;
+ VkDescriptorUpdateTemplateTypeKHR templateType;
+ VkDescriptorSetLayout descriptorSetLayout;
+ VkPipelineBindPoint pipelineBindPoint;
+ VkPipelineLayout pipelineLayout;
+ uint32_t set;
+} VkDescriptorUpdateTemplateCreateInfoKHR;
+
+
+typedef VkResult (VKAPI_PTR *PFN_vkCreateDescriptorUpdateTemplateKHR)(VkDevice device, const VkDescriptorUpdateTemplateCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDescriptorUpdateTemplateKHR* pDescriptorUpdateTemplate);
+typedef void (VKAPI_PTR *PFN_vkDestroyDescriptorUpdateTemplateKHR)(VkDevice device, VkDescriptorUpdateTemplateKHR descriptorUpdateTemplate, const VkAllocationCallbacks* pAllocator);
+typedef void (VKAPI_PTR *PFN_vkUpdateDescriptorSetWithTemplateKHR)(VkDevice device, VkDescriptorSet descriptorSet, VkDescriptorUpdateTemplateKHR descriptorUpdateTemplate, const void* pData);
+typedef void (VKAPI_PTR *PFN_vkCmdPushDescriptorSetWithTemplateKHR)(VkCommandBuffer commandBuffer, VkDescriptorUpdateTemplateKHR descriptorUpdateTemplate, VkPipelineLayout layout, uint32_t set, const void* pData);
+
+#ifndef VK_NO_PROTOTYPES
+VKAPI_ATTR VkResult VKAPI_CALL vkCreateDescriptorUpdateTemplateKHR(
+ VkDevice device,
+ const VkDescriptorUpdateTemplateCreateInfoKHR* pCreateInfo,
+ const VkAllocationCallbacks* pAllocator,
+ VkDescriptorUpdateTemplateKHR* pDescriptorUpdateTemplate);
+
+VKAPI_ATTR void VKAPI_CALL vkDestroyDescriptorUpdateTemplateKHR(
+ VkDevice device,
+ VkDescriptorUpdateTemplateKHR descriptorUpdateTemplate,
+ const VkAllocationCallbacks* pAllocator);
+
+VKAPI_ATTR void VKAPI_CALL vkUpdateDescriptorSetWithTemplateKHR(
+ VkDevice device,
+ VkDescriptorSet descriptorSet,
+ VkDescriptorUpdateTemplateKHR descriptorUpdateTemplate,
+ const void* pData);
+
+VKAPI_ATTR void VKAPI_CALL vkCmdPushDescriptorSetWithTemplateKHR(
+ VkCommandBuffer commandBuffer,
+ VkDescriptorUpdateTemplateKHR descriptorUpdateTemplate,
+ VkPipelineLayout layout,
+ uint32_t set,
+ const void* pData);
#endif
#define VK_EXT_debug_report 1
VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkDebugReportCallbackEXT)
-#define VK_EXT_DEBUG_REPORT_SPEC_VERSION 4
+#define VK_EXT_DEBUG_REPORT_SPEC_VERSION 5
#define VK_EXT_DEBUG_REPORT_EXTENSION_NAME "VK_EXT_debug_report"
#define VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT
@@ -4069,7 +4237,7 @@
#define VK_EXT_debug_marker 1
-#define VK_EXT_DEBUG_MARKER_SPEC_VERSION 3
+#define VK_EXT_DEBUG_MARKER_SPEC_VERSION 4
#define VK_EXT_DEBUG_MARKER_EXTENSION_NAME "VK_EXT_debug_marker"
typedef struct VkDebugMarkerObjectNameInfoEXT {
@@ -4154,6 +4322,7 @@
} VkDedicatedAllocationMemoryAllocateInfoNV;
+
#define VK_AMD_draw_indirect_count 1
#define VK_AMD_DRAW_INDIRECT_COUNT_SPEC_VERSION 1
#define VK_AMD_DRAW_INDIRECT_COUNT_EXTENSION_NAME "VK_AMD_draw_indirect_count"
@@ -4196,6 +4365,38 @@
#define VK_AMD_SHADER_BALLOT_EXTENSION_NAME "VK_AMD_shader_ballot"
+#define VK_KHX_multiview 1
+#define VK_KHX_MULTIVIEW_SPEC_VERSION 1
+#define VK_KHX_MULTIVIEW_EXTENSION_NAME "VK_KHX_multiview"
+
+typedef struct VkRenderPassMultiviewCreateInfoKHX {
+ VkStructureType sType;
+ const void* pNext;
+ uint32_t subpassCount;
+ const uint32_t* pViewMasks;
+ uint32_t dependencyCount;
+ const int32_t* pViewOffsets;
+ uint32_t correlationMaskCount;
+ const uint32_t* pCorrelationMasks;
+} VkRenderPassMultiviewCreateInfoKHX;
+
+typedef struct VkPhysicalDeviceMultiviewFeaturesKHX {
+ VkStructureType sType;
+ void* pNext;
+ VkBool32 multiview;
+ VkBool32 multiviewGeometryShader;
+ VkBool32 multiviewTessellationShader;
+} VkPhysicalDeviceMultiviewFeaturesKHX;
+
+typedef struct VkPhysicalDeviceMultiviewPropertiesKHX {
+ VkStructureType sType;
+ void* pNext;
+ uint32_t maxMultiviewViewCount;
+ uint32_t maxMultiviewInstanceIndex;
+} VkPhysicalDeviceMultiviewPropertiesKHX;
+
+
+
#define VK_IMG_format_pvrtc 1
#define VK_IMG_FORMAT_PVRTC_SPEC_VERSION 1
#define VK_IMG_FORMAT_PVRTC_EXTENSION_NAME "VK_IMG_format_pvrtc"
@@ -4314,6 +4515,204 @@
#endif /* VK_USE_PLATFORM_WIN32_KHR */
+#define VK_KHX_device_group 1
+#define VK_MAX_DEVICE_GROUP_SIZE_KHX 32
+#define VK_KHX_DEVICE_GROUP_SPEC_VERSION 1
+#define VK_KHX_DEVICE_GROUP_EXTENSION_NAME "VK_KHX_device_group"
+
+
+typedef enum VkPeerMemoryFeatureFlagBitsKHX {
+ VK_PEER_MEMORY_FEATURE_COPY_SRC_BIT_KHX = 0x00000001,
+ VK_PEER_MEMORY_FEATURE_COPY_DST_BIT_KHX = 0x00000002,
+ VK_PEER_MEMORY_FEATURE_GENERIC_SRC_BIT_KHX = 0x00000004,
+ VK_PEER_MEMORY_FEATURE_GENERIC_DST_BIT_KHX = 0x00000008,
+ VK_PEER_MEMORY_FEATURE_FLAG_BITS_MAX_ENUM_KHX = 0x7FFFFFFF
+} VkPeerMemoryFeatureFlagBitsKHX;
+typedef VkFlags VkPeerMemoryFeatureFlagsKHX;
+
+typedef enum VkMemoryAllocateFlagBitsKHX {
+ VK_MEMORY_ALLOCATE_DEVICE_MASK_BIT_KHX = 0x00000001,
+ VK_MEMORY_ALLOCATE_FLAG_BITS_MAX_ENUM_KHX = 0x7FFFFFFF
+} VkMemoryAllocateFlagBitsKHX;
+typedef VkFlags VkMemoryAllocateFlagsKHX;
+
+typedef enum VkDeviceGroupPresentModeFlagBitsKHX {
+ VK_DEVICE_GROUP_PRESENT_MODE_LOCAL_BIT_KHX = 0x00000001,
+ VK_DEVICE_GROUP_PRESENT_MODE_REMOTE_BIT_KHX = 0x00000002,
+ VK_DEVICE_GROUP_PRESENT_MODE_SUM_BIT_KHX = 0x00000004,
+ VK_DEVICE_GROUP_PRESENT_MODE_LOCAL_MULTI_DEVICE_BIT_KHX = 0x00000008,
+ VK_DEVICE_GROUP_PRESENT_MODE_FLAG_BITS_MAX_ENUM_KHX = 0x7FFFFFFF
+} VkDeviceGroupPresentModeFlagBitsKHX;
+typedef VkFlags VkDeviceGroupPresentModeFlagsKHX;
+
+typedef struct VkMemoryAllocateFlagsInfoKHX {
+ VkStructureType sType;
+ const void* pNext;
+ VkMemoryAllocateFlagsKHX flags;
+ uint32_t deviceMask;
+} VkMemoryAllocateFlagsInfoKHX;
+
+typedef struct VkBindBufferMemoryInfoKHX {
+ VkStructureType sType;
+ const void* pNext;
+ VkBuffer buffer;
+ VkDeviceMemory memory;
+ VkDeviceSize memoryOffset;
+ uint32_t deviceIndexCount;
+ const uint32_t* pDeviceIndices;
+} VkBindBufferMemoryInfoKHX;
+
+typedef struct VkBindImageMemoryInfoKHX {
+ VkStructureType sType;
+ const void* pNext;
+ VkImage image;
+ VkDeviceMemory memory;
+ VkDeviceSize memoryOffset;
+ uint32_t deviceIndexCount;
+ const uint32_t* pDeviceIndices;
+ uint32_t SFRRectCount;
+ const VkRect2D* pSFRRects;
+} VkBindImageMemoryInfoKHX;
+
+typedef struct VkDeviceGroupRenderPassBeginInfoKHX {
+ VkStructureType sType;
+ const void* pNext;
+ uint32_t deviceMask;
+ uint32_t deviceRenderAreaCount;
+ const VkRect2D* pDeviceRenderAreas;
+} VkDeviceGroupRenderPassBeginInfoKHX;
+
+typedef struct VkDeviceGroupCommandBufferBeginInfoKHX {
+ VkStructureType sType;
+ const void* pNext;
+ uint32_t deviceMask;
+} VkDeviceGroupCommandBufferBeginInfoKHX;
+
+typedef struct VkDeviceGroupSubmitInfoKHX {
+ VkStructureType sType;
+ const void* pNext;
+ uint32_t waitSemaphoreCount;
+ const uint32_t* pWaitSemaphoreDeviceIndices;
+ uint32_t commandBufferCount;
+ const uint32_t* pCommandBufferDeviceMasks;
+ uint32_t signalSemaphoreCount;
+ const uint32_t* pSignalSemaphoreDeviceIndices;
+} VkDeviceGroupSubmitInfoKHX;
+
+typedef struct VkDeviceGroupBindSparseInfoKHX {
+ VkStructureType sType;
+ const void* pNext;
+ uint32_t resourceDeviceIndex;
+ uint32_t memoryDeviceIndex;
+} VkDeviceGroupBindSparseInfoKHX;
+
+typedef struct VkDeviceGroupPresentCapabilitiesKHX {
+ VkStructureType sType;
+ const void* pNext;
+ uint32_t presentMask[VK_MAX_DEVICE_GROUP_SIZE_KHX];
+ VkDeviceGroupPresentModeFlagsKHX modes;
+} VkDeviceGroupPresentCapabilitiesKHX;
+
+typedef struct VkImageSwapchainCreateInfoKHX {
+ VkStructureType sType;
+ const void* pNext;
+ VkSwapchainKHR swapchain;
+} VkImageSwapchainCreateInfoKHX;
+
+typedef struct VkBindImageMemorySwapchainInfoKHX {
+ VkStructureType sType;
+ const void* pNext;
+ VkSwapchainKHR swapchain;
+ uint32_t imageIndex;
+} VkBindImageMemorySwapchainInfoKHX;
+
+typedef struct VkAcquireNextImageInfoKHX {
+ VkStructureType sType;
+ const void* pNext;
+ VkSwapchainKHR swapchain;
+ uint64_t timeout;
+ VkSemaphore semaphore;
+ VkFence fence;
+ uint32_t deviceMask;
+} VkAcquireNextImageInfoKHX;
+
+typedef struct VkDeviceGroupPresentInfoKHX {
+ VkStructureType sType;
+ const void* pNext;
+ uint32_t swapchainCount;
+ const uint32_t* pDeviceMasks;
+ VkDeviceGroupPresentModeFlagBitsKHX mode;
+} VkDeviceGroupPresentInfoKHX;
+
+typedef struct VkDeviceGroupSwapchainCreateInfoKHX {
+ VkStructureType sType;
+ const void* pNext;
+ VkDeviceGroupPresentModeFlagsKHX modes;
+} VkDeviceGroupSwapchainCreateInfoKHX;
+
+
+typedef void (VKAPI_PTR *PFN_vkGetDeviceGroupPeerMemoryFeaturesKHX)(VkDevice device, uint32_t heapIndex, uint32_t localDeviceIndex, uint32_t remoteDeviceIndex, VkPeerMemoryFeatureFlagsKHX* pPeerMemoryFeatures);
+typedef VkResult (VKAPI_PTR *PFN_vkBindBufferMemory2KHX)(VkDevice device, uint32_t bindInfoCount, const VkBindBufferMemoryInfoKHX* pBindInfos);
+typedef VkResult (VKAPI_PTR *PFN_vkBindImageMemory2KHX)(VkDevice device, uint32_t bindInfoCount, const VkBindImageMemoryInfoKHX* pBindInfos);
+typedef void (VKAPI_PTR *PFN_vkCmdSetDeviceMaskKHX)(VkCommandBuffer commandBuffer, uint32_t deviceMask);
+typedef VkResult (VKAPI_PTR *PFN_vkGetDeviceGroupPresentCapabilitiesKHX)(VkDevice device, VkDeviceGroupPresentCapabilitiesKHX* pDeviceGroupPresentCapabilities);
+typedef VkResult (VKAPI_PTR *PFN_vkGetDeviceGroupSurfacePresentModesKHX)(VkDevice device, VkSurfaceKHR surface, VkDeviceGroupPresentModeFlagsKHX* pModes);
+typedef VkResult (VKAPI_PTR *PFN_vkAcquireNextImage2KHX)(VkDevice device, const VkAcquireNextImageInfoKHX* pAcquireInfo, uint32_t* pImageIndex);
+typedef void (VKAPI_PTR *PFN_vkCmdDispatchBaseKHX)(VkCommandBuffer commandBuffer, uint32_t baseGroupX, uint32_t baseGroupY, uint32_t baseGroupZ, uint32_t groupCountX, uint32_t groupCountY, uint32_t groupCountZ);
+typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDevicePresentRectanglesKHX)(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, uint32_t* pRectCount, VkRect2D* pRects);
+
+#ifndef VK_NO_PROTOTYPES
+VKAPI_ATTR void VKAPI_CALL vkGetDeviceGroupPeerMemoryFeaturesKHX(
+ VkDevice device,
+ uint32_t heapIndex,
+ uint32_t localDeviceIndex,
+ uint32_t remoteDeviceIndex,
+ VkPeerMemoryFeatureFlagsKHX* pPeerMemoryFeatures);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkBindBufferMemory2KHX(
+ VkDevice device,
+ uint32_t bindInfoCount,
+ const VkBindBufferMemoryInfoKHX* pBindInfos);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkBindImageMemory2KHX(
+ VkDevice device,
+ uint32_t bindInfoCount,
+ const VkBindImageMemoryInfoKHX* pBindInfos);
+
+VKAPI_ATTR void VKAPI_CALL vkCmdSetDeviceMaskKHX(
+ VkCommandBuffer commandBuffer,
+ uint32_t deviceMask);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkGetDeviceGroupPresentCapabilitiesKHX(
+ VkDevice device,
+ VkDeviceGroupPresentCapabilitiesKHX* pDeviceGroupPresentCapabilities);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkGetDeviceGroupSurfacePresentModesKHX(
+ VkDevice device,
+ VkSurfaceKHR surface,
+ VkDeviceGroupPresentModeFlagsKHX* pModes);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkAcquireNextImage2KHX(
+ VkDevice device,
+ const VkAcquireNextImageInfoKHX* pAcquireInfo,
+ uint32_t* pImageIndex);
+
+VKAPI_ATTR void VKAPI_CALL vkCmdDispatchBaseKHX(
+ VkCommandBuffer commandBuffer,
+ uint32_t baseGroupX,
+ uint32_t baseGroupY,
+ uint32_t baseGroupZ,
+ uint32_t groupCountX,
+ uint32_t groupCountY,
+ uint32_t groupCountZ);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDevicePresentRectanglesKHX(
+ VkPhysicalDevice physicalDevice,
+ VkSurfaceKHR surface,
+ uint32_t* pRectCount,
+ VkRect2D* pRects);
+#endif
+
#define VK_EXT_validation_flags 1
#define VK_EXT_VALIDATION_FLAGS_SPEC_VERSION 1
#define VK_EXT_VALIDATION_FLAGS_EXTENSION_NAME "VK_EXT_validation_flags"
@@ -4336,6 +4735,428 @@
+#ifdef VK_USE_PLATFORM_VI_NN
+#define VK_NN_vi_surface 1
+#define VK_NN_VI_SURFACE_SPEC_VERSION 1
+#define VK_NN_VI_SURFACE_EXTENSION_NAME "VK_NN_vi_surface"
+
+typedef VkFlags VkViSurfaceCreateFlagsNN;
+
+typedef struct VkViSurfaceCreateInfoNN {
+ VkStructureType sType;
+ const void* pNext;
+ VkViSurfaceCreateFlagsNN flags;
+ void* window;
+} VkViSurfaceCreateInfoNN;
+
+
+typedef VkResult (VKAPI_PTR *PFN_vkCreateViSurfaceNN)(VkInstance instance, const VkViSurfaceCreateInfoNN* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface);
+
+#ifndef VK_NO_PROTOTYPES
+VKAPI_ATTR VkResult VKAPI_CALL vkCreateViSurfaceNN(
+ VkInstance instance,
+ const VkViSurfaceCreateInfoNN* pCreateInfo,
+ const VkAllocationCallbacks* pAllocator,
+ VkSurfaceKHR* pSurface);
+#endif
+#endif /* VK_USE_PLATFORM_VI_NN */
+
+#define VK_EXT_shader_subgroup_ballot 1
+#define VK_EXT_SHADER_SUBGROUP_BALLOT_SPEC_VERSION 1
+#define VK_EXT_SHADER_SUBGROUP_BALLOT_EXTENSION_NAME "VK_EXT_shader_subgroup_ballot"
+
+
+#define VK_EXT_shader_subgroup_vote 1
+#define VK_EXT_SHADER_SUBGROUP_VOTE_SPEC_VERSION 1
+#define VK_EXT_SHADER_SUBGROUP_VOTE_EXTENSION_NAME "VK_EXT_shader_subgroup_vote"
+
+
+#define VK_KHX_device_group_creation 1
+#define VK_KHX_DEVICE_GROUP_CREATION_SPEC_VERSION 1
+#define VK_KHX_DEVICE_GROUP_CREATION_EXTENSION_NAME "VK_KHX_device_group_creation"
+
+typedef struct VkPhysicalDeviceGroupPropertiesKHX {
+ VkStructureType sType;
+ const void* pNext;
+ uint32_t physicalDeviceCount;
+ VkPhysicalDevice physicalDevices[VK_MAX_DEVICE_GROUP_SIZE_KHX];
+ VkBool32 subsetAllocation;
+} VkPhysicalDeviceGroupPropertiesKHX;
+
+typedef struct VkDeviceGroupDeviceCreateInfoKHX {
+ VkStructureType sType;
+ const void* pNext;
+ uint32_t physicalDeviceCount;
+ const VkPhysicalDevice* pPhysicalDevices;
+} VkDeviceGroupDeviceCreateInfoKHX;
+
+
+typedef VkResult (VKAPI_PTR *PFN_vkEnumeratePhysicalDeviceGroupsKHX)(VkInstance instance, uint32_t* pPhysicalDeviceGroupCount, VkPhysicalDeviceGroupPropertiesKHX* pPhysicalDeviceGroupProperties);
+
+#ifndef VK_NO_PROTOTYPES
+VKAPI_ATTR VkResult VKAPI_CALL vkEnumeratePhysicalDeviceGroupsKHX(
+ VkInstance instance,
+ uint32_t* pPhysicalDeviceGroupCount,
+ VkPhysicalDeviceGroupPropertiesKHX* pPhysicalDeviceGroupProperties);
+#endif
+
+#define VK_KHX_external_memory_capabilities 1
+#define VK_LUID_SIZE_KHX 8
+#define VK_KHX_EXTERNAL_MEMORY_CAPABILITIES_SPEC_VERSION 1
+#define VK_KHX_EXTERNAL_MEMORY_CAPABILITIES_EXTENSION_NAME "VK_KHX_external_memory_capabilities"
+
+
+typedef enum VkExternalMemoryHandleTypeFlagBitsKHX {
+ VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT_KHX = 0x00000001,
+ VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT_KHX = 0x00000002,
+ VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT_KHX = 0x00000004,
+ VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_BIT_KHX = 0x00000008,
+ VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_KMT_BIT_KHX = 0x00000010,
+ VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_HEAP_BIT_KHX = 0x00000020,
+ VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_RESOURCE_BIT_KHX = 0x00000040,
+ VK_EXTERNAL_MEMORY_HANDLE_TYPE_FLAG_BITS_MAX_ENUM_KHX = 0x7FFFFFFF
+} VkExternalMemoryHandleTypeFlagBitsKHX;
+typedef VkFlags VkExternalMemoryHandleTypeFlagsKHX;
+
+typedef enum VkExternalMemoryFeatureFlagBitsKHX {
+ VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT_KHX = 0x00000001,
+ VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT_KHX = 0x00000002,
+ VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT_KHX = 0x00000004,
+ VK_EXTERNAL_MEMORY_FEATURE_FLAG_BITS_MAX_ENUM_KHX = 0x7FFFFFFF
+} VkExternalMemoryFeatureFlagBitsKHX;
+typedef VkFlags VkExternalMemoryFeatureFlagsKHX;
+
+typedef struct VkExternalMemoryPropertiesKHX {
+ VkExternalMemoryFeatureFlagsKHX externalMemoryFeatures;
+ VkExternalMemoryHandleTypeFlagsKHX exportFromImportedHandleTypes;
+ VkExternalMemoryHandleTypeFlagsKHX compatibleHandleTypes;
+} VkExternalMemoryPropertiesKHX;
+
+typedef struct VkPhysicalDeviceExternalImageFormatInfoKHX {
+ VkStructureType sType;
+ const void* pNext;
+ VkExternalMemoryHandleTypeFlagBitsKHX handleType;
+} VkPhysicalDeviceExternalImageFormatInfoKHX;
+
+typedef struct VkExternalImageFormatPropertiesKHX {
+ VkStructureType sType;
+ void* pNext;
+ VkExternalMemoryPropertiesKHX externalMemoryProperties;
+} VkExternalImageFormatPropertiesKHX;
+
+typedef struct VkPhysicalDeviceExternalBufferInfoKHX {
+ VkStructureType sType;
+ const void* pNext;
+ VkBufferCreateFlags flags;
+ VkBufferUsageFlags usage;
+ VkExternalMemoryHandleTypeFlagBitsKHX handleType;
+} VkPhysicalDeviceExternalBufferInfoKHX;
+
+typedef struct VkExternalBufferPropertiesKHX {
+ VkStructureType sType;
+ void* pNext;
+ VkExternalMemoryPropertiesKHX externalMemoryProperties;
+} VkExternalBufferPropertiesKHX;
+
+typedef struct VkPhysicalDeviceIDPropertiesKHX {
+ VkStructureType sType;
+ void* pNext;
+ uint8_t deviceUUID[VK_UUID_SIZE];
+ uint8_t driverUUID[VK_UUID_SIZE];
+ uint8_t deviceLUID[VK_LUID_SIZE_KHX];
+ VkBool32 deviceLUIDValid;
+} VkPhysicalDeviceIDPropertiesKHX;
+
+
+typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceExternalBufferPropertiesKHX)(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceExternalBufferInfoKHX* pExternalBufferInfo, VkExternalBufferPropertiesKHX* pExternalBufferProperties);
+
+#ifndef VK_NO_PROTOTYPES
+VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceExternalBufferPropertiesKHX(
+ VkPhysicalDevice physicalDevice,
+ const VkPhysicalDeviceExternalBufferInfoKHX* pExternalBufferInfo,
+ VkExternalBufferPropertiesKHX* pExternalBufferProperties);
+#endif
+
+#define VK_KHX_external_memory 1
+#define VK_KHX_EXTERNAL_MEMORY_SPEC_VERSION 1
+#define VK_KHX_EXTERNAL_MEMORY_EXTENSION_NAME "VK_KHX_external_memory"
+#define VK_QUEUE_FAMILY_EXTERNAL_KHX (~0U-1)
+
+typedef struct VkExternalMemoryImageCreateInfoKHX {
+ VkStructureType sType;
+ const void* pNext;
+ VkExternalMemoryHandleTypeFlagsKHX handleTypes;
+} VkExternalMemoryImageCreateInfoKHX;
+
+typedef struct VkExternalMemoryBufferCreateInfoKHX {
+ VkStructureType sType;
+ const void* pNext;
+ VkExternalMemoryHandleTypeFlagsKHX handleTypes;
+} VkExternalMemoryBufferCreateInfoKHX;
+
+typedef struct VkExportMemoryAllocateInfoKHX {
+ VkStructureType sType;
+ const void* pNext;
+ VkExternalMemoryHandleTypeFlagsKHX handleTypes;
+} VkExportMemoryAllocateInfoKHX;
+
+
+
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+#define VK_KHX_external_memory_win32 1
+#define VK_KHX_EXTERNAL_MEMORY_WIN32_SPEC_VERSION 1
+#define VK_KHX_EXTERNAL_MEMORY_WIN32_EXTENSION_NAME "VK_KHX_external_memory_win32"
+
+typedef struct VkImportMemoryWin32HandleInfoKHX {
+ VkStructureType sType;
+ const void* pNext;
+ VkExternalMemoryHandleTypeFlagBitsKHX handleType;
+ HANDLE handle;
+} VkImportMemoryWin32HandleInfoKHX;
+
+typedef struct VkExportMemoryWin32HandleInfoKHX {
+ VkStructureType sType;
+ const void* pNext;
+ const SECURITY_ATTRIBUTES* pAttributes;
+ DWORD dwAccess;
+ LPCWSTR name;
+} VkExportMemoryWin32HandleInfoKHX;
+
+typedef struct VkMemoryWin32HandlePropertiesKHX {
+ VkStructureType sType;
+ void* pNext;
+ uint32_t memoryTypeBits;
+} VkMemoryWin32HandlePropertiesKHX;
+
+
+typedef VkResult (VKAPI_PTR *PFN_vkGetMemoryWin32HandleKHX)(VkDevice device, VkDeviceMemory memory, VkExternalMemoryHandleTypeFlagBitsKHX handleType, HANDLE* pHandle);
+typedef VkResult (VKAPI_PTR *PFN_vkGetMemoryWin32HandlePropertiesKHX)(VkDevice device, VkExternalMemoryHandleTypeFlagBitsKHX handleType, HANDLE handle, VkMemoryWin32HandlePropertiesKHX* pMemoryWin32HandleProperties);
+
+#ifndef VK_NO_PROTOTYPES
+VKAPI_ATTR VkResult VKAPI_CALL vkGetMemoryWin32HandleKHX(
+ VkDevice device,
+ VkDeviceMemory memory,
+ VkExternalMemoryHandleTypeFlagBitsKHX handleType,
+ HANDLE* pHandle);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkGetMemoryWin32HandlePropertiesKHX(
+ VkDevice device,
+ VkExternalMemoryHandleTypeFlagBitsKHX handleType,
+ HANDLE handle,
+ VkMemoryWin32HandlePropertiesKHX* pMemoryWin32HandleProperties);
+#endif
+#endif /* VK_USE_PLATFORM_WIN32_KHR */
+
+#define VK_KHX_external_memory_fd 1
+#define VK_KHX_EXTERNAL_MEMORY_FD_SPEC_VERSION 1
+#define VK_KHX_EXTERNAL_MEMORY_FD_EXTENSION_NAME "VK_KHX_external_memory_fd"
+
+typedef struct VkImportMemoryFdInfoKHX {
+ VkStructureType sType;
+ const void* pNext;
+ VkExternalMemoryHandleTypeFlagBitsKHX handleType;
+ int fd;
+} VkImportMemoryFdInfoKHX;
+
+typedef struct VkMemoryFdPropertiesKHX {
+ VkStructureType sType;
+ void* pNext;
+ uint32_t memoryTypeBits;
+} VkMemoryFdPropertiesKHX;
+
+
+typedef VkResult (VKAPI_PTR *PFN_vkGetMemoryFdKHX)(VkDevice device, VkDeviceMemory memory, VkExternalMemoryHandleTypeFlagBitsKHX handleType, int* pFd);
+typedef VkResult (VKAPI_PTR *PFN_vkGetMemoryFdPropertiesKHX)(VkDevice device, VkExternalMemoryHandleTypeFlagBitsKHX handleType, int fd, VkMemoryFdPropertiesKHX* pMemoryFdProperties);
+
+#ifndef VK_NO_PROTOTYPES
+VKAPI_ATTR VkResult VKAPI_CALL vkGetMemoryFdKHX(
+ VkDevice device,
+ VkDeviceMemory memory,
+ VkExternalMemoryHandleTypeFlagBitsKHX handleType,
+ int* pFd);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkGetMemoryFdPropertiesKHX(
+ VkDevice device,
+ VkExternalMemoryHandleTypeFlagBitsKHX handleType,
+ int fd,
+ VkMemoryFdPropertiesKHX* pMemoryFdProperties);
+#endif
+
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+#define VK_KHX_win32_keyed_mutex 1
+#define VK_KHX_WIN32_KEYED_MUTEX_SPEC_VERSION 1
+#define VK_KHX_WIN32_KEYED_MUTEX_EXTENSION_NAME "VK_KHX_win32_keyed_mutex"
+
+typedef struct VkWin32KeyedMutexAcquireReleaseInfoKHX {
+ VkStructureType sType;
+ const void* pNext;
+ uint32_t acquireCount;
+ const VkDeviceMemory* pAcquireSyncs;
+ const uint64_t* pAcquireKeys;
+ const uint32_t* pAcquireTimeouts;
+ uint32_t releaseCount;
+ const VkDeviceMemory* pReleaseSyncs;
+ const uint64_t* pReleaseKeys;
+} VkWin32KeyedMutexAcquireReleaseInfoKHX;
+
+
+#endif /* VK_USE_PLATFORM_WIN32_KHR */
+
+#define VK_KHX_external_semaphore_capabilities 1
+#define VK_KHX_EXTERNAL_SEMAPHORE_CAPABILITIES_SPEC_VERSION 1
+#define VK_KHX_EXTERNAL_SEMAPHORE_CAPABILITIES_EXTENSION_NAME "VK_KHX_external_semaphore_capabilities"
+
+
+typedef enum VkExternalSemaphoreHandleTypeFlagBitsKHX {
+ VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT_KHX = 0x00000001,
+ VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT_KHX = 0x00000002,
+ VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT_KHX = 0x00000004,
+ VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_D3D12_FENCE_BIT_KHX = 0x00000008,
+ VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_FENCE_FD_BIT_KHX = 0x00000010,
+ VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_FLAG_BITS_MAX_ENUM_KHX = 0x7FFFFFFF
+} VkExternalSemaphoreHandleTypeFlagBitsKHX;
+typedef VkFlags VkExternalSemaphoreHandleTypeFlagsKHX;
+
+typedef enum VkExternalSemaphoreFeatureFlagBitsKHX {
+ VK_EXTERNAL_SEMAPHORE_FEATURE_EXPORTABLE_BIT_KHX = 0x00000001,
+ VK_EXTERNAL_SEMAPHORE_FEATURE_IMPORTABLE_BIT_KHX = 0x00000002,
+ VK_EXTERNAL_SEMAPHORE_FEATURE_FLAG_BITS_MAX_ENUM_KHX = 0x7FFFFFFF
+} VkExternalSemaphoreFeatureFlagBitsKHX;
+typedef VkFlags VkExternalSemaphoreFeatureFlagsKHX;
+
+typedef struct VkPhysicalDeviceExternalSemaphoreInfoKHX {
+ VkStructureType sType;
+ const void* pNext;
+ VkExternalSemaphoreHandleTypeFlagBitsKHX handleType;
+} VkPhysicalDeviceExternalSemaphoreInfoKHX;
+
+typedef struct VkExternalSemaphorePropertiesKHX {
+ VkStructureType sType;
+ void* pNext;
+ VkExternalSemaphoreHandleTypeFlagsKHX exportFromImportedHandleTypes;
+ VkExternalSemaphoreHandleTypeFlagsKHX compatibleHandleTypes;
+ VkExternalSemaphoreFeatureFlagsKHX externalSemaphoreFeatures;
+} VkExternalSemaphorePropertiesKHX;
+
+
+typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceExternalSemaphorePropertiesKHX)(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceExternalSemaphoreInfoKHX* pExternalSemaphoreInfo, VkExternalSemaphorePropertiesKHX* pExternalSemaphoreProperties);
+
+#ifndef VK_NO_PROTOTYPES
+VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceExternalSemaphorePropertiesKHX(
+ VkPhysicalDevice physicalDevice,
+ const VkPhysicalDeviceExternalSemaphoreInfoKHX* pExternalSemaphoreInfo,
+ VkExternalSemaphorePropertiesKHX* pExternalSemaphoreProperties);
+#endif
+
+#define VK_KHX_external_semaphore 1
+#define VK_KHX_EXTERNAL_SEMAPHORE_SPEC_VERSION 1
+#define VK_KHX_EXTERNAL_SEMAPHORE_EXTENSION_NAME "VK_KHX_external_semaphore"
+
+typedef struct VkExportSemaphoreCreateInfoKHX {
+ VkStructureType sType;
+ const void* pNext;
+ VkExternalSemaphoreHandleTypeFlagsKHX handleTypes;
+} VkExportSemaphoreCreateInfoKHX;
+
+
+
+#ifdef VK_USE_PLATFORM_WIN32_KHX
+#define VK_KHX_external_semaphore_win32 1
+#define VK_KHX_EXTERNAL_SEMAPHORE_WIN32_SPEC_VERSION 1
+#define VK_KHX_EXTERNAL_SEMAPHORE_WIN32_EXTENSION_NAME "VK_KHX_external_semaphore_win32"
+
+typedef struct VkImportSemaphoreWin32HandleInfoKHX {
+ VkStructureType sType;
+ const void* pNext;
+ VkSemaphore semaphore;
+ VkExternalSemaphoreHandleTypeFlagsKHX handleType;
+ HANDLE handle;
+} VkImportSemaphoreWin32HandleInfoKHX;
+
+typedef struct VkExportSemaphoreWin32HandleInfoKHX {
+ VkStructureType sType;
+ const void* pNext;
+ const SECURITY_ATTRIBUTES* pAttributes;
+ DWORD dwAccess;
+ LPCWSTR name;
+} VkExportSemaphoreWin32HandleInfoKHX;
+
+typedef struct VkD3D12FenceSubmitInfoKHX {
+ VkStructureType sType;
+ const void* pNext;
+ uint32_t waitSemaphoreValuesCount;
+ const uint64_t* pWaitSemaphoreValues;
+ uint32_t signalSemaphoreValuesCount;
+ const uint64_t* pSignalSemaphoreValues;
+} VkD3D12FenceSubmitInfoKHX;
+
+
+typedef VkResult (VKAPI_PTR *PFN_vkImportSemaphoreWin32HandleKHX)(VkDevice device, const VkImportSemaphoreWin32HandleInfoKHX* pImportSemaphoreWin32HandleInfo);
+typedef VkResult (VKAPI_PTR *PFN_vkGetSemaphoreWin32HandleKHX)(VkDevice device, VkSemaphore semaphore, VkExternalSemaphoreHandleTypeFlagBitsKHX handleType, HANDLE* pHandle);
+
+#ifndef VK_NO_PROTOTYPES
+VKAPI_ATTR VkResult VKAPI_CALL vkImportSemaphoreWin32HandleKHX(
+ VkDevice device,
+ const VkImportSemaphoreWin32HandleInfoKHX* pImportSemaphoreWin32HandleInfo);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkGetSemaphoreWin32HandleKHX(
+ VkDevice device,
+ VkSemaphore semaphore,
+ VkExternalSemaphoreHandleTypeFlagBitsKHX handleType,
+ HANDLE* pHandle);
+#endif
+#endif /* VK_USE_PLATFORM_WIN32_KHX */
+
+#define VK_KHX_external_semaphore_fd 1
+#define VK_KHX_EXTERNAL_SEMAPHORE_FD_SPEC_VERSION 1
+#define VK_KHX_EXTERNAL_SEMAPHORE_FD_EXTENSION_NAME "VK_KHX_external_semaphore_fd"
+
+typedef struct VkImportSemaphoreFdInfoKHX {
+ VkStructureType sType;
+ const void* pNext;
+ VkSemaphore semaphore;
+ VkExternalSemaphoreHandleTypeFlagBitsKHX handleType;
+ int fd;
+} VkImportSemaphoreFdInfoKHX;
+
+
+typedef VkResult (VKAPI_PTR *PFN_vkImportSemaphoreFdKHX)(VkDevice device, const VkImportSemaphoreFdInfoKHX* pImportSemaphoreFdInfo);
+typedef VkResult (VKAPI_PTR *PFN_vkGetSemaphoreFdKHX)(VkDevice device, VkSemaphore semaphore, VkExternalSemaphoreHandleTypeFlagBitsKHX handleType, int* pFd);
+
+#ifndef VK_NO_PROTOTYPES
+VKAPI_ATTR VkResult VKAPI_CALL vkImportSemaphoreFdKHX(
+ VkDevice device,
+ const VkImportSemaphoreFdInfoKHX* pImportSemaphoreFdInfo);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkGetSemaphoreFdKHX(
+ VkDevice device,
+ VkSemaphore semaphore,
+ VkExternalSemaphoreHandleTypeFlagBitsKHX handleType,
+ int* pFd);
+#endif
+
+#define VK_KHR_incremental_present 1
+#define VK_KHR_INCREMENTAL_PRESENT_SPEC_VERSION 1
+#define VK_KHR_INCREMENTAL_PRESENT_EXTENSION_NAME "VK_KHR_incremental_present"
+
+typedef struct VkRectLayerKHR {
+ VkOffset2D offset;
+ VkExtent2D extent;
+ uint32_t layer;
+} VkRectLayerKHR;
+
+typedef struct VkPresentRegionKHR {
+ uint32_t rectangleCount;
+ const VkRectLayerKHR* pRectangles;
+} VkPresentRegionKHR;
+
+typedef struct VkPresentRegionsKHR {
+ VkStructureType sType;
+ const void* pNext;
+ uint32_t swapchainCount;
+ const VkPresentRegionKHR* pRegions;
+} VkPresentRegionsKHR;
+
#define VK_NVX_device_generated_commands 1
VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkObjectTableNVX)
VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkIndirectCommandsLayoutNVX)
@@ -4491,6 +5312,7 @@
VkObjectEntryTypeNVX type;
VkObjectEntryUsageFlagsNVX flags;
VkBuffer buffer;
+ VkIndexType indexType;
} VkObjectTableIndexBufferEntryNVX;
typedef struct VkObjectTablePushConstantEntryNVX {
@@ -4562,6 +5384,194 @@
VkDeviceGeneratedCommandsLimitsNVX* pLimits);
#endif
+#define VK_NV_clip_space_w_scaling 1
+#define VK_NV_CLIP_SPACE_W_SCALING_SPEC_VERSION 1
+#define VK_NV_CLIP_SPACE_W_SCALING_EXTENSION_NAME "VK_NV_clip_space_w_scaling"
+
+typedef struct VkViewportWScalingNV {
+ float xcoeff;
+ float ycoeff;
+} VkViewportWScalingNV;
+
+typedef struct VkPipelineViewportWScalingStateCreateInfoNV {
+ VkStructureType sType;
+ const void* pNext;
+ VkBool32 viewportWScalingEnable;
+ uint32_t viewportCount;
+ const VkViewportWScalingNV* pViewportWScalings;
+} VkPipelineViewportWScalingStateCreateInfoNV;
+
+
+typedef void (VKAPI_PTR *PFN_vkCmdSetViewportWScalingNV)(VkCommandBuffer commandBuffer, uint32_t firstViewport, uint32_t viewportCount, const VkViewportWScalingNV* pViewportWScalings);
+
+#ifndef VK_NO_PROTOTYPES
+VKAPI_ATTR void VKAPI_CALL vkCmdSetViewportWScalingNV(
+ VkCommandBuffer commandBuffer,
+ uint32_t firstViewport,
+ uint32_t viewportCount,
+ const VkViewportWScalingNV* pViewportWScalings);
+#endif
+
+#define VK_EXT_direct_mode_display 1
+#define VK_EXT_DIRECT_MODE_DISPLAY_SPEC_VERSION 1
+#define VK_EXT_DIRECT_MODE_DISPLAY_EXTENSION_NAME "VK_EXT_direct_mode_display"
+
+typedef VkResult (VKAPI_PTR *PFN_vkReleaseDisplayEXT)(VkPhysicalDevice physicalDevice, VkDisplayKHR display);
+
+#ifndef VK_NO_PROTOTYPES
+VKAPI_ATTR VkResult VKAPI_CALL vkReleaseDisplayEXT(
+ VkPhysicalDevice physicalDevice,
+ VkDisplayKHR display);
+#endif
+
+#ifdef VK_USE_PLATFORM_XLIB_XRANDR_EXT
+#define VK_EXT_acquire_xlib_display 1
+#include <X11/extensions/Xrandr.h>
+
+#define VK_EXT_ACQUIRE_XLIB_DISPLAY_SPEC_VERSION 1
+#define VK_EXT_ACQUIRE_XLIB_DISPLAY_EXTENSION_NAME "VK_EXT_acquire_xlib_display"
+
+typedef VkResult (VKAPI_PTR *PFN_vkAcquireXlibDisplayEXT)(VkPhysicalDevice physicalDevice, Display* dpy, VkDisplayKHR display);
+typedef VkResult (VKAPI_PTR *PFN_vkGetRandROutputDisplayEXT)(VkPhysicalDevice physicalDevice, Display* dpy, RROutput rrOutput, VkDisplayKHR* pDisplay);
+
+#ifndef VK_NO_PROTOTYPES
+VKAPI_ATTR VkResult VKAPI_CALL vkAcquireXlibDisplayEXT(
+ VkPhysicalDevice physicalDevice,
+ Display* dpy,
+ VkDisplayKHR display);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkGetRandROutputDisplayEXT(
+ VkPhysicalDevice physicalDevice,
+ Display* dpy,
+ RROutput rrOutput,
+ VkDisplayKHR* pDisplay);
+#endif
+#endif /* VK_USE_PLATFORM_XLIB_XRANDR_EXT */
+
+#define VK_EXT_display_surface_counter 1
+#define VK_EXT_DISPLAY_SURFACE_COUNTER_SPEC_VERSION 1
+#define VK_EXT_DISPLAY_SURFACE_COUNTER_EXTENSION_NAME "VK_EXT_display_surface_counter"
+
+
+typedef enum VkSurfaceCounterFlagBitsEXT {
+ VK_SURFACE_COUNTER_VBLANK_EXT = 0x00000001,
+ VK_SURFACE_COUNTER_FLAG_BITS_MAX_ENUM_EXT = 0x7FFFFFFF
+} VkSurfaceCounterFlagBitsEXT;
+typedef VkFlags VkSurfaceCounterFlagsEXT;
+
+typedef struct VkSurfaceCapabilities2EXT {
+ VkStructureType sType;
+ void* pNext;
+ uint32_t minImageCount;
+ uint32_t maxImageCount;
+ VkExtent2D currentExtent;
+ VkExtent2D minImageExtent;
+ VkExtent2D maxImageExtent;
+ uint32_t maxImageArrayLayers;
+ VkSurfaceTransformFlagsKHR supportedTransforms;
+ VkSurfaceTransformFlagBitsKHR currentTransform;
+ VkCompositeAlphaFlagsKHR supportedCompositeAlpha;
+ VkImageUsageFlags supportedUsageFlags;
+ VkSurfaceCounterFlagsEXT supportedSurfaceCounters;
+} VkSurfaceCapabilities2EXT;
+
+
+typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceSurfaceCapabilities2EXT)(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, VkSurfaceCapabilities2EXT* pSurfaceCapabilities);
+
+#ifndef VK_NO_PROTOTYPES
+VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceSurfaceCapabilities2EXT(
+ VkPhysicalDevice physicalDevice,
+ VkSurfaceKHR surface,
+ VkSurfaceCapabilities2EXT* pSurfaceCapabilities);
+#endif
+
+#define VK_EXT_display_control 1
+#define VK_EXT_DISPLAY_CONTROL_SPEC_VERSION 1
+#define VK_EXT_DISPLAY_CONTROL_EXTENSION_NAME "VK_EXT_display_control"
+
+
+typedef enum VkDisplayPowerStateEXT {
+ VK_DISPLAY_POWER_STATE_OFF_EXT = 0,
+ VK_DISPLAY_POWER_STATE_SUSPEND_EXT = 1,
+ VK_DISPLAY_POWER_STATE_ON_EXT = 2,
+ VK_DISPLAY_POWER_STATE_BEGIN_RANGE_EXT = VK_DISPLAY_POWER_STATE_OFF_EXT,
+ VK_DISPLAY_POWER_STATE_END_RANGE_EXT = VK_DISPLAY_POWER_STATE_ON_EXT,
+ VK_DISPLAY_POWER_STATE_RANGE_SIZE_EXT = (VK_DISPLAY_POWER_STATE_ON_EXT - VK_DISPLAY_POWER_STATE_OFF_EXT + 1),
+ VK_DISPLAY_POWER_STATE_MAX_ENUM_EXT = 0x7FFFFFFF
+} VkDisplayPowerStateEXT;
+
+typedef enum VkDeviceEventTypeEXT {
+ VK_DEVICE_EVENT_TYPE_DISPLAY_HOTPLUG_EXT = 0,
+ VK_DEVICE_EVENT_TYPE_BEGIN_RANGE_EXT = VK_DEVICE_EVENT_TYPE_DISPLAY_HOTPLUG_EXT,
+ VK_DEVICE_EVENT_TYPE_END_RANGE_EXT = VK_DEVICE_EVENT_TYPE_DISPLAY_HOTPLUG_EXT,
+ VK_DEVICE_EVENT_TYPE_RANGE_SIZE_EXT = (VK_DEVICE_EVENT_TYPE_DISPLAY_HOTPLUG_EXT - VK_DEVICE_EVENT_TYPE_DISPLAY_HOTPLUG_EXT + 1),
+ VK_DEVICE_EVENT_TYPE_MAX_ENUM_EXT = 0x7FFFFFFF
+} VkDeviceEventTypeEXT;
+
+typedef enum VkDisplayEventTypeEXT {
+ VK_DISPLAY_EVENT_TYPE_FIRST_PIXEL_OUT_EXT = 0,
+ VK_DISPLAY_EVENT_TYPE_BEGIN_RANGE_EXT = VK_DISPLAY_EVENT_TYPE_FIRST_PIXEL_OUT_EXT,
+ VK_DISPLAY_EVENT_TYPE_END_RANGE_EXT = VK_DISPLAY_EVENT_TYPE_FIRST_PIXEL_OUT_EXT,
+ VK_DISPLAY_EVENT_TYPE_RANGE_SIZE_EXT = (VK_DISPLAY_EVENT_TYPE_FIRST_PIXEL_OUT_EXT - VK_DISPLAY_EVENT_TYPE_FIRST_PIXEL_OUT_EXT + 1),
+ VK_DISPLAY_EVENT_TYPE_MAX_ENUM_EXT = 0x7FFFFFFF
+} VkDisplayEventTypeEXT;
+
+typedef struct VkDisplayPowerInfoEXT {
+ VkStructureType sType;
+ const void* pNext;
+ VkDisplayPowerStateEXT powerState;
+} VkDisplayPowerInfoEXT;
+
+typedef struct VkDeviceEventInfoEXT {
+ VkStructureType sType;
+ const void* pNext;
+ VkDeviceEventTypeEXT deviceEvent;
+} VkDeviceEventInfoEXT;
+
+typedef struct VkDisplayEventInfoEXT {
+ VkStructureType sType;
+ const void* pNext;
+ VkDisplayEventTypeEXT displayEvent;
+} VkDisplayEventInfoEXT;
+
+typedef struct VkSwapchainCounterCreateInfoEXT {
+ VkStructureType sType;
+ const void* pNext;
+ VkSurfaceCounterFlagsEXT surfaceCounters;
+} VkSwapchainCounterCreateInfoEXT;
+
+
+typedef VkResult (VKAPI_PTR *PFN_vkDisplayPowerControlEXT)(VkDevice device, VkDisplayKHR display, const VkDisplayPowerInfoEXT* pDisplayPowerInfo);
+typedef VkResult (VKAPI_PTR *PFN_vkRegisterDeviceEventEXT)(VkDevice device, const VkDeviceEventInfoEXT* pDeviceEventInfo, const VkAllocationCallbacks* pAllocator, VkFence* pFence);
+typedef VkResult (VKAPI_PTR *PFN_vkRegisterDisplayEventEXT)(VkDevice device, VkDisplayKHR display, const VkDisplayEventInfoEXT* pDisplayEventInfo, const VkAllocationCallbacks* pAllocator, VkFence* pFence);
+typedef VkResult (VKAPI_PTR *PFN_vkGetSwapchainCounterEXT)(VkDevice device, VkSwapchainKHR swapchain, VkSurfaceCounterFlagBitsEXT counter, uint64_t* pCounterValue);
+
+#ifndef VK_NO_PROTOTYPES
+VKAPI_ATTR VkResult VKAPI_CALL vkDisplayPowerControlEXT(
+ VkDevice device,
+ VkDisplayKHR display,
+ const VkDisplayPowerInfoEXT* pDisplayPowerInfo);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkRegisterDeviceEventEXT(
+ VkDevice device,
+ const VkDeviceEventInfoEXT* pDeviceEventInfo,
+ const VkAllocationCallbacks* pAllocator,
+ VkFence* pFence);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkRegisterDisplayEventEXT(
+ VkDevice device,
+ VkDisplayKHR display,
+ const VkDisplayEventInfoEXT* pDisplayEventInfo,
+ const VkAllocationCallbacks* pAllocator,
+ VkFence* pFence);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkGetSwapchainCounterEXT(
+ VkDevice device,
+ VkSwapchainKHR swapchain,
+ VkSurfaceCounterFlagBitsEXT counter,
+ uint64_t* pCounterValue);
+#endif
+
#define VK_GOOGLE_display_timing 1
#define VK_GOOGLE_DISPLAY_TIMING_SPEC_VERSION 1
#define VK_GOOGLE_DISPLAY_TIMING_EXTENSION_NAME "VK_GOOGLE_display_timing"
@@ -4607,12 +5617,120 @@
VkPastPresentationTimingGOOGLE* pPresentationTimings);
#endif
+#define VK_NV_sample_mask_override_coverage 1
+#define VK_NV_SAMPLE_MASK_OVERRIDE_COVERAGE_SPEC_VERSION 1
+#define VK_NV_SAMPLE_MASK_OVERRIDE_COVERAGE_EXTENSION_NAME "VK_NV_sample_mask_override_coverage"
+
+
+#define VK_NV_geometry_shader_passthrough 1
+#define VK_NV_GEOMETRY_SHADER_PASSTHROUGH_SPEC_VERSION 1
+#define VK_NV_GEOMETRY_SHADER_PASSTHROUGH_EXTENSION_NAME "VK_NV_geometry_shader_passthrough"
+
+
+#define VK_NV_viewport_array2 1
+#define VK_NV_VIEWPORT_ARRAY2_SPEC_VERSION 1
+#define VK_NV_VIEWPORT_ARRAY2_EXTENSION_NAME "VK_NV_viewport_array2"
+
+
+#define VK_NVX_multiview_per_view_attributes 1
+#define VK_NVX_MULTIVIEW_PER_VIEW_ATTRIBUTES_SPEC_VERSION 1
+#define VK_NVX_MULTIVIEW_PER_VIEW_ATTRIBUTES_EXTENSION_NAME "VK_NVX_multiview_per_view_attributes"
+
+typedef struct VkPhysicalDeviceMultiviewPerViewAttributesPropertiesNVX {
+ VkStructureType sType;
+ void* pNext;
+ VkBool32 perViewPositionAllComponents;
+} VkPhysicalDeviceMultiviewPerViewAttributesPropertiesNVX;
+
+
+
+#define VK_NV_viewport_swizzle 1
+#define VK_NV_VIEWPORT_SWIZZLE_SPEC_VERSION 1
+#define VK_NV_VIEWPORT_SWIZZLE_EXTENSION_NAME "VK_NV_viewport_swizzle"
+
+
+typedef enum VkViewportCoordinateSwizzleNV {
+ VK_VIEWPORT_COORDINATE_SWIZZLE_POSITIVE_X_NV = 0,
+ VK_VIEWPORT_COORDINATE_SWIZZLE_NEGATIVE_X_NV = 1,
+ VK_VIEWPORT_COORDINATE_SWIZZLE_POSITIVE_Y_NV = 2,
+ VK_VIEWPORT_COORDINATE_SWIZZLE_NEGATIVE_Y_NV = 3,
+ VK_VIEWPORT_COORDINATE_SWIZZLE_POSITIVE_Z_NV = 4,
+ VK_VIEWPORT_COORDINATE_SWIZZLE_NEGATIVE_Z_NV = 5,
+ VK_VIEWPORT_COORDINATE_SWIZZLE_POSITIVE_W_NV = 6,
+ VK_VIEWPORT_COORDINATE_SWIZZLE_NEGATIVE_W_NV = 7,
+ VK_VIEWPORT_COORDINATE_SWIZZLE_BEGIN_RANGE_NV = VK_VIEWPORT_COORDINATE_SWIZZLE_POSITIVE_X_NV,
+ VK_VIEWPORT_COORDINATE_SWIZZLE_END_RANGE_NV = VK_VIEWPORT_COORDINATE_SWIZZLE_NEGATIVE_W_NV,
+ VK_VIEWPORT_COORDINATE_SWIZZLE_RANGE_SIZE_NV = (VK_VIEWPORT_COORDINATE_SWIZZLE_NEGATIVE_W_NV - VK_VIEWPORT_COORDINATE_SWIZZLE_POSITIVE_X_NV + 1),
+ VK_VIEWPORT_COORDINATE_SWIZZLE_MAX_ENUM_NV = 0x7FFFFFFF
+} VkViewportCoordinateSwizzleNV;
+
+typedef VkFlags VkPipelineViewportSwizzleStateCreateFlagsNV;
+
+typedef struct VkViewportSwizzleNV {
+ VkViewportCoordinateSwizzleNV x;
+ VkViewportCoordinateSwizzleNV y;
+ VkViewportCoordinateSwizzleNV z;
+ VkViewportCoordinateSwizzleNV w;
+} VkViewportSwizzleNV;
+
+typedef struct VkPipelineViewportSwizzleStateCreateInfoNV {
+ VkStructureType sType;
+ const void* pNext;
+ VkPipelineViewportSwizzleStateCreateFlagsNV flags;
+ uint32_t viewportCount;
+ const VkViewportSwizzleNV* pViewportSwizzles;
+} VkPipelineViewportSwizzleStateCreateInfoNV;
+
+
+
+#define VK_EXT_discard_rectangles 1
+#define VK_EXT_DISCARD_RECTANGLES_SPEC_VERSION 1
+#define VK_EXT_DISCARD_RECTANGLES_EXTENSION_NAME "VK_EXT_discard_rectangles"
+
+
+typedef enum VkDiscardRectangleModeEXT {
+ VK_DISCARD_RECTANGLE_MODE_INCLUSIVE_EXT = 0,
+ VK_DISCARD_RECTANGLE_MODE_EXCLUSIVE_EXT = 1,
+ VK_DISCARD_RECTANGLE_MODE_BEGIN_RANGE_EXT = VK_DISCARD_RECTANGLE_MODE_INCLUSIVE_EXT,
+ VK_DISCARD_RECTANGLE_MODE_END_RANGE_EXT = VK_DISCARD_RECTANGLE_MODE_EXCLUSIVE_EXT,
+ VK_DISCARD_RECTANGLE_MODE_RANGE_SIZE_EXT = (VK_DISCARD_RECTANGLE_MODE_EXCLUSIVE_EXT - VK_DISCARD_RECTANGLE_MODE_INCLUSIVE_EXT + 1),
+ VK_DISCARD_RECTANGLE_MODE_MAX_ENUM_EXT = 0x7FFFFFFF
+} VkDiscardRectangleModeEXT;
+
+typedef VkFlags VkPipelineDiscardRectangleStateCreateFlagsEXT;
+
+typedef struct VkPhysicalDeviceDiscardRectanglePropertiesEXT {
+ VkStructureType sType;
+ const void* pNext;
+ uint32_t maxDiscardRectangles;
+} VkPhysicalDeviceDiscardRectanglePropertiesEXT;
+
+typedef struct VkPipelineDiscardRectangleStateCreateInfoEXT {
+ VkStructureType sType;
+ const void* pNext;
+ VkPipelineDiscardRectangleStateCreateFlagsEXT flags;
+ VkDiscardRectangleModeEXT discardRectangleMode;
+ uint32_t discardRectangleCount;
+ const VkRect2D* pDiscardRectangles;
+} VkPipelineDiscardRectangleStateCreateInfoEXT;
+
+
+typedef void (VKAPI_PTR *PFN_vkCmdSetDiscardRectangleEXT)(VkCommandBuffer commandBuffer, uint32_t firstDiscardRectangle, uint32_t discardRectangleCount, const VkRect2D* pDiscardRectangles);
+
+#ifndef VK_NO_PROTOTYPES
+VKAPI_ATTR void VKAPI_CALL vkCmdSetDiscardRectangleEXT(
+ VkCommandBuffer commandBuffer,
+ uint32_t firstDiscardRectangle,
+ uint32_t discardRectangleCount,
+ const VkRect2D* pDiscardRectangles);
+#endif
+
#define VK_EXT_swapchain_colorspace 1
#define VK_EXT_SWAPCHAIN_COLOR_SPACE_SPEC_VERSION 1
#define VK_EXT_SWAPCHAIN_COLOR_SPACE_EXTENSION_NAME "VK_EXT_swapchain_colorspace"
#define VK_EXT_hdr_metadata 1
-#define VK_EXT_HDR_METADATA_SPEC_VERSION 0
+#define VK_EXT_HDR_METADATA_SPEC_VERSION 1
#define VK_EXT_HDR_METADATA_EXTENSION_NAME "VK_EXT_hdr_metadata"
typedef struct VkXYColorEXT {
@@ -4644,6 +5762,71 @@
const VkHdrMetadataEXT* pMetadata);
#endif
+#define VK_KHR_shared_presentable_image 1
+#define VK_KHR_SHARED_PRESENTABLE_IMAGE_SPEC_VERSION 1
+#define VK_KHR_SHARED_PRESENTABLE_IMAGE_EXTENSION_NAME "VK_KHR_shared_presentable_image"
+
+typedef VkResult (VKAPI_PTR *PFN_vkGetSwapchainStatusKHR)(VkDevice device, VkSwapchainKHR swapchain);
+
+#ifndef VK_NO_PROTOTYPES
+VKAPI_ATTR VkResult VKAPI_CALL vkGetSwapchainStatusKHR(
+ VkDevice device,
+ VkSwapchainKHR swapchain);
+#endif
+
+
+#ifdef VK_USE_PLATFORM_IOS_MVK
+#define VK_MVK_ios_surface 1
+#define VK_MVK_IOS_SURFACE_SPEC_VERSION 2
+#define VK_MVK_IOS_SURFACE_EXTENSION_NAME "VK_MVK_ios_surface"
+
+typedef VkFlags VkIOSSurfaceCreateFlagsMVK;
+
+typedef struct VkIOSSurfaceCreateInfoMVK {
+ VkStructureType sType;
+ const void* pNext;
+ VkIOSSurfaceCreateFlagsMVK flags;
+ const void* pView;
+} VkIOSSurfaceCreateInfoMVK;
+
+
+typedef VkResult (VKAPI_PTR *PFN_vkCreateIOSSurfaceMVK)(VkInstance instance, const VkIOSSurfaceCreateInfoMVK* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface);
+
+#ifndef VK_NO_PROTOTYPES
+VKAPI_ATTR VkResult VKAPI_CALL vkCreateIOSSurfaceMVK(
+ VkInstance instance,
+ const VkIOSSurfaceCreateInfoMVK* pCreateInfo,
+ const VkAllocationCallbacks* pAllocator,
+ VkSurfaceKHR* pSurface);
+#endif
+#endif /* VK_USE_PLATFORM_IOS_MVK */
+
+#ifdef VK_USE_PLATFORM_MACOS_MVK
+#define VK_MVK_macos_surface 1
+#define VK_MVK_MACOS_SURFACE_SPEC_VERSION 2
+#define VK_MVK_MACOS_SURFACE_EXTENSION_NAME "VK_MVK_macos_surface"
+
+typedef VkFlags VkMacOSSurfaceCreateFlagsMVK;
+
+typedef struct VkMacOSSurfaceCreateInfoMVK {
+ VkStructureType sType;
+ const void* pNext;
+ VkMacOSSurfaceCreateFlagsMVK flags;
+ const void* pView;
+} VkMacOSSurfaceCreateInfoMVK;
+
+
+typedef VkResult (VKAPI_PTR *PFN_vkCreateMacOSSurfaceMVK)(VkInstance instance, const VkMacOSSurfaceCreateInfoMVK* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface);
+
+#ifndef VK_NO_PROTOTYPES
+VKAPI_ATTR VkResult VKAPI_CALL vkCreateMacOSSurfaceMVK(
+ VkInstance instance,
+ const VkMacOSSurfaceCreateInfoMVK* pCreateInfo,
+ const VkAllocationCallbacks* pAllocator,
+ VkSurfaceKHR* pSurface);
+#endif
+#endif /* VK_USE_PLATFORM_MACOS_MVK */
+
#ifdef __cplusplus
}
#endif
diff --git a/vulkan/libvulkan/api_gen.cpp b/vulkan/libvulkan/api_gen.cpp
index b8b7e94..69e38de 100644
--- a/vulkan/libvulkan/api_gen.cpp
+++ b/vulkan/libvulkan/api_gen.cpp
@@ -389,7 +389,7 @@
VKAPI_ATTR void CmdDrawIndexed(VkCommandBuffer commandBuffer, uint32_t indexCount, uint32_t instanceCount, uint32_t firstIndex, int32_t vertexOffset, uint32_t firstInstance);
VKAPI_ATTR void CmdDrawIndirect(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, uint32_t drawCount, uint32_t stride);
VKAPI_ATTR void CmdDrawIndexedIndirect(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, uint32_t drawCount, uint32_t stride);
-VKAPI_ATTR void CmdDispatch(VkCommandBuffer commandBuffer, uint32_t x, uint32_t y, uint32_t z);
+VKAPI_ATTR void CmdDispatch(VkCommandBuffer commandBuffer, uint32_t groupCountX, uint32_t groupCountY, uint32_t groupCountZ);
VKAPI_ATTR void CmdDispatchIndirect(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset);
VKAPI_ATTR void CmdCopyBuffer(VkCommandBuffer commandBuffer, VkBuffer srcBuffer, VkBuffer dstBuffer, uint32_t regionCount, const VkBufferCopy* pRegions);
VKAPI_ATTR void CmdCopyImage(VkCommandBuffer commandBuffer, VkImage srcImage, VkImageLayout srcImageLayout, VkImage dstImage, VkImageLayout dstImageLayout, uint32_t regionCount, const VkImageCopy* pRegions);
@@ -451,9 +451,12 @@
"vkEnumerateDeviceLayerProperties",
"vkEnumerateInstanceExtensionProperties",
"vkEnumerateInstanceLayerProperties",
+ "vkEnumeratePhysicalDeviceGroupsKHX",
"vkEnumeratePhysicalDevices",
"vkGetInstanceProcAddr",
+ "vkGetPhysicalDeviceExternalBufferPropertiesKHX",
"vkGetPhysicalDeviceExternalImageFormatPropertiesNV",
+ "vkGetPhysicalDeviceExternalSemaphorePropertiesKHX",
"vkGetPhysicalDeviceFeatures",
"vkGetPhysicalDeviceFeatures2KHR",
"vkGetPhysicalDeviceFormatProperties",
@@ -463,6 +466,7 @@
"vkGetPhysicalDeviceImageFormatProperties2KHR",
"vkGetPhysicalDeviceMemoryProperties",
"vkGetPhysicalDeviceMemoryProperties2KHR",
+ "vkGetPhysicalDevicePresentRectanglesKHX",
"vkGetPhysicalDeviceProperties",
"vkGetPhysicalDeviceProperties2KHR",
"vkGetPhysicalDeviceQueueFamilyProperties",
@@ -1058,8 +1062,8 @@
GetData(commandBuffer).dispatch.CmdDrawIndexedIndirect(commandBuffer, buffer, offset, drawCount, stride);
}
-VKAPI_ATTR void CmdDispatch(VkCommandBuffer commandBuffer, uint32_t x, uint32_t y, uint32_t z) {
- GetData(commandBuffer).dispatch.CmdDispatch(commandBuffer, x, y, z);
+VKAPI_ATTR void CmdDispatch(VkCommandBuffer commandBuffer, uint32_t groupCountX, uint32_t groupCountY, uint32_t groupCountZ) {
+ GetData(commandBuffer).dispatch.CmdDispatch(commandBuffer, groupCountX, groupCountY, groupCountZ);
}
VKAPI_ATTR void CmdDispatchIndirect(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset) {
@@ -1771,8 +1775,8 @@
}
__attribute__((visibility("default")))
-VKAPI_ATTR void vkCmdDispatch(VkCommandBuffer commandBuffer, uint32_t x, uint32_t y, uint32_t z) {
- vulkan::api::CmdDispatch(commandBuffer, x, y, z);
+VKAPI_ATTR void vkCmdDispatch(VkCommandBuffer commandBuffer, uint32_t groupCountX, uint32_t groupCountY, uint32_t groupCountZ) {
+ vulkan::api::CmdDispatch(commandBuffer, groupCountX, groupCountY, groupCountZ);
}
__attribute__((visibility("default")))
diff --git a/vulkan/libvulkan/code-generator.tmpl b/vulkan/libvulkan/code-generator.tmpl
index 992c5d1..185121c 100644
--- a/vulkan/libvulkan/code-generator.tmpl
+++ b/vulkan/libvulkan/code-generator.tmpl
@@ -1129,11 +1129,21 @@
{{$ext := index $.Arguments 0}}
{{ if eq $ext "VK_KHR_display"}}true
{{else if eq $ext "VK_KHR_display_swapchain"}}true
- {{else if eq $ext "VK_KHR_xlib_surface"}}true
- {{else if eq $ext "VK_KHR_xcb_surface"}}true
- {{else if eq $ext "VK_KHR_wayland_surface"}}true
{{else if eq $ext "VK_KHR_mir_surface"}}true
+ {{else if eq $ext "VK_KHR_xcb_surface"}}true
+ {{else if eq $ext "VK_KHR_xlib_surface"}}true
+ {{else if eq $ext "VK_KHR_wayland_surface"}}true
{{else if eq $ext "VK_KHR_win32_surface"}}true
+ {{else if eq $ext "VK_KHX_external_memory_win32"}}true
+ {{else if eq $ext "VK_KHX_win32_keyed_mutex"}}true
+ {{else if eq $ext "VK_KHX_external_semaphore_win32"}}true
+ {{else if eq $ext "VK_EXT_acquire_xlib_display"}}true
+ {{else if eq $ext "VK_EXT_direct_mode_display"}}true
+ {{else if eq $ext "VK_EXT_display_surface_counter"}}true
+ {{else if eq $ext "VK_EXT_display_control"}}true
+ {{else if eq $ext "VK_MVK_ios_surface"}}true
+ {{else if eq $ext "VK_MVK_macos_surface"}}true
+ {{else if eq $ext "VK_NN_vi_surface"}}true
{{else if eq $ext "VK_NV_external_memory_win32"}}true
{{else if eq $ext "VK_NV_win32_keyed_mutex"}}true
{{end}}
diff --git a/vulkan/nulldrv/null_driver_gen.h b/vulkan/nulldrv/null_driver_gen.h
index d73bf14..8a9a963 100644
--- a/vulkan/nulldrv/null_driver_gen.h
+++ b/vulkan/nulldrv/null_driver_gen.h
@@ -138,7 +138,7 @@
VKAPI_ATTR void CmdDrawIndexed(VkCommandBuffer commandBuffer, uint32_t indexCount, uint32_t instanceCount, uint32_t firstIndex, int32_t vertexOffset, uint32_t firstInstance);
VKAPI_ATTR void CmdDrawIndirect(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, uint32_t drawCount, uint32_t stride);
VKAPI_ATTR void CmdDrawIndexedIndirect(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, uint32_t drawCount, uint32_t stride);
-VKAPI_ATTR void CmdDispatch(VkCommandBuffer commandBuffer, uint32_t x, uint32_t y, uint32_t z);
+VKAPI_ATTR void CmdDispatch(VkCommandBuffer commandBuffer, uint32_t groupCountX, uint32_t groupCountY, uint32_t groupCountZ);
VKAPI_ATTR void CmdDispatchIndirect(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset);
VKAPI_ATTR void CmdCopyBuffer(VkCommandBuffer commandBuffer, VkBuffer srcBuffer, VkBuffer dstBuffer, uint32_t regionCount, const VkBufferCopy* pRegions);
VKAPI_ATTR void CmdCopyImage(VkCommandBuffer commandBuffer, VkImage srcImage, VkImageLayout srcImageLayout, VkImage dstImage, VkImageLayout dstImageLayout, uint32_t regionCount, const VkImageCopy* pRegions);