Merge "Add Surface::waitForNextFrame" into nyc-dev
diff --git a/cmds/bugreport/bugreport.cpp b/cmds/bugreport/bugreport.cpp
index 6892b57..917c813 100644
--- a/cmds/bugreport/bugreport.cpp
+++ b/cmds/bugreport/bugreport.cpp
@@ -28,6 +28,11 @@
// output. All of the dumpstate output is written to stdout, including
// any errors encountered while reading/writing the output.
int main() {
+
+ fprintf(stderr, "=============================================================================\n");
+ fprintf(stderr, "WARNING: flat bugreports are deprecated, use adb bugreport <zip_file> instead\n");
+ fprintf(stderr, "=============================================================================\n\n\n");
+
// Start the dumpstate service.
property_set("ctl.start", "dumpstate");
diff --git a/cmds/bugreportz/Android.mk b/cmds/bugreportz/Android.mk
new file mode 100644
index 0000000..14ba225
--- /dev/null
+++ b/cmds/bugreportz/Android.mk
@@ -0,0 +1,12 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= bugreportz.cpp
+
+LOCAL_MODULE:= bugreportz
+
+LOCAL_CFLAGS := -Wall
+
+LOCAL_SHARED_LIBRARIES := libcutils
+
+include $(BUILD_EXECUTABLE)
diff --git a/cmds/bugreportz/bugreportz.cpp b/cmds/bugreportz/bugreportz.cpp
new file mode 100644
index 0000000..b6856bb
--- /dev/null
+++ b/cmds/bugreportz/bugreportz.cpp
@@ -0,0 +1,93 @@
+/*
+ * 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 <errno.h>
+#include <stdio.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <cutils/properties.h>
+#include <cutils/sockets.h>
+
+// TODO: code below was copy-and-pasted from bugreport.cpp (except by the timeout value);
+// should be reused instead.
+int main() {
+
+ // Start the dumpstatez service.
+ property_set("ctl.start", "dumpstatez");
+
+ // Socket will not be available until service starts.
+ int s;
+ for (int i = 0; i < 20; i++) {
+ s = socket_local_client("dumpstate", ANDROID_SOCKET_NAMESPACE_RESERVED, SOCK_STREAM);
+ if (s >= 0)
+ break;
+ // Try again in 1 second.
+ sleep(1);
+ }
+
+ if (s == -1) {
+ printf("Failed to connect to dumpstatez service: %s\n", strerror(errno));
+ return 1;
+ }
+
+ // Set a timeout so that if nothing is read in 10 minutes, we'll stop
+ // reading and quit. No timeout in dumpstate is longer than 60 seconds,
+ // so this gives lots of leeway in case of unforeseen time outs.
+ struct timeval tv;
+ tv.tv_sec = 10 * 60;
+ tv.tv_usec = 0;
+ if (setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) == -1) {
+ printf("WARNING: Cannot set socket timeout: %s\n", strerror(errno));
+ }
+
+ while (1) {
+ char buffer[65536];
+ ssize_t bytes_read = TEMP_FAILURE_RETRY(
+ read(s, buffer, sizeof(buffer)));
+ if (bytes_read == 0) {
+ break;
+ } else if (bytes_read == -1) {
+ // EAGAIN really means time out, so change the errno.
+ if (errno == EAGAIN) {
+ errno = ETIMEDOUT;
+ }
+ printf("\nBugreport read terminated abnormally (%s).\n",
+ strerror(errno));
+ break;
+ }
+
+ ssize_t bytes_to_send = bytes_read;
+ ssize_t bytes_written;
+ do {
+ bytes_written = TEMP_FAILURE_RETRY(
+ write(STDOUT_FILENO, buffer + bytes_read - bytes_to_send,
+ bytes_to_send));
+ if (bytes_written == -1) {
+ printf(
+ "Failed to write data to stdout: read %zd, trying to send %zd (%s)\n",
+ bytes_read, bytes_to_send, strerror(errno));
+ return 1;
+ }
+ bytes_to_send -= bytes_written;
+ } while (bytes_written != 0 && bytes_to_send > 0);
+ }
+
+ close(s);
+ return 0;
+
+}
diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp
index f486e08..ea14c66 100644
--- a/cmds/dumpstate/dumpstate.cpp
+++ b/cmds/dumpstate/dumpstate.cpp
@@ -63,6 +63,7 @@
void add_mountinfo();
static bool add_zip_entry(const std::string& entry_name, const std::string& entry_path);
static bool add_zip_entry_from_fd(const std::string& entry_name, int fd);
+static int control_socket_fd;
#define PSTORE_LAST_KMSG "/sys/fs/pstore/console-ramoops"
@@ -92,8 +93,7 @@
* See bugreport-format.txt for more info.
*/
// TODO: change to "v1" before final N build
-static std::string VERSION_DEFAULT = "v1-dev3";
-static std::string VERSION_BUILD_ON_NAME = "v1-dev4";
+static std::string VERSION_DEFAULT = "v1-dev4";
/* gets the tombstone data, according to the bugreport type: if zipped gets all tombstones,
* otherwise gets just those modified in the last half an hour. */
@@ -929,20 +929,26 @@
}
static void usage() {
- fprintf(stderr, "usage: dumpstate [-b soundfile] [-e soundfile] [-o file [-d] [-p] [-z]] [-s] [-q] [-B] [-P] [-R] [-V version]\n"
- " -b: play sound file instead of vibrate, at beginning of job\n"
- " -e: play sound file instead of vibrate, at end of job\n"
- " -o: write to file (instead of stdout)\n"
- " -d: append date to filename (requires -o)\n"
- " -p: capture screenshot to filename.png (requires -o)\n"
- " -z: generates zipped file (requires -o)\n"
- " -s: write output to control socket (for init)\n"
- " -q: disable vibrate\n"
- " -B: send broadcast when finished (requires -o)\n"
- " -P: send broadcast when started and update system properties on progress (requires -o and -B)\n"
- " -R: take bugreport in remote mode (requires -o, -z, -d and -B, shouldn't be used with -P)\n"
- " -V: sets the bugreport format version (valid values: %s, %s)\n",
- VERSION_DEFAULT.c_str(), VERSION_BUILD_ON_NAME.c_str());
+ fprintf(stderr,
+ "usage: dumpstate [-h] [-b soundfile] [-e soundfile] [-o file [-d] [-p] "
+ "[-z]] [-s] [-S] [-q] [-B] [-P] [-R] [-V version]\n"
+ " -h: display this help message\n"
+ " -b: play sound file instead of vibrate, at beginning of job\n"
+ " -e: play sound file instead of vibrate, at end of job\n"
+ " -o: write to file (instead of stdout)\n"
+ " -d: append date to filename (requires -o)\n"
+ " -p: capture screenshot to filename.png (requires -o)\n"
+ " -z: generate zipped file (requires -o)\n"
+ " -s: write output to control socket (for init)\n"
+ " -S: write file location to control socket (for init; requires -o and -z)"
+ " -q: disable vibrate\n"
+ " -B: send broadcast when finished (requires -o)\n"
+ " -P: send broadcast when started and update system properties on "
+ "progress (requires -o and -B)\n"
+ " -R: take bugreport in remote mode (requires -o, -z, -d and -B, "
+ "shouldn't be used with -P)\n"
+ " -V: sets the bugreport format version (valid values: %s)\n",
+ VERSION_DEFAULT.c_str());
}
static void sigpipe_handler(int n) {
@@ -1014,6 +1020,7 @@
int do_vibrate = 1;
char* use_outfile = 0;
int use_socket = 0;
+ int use_control_socket = 0;
int do_fb = 0;
int do_broadcast = 0;
int do_early_screenshot = 0;
@@ -1022,15 +1029,6 @@
now = time(NULL);
- if (getuid() != 0) {
- // Old versions of the adb client would call the
- // dumpstate command directly. Newer clients
- // call /system/bin/bugreport instead. If we detect
- // we're being called incorrectly, then exec the
- // correct program.
- return execl("/system/bin/bugreport", "/system/bin/bugreport", NULL);
- }
-
MYLOGI("begin\n");
/* gets the sequential id */
@@ -1059,12 +1057,13 @@
format_args(argc, const_cast<const char **>(argv), &args);
MYLOGD("Dumpstate command line: %s\n", args.c_str());
int c;
- while ((c = getopt(argc, argv, "dho:svqzpPBRV:")) != -1) {
+ while ((c = getopt(argc, argv, "dho:svqzpPBRSV:")) != -1) {
switch (c) {
case 'd': do_add_date = 1; break;
case 'z': do_zip_file = 1; break;
case 'o': use_outfile = optarg; break;
case 's': use_socket = 1; break;
+ case 'S': use_control_socket = 1; break;
case 'v': break; // compatibility no-op
case 'q': do_vibrate = 0; break;
case 'p': do_fb = 1; break;
@@ -1084,6 +1083,11 @@
exit(1);
}
+ if (use_control_socket && !do_zip_file) {
+ usage();
+ exit(1);
+ }
+
if (do_update_progress && !do_broadcast) {
usage();
exit(1);
@@ -1094,9 +1098,9 @@
exit(1);
}
- if (version != VERSION_DEFAULT && version != VERSION_BUILD_ON_NAME) {
- usage();
- exit(1);
+ if (version != VERSION_DEFAULT) {
+ usage();
+ exit(1);
}
MYLOGI("bugreport format version: %s\n", version.c_str());
@@ -1109,6 +1113,11 @@
redirect_to_socket(stdout, "dumpstate");
}
+ if (use_control_socket) {
+ MYLOGD("Opening control socket\n");
+ control_socket_fd = open_socket("dumpstate");
+ }
+
/* full path of the directory where the bugreport files will be written */
std::string bugreport_dir;
@@ -1150,11 +1159,9 @@
} else {
suffix = "undated";
}
- if (version == VERSION_BUILD_ON_NAME) {
- char build_id[PROPERTY_VALUE_MAX];
- property_get("ro.build.id", build_id, "UNKNOWN_BUILD");
- base_name = base_name + "-" + build_id;
- }
+ char build_id[PROPERTY_VALUE_MAX];
+ property_get("ro.build.id", build_id, "UNKNOWN_BUILD");
+ base_name = base_name + "-" + build_id;
if (do_fb) {
// TODO: if dumpstate was an object, the paths could be internal variables and then
// we could have a function to calculate the derived values, such as:
@@ -1350,6 +1357,14 @@
path.clear();
}
}
+ if (use_control_socket) {
+ if (do_text_file) {
+ dprintf(control_socket_fd, "FAIL:could not create zip file, check %s "
+ "for more details\n", log_path.c_str());
+ } else {
+ dprintf(control_socket_fd, "OK:%s\n", path.c_str());
+ }
+ }
}
/* vibrate a few but shortly times to let user know it's finished */
@@ -1397,5 +1412,10 @@
fclose(stderr);
}
+ if (use_control_socket && control_socket_fd >= 0) {
+ MYLOGD("Closing control socket\n");
+ close(control_socket_fd);
+ }
+
return 0;
}
diff --git a/cmds/dumpstate/dumpstate.h b/cmds/dumpstate/dumpstate.h
index baba0f9..c51c79a 100644
--- a/cmds/dumpstate/dumpstate.h
+++ b/cmds/dumpstate/dumpstate.h
@@ -130,6 +130,9 @@
/* prints all the system properties */
void print_properties();
+/** opens a socket and returns its file descriptor */
+int open_socket(const char *service);
+
/* redirect output to a service control socket */
void redirect_to_socket(FILE *redirect, const char *service);
diff --git a/cmds/dumpstate/dumpstate.rc b/cmds/dumpstate/dumpstate.rc
index 96232c4..1f56d21 100644
--- a/cmds/dumpstate/dumpstate.rc
+++ b/cmds/dumpstate/dumpstate.rc
@@ -9,6 +9,15 @@
disabled
oneshot
+# dumpstatez generates a zipped bugreport but also uses a socket to print the file location once
+# it is finished.
+service dumpstatez /system/bin/dumpstate -S -d -z \
+ -o /data/user_de/0/com.android.shell/files/bugreports/bugreport
+ socket dumpstate stream 0660 shell log
+ class main
+ disabled
+ oneshot
+
# bugreportplus is an enhanced version of bugreport that provides a better
# user interface (like displaying progress and allowing user to enter details).
# It's typically triggered by the power button or developer settings.
diff --git a/cmds/dumpstate/utils.cpp b/cmds/dumpstate/utils.cpp
index d9738bb..da4b5ad 100644
--- a/cmds/dumpstate/utils.cpp
+++ b/cmds/dumpstate/utils.cpp
@@ -909,8 +909,7 @@
printf("\n");
}
-/* redirect output to a service control socket */
-void redirect_to_socket(FILE *redirect, const char *service) {
+int open_socket(const char *service) {
int s = android_get_control_socket(service);
if (s < 0) {
MYLOGE("android_get_control_socket(%s): %s\n", service, strerror(errno));
@@ -930,11 +929,18 @@
exit(1);
}
+ return fd;
+}
+
+/* redirect output to a service control socket */
+void redirect_to_socket(FILE *redirect, const char *service) {
+ int fd = open_socket(service);
fflush(redirect);
dup2(fd, fileno(redirect));
close(fd);
}
+// TODO: should call is_valid_output_file and/or be merged into it.
void create_parent_dirs(const char *path) {
char *chp = const_cast<char *> (path);
diff --git a/cmds/installd/commands.cpp b/cmds/installd/commands.cpp
index 2bfea63..20ad5f9 100644
--- a/cmds/installd/commands.cpp
+++ b/cmds/installd/commands.cpp
@@ -74,7 +74,7 @@
uid_t uid = multiuser_get_uid(userid, appid);
int target_mode = target_sdk_version >= MIN_RESTRICTED_HOME_SDK_VERSION ? 0700 : 0751;
if (flags & FLAG_STORAGE_CE) {
- auto path = create_data_user_package_path(uuid, userid, pkgname);
+ auto path = create_data_user_ce_package_path(uuid, userid, pkgname);
if (fs_prepare_dir_strict(path.c_str(), target_mode, uid, uid) != 0) {
PLOG(ERROR) << "Failed to prepare " << path;
return -1;
@@ -124,7 +124,7 @@
// consistent location. This only works on non-FBE devices, since we
// never want to risk exposing data on a device with real CE/DE storage.
- auto ce_path = create_data_user_package_path(uuid, userid, pkgname);
+ auto ce_path = create_data_user_ce_package_path(uuid, userid, pkgname);
auto de_path = create_data_user_de_package_path(uuid, userid, pkgname);
// If neither directory is marked as default, assume CE is default
@@ -234,7 +234,8 @@
return success ? 0 : -1;
}
-int clear_app_data(const char *uuid, const char *pkgname, userid_t userid, int flags) {
+int clear_app_data(const char *uuid, const char *pkgname, userid_t userid, int flags,
+ ino_t ce_data_inode) {
std::string suffix = "";
bool only_cache = false;
if (flags & FLAG_CLEAR_CACHE_ONLY) {
@@ -247,7 +248,7 @@
int res = 0;
if (flags & FLAG_STORAGE_CE) {
- auto path = create_data_user_package_path(uuid, userid, pkgname) + suffix;
+ auto path = create_data_user_ce_package_path(uuid, userid, pkgname, ce_data_inode) + suffix;
if (access(path.c_str(), F_OK) == 0) {
res |= delete_dir_contents(path);
}
@@ -289,11 +290,12 @@
return result;
}
-int destroy_app_data(const char *uuid, const char *pkgname, userid_t userid, int flags) {
+int destroy_app_data(const char *uuid, const char *pkgname, userid_t userid, int flags,
+ ino_t ce_data_inode) {
int res = 0;
if (flags & FLAG_STORAGE_CE) {
res |= delete_dir_contents_and_dir(
- create_data_user_package_path(uuid, userid, pkgname));
+ create_data_user_ce_package_path(uuid, userid, pkgname, ce_data_inode));
}
if (flags & FLAG_STORAGE_DE) {
res |= delete_dir_contents_and_dir(
@@ -346,9 +348,9 @@
// Copy private data for all known users
// TODO: handle user_de paths
for (auto user : users) {
- std::string from(create_data_user_package_path(from_uuid, user, package_name));
- std::string to(create_data_user_package_path(to_uuid, user, package_name));
- std::string to_parent(create_data_user_path(to_uuid, user));
+ std::string from(create_data_user_ce_package_path(from_uuid, user, package_name));
+ std::string to(create_data_user_ce_package_path(to_uuid, user, package_name));
+ std::string to_parent(create_data_user_ce_path(to_uuid, user));
// Data source may not exist for all users; that's okay
if (access(from.c_str(), F_OK) != 0) {
@@ -356,7 +358,7 @@
continue;
}
- std::string user_path(create_data_user_path(to_uuid, user));
+ std::string user_path(create_data_user_ce_path(to_uuid, user));
if (fs_prepare_dir(user_path.c_str(), 0771, AID_SYSTEM, AID_SYSTEM) != 0) {
LOG(ERROR) << "Failed to prepare user target " << user_path;
goto fail;
@@ -409,7 +411,7 @@
}
}
for (auto user : users) {
- std::string to(create_data_user_package_path(to_uuid, user, package_name));
+ std::string to(create_data_user_ce_package_path(to_uuid, user, package_name));
if (delete_dir_contents(to.c_str(), 1, NULL) != 0) {
LOG(WARNING) << "Failed to rollback " << to;
}
@@ -429,7 +431,7 @@
int delete_user(const char *uuid, userid_t userid) {
int res = 0;
- std::string data_path(create_data_user_path(uuid, userid));
+ std::string data_path(create_data_user_ce_path(uuid, userid));
std::string data_de_path(create_data_user_de_path(uuid, userid));
std::string media_path(create_data_media_path(uuid, userid));
std::string profiles_path(create_data_user_profiles_path(userid));
@@ -480,7 +482,7 @@
// Special case for owner on internal storage
if (uuid == nullptr) {
- std::string _tmpdir(create_data_user_path(nullptr, 0));
+ std::string _tmpdir(create_data_user_ce_path(nullptr, 0));
add_cache_files(cache, _tmpdir.c_str(), "cache");
}
@@ -567,142 +569,96 @@
}
}
-int get_app_size(const char *uuid, const char *pkgname, int userid, int flags,
- const char *apkpath, const char *libdirpath, const char *fwdlock_apkpath,
- const char *asecpath, const char *instruction_set, int64_t *_codesize, int64_t *_datasize,
- int64_t *_cachesize, int64_t* _asecsize) {
+static void add_app_data_size(std::string& path, int64_t *codesize, int64_t *datasize,
+ int64_t *cachesize) {
DIR *d;
int dfd;
struct dirent *de;
struct stat s;
- char path[PKG_PATH_MAX];
- int64_t codesize = 0;
- int64_t datasize = 0;
- int64_t cachesize = 0;
- int64_t asecsize = 0;
+ d = opendir(path.c_str());
+ if (d == nullptr) {
+ PLOG(WARNING) << "Failed to open " << path;
+ return;
+ }
+ dfd = dirfd(d);
+ while ((de = readdir(d))) {
+ const char *name = de->d_name;
- /* count the source apk as code -- but only if it's not
- * on the /system partition and its not on the sdcard. */
- if (validate_system_app_path(apkpath) &&
- strncmp(apkpath, android_asec_dir.path, android_asec_dir.len) != 0) {
- if (stat(apkpath, &s) == 0) {
- codesize += stat_size(&s);
- if (S_ISDIR(s.st_mode)) {
- d = opendir(apkpath);
- if (d != NULL) {
- dfd = dirfd(d);
- codesize += calculate_dir_size(dfd);
- closedir(d);
- }
+ int64_t statsize = 0;
+ if (fstatat(dfd, name, &s, AT_SYMLINK_NOFOLLOW) == 0) {
+ statsize = stat_size(&s);
+ }
+
+ if (de->d_type == DT_DIR) {
+ int subfd;
+ int64_t dirsize = 0;
+ /* always skip "." and ".." */
+ if (name[0] == '.') {
+ if (name[1] == 0) continue;
+ if ((name[1] == '.') && (name[2] == 0)) continue;
}
- }
- }
-
- /* count the forward locked apk as code if it is given */
- if (fwdlock_apkpath != NULL && fwdlock_apkpath[0] != '!') {
- if (stat(fwdlock_apkpath, &s) == 0) {
- codesize += stat_size(&s);
- }
- }
-
- /* count the cached dexfile as code */
- if (create_cache_path(path, apkpath, instruction_set)) {
- if (stat(path, &s) == 0) {
- codesize += stat_size(&s);
- }
- }
-
- /* add in size of any libraries */
- if (libdirpath != NULL && libdirpath[0] != '!') {
- d = opendir(libdirpath);
- if (d != NULL) {
- dfd = dirfd(d);
- codesize += calculate_dir_size(dfd);
- closedir(d);
- }
- }
-
- /* compute asec size if it is given */
- if (asecpath != NULL && asecpath[0] != '!') {
- if (stat(asecpath, &s) == 0) {
- asecsize += stat_size(&s);
- }
- }
-
- std::vector<userid_t> users;
- if (userid == -1) {
- users = get_known_users(uuid);
- } else {
- users.push_back(userid);
- }
-
- for (auto user : users) {
- // TODO: handle user_de directories
- if (!(flags & FLAG_STORAGE_CE)) continue;
-
- std::string _pkgdir(create_data_user_package_path(uuid, user, pkgname));
- const char* pkgdir = _pkgdir.c_str();
-
- d = opendir(pkgdir);
- if (d == NULL) {
- PLOG(WARNING) << "Failed to open " << pkgdir;
- continue;
- }
- dfd = dirfd(d);
-
- /* most stuff in the pkgdir is data, except for the "cache"
- * directory and below, which is cache, and the "lib" directory
- * and below, which is code...
- */
- while ((de = readdir(d))) {
- const char *name = de->d_name;
-
- if (de->d_type == DT_DIR) {
- int subfd;
- int64_t statsize = 0;
- int64_t dirsize = 0;
- /* always skip "." and ".." */
- if (name[0] == '.') {
- if (name[1] == 0) continue;
- if ((name[1] == '.') && (name[2] == 0)) continue;
- }
- if (fstatat(dfd, name, &s, AT_SYMLINK_NOFOLLOW) == 0) {
- statsize = stat_size(&s);
- }
- subfd = openat(dfd, name, O_RDONLY | O_DIRECTORY);
- if (subfd >= 0) {
- dirsize = calculate_dir_size(subfd);
- }
- if(!strcmp(name,"lib")) {
- codesize += dirsize + statsize;
- } else if(!strcmp(name,"cache")) {
- cachesize += dirsize + statsize;
- } else {
- datasize += dirsize + statsize;
- }
- } else if (de->d_type == DT_LNK && !strcmp(name,"lib")) {
- // This is the symbolic link to the application's library
- // code. We'll count this as code instead of data, since
- // it is not something that the app creates.
- if (fstatat(dfd, name, &s, AT_SYMLINK_NOFOLLOW) == 0) {
- codesize += stat_size(&s);
- }
+ subfd = openat(dfd, name, O_RDONLY | O_DIRECTORY);
+ if (subfd >= 0) {
+ dirsize = calculate_dir_size(subfd);
+ close(subfd);
+ }
+ // TODO: check xattrs!
+ if (!strcmp(name, "cache") || !strcmp(name, "code_cache")) {
+ *datasize += statsize;
+ *cachesize += dirsize;
} else {
- if (fstatat(dfd, name, &s, AT_SYMLINK_NOFOLLOW) == 0) {
- datasize += stat_size(&s);
- }
+ *datasize += dirsize + statsize;
}
+ } else if (de->d_type == DT_LNK && !strcmp(name, "lib")) {
+ *codesize += statsize;
+ } else {
+ *datasize += statsize;
}
+ }
+ closedir(d);
+}
+
+int get_app_size(const char *uuid, const char *pkgname, int userid, int flags, ino_t ce_data_inode,
+ const char *code_path, int64_t *codesize, int64_t *datasize, int64_t *cachesize,
+ int64_t* asecsize) {
+ DIR *d;
+ int dfd;
+
+ d = opendir(code_path);
+ if (d != nullptr) {
+ dfd = dirfd(d);
+ *codesize += calculate_dir_size(dfd);
closedir(d);
}
- *_codesize = codesize;
- *_datasize = datasize;
- *_cachesize = cachesize;
- *_asecsize = asecsize;
+
+ if (flags & FLAG_STORAGE_CE) {
+ auto path = create_data_user_ce_package_path(uuid, userid, pkgname, ce_data_inode);
+ add_app_data_size(path, codesize, datasize, cachesize);
+ }
+ if (flags & FLAG_STORAGE_DE) {
+ auto path = create_data_user_de_package_path(uuid, userid, pkgname);
+ add_app_data_size(path, codesize, datasize, cachesize);
+ }
+
+ *asecsize = 0;
+
return 0;
}
+int get_app_data_inode(const char *uuid, const char *pkgname, int userid, int flags, ino_t *inode) {
+ struct stat buf;
+ memset(&buf, 0, sizeof(buf));
+ if (flags & FLAG_STORAGE_CE) {
+ auto path = create_data_user_ce_package_path(uuid, userid, pkgname);
+ if (stat(path.c_str(), &buf) == 0) {
+ *inode = buf.st_ino;
+ return 0;
+ }
+ }
+ return -1;
+}
+
static int split_count(const char *str)
{
char *ctx;
@@ -1304,13 +1260,17 @@
return true;
}
-static int open_output_file(char* file_name, bool recreate) {
+static int open_output_file(char* file_name, bool recreate, int permissions) {
int flags = O_RDWR | O_CREAT;
if (recreate) {
- unlink(file_name);
+ if (unlink(file_name) < 0) {
+ if (errno != ENOENT) {
+ PLOG(ERROR) << "open_output_file: Couldn't unlink " << file_name;
+ }
+ }
flags |= O_EXCL;
}
- return open(file_name, flags, 0600);
+ return open(file_name, flags, permissions);
}
static bool set_permissions_and_ownership(int fd, bool is_public, int uid, const char* path) {
@@ -1427,8 +1387,7 @@
return -1;
}
- unlink(out_path);
- out_fd = open(out_path, O_RDWR | O_CREAT | O_EXCL, 0644);
+ out_fd = open_output_file(out_path, /*recreate*/true, /*permissions*/0644);
if (out_fd < 0) {
ALOGE("installd cannot open '%s' for output during dexopt\n", out_path);
goto fail;
@@ -1442,7 +1401,7 @@
// Make sure there really is enough space.
strcpy(swap_file_name, out_path);
if (add_extension_to_file_name(swap_file_name, ".swap")) {
- swap_fd = open_output_file(swap_file_name, /*recreate*/true);
+ swap_fd = open_output_file(swap_file_name, /*recreate*/true, /*permissions*/0600);
}
if (swap_fd < 0) {
// Could not create swap file. Optimistically go on and hope that we can compile
@@ -1450,7 +1409,9 @@
ALOGE("installd could not create '%s' for swap during dexopt\n", swap_file_name);
} else {
// Immediately unlink. We don't really want to hit flash.
- unlink(swap_file_name);
+ if (unlink(swap_file_name) < 0) {
+ PLOG(ERROR) << "Couldn't unlink swap file " << swap_file_name;
+ }
}
}
@@ -1466,7 +1427,7 @@
if (profile_guided && have_app_image_format) {
// Recreate is true since we do not want to modify a mapped image. If the app is already
// running and we modify the image file, it can cause crashes (b/27493510).
- image_fd = open_output_file(image_path, /*recreate*/true);
+ image_fd = open_output_file(image_path, /*recreate*/true, /*permissions*/0600);
if (image_fd < 0) {
// Could not create application image file. Go on since we can compile without it.
ALOGE("installd could not create '%s' for image file during dexopt\n", image_path);
@@ -1476,7 +1437,11 @@
}
// If we have a valid image file path but no image fd, erase the image file.
if (image_fd < 0) {
- unlink(image_path);
+ if (unlink(image_path) < 0) {
+ if (errno != ENOENT) {
+ PLOG(ERROR) << "Couldn't unlink image file " << image_path;
+ }
+ }
}
}
@@ -1608,7 +1573,7 @@
struct stat s, libStat;
int rc = 0;
- std::string _pkgdir(create_data_user_package_path(uuid, userId, pkgname));
+ std::string _pkgdir(create_data_user_ce_package_path(uuid, userId, pkgname));
std::string _libsymlink(_pkgdir + PKG_LIB_POSTFIX);
const char* pkgdir = _pkgdir.c_str();
@@ -1795,7 +1760,7 @@
uid_t uid = multiuser_get_uid(userid, appid);
if (flags & FLAG_STORAGE_CE) {
- auto path = create_data_user_package_path(uuid, userid, pkgName);
+ auto path = create_data_user_ce_package_path(uuid, userid, pkgName);
if (selinux_android_restorecon_pkgdir(path.c_str(), seinfo, uid, seflags) < 0) {
PLOG(ERROR) << "restorecon failed for " << path;
res = -1;
diff --git a/cmds/installd/commands.h b/cmds/installd/commands.h
index 13143c5..f13ceea 100644
--- a/cmds/installd/commands.h
+++ b/cmds/installd/commands.h
@@ -33,16 +33,18 @@
int restorecon_app_data(const char* uuid, const char* pkgName, userid_t userid, int flags,
appid_t appid, const char* seinfo);
int migrate_app_data(const char *uuid, const char *pkgname, userid_t userid, int flags);
-int clear_app_data(const char *uuid, const char *pkgname, userid_t userid, int flags);
-int destroy_app_data(const char *uuid, const char *pkgname, userid_t userid, int flags);
+int clear_app_data(const char *uuid, const char *pkgname, userid_t userid, int flags,
+ ino_t ce_data_inode);
+int destroy_app_data(const char *uuid, const char *pkgname, userid_t userid, int flags,
+ ino_t ce_data_inode);
int move_complete_app(const char* from_uuid, const char *to_uuid, const char *package_name,
const char *data_app_name, appid_t appid, const char* seinfo, int target_sdk_version);
-int get_app_size(const char *uuid, const char *pkgname, int userid, int flags,
- const char *apkpath, const char *libdirpath, const char *fwdlock_apkpath,
- const char *asecpath, const char *instruction_set, int64_t *codesize, int64_t *datasize,
- int64_t *cachesize, int64_t *asecsize);
+int get_app_size(const char *uuid, const char *pkgname, int userid, int flags, ino_t ce_data_inode,
+ const char* code_path, int64_t *codesize, int64_t *datasize, int64_t *cachesize,
+ int64_t *asecsize);
+int get_app_data_inode(const char *uuid, const char *pkgname, int userid, int flags, ino_t *inode);
int make_user_config(userid_t userid);
int delete_user(const char *uuid, userid_t userid);
diff --git a/cmds/installd/installd.cpp b/cmds/installd/installd.cpp
index de3f54a..5c29eb4 100644
--- a/cmds/installd/installd.cpp
+++ b/cmds/installd/installd.cpp
@@ -207,13 +207,13 @@
}
static int do_clear_app_data(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED) {
- /* const char *uuid, const char *pkgname, userid_t userid, int flags */
- return clear_app_data(parse_null(arg[0]), arg[1], atoi(arg[2]), atoi(arg[3]));
+ /* const char *uuid, const char *pkgname, userid_t userid, int flags, ino_t ce_data_inode */
+ return clear_app_data(parse_null(arg[0]), arg[1], atoi(arg[2]), atoi(arg[3]), atol(arg[4]));
}
static int do_destroy_app_data(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED) {
- /* const char *uuid, const char *pkgname, userid_t userid, int flags */
- return destroy_app_data(parse_null(arg[0]), arg[1], atoi(arg[2]), atoi(arg[3]));
+ /* const char *uuid, const char *pkgname, userid_t userid, int flags, ino_t ce_data_inode */
+ return destroy_app_data(parse_null(arg[0]), arg[1], atoi(arg[2]), atoi(arg[3]), atol(arg[4]));
}
// We use otapreopt_chroot to get into the chroot.
@@ -303,11 +303,10 @@
int64_t asecsize = 0;
int res = 0;
- /* const char *uuid, const char *pkgname, userid_t userid, int flags,
- const char *apkpath, const char *libdirpath, const char *fwdlock_apkpath,
- const char *asecpath, const char *instruction_set */
- res = get_app_size(parse_null(arg[0]), arg[1], atoi(arg[2]), atoi(arg[3]), arg[4], arg[5],
- arg[6], arg[7], arg[8], &codesize, &datasize, &cachesize, &asecsize);
+ /* const char *uuid, const char *pkgname, int userid, int flags, ino_t ce_data_inode,
+ const char* code_path */
+ res = get_app_size(parse_null(arg[0]), arg[1], atoi(arg[2]), atoi(arg[3]), atol(arg[4]),
+ arg[5], &codesize, &datasize, &cachesize, &asecsize);
/*
* Each int64_t can take up 22 characters printed out. Make sure it
@@ -318,6 +317,17 @@
return res;
}
+static int do_get_app_data_inode(char **arg, char reply[REPLY_MAX]) {
+ ino_t inode = 0;
+ int res = 0;
+
+ /* const char *uuid, const char *pkgname, int userid, int flags */
+ res = get_app_data_inode(parse_null(arg[0]), arg[1], atoi(arg[2]), atoi(arg[3]), &inode);
+
+ snprintf(reply, REPLY_MAX, "%" PRId64, (int64_t) inode);
+ return res;
+}
+
static int do_move_complete_app(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED) {
/* const char* from_uuid, const char *to_uuid, const char *package_name,
const char *data_app_name, appid_t appid, const char* seinfo,
@@ -393,10 +403,11 @@
{ "create_app_data", 7, do_create_app_data },
{ "restorecon_app_data", 6, do_restorecon_app_data },
{ "migrate_app_data", 4, do_migrate_app_data },
- { "clear_app_data", 4, do_clear_app_data },
- { "destroy_app_data", 4, do_destroy_app_data },
+ { "clear_app_data", 5, do_clear_app_data },
+ { "destroy_app_data", 5, do_destroy_app_data },
{ "move_complete_app", 7, do_move_complete_app },
- { "get_app_size", 9, do_get_app_size },
+ { "get_app_size", 6, do_get_app_size },
+ { "get_app_data_inode", 4, do_get_app_data_inode },
{ "dexopt", 9, do_dexopt },
{ "markbootcomplete", 1, do_mark_boot_complete },
diff --git a/cmds/installd/tests/installd_utils_test.cpp b/cmds/installd/tests/installd_utils_test.cpp
index ff69f4b..9b2de88 100644
--- a/cmds/installd/tests/installd_utils_test.cpp
+++ b/cmds/installd/tests/installd_utils_test.cpp
@@ -472,13 +472,13 @@
}
TEST_F(UtilsTest, CreateDataUserPath) {
- EXPECT_EQ("/data/data", create_data_user_path(nullptr, 0));
- EXPECT_EQ("/data/user/10", create_data_user_path(nullptr, 10));
+ EXPECT_EQ("/data/data", create_data_user_ce_path(nullptr, 0));
+ EXPECT_EQ("/data/user/10", create_data_user_ce_path(nullptr, 10));
EXPECT_EQ("/mnt/expand/57f8f4bc-abf4-655f-bf67-946fc0f9f25b/user/0",
- create_data_user_path("57f8f4bc-abf4-655f-bf67-946fc0f9f25b", 0));
+ create_data_user_ce_path("57f8f4bc-abf4-655f-bf67-946fc0f9f25b", 0));
EXPECT_EQ("/mnt/expand/57f8f4bc-abf4-655f-bf67-946fc0f9f25b/user/10",
- create_data_user_path("57f8f4bc-abf4-655f-bf67-946fc0f9f25b", 10));
+ create_data_user_ce_path("57f8f4bc-abf4-655f-bf67-946fc0f9f25b", 10));
}
TEST_F(UtilsTest, CreateDataMediaPath) {
@@ -499,13 +499,13 @@
}
TEST_F(UtilsTest, CreateDataUserPackagePath) {
- EXPECT_EQ("/data/data/com.example", create_data_user_package_path(nullptr, 0, "com.example"));
- EXPECT_EQ("/data/user/10/com.example", create_data_user_package_path(nullptr, 10, "com.example"));
+ EXPECT_EQ("/data/data/com.example", create_data_user_ce_package_path(nullptr, 0, "com.example"));
+ EXPECT_EQ("/data/user/10/com.example", create_data_user_ce_package_path(nullptr, 10, "com.example"));
EXPECT_EQ("/mnt/expand/57f8f4bc-abf4-655f-bf67-946fc0f9f25b/user/0/com.example",
- create_data_user_package_path("57f8f4bc-abf4-655f-bf67-946fc0f9f25b", 0, "com.example"));
+ create_data_user_ce_package_path("57f8f4bc-abf4-655f-bf67-946fc0f9f25b", 0, "com.example"));
EXPECT_EQ("/mnt/expand/57f8f4bc-abf4-655f-bf67-946fc0f9f25b/user/10/com.example",
- create_data_user_package_path("57f8f4bc-abf4-655f-bf67-946fc0f9f25b", 10, "com.example"));
+ create_data_user_ce_package_path("57f8f4bc-abf4-655f-bf67-946fc0f9f25b", 10, "com.example"));
}
} // namespace installd
diff --git a/cmds/installd/utils.cpp b/cmds/installd/utils.cpp
index d84d9f6..878fb2d 100644
--- a/cmds/installd/utils.cpp
+++ b/cmds/installd/utils.cpp
@@ -81,11 +81,39 @@
* volume UUID, package name, and user ID. An empty UUID is assumed to be
* internal storage.
*/
-std::string create_data_user_package_path(const char* volume_uuid,
+std::string create_data_user_ce_package_path(const char* volume_uuid,
userid_t user, const char* package_name) {
check_package_name(package_name);
return StringPrintf("%s/%s",
- create_data_user_path(volume_uuid, user).c_str(), package_name);
+ create_data_user_ce_path(volume_uuid, user).c_str(), package_name);
+}
+
+std::string create_data_user_ce_package_path(const char* volume_uuid, userid_t user,
+ const char* package_name, ino_t ce_data_inode) {
+ // For testing purposes, rely on the inode when defined; this could be
+ // optimized to use access() in the future.
+ auto fallback = create_data_user_ce_package_path(volume_uuid, user, package_name);
+ if (ce_data_inode != 0) {
+ auto user_path = create_data_user_ce_path(volume_uuid, user);
+ DIR* dir = opendir(user_path.c_str());
+ if (dir == nullptr) {
+ PLOG(ERROR) << "Failed to opendir " << user_path;
+ return fallback;
+ }
+
+ struct dirent* ent;
+ while ((ent = readdir(dir))) {
+ if (ent->d_ino == ce_data_inode) {
+ closedir(dir);
+ return StringPrintf("%s/%s", user_path.c_str(), ent->d_name);
+ }
+ }
+ LOG(WARNING) << "Failed to find inode " << ce_data_inode << " for package " << package_name;
+ closedir(dir);
+ return fallback;
+ } else {
+ return fallback;
+ }
}
std::string create_data_user_de_package_path(const char* volume_uuid,
@@ -102,7 +130,7 @@
return -1;
}
- std::string _tmp(create_data_user_package_path(nullptr, userid, pkgname) + postfix);
+ std::string _tmp(create_data_user_ce_package_path(nullptr, userid, pkgname) + postfix);
const char* tmp = _tmp.c_str();
if (strlen(tmp) >= PKG_PATH_MAX) {
path[0] = '\0';
@@ -132,7 +160,7 @@
/**
* Create the path name for user data for a certain userid.
*/
-std::string create_data_user_path(const char* volume_uuid, userid_t userid) {
+std::string create_data_user_ce_path(const char* volume_uuid, userid_t userid) {
std::string data(create_data_path(volume_uuid));
if (volume_uuid == nullptr) {
if (userid == 0) {
diff --git a/cmds/installd/utils.h b/cmds/installd/utils.h
index 416a726..9d9a423 100644
--- a/cmds/installd/utils.h
+++ b/cmds/installd/utils.h
@@ -73,12 +73,13 @@
std::string create_data_app_package_path(const char* volume_uuid, const char* package_name);
-// TODO: finish refactoring to "_ce"
-std::string create_data_user_path(const char* volume_uuid, userid_t userid);
+std::string create_data_user_ce_path(const char* volume_uuid, userid_t userid);
std::string create_data_user_de_path(const char* volume_uuid, userid_t userid);
-std::string create_data_user_package_path(const char* volume_uuid,
+std::string create_data_user_ce_package_path(const char* volume_uuid,
userid_t user, const char* package_name);
+std::string create_data_user_ce_package_path(const char* volume_uuid,
+ userid_t user, const char* package_name, ino_t ce_data_inode);
std::string create_data_user_de_package_path(const char* volume_uuid,
userid_t user, const char* package_name);
diff --git a/include/batteryservice/BatteryService.h b/include/batteryservice/BatteryService.h
index 912dcf6..b399905 100644
--- a/include/batteryservice/BatteryService.h
+++ b/include/batteryservice/BatteryService.h
@@ -68,6 +68,7 @@
int batteryCurrent;
int batteryCycleCount;
int batteryFullCharge;
+ int batteryChargeCounter;
String8 batteryTechnology;
status_t writeToParcel(Parcel* parcel) const;
diff --git a/include/gui/ISurfaceComposer.h b/include/gui/ISurfaceComposer.h
index 8c3d49e..af26721 100644
--- a/include/gui/ISurfaceComposer.h
+++ b/include/gui/ISurfaceComposer.h
@@ -39,6 +39,7 @@
class DisplayState;
struct DisplayInfo;
struct DisplayStatInfo;
+class HdrCapabilities;
class IDisplayEventConnection;
class IMemoryHeap;
class Rect;
@@ -157,6 +158,13 @@
* Requires the ACCESS_SURFACE_FLINGER permission.
*/
virtual status_t getAnimationFrameStats(FrameStats* outStats) const = 0;
+
+ /* Gets the supported HDR capabilities of the given display.
+ *
+ * Requires the ACCESS_SURFACE_FLINGER permission.
+ */
+ virtual status_t getHdrCapabilities(const sp<IBinder>& display,
+ HdrCapabilities* outCapabilities) const = 0;
};
// ----------------------------------------------------------------------------
@@ -184,6 +192,7 @@
GET_ANIMATION_FRAME_STATS,
SET_POWER_MODE,
GET_DISPLAY_STATS,
+ GET_HDR_CAPABILITIES,
};
virtual status_t onTransact(uint32_t code, const Parcel& data,
diff --git a/include/gui/Sensor.h b/include/gui/Sensor.h
index 3792540..353003c 100644
--- a/include/gui/Sensor.h
+++ b/include/gui/Sensor.h
@@ -56,7 +56,7 @@
uint8_t b[16];
} uuid_t;
- Sensor();
+ Sensor(const char * name = "");
Sensor(struct sensor_t const* hwSensor, int halVersion = 0);
~Sensor();
@@ -80,6 +80,7 @@
int32_t getMaxDelay() const;
uint32_t getFlags() const;
bool isWakeUpSensor() const;
+ bool isDynamicSensor() const;
int32_t getReportingMode() const;
const uuid_t& getUuid() const;
diff --git a/include/gui/SurfaceComposerClient.h b/include/gui/SurfaceComposerClient.h
index 794fe4c..9161dbb 100644
--- a/include/gui/SurfaceComposerClient.h
+++ b/include/gui/SurfaceComposerClient.h
@@ -40,6 +40,7 @@
class DisplayInfo;
class Composer;
+class HdrCapabilities;
class ISurfaceComposerClient;
class IGraphicBufferProducer;
class Region;
@@ -145,6 +146,9 @@
static status_t clearAnimationFrameStats();
static status_t getAnimationFrameStats(FrameStats* outStats);
+ static status_t getHdrCapabilities(const sp<IBinder>& display,
+ HdrCapabilities* outCapabilities);
+
static void setDisplaySurface(const sp<IBinder>& token,
const sp<IGraphicBufferProducer>& bufferProducer);
static void setDisplayLayerStack(const sp<IBinder>& token,
diff --git a/include/media/openmax/OMX_VideoExt.h b/include/media/openmax/OMX_VideoExt.h
index e11f569..4bb5f9a 100644
--- a/include/media/openmax/OMX_VideoExt.h
+++ b/include/media/openmax/OMX_VideoExt.h
@@ -77,10 +77,13 @@
/** VP9 profiles */
typedef enum OMX_VIDEO_VP9PROFILETYPE {
- OMX_VIDEO_VP9Profile0 = 0x0,
- OMX_VIDEO_VP9Profile1 = 0x1,
- OMX_VIDEO_VP9Profile2 = 0x2,
- OMX_VIDEO_VP9Profile3 = 0x3,
+ OMX_VIDEO_VP9Profile0 = 0x1,
+ OMX_VIDEO_VP9Profile1 = 0x2,
+ OMX_VIDEO_VP9Profile2 = 0x4,
+ OMX_VIDEO_VP9Profile3 = 0x8,
+ // HDR profiles also support passing HDR metadata
+ OMX_VIDEO_VP9Profile2HDR = 0x1000,
+ OMX_VIDEO_VP9Profile3HDR = 0x2000,
OMX_VIDEO_VP9ProfileUnknown = 0x6EFFFFFF,
OMX_VIDEO_VP9ProfileMax = 0x7FFFFFFF
} OMX_VIDEO_VP9PROFILETYPE;
diff --git a/include/ui/HdrCapabilities.h b/include/ui/HdrCapabilities.h
new file mode 100644
index 0000000..a7cd5fb
--- /dev/null
+++ b/include/ui/HdrCapabilities.h
@@ -0,0 +1,66 @@
+/*
+ * Copyright 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 ANDROID_UI_HDR_CAPABILTIES_H
+#define ANDROID_UI_HDR_CAPABILTIES_H
+
+#include <binder/Parcelable.h>
+
+namespace android {
+
+class HdrCapabilities : public Parcelable
+{
+public:
+ HdrCapabilities(const std::vector<int32_t /*android_hdr_t*/>& types,
+ float maxLuminance, float maxAverageLuminance, float minLuminance)
+ : mSupportedHdrTypes(types),
+ mMaxLuminance(maxLuminance),
+ mMaxAverageLuminance(maxAverageLuminance),
+ mMinLuminance(minLuminance) {}
+
+ // Make this move-constructable and move-assignable
+ HdrCapabilities(HdrCapabilities&& other) = default;
+ HdrCapabilities& operator=(HdrCapabilities&& other) = default;
+
+ HdrCapabilities()
+ : mSupportedHdrTypes(),
+ mMaxLuminance(-1.0f),
+ mMaxAverageLuminance(-1.0f),
+ mMinLuminance(-1.0f) {}
+
+ virtual ~HdrCapabilities() = default;
+
+ const std::vector<int32_t /*android_hdr_t*/>& getSupportedHdrTypes() const {
+ return mSupportedHdrTypes;
+ }
+ float getDesiredMaxLuminance() const { return mMaxLuminance; }
+ float getDesiredMaxAverageLuminance() const { return mMaxAverageLuminance; }
+ float getDesiredMinLuminance() const { return mMinLuminance; }
+
+ // Parcelable interface
+ virtual status_t writeToParcel(Parcel* parcel) const override;
+ virtual status_t readFromParcel(const Parcel* parcel) override;
+
+private:
+ std::vector<int32_t /*android_hdr_t*/> mSupportedHdrTypes;
+ float mMaxLuminance;
+ float mMaxAverageLuminance;
+ float mMinLuminance;
+};
+
+} // namespace android
+
+#endif
diff --git a/libs/binder/ProcessState.cpp b/libs/binder/ProcessState.cpp
index 33fe26c..b221e51 100644
--- a/libs/binder/ProcessState.cpp
+++ b/libs/binder/ProcessState.cpp
@@ -40,12 +40,12 @@
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <sys/stat.h>
+#include <sys/types.h>
#define BINDER_VM_SIZE ((1*1024*1024) - (4096 *2))
#define DEFAULT_MAX_BINDER_THREADS 15
-
-// ---------------------------------------------------------------------------
+// -------------------------------------------------------------------------
namespace android {
@@ -278,8 +278,9 @@
String8 ProcessState::makeBinderThreadName() {
int32_t s = android_atomic_add(1, &mThreadPoolSeq);
+ pid_t pid = getpid();
String8 name;
- name.appendFormat("Binder_%X", s);
+ name.appendFormat("Binder:%d_%X", pid, s);
return name;
}
diff --git a/libs/diskusage/dirsize.c b/libs/diskusage/dirsize.c
index 7576994..5b5ab70 100644
--- a/libs/diskusage/dirsize.c
+++ b/libs/diskusage/dirsize.c
@@ -24,16 +24,7 @@
int64_t stat_size(struct stat *s)
{
- int64_t blksize = s->st_blksize;
- // count actual blocks used instead of nominal file size
- int64_t size = s->st_blocks * 512;
-
- if (blksize) {
- /* round up to filesystem block size */
- size = (size + blksize - 1) & (~(blksize - 1));
- }
-
- return size;
+ return s->st_blocks * 512;
}
int64_t calculate_dir_size(int dfd)
@@ -51,9 +42,6 @@
while ((de = readdir(d))) {
const char *name = de->d_name;
- if (fstatat(dfd, name, &s, AT_SYMLINK_NOFOLLOW) == 0) {
- size += stat_size(&s);
- }
if (de->d_type == DT_DIR) {
int subfd;
@@ -65,10 +53,17 @@
continue;
}
+ if (fstatat(dfd, name, &s, AT_SYMLINK_NOFOLLOW) == 0) {
+ size += stat_size(&s);
+ }
subfd = openat(dfd, name, O_RDONLY | O_DIRECTORY);
if (subfd >= 0) {
size += calculate_dir_size(subfd);
}
+ } else {
+ if (fstatat(dfd, name, &s, AT_SYMLINK_NOFOLLOW) == 0) {
+ size += stat_size(&s);
+ }
}
}
closedir(d);
diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp
index b4cbf84..a8b4fa8 100644
--- a/libs/gui/ISurfaceComposer.cpp
+++ b/libs/gui/ISurfaceComposer.cpp
@@ -34,6 +34,7 @@
#include <ui/DisplayInfo.h>
#include <ui/DisplayStatInfo.h>
+#include <ui/HdrCapabilities.h>
#include <utils/Log.h>
@@ -282,6 +283,28 @@
reply.read(*outStats);
return reply.readInt32();
}
+
+ virtual status_t getHdrCapabilities(const sp<IBinder>& display,
+ HdrCapabilities* outCapabilities) const {
+ Parcel data, reply;
+ data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
+ status_t result = data.writeStrongBinder(display);
+ if (result != NO_ERROR) {
+ ALOGE("getHdrCapabilities failed to writeStrongBinder: %d", result);
+ return result;
+ }
+ result = remote()->transact(BnSurfaceComposer::GET_HDR_CAPABILITIES,
+ data, &reply);
+ if (result != NO_ERROR) {
+ ALOGE("getHdrCapabilities failed to transact: %d", result);
+ return result;
+ }
+ result = reply.readInt32();
+ if (result == NO_ERROR) {
+ result = reply.readParcelable(outCapabilities);
+ }
+ return result;
+ }
};
// Out-of-line virtual method definition to trigger vtable emission in this
@@ -467,6 +490,23 @@
setPowerMode(display, mode);
return NO_ERROR;
}
+ case GET_HDR_CAPABILITIES: {
+ CHECK_INTERFACE(ISurfaceComposer, data, reply);
+ sp<IBinder> display = nullptr;
+ status_t result = data.readStrongBinder(&display);
+ if (result != NO_ERROR) {
+ ALOGE("getHdrCapabilities failed to readStrongBinder: %d",
+ result);
+ return result;
+ }
+ HdrCapabilities capabilities;
+ result = getHdrCapabilities(display, &capabilities);
+ reply->writeInt32(result);
+ if (result == NO_ERROR) {
+ reply->writeParcelable(capabilities);
+ }
+ return NO_ERROR;
+ }
default: {
return BBinder::onTransact(code, data, reply, flags);
}
diff --git a/libs/gui/Sensor.cpp b/libs/gui/Sensor.cpp
index 0b2b942..4b9a2ab 100644
--- a/libs/gui/Sensor.cpp
+++ b/libs/gui/Sensor.cpp
@@ -35,8 +35,8 @@
namespace android {
// ----------------------------------------------------------------------------
-Sensor::Sensor()
- : mHandle(0), mType(0),
+Sensor::Sensor(const char * name)
+ : mName(name), mHandle(0), mType(0),
mMinValue(0), mMaxValue(0), mResolution(0),
mPower(0), mMinDelay(0), mVersion(0), mFifoReservedEventCount(0),
mFifoMaxEventCount(0), mRequiredAppOp(0),
@@ -390,6 +390,10 @@
return mFlags & SENSOR_FLAG_WAKE_UP;
}
+bool Sensor::isDynamicSensor() const {
+ return mFlags & SENSOR_FLAG_DYNAMIC_SENSOR;
+}
+
int32_t Sensor::getReportingMode() const {
return ((mFlags & REPORTING_MODE_MASK) >> REPORTING_MODE_SHIFT);
}
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index 04b5446..418892a 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -722,6 +722,12 @@
return ComposerService::getComposerService()->getAnimationFrameStats(outStats);
}
+status_t SurfaceComposerClient::getHdrCapabilities(const sp<IBinder>& display,
+ HdrCapabilities* outCapabilities) {
+ return ComposerService::getComposerService()->getHdrCapabilities(display,
+ outCapabilities);
+}
+
// ----------------------------------------------------------------------------
status_t ScreenshotClient::capture(
diff --git a/libs/ui/Android.mk b/libs/ui/Android.mk
index e4cdcab..ee6c093 100644
--- a/libs/ui/Android.mk
+++ b/libs/ui/Android.mk
@@ -40,12 +40,14 @@
GraphicBuffer.cpp \
GraphicBufferAllocator.cpp \
GraphicBufferMapper.cpp \
+ HdrCapabilities.cpp \
PixelFormat.cpp \
Rect.cpp \
Region.cpp \
UiConfig.cpp
LOCAL_SHARED_LIBRARIES := \
+ libbinder \
libcutils \
libhardware \
libsync \
diff --git a/libs/ui/HdrCapabilities.cpp b/libs/ui/HdrCapabilities.cpp
new file mode 100644
index 0000000..511f68a
--- /dev/null
+++ b/libs/ui/HdrCapabilities.cpp
@@ -0,0 +1,59 @@
+/*
+ * Copyright 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 <ui/HdrCapabilities.h>
+
+#include <binder/Parcel.h>
+
+namespace android {
+
+status_t HdrCapabilities::writeToParcel(Parcel* parcel) const
+{
+ status_t result = parcel->writeInt32Vector(mSupportedHdrTypes);
+ if (result != OK) {
+ return result;
+ }
+ result = parcel->writeFloat(mMaxLuminance);
+ if (result != OK) {
+ return result;
+ }
+ result = parcel->writeFloat(mMaxAverageLuminance);
+ if (result != OK) {
+ return result;
+ }
+ result = parcel->writeFloat(mMinLuminance);
+ return result;
+}
+
+status_t HdrCapabilities::readFromParcel(const Parcel* parcel)
+{
+ status_t result = parcel->readInt32Vector(&mSupportedHdrTypes);
+ if (result != OK) {
+ return result;
+ }
+ result = parcel->readFloat(&mMaxLuminance);
+ if (result != OK) {
+ return result;
+ }
+ result = parcel->readFloat(&mMaxAverageLuminance);
+ if (result != OK) {
+ return result;
+ }
+ result = parcel->readFloat(&mMinLuminance);
+ return result;
+}
+
+} // namespace android
diff --git a/services/batteryservice/BatteryProperties.cpp b/services/batteryservice/BatteryProperties.cpp
index 07cc797..d89d4c9 100644
--- a/services/batteryservice/BatteryProperties.cpp
+++ b/services/batteryservice/BatteryProperties.cpp
@@ -41,6 +41,7 @@
batteryLevel = p->readInt32();
batteryVoltage = p->readInt32();
batteryTemperature = p->readInt32();
+ batteryChargeCounter = p->readInt32();
batteryTechnology = String8((p->readString16()).string());
return OK;
}
@@ -57,6 +58,7 @@
p->writeInt32(batteryLevel);
p->writeInt32(batteryVoltage);
p->writeInt32(batteryTemperature);
+ p->writeInt32(batteryChargeCounter);
p->writeString16(String16(batteryTechnology));
return OK;
}
diff --git a/services/sensorservice/Android.mk b/services/sensorservice/Android.mk
index 57c56a6..85e96d6 100644
--- a/services/sensorservice/Android.mk
+++ b/services/sensorservice/Android.mk
@@ -16,6 +16,7 @@
SensorEventConnection.cpp \
MostRecentEventLogger.cpp \
SensorRecord.cpp \
+ SensorList.cpp \
LOCAL_CFLAGS:= -DLOG_TAG=\"SensorService\"
diff --git a/services/sensorservice/CorrectedGyroSensor.cpp b/services/sensorservice/CorrectedGyroSensor.cpp
index 7b1f346..788def9 100644
--- a/services/sensorservice/CorrectedGyroSensor.cpp
+++ b/services/sensorservice/CorrectedGyroSensor.cpp
@@ -39,6 +39,18 @@
break;
}
}
+
+ sensor_t hwSensor;
+ hwSensor.name = "Corrected Gyroscope Sensor";
+ hwSensor.vendor = "AOSP";
+ hwSensor.version = 1;
+ hwSensor.handle = '_cgy';
+ hwSensor.type = SENSOR_TYPE_GYROSCOPE;
+ hwSensor.maxRange = mGyro.getMaxValue();
+ hwSensor.resolution = mGyro.getResolution();
+ hwSensor.power = mSensorFusion.getPowerUsage();
+ hwSensor.minDelay = mGyro.getMinDelay();
+ mSensor = Sensor(&hwSensor);
}
bool CorrectedGyroSensor::process(sensors_event_t* outEvent,
@@ -66,19 +78,8 @@
return mSensorFusion.setDelay(FUSION_9AXIS, ident, ns);
}
-Sensor CorrectedGyroSensor::getSensor() const {
- sensor_t hwSensor;
- hwSensor.name = "Corrected Gyroscope Sensor";
- hwSensor.vendor = "AOSP";
- hwSensor.version = 1;
- hwSensor.handle = '_cgy';
- hwSensor.type = SENSOR_TYPE_GYROSCOPE;
- hwSensor.maxRange = mGyro.getMaxValue();
- hwSensor.resolution = mGyro.getResolution();
- hwSensor.power = mSensorFusion.getPowerUsage();
- hwSensor.minDelay = mGyro.getMinDelay();
- Sensor sensor(&hwSensor);
- return sensor;
+const Sensor& CorrectedGyroSensor::getSensor() const {
+ return mSensor;
}
// ---------------------------------------------------------------------------
diff --git a/services/sensorservice/CorrectedGyroSensor.h b/services/sensorservice/CorrectedGyroSensor.h
index 3c49c08..3419a8a 100644
--- a/services/sensorservice/CorrectedGyroSensor.h
+++ b/services/sensorservice/CorrectedGyroSensor.h
@@ -35,15 +35,15 @@
SensorDevice& mSensorDevice;
SensorFusion& mSensorFusion;
Sensor mGyro;
+ Sensor mSensor;
public:
CorrectedGyroSensor(sensor_t const* list, size_t count);
- virtual bool process(sensors_event_t* outEvent,
- const sensors_event_t& event);
- virtual status_t activate(void* ident, bool enabled);
- virtual status_t setDelay(void* ident, int handle, int64_t ns);
- virtual Sensor getSensor() const;
- virtual bool isVirtual() const { return true; }
+ virtual bool process(sensors_event_t* outEvent, const sensors_event_t& event) override;
+ virtual status_t activate(void* ident, bool enabled) override;
+ virtual status_t setDelay(void* ident, int handle, int64_t ns) override;
+ virtual const Sensor& getSensor() const override;
+ virtual bool isVirtual() const override { return true; }
};
// ---------------------------------------------------------------------------
diff --git a/services/sensorservice/GravitySensor.cpp b/services/sensorservice/GravitySensor.cpp
index a165a5b..0e80f16 100644
--- a/services/sensorservice/GravitySensor.cpp
+++ b/services/sensorservice/GravitySensor.cpp
@@ -39,6 +39,18 @@
break;
}
}
+
+ sensor_t hwSensor;
+ hwSensor.name = "Gravity Sensor";
+ hwSensor.vendor = "AOSP";
+ hwSensor.version = 3;
+ hwSensor.handle = '_grv';
+ hwSensor.type = SENSOR_TYPE_GRAVITY;
+ hwSensor.maxRange = GRAVITY_EARTH * 2;
+ hwSensor.resolution = mAccelerometer.getResolution();
+ hwSensor.power = mSensorFusion.getPowerUsage();
+ hwSensor.minDelay = mSensorFusion.getMinDelay();
+ mSensor = Sensor(&hwSensor);
}
bool GravitySensor::process(sensors_event_t* outEvent,
@@ -73,19 +85,8 @@
return mSensorFusion.setDelay(FUSION_NOMAG, ident, ns);
}
-Sensor GravitySensor::getSensor() const {
- sensor_t hwSensor;
- hwSensor.name = "Gravity Sensor";
- hwSensor.vendor = "AOSP";
- hwSensor.version = 3;
- hwSensor.handle = '_grv';
- hwSensor.type = SENSOR_TYPE_GRAVITY;
- hwSensor.maxRange = GRAVITY_EARTH * 2;
- hwSensor.resolution = mAccelerometer.getResolution();
- hwSensor.power = mSensorFusion.getPowerUsage();
- hwSensor.minDelay = mSensorFusion.getMinDelay();
- Sensor sensor(&hwSensor);
- return sensor;
+const Sensor& GravitySensor::getSensor() const {
+ return mSensor;
}
// ---------------------------------------------------------------------------
diff --git a/services/sensorservice/GravitySensor.h b/services/sensorservice/GravitySensor.h
index ac177c4..f9c0a99 100644
--- a/services/sensorservice/GravitySensor.h
+++ b/services/sensorservice/GravitySensor.h
@@ -35,15 +35,15 @@
SensorDevice& mSensorDevice;
SensorFusion& mSensorFusion;
Sensor mAccelerometer;
+ Sensor mSensor;
public:
GravitySensor(sensor_t const* list, size_t count);
- virtual bool process(sensors_event_t* outEvent,
- const sensors_event_t& event);
- virtual status_t activate(void* ident, bool enabled);
- virtual status_t setDelay(void* ident, int handle, int64_t ns);
- virtual Sensor getSensor() const;
- virtual bool isVirtual() const { return true; }
+ virtual bool process(sensors_event_t* outEvent, const sensors_event_t& event) override;
+ virtual status_t activate(void* ident, bool enabled) override;
+ virtual status_t setDelay(void* ident, int handle, int64_t ns) override;
+ virtual const Sensor& getSensor() const override;
+ virtual bool isVirtual() const override { return true; }
};
// ---------------------------------------------------------------------------
diff --git a/services/sensorservice/LinearAccelerationSensor.cpp b/services/sensorservice/LinearAccelerationSensor.cpp
index d5f20d2..04beced 100644
--- a/services/sensorservice/LinearAccelerationSensor.cpp
+++ b/services/sensorservice/LinearAccelerationSensor.cpp
@@ -33,6 +33,18 @@
: mSensorDevice(SensorDevice::getInstance()),
mGravitySensor(list, count)
{
+ const Sensor &gsensor = mGravitySensor.getSensor();
+ sensor_t hwSensor;
+ hwSensor.name = "Linear Acceleration Sensor";
+ hwSensor.vendor = "AOSP";
+ hwSensor.version = gsensor.getVersion();
+ hwSensor.handle = '_lin';
+ hwSensor.type = SENSOR_TYPE_LINEAR_ACCELERATION;
+ hwSensor.maxRange = gsensor.getMaxValue();
+ hwSensor.resolution = gsensor.getResolution();
+ hwSensor.power = gsensor.getPowerUsage();
+ hwSensor.minDelay = gsensor.getMinDelay();
+ mSensor = Sensor(&hwSensor);
}
bool LinearAccelerationSensor::process(sensors_event_t* outEvent,
@@ -58,20 +70,8 @@
return mGravitySensor.setDelay(ident, handle, ns);
}
-Sensor LinearAccelerationSensor::getSensor() const {
- Sensor gsensor(mGravitySensor.getSensor());
- sensor_t hwSensor;
- hwSensor.name = "Linear Acceleration Sensor";
- hwSensor.vendor = "AOSP";
- hwSensor.version = gsensor.getVersion();
- hwSensor.handle = '_lin';
- hwSensor.type = SENSOR_TYPE_LINEAR_ACCELERATION;
- hwSensor.maxRange = gsensor.getMaxValue();
- hwSensor.resolution = gsensor.getResolution();
- hwSensor.power = gsensor.getPowerUsage();
- hwSensor.minDelay = gsensor.getMinDelay();
- Sensor sensor(&hwSensor);
- return sensor;
+const Sensor& LinearAccelerationSensor::getSensor() const {
+ return mSensor;
}
// ---------------------------------------------------------------------------
diff --git a/services/sensorservice/LinearAccelerationSensor.h b/services/sensorservice/LinearAccelerationSensor.h
index 5deb24f..6b8027b 100644
--- a/services/sensorservice/LinearAccelerationSensor.h
+++ b/services/sensorservice/LinearAccelerationSensor.h
@@ -35,15 +35,16 @@
class LinearAccelerationSensor : public SensorInterface {
SensorDevice& mSensorDevice;
GravitySensor mGravitySensor;
+ Sensor mSensor;
virtual bool process(sensors_event_t* outEvent,
const sensors_event_t& event);
public:
LinearAccelerationSensor(sensor_t const* list, size_t count);
- virtual status_t activate(void* ident, bool enabled);
- virtual status_t setDelay(void* ident, int handle, int64_t ns);
- virtual Sensor getSensor() const;
- virtual bool isVirtual() const { return true; }
+ virtual status_t activate(void* ident, bool enabled) override;
+ virtual status_t setDelay(void* ident, int handle, int64_t ns) override;
+ virtual const Sensor& getSensor() const override;
+ virtual bool isVirtual() const override { return true; }
};
// ---------------------------------------------------------------------------
diff --git a/services/sensorservice/OrientationSensor.cpp b/services/sensorservice/OrientationSensor.cpp
index d55f336..20b49be 100644
--- a/services/sensorservice/OrientationSensor.cpp
+++ b/services/sensorservice/OrientationSensor.cpp
@@ -36,6 +36,17 @@
// FIXME: instead of using the SensorFusion code, we should use
// the SENSOR_TYPE_ROTATION_VECTOR instead. This way we could use the
// HAL's implementation.
+ sensor_t hwSensor;
+ hwSensor.name = "Orientation Sensor";
+ hwSensor.vendor = "AOSP";
+ hwSensor.version = 1;
+ hwSensor.handle = '_ypr';
+ hwSensor.type = SENSOR_TYPE_ORIENTATION;
+ hwSensor.maxRange = 360.0f;
+ hwSensor.resolution = 1.0f/256.0f; // FIXME: real value here
+ hwSensor.power = mSensorFusion.getPowerUsage();
+ hwSensor.minDelay = mSensorFusion.getMinDelay();
+ mSensor = Sensor(&hwSensor);
}
bool OrientationSensor::process(sensors_event_t* outEvent,
@@ -73,19 +84,8 @@
return mSensorFusion.setDelay(FUSION_9AXIS, ident, ns);
}
-Sensor OrientationSensor::getSensor() const {
- sensor_t hwSensor;
- hwSensor.name = "Orientation Sensor";
- hwSensor.vendor = "AOSP";
- hwSensor.version = 1;
- hwSensor.handle = '_ypr';
- hwSensor.type = SENSOR_TYPE_ORIENTATION;
- hwSensor.maxRange = 360.0f;
- hwSensor.resolution = 1.0f/256.0f; // FIXME: real value here
- hwSensor.power = mSensorFusion.getPowerUsage();
- hwSensor.minDelay = mSensorFusion.getMinDelay();
- Sensor sensor(&hwSensor);
- return sensor;
+const Sensor& OrientationSensor::getSensor() const {
+ return mSensor;
}
// ---------------------------------------------------------------------------
diff --git a/services/sensorservice/OrientationSensor.h b/services/sensorservice/OrientationSensor.h
index 855949d..644a774 100644
--- a/services/sensorservice/OrientationSensor.h
+++ b/services/sensorservice/OrientationSensor.h
@@ -34,15 +34,15 @@
class OrientationSensor : public SensorInterface {
SensorDevice& mSensorDevice;
SensorFusion& mSensorFusion;
+ Sensor mSensor;
public:
OrientationSensor();
- virtual bool process(sensors_event_t* outEvent,
- const sensors_event_t& event);
- virtual status_t activate(void* ident, bool enabled);
- virtual status_t setDelay(void* ident, int handle, int64_t ns);
- virtual Sensor getSensor() const;
- virtual bool isVirtual() const { return true; }
+ virtual bool process(sensors_event_t* outEvent, const sensors_event_t& event) override;
+ virtual status_t activate(void* ident, bool enabled) override;
+ virtual status_t setDelay(void* ident, int handle, int64_t ns) override;
+ virtual const Sensor& getSensor() const override;
+ virtual bool isVirtual() const override { return true; }
};
// ---------------------------------------------------------------------------
diff --git a/services/sensorservice/RotationVectorSensor.cpp b/services/sensorservice/RotationVectorSensor.cpp
index 238845b..5a40ef9 100644
--- a/services/sensorservice/RotationVectorSensor.cpp
+++ b/services/sensorservice/RotationVectorSensor.cpp
@@ -32,6 +32,17 @@
mSensorFusion(SensorFusion::getInstance()),
mMode(mode)
{
+ sensor_t hwSensor;
+ hwSensor.name = getSensorName();
+ hwSensor.vendor = "AOSP";
+ hwSensor.version = 3;
+ hwSensor.handle = getSensorToken();
+ hwSensor.type = getSensorType();
+ hwSensor.maxRange = 1;
+ hwSensor.resolution = 1.0f / (1<<24);
+ hwSensor.power = mSensorFusion.getPowerUsage();
+ hwSensor.minDelay = mSensorFusion.getMinDelay();
+ mSensor = Sensor(&hwSensor);
}
bool RotationVectorSensor::process(sensors_event_t* outEvent,
@@ -61,19 +72,8 @@
return mSensorFusion.setDelay(mMode, ident, ns);
}
-Sensor RotationVectorSensor::getSensor() const {
- sensor_t hwSensor;
- hwSensor.name = getSensorName();
- hwSensor.vendor = "AOSP";
- hwSensor.version = 3;
- hwSensor.handle = getSensorToken();
- hwSensor.type = getSensorType();
- hwSensor.maxRange = 1;
- hwSensor.resolution = 1.0f / (1<<24);
- hwSensor.power = mSensorFusion.getPowerUsage();
- hwSensor.minDelay = mSensorFusion.getMinDelay();
- Sensor sensor(&hwSensor);
- return sensor;
+const Sensor& RotationVectorSensor::getSensor() const {
+ return mSensor;
}
int RotationVectorSensor::getSensorType() const {
@@ -124,6 +124,17 @@
: mSensorDevice(SensorDevice::getInstance()),
mSensorFusion(SensorFusion::getInstance())
{
+ sensor_t hwSensor;
+ hwSensor.name = "Gyroscope Bias (debug)";
+ hwSensor.vendor = "AOSP";
+ hwSensor.version = 1;
+ hwSensor.handle = '_gbs';
+ hwSensor.type = SENSOR_TYPE_ACCELEROMETER;
+ hwSensor.maxRange = 1;
+ hwSensor.resolution = 1.0f / (1<<24);
+ hwSensor.power = mSensorFusion.getPowerUsage();
+ hwSensor.minDelay = mSensorFusion.getMinDelay();
+ mSensor = Sensor(&hwSensor);
}
bool GyroDriftSensor::process(sensors_event_t* outEvent,
@@ -152,19 +163,8 @@
return mSensorFusion.setDelay(FUSION_9AXIS, ident, ns);
}
-Sensor GyroDriftSensor::getSensor() const {
- sensor_t hwSensor;
- hwSensor.name = "Gyroscope Bias (debug)";
- hwSensor.vendor = "AOSP";
- hwSensor.version = 1;
- hwSensor.handle = '_gbs';
- hwSensor.type = SENSOR_TYPE_ACCELEROMETER;
- hwSensor.maxRange = 1;
- hwSensor.resolution = 1.0f / (1<<24);
- hwSensor.power = mSensorFusion.getPowerUsage();
- hwSensor.minDelay = mSensorFusion.getMinDelay();
- Sensor sensor(&hwSensor);
- return sensor;
+const Sensor& GyroDriftSensor::getSensor() const {
+ return mSensor;
}
// ---------------------------------------------------------------------------
diff --git a/services/sensorservice/RotationVectorSensor.h b/services/sensorservice/RotationVectorSensor.h
index 1fc316b..5dba0d5 100644
--- a/services/sensorservice/RotationVectorSensor.h
+++ b/services/sensorservice/RotationVectorSensor.h
@@ -36,6 +36,7 @@
SensorDevice& mSensorDevice;
SensorFusion& mSensorFusion;
int mMode;
+ Sensor mSensor;
int getSensorType() const;
const char* getSensorName() const ;
@@ -43,12 +44,11 @@
public:
RotationVectorSensor(int mode = FUSION_9AXIS);
- virtual bool process(sensors_event_t* outEvent,
- const sensors_event_t& event);
- virtual status_t activate(void* ident, bool enabled);
- virtual status_t setDelay(void* ident, int handle, int64_t ns);
- virtual Sensor getSensor() const;
- virtual bool isVirtual() const { return true; }
+ virtual bool process(sensors_event_t* outEvent, const sensors_event_t& event) override;
+ virtual status_t activate(void* ident, bool enabled) override;
+ virtual status_t setDelay(void* ident, int handle, int64_t ns) override;
+ virtual const Sensor& getSensor() const override;
+ virtual bool isVirtual() const override { return true; }
};
class GameRotationVectorSensor : public RotationVectorSensor {
@@ -64,15 +64,15 @@
class GyroDriftSensor : public SensorInterface {
SensorDevice& mSensorDevice;
SensorFusion& mSensorFusion;
+ Sensor mSensor;
public:
GyroDriftSensor();
- virtual bool process(sensors_event_t* outEvent,
- const sensors_event_t& event);
- virtual status_t activate(void* ident, bool enabled);
- virtual status_t setDelay(void* ident, int handle, int64_t ns);
- virtual Sensor getSensor() const;
- virtual bool isVirtual() const { return true; }
+ virtual bool process(sensors_event_t* outEvent, const sensors_event_t& event) override;
+ virtual status_t activate(void* ident, bool enabled) override;
+ virtual status_t setDelay(void* ident, int handle, int64_t ns) override;
+ virtual const Sensor& getSensor() const override;
+ virtual bool isVirtual() const override { return true; }
};
// ---------------------------------------------------------------------------
diff --git a/services/sensorservice/SensorInterface.cpp b/services/sensorservice/SensorInterface.cpp
index 970220b..bb2a8a2 100644
--- a/services/sensorservice/SensorInterface.cpp
+++ b/services/sensorservice/SensorInterface.cpp
@@ -65,7 +65,7 @@
mSensorDevice.autoDisable(ident, handle);
}
-Sensor HardwareSensor::getSensor() const {
+const Sensor& HardwareSensor::getSensor() const {
return mSensor;
}
diff --git a/services/sensorservice/SensorInterface.h b/services/sensorservice/SensorInterface.h
index 3e76377..06cca75 100644
--- a/services/sensorservice/SensorInterface.h
+++ b/services/sensorservice/SensorInterface.h
@@ -33,8 +33,7 @@
public:
virtual ~SensorInterface();
- virtual bool process(sensors_event_t* outEvent,
- const sensors_event_t& event) = 0;
+ virtual bool process(sensors_event_t* outEvent, const sensors_event_t& event) = 0;
virtual status_t activate(void* ident, bool enabled) = 0;
virtual status_t setDelay(void* ident, int handle, int64_t ns) = 0;
@@ -52,7 +51,7 @@
return -EINVAL;
}
- virtual Sensor getSensor() const = 0;
+ virtual const Sensor& getSensor() const = 0;
virtual bool isVirtual() const = 0;
virtual void autoDisable(void* /*ident*/, int /*handle*/) { }
};
@@ -72,14 +71,14 @@
virtual bool process(sensors_event_t* outEvent,
const sensors_event_t& event);
- virtual status_t activate(void* ident, bool enabled);
+ virtual status_t activate(void* ident, bool enabled) override;
virtual status_t batch(void* ident, int handle, int flags, int64_t samplingPeriodNs,
- int64_t maxBatchReportLatencyNs);
- virtual status_t setDelay(void* ident, int handle, int64_t ns);
- virtual status_t flush(void* ident, int handle);
- virtual Sensor getSensor() const;
- virtual bool isVirtual() const { return false; }
- virtual void autoDisable(void *ident, int handle);
+ int64_t maxBatchReportLatencyNs) override;
+ virtual status_t setDelay(void* ident, int handle, int64_t ns) override;
+ virtual status_t flush(void* ident, int handle) override;
+ virtual const Sensor& getSensor() const override;
+ virtual bool isVirtual() const override { return false; }
+ virtual void autoDisable(void *ident, int handle) override;
};
diff --git a/services/sensorservice/SensorList.cpp b/services/sensorservice/SensorList.cpp
new file mode 100644
index 0000000..f28acd2
--- /dev/null
+++ b/services/sensorservice/SensorList.cpp
@@ -0,0 +1,198 @@
+/*
+ * 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 "SensorList.h"
+
+#include <hardware/sensors.h>
+#include <utils/String8.h>
+
+namespace android {
+namespace SensorServiceUtil {
+
+const Sensor SensorList::mNonSensor = Sensor("unknown");
+
+bool SensorList::add(
+ int handle, SensorInterface* si, bool isForDebug, bool isVirtual) {
+ std::lock_guard<std::mutex> lk(mLock);
+ if (handle == si->getSensor().getHandle() &&
+ mUsedHandle.insert(handle).second) {
+ // will succeed as the mUsedHandle does not have this handle
+ mHandleMap.emplace(handle, Entry(si, isForDebug, isVirtual));
+ return true;
+ }
+ // handle exist already or handle mismatch
+ return false;
+}
+
+bool SensorList::remove(int handle) {
+ std::lock_guard<std::mutex> lk(mLock);
+ auto entry = mHandleMap.find(handle);
+ if (entry != mHandleMap.end()) {
+ mRecycle.push_back(entry->second.si);
+ mHandleMap.erase(entry);
+ return true;
+ }
+ return false;
+}
+
+String8 SensorList::getName(int handle) const {
+ return getOne<String8>(
+ handle, [] (const Entry& e) -> String8 {return e.si->getSensor().getName();},
+ mNonSensor.getName());
+}
+
+const Sensor& SensorList::get(int handle) const {
+ return getOne<const Sensor&>(
+ handle, [] (const Entry& e) -> const Sensor& {return e.si->getSensor();}, mNonSensor);
+}
+
+SensorInterface* SensorList::getInterface(int handle) const {
+ return getOne<SensorInterface *>(
+ handle, [] (const Entry& e) -> SensorInterface* {return e.si;}, nullptr);
+}
+
+
+bool SensorList::isNewHandle(int handle) const {
+ std::lock_guard<std::mutex> lk(mLock);
+ return mUsedHandle.find(handle) == mUsedHandle.end();
+}
+
+const Vector<Sensor> SensorList::getUserSensors() const {
+ // lock in forEachEntry
+ Vector<Sensor> sensors;
+ forEachEntry(
+ [&sensors] (const Entry& e) -> bool {
+ if (!e.isForDebug && !e.si->getSensor().isDynamicSensor()) {
+ sensors.add(e.si->getSensor());
+ }
+ return true;
+ });
+ return sensors;
+}
+
+const Vector<Sensor> SensorList::getUserDebugSensors() const {
+ // lock in forEachEntry
+ Vector<Sensor> sensors;
+ forEachEntry(
+ [&sensors] (const Entry& e) -> bool {
+ if (!e.si->getSensor().isDynamicSensor()) {
+ sensors.add(e.si->getSensor());
+ }
+ return true;
+ });
+ return sensors;
+}
+
+const Vector<Sensor> SensorList::getDynamicSensors() const {
+ // lock in forEachEntry
+ Vector<Sensor> sensors;
+ forEachEntry(
+ [&sensors] (const Entry& e) -> bool {
+ if (!e.isForDebug && e.si->getSensor().isDynamicSensor()) {
+ sensors.add(e.si->getSensor());
+ }
+ return true;
+ });
+ return sensors;
+}
+
+const Vector<Sensor> SensorList::getVirtualSensors() const {
+ // lock in forEachEntry
+ Vector<Sensor> sensors;
+ forEachEntry(
+ [&sensors] (const Entry& e) -> bool {
+ if (e.isVirtual) {
+ sensors.add(e.si->getSensor());
+ }
+ return true;
+ });
+ return sensors;
+}
+
+std::string SensorList::dump() const {
+ String8 result;
+
+ result.append("Sensor List:\n");
+ forEachSensor([&result] (const Sensor& s) -> bool {
+ result.appendFormat(
+ "%-15s| %-10s| version=%d |%-20s| 0x%08x | \"%s\" | type=%d |",
+ s.getName().string(),
+ s.getVendor().string(),
+ s.getVersion(),
+ s.getStringType().string(),
+ s.getHandle(),
+ s.getRequiredPermission().string(),
+ s.getType());
+
+ const int reportingMode = s.getReportingMode();
+ if (reportingMode == AREPORTING_MODE_CONTINUOUS) {
+ result.append(" continuous | ");
+ } else if (reportingMode == AREPORTING_MODE_ON_CHANGE) {
+ result.append(" on-change | ");
+ } else if (reportingMode == AREPORTING_MODE_ONE_SHOT) {
+ result.append(" one-shot | ");
+ } else if (reportingMode == AREPORTING_MODE_SPECIAL_TRIGGER) {
+ result.append(" special-trigger | ");
+ } else {
+ result.append(" unknown-mode | ");
+ }
+
+ if (s.getMaxDelay() > 0) {
+ result.appendFormat("minRate=%.2fHz | ", 1e6f / s.getMaxDelay());
+ } else {
+ result.appendFormat("maxDelay=%dus | ", s.getMaxDelay());
+ }
+
+ if (s.getMinDelay() > 0) {
+ result.appendFormat("maxRate=%.2fHz | ", 1e6f / s.getMinDelay());
+ } else {
+ result.appendFormat("minDelay=%dus | ", s.getMinDelay());
+ }
+
+ if (s.getFifoMaxEventCount() > 0) {
+ result.appendFormat("FifoMax=%d events | ",
+ s.getFifoMaxEventCount());
+ } else {
+ result.append("no batching | ");
+ }
+
+ if (s.isWakeUpSensor()) {
+ result.appendFormat("wakeUp | ");
+ } else {
+ result.appendFormat("non-wakeUp | ");
+ }
+
+ result.append("\n");
+ return true;
+ });
+ return std::string(result.string());
+}
+
+SensorList::~SensorList() {
+ // from this point on no one should access anything in SensorList
+ mLock.lock();
+ for (auto i : mRecycle) {
+ delete i;
+ }
+ for (auto&& i : mHandleMap) {
+ delete i.second.si;
+ }
+ // the lock will eventually get destructed, there is no guarantee after that.
+}
+
+} // namespace SensorServiceUtil
+} // namespace android
+
diff --git a/services/sensorservice/SensorList.h b/services/sensorservice/SensorList.h
new file mode 100644
index 0000000..3fe73cc
--- /dev/null
+++ b/services/sensorservice/SensorList.h
@@ -0,0 +1,145 @@
+/*
+ * 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 ANDROID_SENSOR_LIST_H
+#define ANDROID_SENSOR_LIST_H
+
+#include "SensorInterface.h"
+
+#include <gui/Sensor.h>
+#include <utils/String8.h>
+#include <utils/Vector.h>
+
+#include <mutex>
+#include <map>
+#include <string>
+#include <unordered_set>
+#include <vector>
+
+namespace android {
+class SensorInterface;
+
+namespace SensorServiceUtil {
+
+class Dumpable {
+public:
+ virtual std::string dump() const;
+ virtual void setFormat(std::string ) {}
+ virtual ~Dumpable() {}
+};
+
+class SensorList : public Dumpable {
+public:
+ // After SensorInterface * is added into SensorList, it can be assumed that SensorList own the
+ // object it pointed to and the object should not be released elsewhere.
+ bool add(int handle, SensorInterface* si, bool isForDebug = false, bool isVirtual = false);
+ bool remove(int handle);
+
+ inline bool hasAnySensor() const { return mHandleMap.size() > 0;}
+
+ //helper functions
+ const Vector<Sensor> getUserSensors() const;
+ const Vector<Sensor> getUserDebugSensors() const;
+ const Vector<Sensor> getDynamicSensors() const;
+ const Vector<Sensor> getVirtualSensors() const;
+
+ String8 getName(int handle) const;
+ const Sensor& get(int handle) const;
+ SensorInterface* getInterface(int handle) const;
+ bool isNewHandle(int handle) const;
+
+ // Iterate through Sensor in sensor list and perform operation f on each Sensor object.
+ //
+ // TF is a function with the signature:
+ // bool f(const Sensor &);
+ // A return value of 'false' stops the iteration immediately.
+ //
+ // Note: in the function f, it is illegal to make calls to member functions of the same
+ // SensorList object on which forEachSensor is invoked.
+ template <typename TF>
+ void forEachSensor(const TF& f) const;
+
+ const Sensor& getNonSensor() const { return mNonSensor;}
+
+ // Dumpable interface
+ virtual std::string dump() const override;
+
+ virtual ~SensorList();
+private:
+ struct Entry {
+ //TODO: use sp<> here
+ SensorInterface * const si;
+ const bool isForDebug;
+ const bool isVirtual;
+ Entry(SensorInterface* si_, bool debug_, bool virtual_) :
+ si(si_), isForDebug(debug_), isVirtual(virtual_) {
+ }
+ };
+
+ const static Sensor mNonSensor; //.getName() == "unknown",
+
+ // Iterate through Entry in sensor list and perform operation f on each Entry.
+ //
+ // TF is a function with the signature:
+ // bool f(const Entry &);
+ // A return value of 'false' stops the iteration over entries immediately.
+ //
+ // Note: in the function being passed in, it is illegal to make calls to member functions of the
+ // same SensorList object on which forEachSensor is invoked.
+ template <typename TF>
+ void forEachEntry(const TF& f) const;
+
+ template <typename T, typename TF>
+ T getOne(int handle, const TF& accessor, T def = T()) const;
+
+ mutable std::mutex mLock;
+ std::map<int, Entry> mHandleMap;
+ std::unordered_set<int> mUsedHandle;
+ std::vector<SensorInterface *> mRecycle;
+};
+
+template <typename TF>
+void SensorList::forEachSensor(const TF& f) const {
+ // lock happens in forEachEntry
+ forEachEntry([&f] (const Entry& e) -> bool { return f(e.si->getSensor());});
+}
+
+template <typename TF>
+void SensorList::forEachEntry(const TF& f) const {
+ std::lock_guard<std::mutex> lk(mLock);
+
+ for (auto&& i : mHandleMap) {
+ if (!f(i.second)){
+ break;
+ }
+ }
+}
+
+template <typename T, typename TF>
+T SensorList::getOne(int handle, const TF& accessor, T def) const {
+ std::lock_guard<std::mutex> lk(mLock);
+ auto i = mHandleMap.find(handle);
+ if (i != mHandleMap.end()) {
+ return accessor(i->second);
+ } else {
+ return def;
+ }
+}
+
+} // namespace SensorServiceUtil
+} // namespace android
+
+#endif // ANDROID_SENSOR_LIST_H
diff --git a/services/sensorservice/SensorService.cpp b/services/sensorservice/SensorService.cpp
index 31ca0e3..f334e29 100644
--- a/services/sensorservice/SensorService.cpp
+++ b/services/sensorservice/SensorService.cpp
@@ -125,78 +125,51 @@
// registered)
SensorFusion::getInstance();
- // build the sensor list returned to users
- mUserSensorList = mSensorList;
-
if (hasGyro && hasAccel && hasMag) {
// Add Android virtual sensors if they're not already
// available in the HAL
- Sensor aSensor;
+ bool needRotationVector =
+ (virtualSensorsNeeds & (1<<SENSOR_TYPE_ROTATION_VECTOR)) != 0;
- aSensor = registerVirtualSensor( new RotationVectorSensor() );
- if (virtualSensorsNeeds & (1<<SENSOR_TYPE_ROTATION_VECTOR)) {
- mUserSensorList.add(aSensor);
- }
+ registerSensor(new RotationVectorSensor(), !needRotationVector, true);
+ registerSensor(new OrientationSensor(), !needRotationVector, true);
- aSensor = registerVirtualSensor( new OrientationSensor() );
- if (virtualSensorsNeeds & (1<<SENSOR_TYPE_ROTATION_VECTOR)) {
- // if we are doing our own rotation-vector, also add
- // the orientation sensor and remove the HAL provided one.
- mUserSensorList.replaceAt(aSensor, orientationIndex);
- }
+ bool needLinearAcceleration =
+ (virtualSensorsNeeds & (1<<SENSOR_TYPE_LINEAR_ACCELERATION)) != 0;
- aSensor = registerVirtualSensor(
- new LinearAccelerationSensor(list, count) );
- if (virtualSensorsNeeds &
- (1<<SENSOR_TYPE_LINEAR_ACCELERATION)) {
- mUserSensorList.add(aSensor);
- }
+ registerSensor(new LinearAccelerationSensor(list, count),
+ !needLinearAcceleration, true);
- // virtual debugging sensors are not added to mUserSensorList
- registerVirtualSensor( new CorrectedGyroSensor(list, count) );
- registerVirtualSensor( new GyroDriftSensor() );
+ // virtual debugging sensors are not for user
+ registerSensor( new CorrectedGyroSensor(list, count), false, true);
+ registerSensor( new GyroDriftSensor(), false, true);
}
if (hasAccel && hasGyro) {
- Sensor aSensor;
+ bool needGravitySensor = (virtualSensorsNeeds & (1<<SENSOR_TYPE_GRAVITY)) != 0;
+ registerSensor(new GravitySensor(list, count), !needGravitySensor, true);
- aSensor = registerVirtualSensor(
- new GravitySensor(list, count) );
- if (virtualSensorsNeeds & (1<<SENSOR_TYPE_GRAVITY)) {
- mUserSensorList.add(aSensor);
- }
-
- aSensor = registerVirtualSensor(
- new GameRotationVectorSensor() );
- if (virtualSensorsNeeds &
- (1<<SENSOR_TYPE_GAME_ROTATION_VECTOR)) {
- mUserSensorList.add(aSensor);
- }
+ bool needGameRotationVector =
+ (virtualSensorsNeeds & (1<<SENSOR_TYPE_GAME_ROTATION_VECTOR)) != 0;
+ registerSensor(new GameRotationVectorSensor(), !needGameRotationVector, true);
}
if (hasAccel && hasMag) {
- Sensor aSensor;
-
- aSensor = registerVirtualSensor(
- new GeoMagRotationVectorSensor() );
- if (virtualSensorsNeeds &
- (1<<SENSOR_TYPE_GEOMAGNETIC_ROTATION_VECTOR)) {
- mUserSensorList.add(aSensor);
- }
+ bool needGeoMagRotationVector =
+ (virtualSensorsNeeds & (1<<SENSOR_TYPE_GEOMAGNETIC_ROTATION_VECTOR)) != 0;
+ registerSensor(new GeoMagRotationVectorSensor(), !needGeoMagRotationVector, true);
}
- // debugging sensor list
- mUserSensorListDebug = mSensorList;
-
// Check if the device really supports batching by looking at the FIFO event
// counts for each sensor.
bool batchingSupported = false;
- for (size_t i = 0; i < mSensorList.size(); ++i) {
- if (mSensorList[i].getFifoMaxEventCount() > 0) {
- batchingSupported = true;
- break;
- }
- }
+ mSensors.forEachSensor(
+ [&batchingSupported] (const Sensor& s) -> bool {
+ if (s.getFifoMaxEventCount() > 0) {
+ batchingSupported = true;
+ }
+ return !batchingSupported;
+ });
if (batchingSupported) {
// Increase socket buffer size to a max of 100 KB for batching capabilities.
@@ -242,75 +215,35 @@
}
}
-Sensor SensorService::registerSensor(SensorInterface* s) {
- const Sensor sensor(s->getSensor());
-
- // add handle to used handle list
- mUsedHandleList.add(sensor.getHandle());
- // add to the sensor list (returned to clients)
- mSensorList.add(sensor);
- // add to our handle->SensorInterface mapping
- mSensorMap.add(sensor.getHandle(), s);
- // create an entry in the mLastEventSeen array
- mLastEventSeen.add(sensor.getHandle(), NULL);
-
- return sensor;
+const Sensor& SensorService::registerSensor(SensorInterface* s, bool isDebug, bool isVirtual) {
+ int handle = s->getSensor().getHandle();
+ if (mSensors.add(handle, s, isDebug, isVirtual)){
+ mLastEventSeen.add(handle, nullptr);
+ return s->getSensor();
+ } else {
+ return mSensors.getNonSensor();
+ }
}
-Sensor SensorService::registerDynamicSensor(SensorInterface* s) {
- Sensor sensor = registerSensor(s);
- mDynamicSensorList.add(sensor);
-
- auto compareSensorHandle = [] (const Sensor* lhs, const Sensor* rhs) {
- return lhs->getHandle() - rhs->getHandle();
- };
- mDynamicSensorList.sort(compareSensorHandle);
- return sensor;
+const Sensor& SensorService::registerDynamicSensor(SensorInterface* s, bool isDebug) {
+ return registerSensor(s, isDebug);
}
bool SensorService::unregisterDynamicSensor(int handle) {
- bool found = false;
-
- for (size_t i = 0 ; i < mSensorList.size() ; i++) {
- if (mSensorList[i].getHandle() == handle) {
- mSensorList.removeAt(i);
- found = true;
- break;
- }
+ bool ret = mSensors.remove(handle);
+ MostRecentEventLogger *buf = mLastEventSeen.valueFor(handle);
+ if (buf) {
+ delete buf;
}
-
- if (found) {
- for (size_t i = 0 ; i < mDynamicSensorList.size() ; i++) {
- if (mDynamicSensorList[i].getHandle() == handle) {
- mDynamicSensorList.removeAt(i);
- }
- }
-
- mSensorMap.removeItem(handle);
- mLastEventSeen.removeItem(handle);
- }
- return found;
+ mLastEventSeen.removeItem(handle);
+ return ret;
}
-Sensor SensorService::registerVirtualSensor(SensorInterface* s) {
- Sensor sensor = registerSensor(s);
- mVirtualSensorList.add( s );
- return sensor;
-}
-
-bool SensorService::isNewHandle(int handle) {
- for (int h : mUsedHandleList) {
- if (h == handle) {
- return false;
- }
- }
- return true;
+const Sensor& SensorService::registerVirtualSensor(SensorInterface* s, bool isDebug) {
+ return registerSensor(s, isDebug, true);
}
SensorService::~SensorService() {
- for (size_t i=0 ; i<mSensorMap.size() ; i++) {
- delete mSensorMap.valueAt(i);
- }
}
status_t SensorService::dump(int fd, const Vector<String16>& args) {
@@ -374,73 +307,31 @@
// Transition to data injection mode supported only from NORMAL mode.
return INVALID_OPERATION;
}
- } else if (mSensorList.size() == 0) {
+ } else if (!mSensors.hasAnySensor()) {
result.append("No Sensors on the device\n");
} else {
// Default dump the sensor list and debugging information.
- result.append("Sensor List:\n");
- for (size_t i=0 ; i<mSensorList.size() ; i++) {
- const Sensor& s(mSensorList[i]);
- result.appendFormat(
- "%-15s| %-10s| version=%d |%-20s| 0x%08x | \"%s\" | type=%d |",
- s.getName().string(),
- s.getVendor().string(),
- s.getVersion(),
- s.getStringType().string(),
- s.getHandle(),
- s.getRequiredPermission().string(),
- s.getType());
+ //
+ result.append(mSensors.dump().c_str());
- const int reportingMode = s.getReportingMode();
- if (reportingMode == AREPORTING_MODE_CONTINUOUS) {
- result.append(" continuous | ");
- } else if (reportingMode == AREPORTING_MODE_ON_CHANGE) {
- result.append(" on-change | ");
- } else if (reportingMode == AREPORTING_MODE_ONE_SHOT) {
- result.append(" one-shot | ");
- } else {
- result.append(" special-trigger | ");
- }
-
- if (s.getMaxDelay() > 0) {
- result.appendFormat("minRate=%.2fHz | ", 1e6f / s.getMaxDelay());
- } else {
- result.appendFormat("maxDelay=%dus |", s.getMaxDelay());
- }
-
- if (s.getMinDelay() > 0) {
- result.appendFormat("maxRate=%.2fHz | ", 1e6f / s.getMinDelay());
- } else {
- result.appendFormat("minDelay=%dus |", s.getMinDelay());
- }
-
- if (s.getFifoMaxEventCount() > 0) {
- result.appendFormat("FifoMax=%d events | ",
- s.getFifoMaxEventCount());
- } else {
- result.append("no batching | ");
- }
-
- if (s.isWakeUpSensor()) {
- result.appendFormat("wakeUp | ");
- } else {
- result.appendFormat("non-wakeUp | ");
- }
-
- int bufIndex = mLastEventSeen.indexOfKey(s.getHandle());
- if (bufIndex >= 0) {
- const MostRecentEventLogger* buf = mLastEventSeen.valueAt(bufIndex);
- if (buf != NULL && s.getRequiredPermission().isEmpty()) {
- buf->printBuffer(result);
- } else {
- result.append("last=<> \n");
- }
- }
- result.append("\n");
- }
SensorFusion::getInstance().dump(result);
SensorDevice::getInstance().dump(result);
+ result.append("Recent Sensor events:\n");
+ auto& lastEvents = mLastEventSeen;
+ mSensors.forEachSensor([&result, &lastEvents] (const Sensor& s) -> bool {
+ int bufIndex = lastEvents.indexOfKey(s.getHandle());
+ if (bufIndex >= 0) {
+ const MostRecentEventLogger* buf = lastEvents.valueAt(bufIndex);
+ if (buf != nullptr && s.getRequiredPermission().isEmpty()) {
+ result.appendFormat("%s (handle:0x%08x): ",
+ s.getName().string(), s.getHandle());
+ buf->printBuffer(result);
+ }
+ }
+ return true;
+ });
+
result.append("Active sensors:\n");
for (size_t i=0 ; i<mActiveSensors.size() ; i++) {
int handle = mActiveSensors.keyAt(i);
@@ -508,6 +399,7 @@
return NO_ERROR;
}
+//TODO: move to SensorEventConnection later
void SensorService::cleanupAutoDisabledSensorLocked(const sp<SensorEventConnection>& connection,
sensors_event_t const* buffer, const int count) {
for (int i=0 ; i<count ; i++) {
@@ -516,12 +408,12 @@
handle = buffer[i].meta_data.sensor;
}
if (connection->hasSensor(handle)) {
- SensorInterface* sensor = getSensorInterfaceFromHandle(handle);
+ SensorInterface* si = mSensors.getInterface(handle);
// If this buffer has an event from a one_shot sensor and this connection is registered
// for this particular one_shot sensor, try cleaning up the connection.
- if (sensor != NULL &&
- sensor->getSensor().getReportingMode() == AREPORTING_MODE_ONE_SHOT) {
- sensor->autoDisable(connection.get(), handle);
+ if (si != NULL &&
+ si->getSensor().getReportingMode() == AREPORTING_MODE_ONE_SHOT) {
+ si->autoDisable(connection.get(), handle);
cleanupWithoutDisableLocked(connection, handle);
}
@@ -535,11 +427,11 @@
// each virtual sensor could generate an event per "real" event, that's why we need to size
// numEventMax much smaller than MAX_RECEIVE_BUFFER_EVENT_COUNT. in practice, this is too
// aggressive, but guaranteed to be enough.
+ const size_t vcount = mSensors.getVirtualSensors().size();
const size_t minBufferSize = SensorEventQueue::MAX_RECEIVE_BUFFER_EVENT_COUNT;
- const size_t numEventMax = minBufferSize / (1 + mVirtualSensorList.size());
+ const size_t numEventMax = minBufferSize / (1 + vcount);
SensorDevice& device(SensorDevice::getInstance());
- const size_t vcount = mVirtualSensorList.size();
const int halVersion = device.getHalDeviceVersion();
do {
@@ -632,10 +524,10 @@
}
for (int i = 0; i < count; ++i) {
- // Map flush_complete_events in the buffer to SensorEventConnections which called flush on
- // the hardware sensor. mapFlushEventsToConnections[i] will be the SensorEventConnection
- // mapped to the corresponding flush_complete_event in mSensorEventBuffer[i] if such a
- // mapping exists (NULL otherwise).
+ // Map flush_complete_events in the buffer to SensorEventConnections which called flush
+ // on the hardware sensor. mapFlushEventsToConnections[i] will be the
+ // SensorEventConnection mapped to the corresponding flush_complete_event in
+ // mSensorEventBuffer[i] if such a mapping exists (NULL otherwise).
mMapFlushEventsToConnections[i] = NULL;
if (mSensorEventBuffer[i].type == SENSOR_TYPE_META_DATA) {
const int sensor_handle = mSensorEventBuffer[i].meta_data.sensor;
@@ -656,7 +548,7 @@
ALOGI("Dynamic sensor handle 0x%x connected, type %d, name %s",
handle, dynamicSensor.type, dynamicSensor.name);
- if (isNewHandle(handle)) {
+ if (mSensors.isNewHandle(handle)) {
sensor_t s = dynamicSensor;
// make sure the dynamic sensor flag is set
s.flags |= DYNAMIC_SENSOR_MASK;
@@ -664,8 +556,8 @@
s.handle = handle;
SensorInterface *si = new HardwareSensor(s);
- // This will release hold on dynamic sensor meta, so it should be called after
- // Sensor object is created.
+ // This will release hold on dynamic sensor meta, so it should be called
+ // after Sensor object is created.
device.handleDynamicSensorConnection(handle, true /*connected*/);
registerDynamicSensor(si);
} else {
@@ -802,14 +694,7 @@
}
String8 SensorService::getSensorName(int handle) const {
- size_t count = mUserSensorList.size();
- for (size_t i=0 ; i<count ; i++) {
- const Sensor& sensor(mUserSensorList[i]);
- if (sensor.getHandle() == handle) {
- return sensor.getName();
- }
- }
- return String8("unknown");
+ return mSensors.getName(handle);
}
bool SensorService::isVirtualSensor(int handle) const {
@@ -830,7 +715,7 @@
char value[PROPERTY_VALUE_MAX];
property_get("debug.sensors", value, "0");
const Vector<Sensor>& initialSensorList = (atoi(value)) ?
- mUserSensorListDebug : mUserSensorList;
+ mSensors.getUserDebugSensors() : mSensors.getUserSensors();
Vector<Sensor> accessibleSensorList;
for (size_t i = 0; i < initialSensorList.size(); i++) {
Sensor sensor = initialSensorList[i];
@@ -848,17 +733,19 @@
Vector<Sensor> SensorService::getDynamicSensorList(const String16& opPackageName) {
Vector<Sensor> accessibleSensorList;
- for (size_t i = 0; i < mDynamicSensorList.size(); i++) {
- Sensor sensor = mDynamicSensorList[i];
- if (canAccessSensor(sensor, "getDynamicSensorList", opPackageName)) {
- accessibleSensorList.add(sensor);
- } else {
- ALOGI("Skipped sensor %s because it requires permission %s and app op %d",
- sensor.getName().string(),
- sensor.getRequiredPermission().string(),
- sensor.getRequiredAppOp());
- }
- }
+ mSensors.forEachSensor(
+ [&opPackageName, &accessibleSensorList] (const Sensor& sensor) -> bool {
+ if (sensor.isDynamicSensor() &&
+ canAccessSensor(sensor, "getDynamicSensorList", opPackageName)) {
+ accessibleSensorList.add(sensor);
+ } else {
+ ALOGI("Skipped sensor %s because it requires permission %s and app op %" PRId32,
+ sensor.getName().string(),
+ sensor.getRequiredPermission().string(),
+ sensor.getRequiredAppOp());
+ }
+ return true;
+ });
return accessibleSensorList;
}
@@ -950,13 +837,11 @@
}
SensorInterface* SensorService::getSensorInterfaceFromHandle(int handle) const {
- ssize_t index = mSensorMap.indexOfKey(handle);
- return index < 0 ? nullptr : mSensorMap.valueAt(index);
+ return mSensors.getInterface(handle);
}
-Sensor SensorService::getSensorFromHandle(int handle) const {
- SensorInterface* si = getSensorInterfaceFromHandle(handle);
- return si ? si->getSensor() : Sensor();
+const Sensor& SensorService::getSensorFromHandle(int handle) const {
+ return mSensors.get(handle);
}
status_t SensorService::enable(const sp<SensorEventConnection>& connection,
diff --git a/services/sensorservice/SensorService.h b/services/sensorservice/SensorService.h
index da97286..e535339 100644
--- a/services/sensorservice/SensorService.h
+++ b/services/sensorservice/SensorService.h
@@ -37,6 +37,7 @@
#include <gui/ISensorEventConnection.h>
#include "SensorInterface.h"
+#include "SensorList.h"
#if __clang__
// Clang warns about SensorEventConnection::dump hiding BBinder::dump. The cause isn't fixable
@@ -156,18 +157,18 @@
virtual int isDataInjectionEnabled();
virtual status_t dump(int fd, const Vector<String16>& args);
-
static int getNumEventsForSensorType(int sensor_event_type);
String8 getSensorName(int handle) const;
bool isVirtualSensor(int handle) const;
SensorInterface* getSensorInterfaceFromHandle(int handle) const;
- Sensor getSensorFromHandle(int handle) const;
+ const Sensor& getSensorFromHandle(int handle) const;
bool isWakeUpSensor(int type) const;
void recordLastValueLocked(sensors_event_t const* buffer, size_t count);
static void sortEventBuffer(sensors_event_t* buffer, size_t count);
- Sensor registerSensor(SensorInterface* sensor);
- Sensor registerVirtualSensor(SensorInterface* sensor);
- Sensor registerDynamicSensor(SensorInterface* sensor);
+ const Sensor& registerSensor(SensorInterface* sensor,
+ bool isDebug = false, bool isVirtual = false);
+ const Sensor& registerVirtualSensor(SensorInterface* sensor, bool isDebug = false);
+ const Sensor& registerDynamicSensor(SensorInterface* sensor, bool isDebug = false);
bool unregisterDynamicSensor(int handle);
status_t cleanupWithoutDisable(const sp<SensorEventConnection>& connection, int handle);
status_t cleanupWithoutDisableLocked(const sp<SensorEventConnection>& connection, int handle);
@@ -182,7 +183,6 @@
void checkWakeLockStateLocked();
bool isWakeLockAcquired();
bool isWakeUpSensorEvent(const sensors_event_t& event) const;
- bool isNewHandle(int handle);
sp<Looper> getLooper() const;
@@ -211,14 +211,7 @@
status_t resetToNormalMode();
status_t resetToNormalModeLocked();
- // lists and maps
- Vector<Sensor> mSensorList;
- Vector<Sensor> mUserSensorListDebug;
- Vector<Sensor> mUserSensorList;
- Vector<Sensor> mDynamicSensorList;
- DefaultKeyedVector<int, SensorInterface*> mSensorMap;
- Vector<SensorInterface *> mVirtualSensorList;
- Vector<int> mUsedHandleList;
+ SensorServiceUtil::SensorList mSensors;
status_t mInitCheck;
// Socket buffersize used to initialize BitTube. This size depends on whether batching is
@@ -233,6 +226,7 @@
bool mWakeLockAcquired;
sensors_event_t *mSensorEventBuffer, *mSensorEventScratch;
SensorEventConnection const **mMapFlushEventsToConnections;
+ KeyedVector<int32_t, MostRecentEventLogger*> mLastEventSeen;
Mode mCurrentOperatingMode;
// This packagaName is set when SensorService is in RESTRICTED or DATA_INJECTION mode. Only
@@ -241,9 +235,6 @@
// sensors.
String8 mWhiteListedPackage;
- // The size of this vector is constant, only the items are mutable
- KeyedVector<int32_t, MostRecentEventLogger *> mLastEventSeen;
-
int mNextSensorRegIndex;
Vector<SensorRegistrationInfo> mLastNSensorRegistrations;
};
diff --git a/services/surfaceflinger/DispSync.cpp b/services/surfaceflinger/DispSync.cpp
index 5ba387d..4cf9370 100644
--- a/services/surfaceflinger/DispSync.cpp
+++ b/services/surfaceflinger/DispSync.cpp
@@ -15,6 +15,7 @@
*/
#define ATRACE_TAG ATRACE_TAG_GRAPHICS
+//#define LOG_NDEBUG 0
// This is needed for stdint.h to define INT64_MAX in C++
#define __STDC_LIMIT_MACROS
@@ -33,12 +34,21 @@
#include "DispSync.h"
#include "EventLog/EventLog.h"
+#include <algorithm>
+
+using std::max;
+using std::min;
+
namespace android {
// Setting this to true enables verbose tracing that can be used to debug
// vsync event model or phase issues.
static const bool kTraceDetailedInfo = false;
+// Setting this to true adds a zero-phase tracer for correlating with hardware
+// vsync events
+static const bool kEnableZeroPhaseTracer = false;
+
// This is the threshold used to determine when hardware vsync events are
// needed to re-synchronize the software vsync model with the hardware. The
// error metric used is the mean of the squared difference between each
@@ -49,28 +59,36 @@
// vsync event.
static const int64_t kPresentTimeOffset = PRESENT_TIME_OFFSET_FROM_VSYNC_NS;
+#undef LOG_TAG
+#define LOG_TAG "DispSyncThread"
class DispSyncThread: public Thread {
public:
- DispSyncThread():
+ DispSyncThread(const char* name):
+ mName(name),
mStop(false),
mPeriod(0),
mPhase(0),
mReferenceTime(0),
- mWakeupLatency(0) {
- }
+ mWakeupLatency(0),
+ mFrameNumber(0) {}
virtual ~DispSyncThread() {}
void updateModel(nsecs_t period, nsecs_t phase, nsecs_t referenceTime) {
+ if (kTraceDetailedInfo) ATRACE_CALL();
Mutex::Autolock lock(mMutex);
mPeriod = period;
mPhase = phase;
mReferenceTime = referenceTime;
+ ALOGV("[%s] updateModel: mPeriod = %" PRId64 ", mPhase = %" PRId64
+ " mReferenceTime = %" PRId64, mName, ns2us(mPeriod),
+ ns2us(mPhase), ns2us(mReferenceTime));
mCond.signal();
}
void stop() {
+ if (kTraceDetailedInfo) ATRACE_CALL();
Mutex::Autolock lock(mMutex);
mStop = true;
mCond.signal();
@@ -89,6 +107,12 @@
{ // Scope for lock
Mutex::Autolock lock(mMutex);
+ if (kTraceDetailedInfo) {
+ ATRACE_INT64("DispSync:Frame", mFrameNumber);
+ }
+ ALOGV("[%s] Frame %" PRId64, mName, mFrameNumber);
+ ++mFrameNumber;
+
if (mStop) {
return false;
}
@@ -109,6 +133,9 @@
bool isWakeup = false;
if (now < targetTime) {
+ ALOGV("[%s] Waiting until %" PRId64, mName,
+ ns2us(targetTime));
+ if (kTraceDetailedInfo) ATRACE_NAME("DispSync waiting");
err = mCond.waitRelative(mMutex, targetTime - now);
if (err == TIMED_OUT) {
@@ -122,15 +149,15 @@
now = systemTime(SYSTEM_TIME_MONOTONIC);
+ // Don't correct by more than 1.5 ms
+ static const nsecs_t kMaxWakeupLatency = us2ns(1500);
+
if (isWakeup) {
mWakeupLatency = ((mWakeupLatency * 63) +
(now - targetTime)) / 64;
- if (mWakeupLatency > 500000) {
- // Don't correct by more than 500 us
- mWakeupLatency = 500000;
- }
+ mWakeupLatency = min(mWakeupLatency, kMaxWakeupLatency);
if (kTraceDetailedInfo) {
- ATRACE_INT64("DispSync:WakeupLat", now - nextEventTime);
+ ATRACE_INT64("DispSync:WakeupLat", now - targetTime);
ATRACE_INT64("DispSync:AvgWakeupLat", mWakeupLatency);
}
}
@@ -146,7 +173,9 @@
return false;
}
- status_t addEventListener(nsecs_t phase, const sp<DispSync::Callback>& callback) {
+ status_t addEventListener(const char* name, nsecs_t phase,
+ const sp<DispSync::Callback>& callback) {
+ if (kTraceDetailedInfo) ATRACE_CALL();
Mutex::Autolock lock(mMutex);
for (size_t i = 0; i < mEventListeners.size(); i++) {
@@ -156,15 +185,14 @@
}
EventListener listener;
+ listener.mName = name;
listener.mPhase = phase;
listener.mCallback = callback;
// We want to allow the firstmost future event to fire without
- // allowing any past events to fire. Because
- // computeListenerNextEventTimeLocked filters out events within a half
- // a period of the last event time, we need to initialize the last
- // event time to a half a period in the past.
- listener.mLastEventTime = systemTime(SYSTEM_TIME_MONOTONIC) - mPeriod / 2;
+ // allowing any past events to fire
+ listener.mLastEventTime = systemTime() - mPeriod / 2 + mPhase -
+ mWakeupLatency;
mEventListeners.push(listener);
@@ -174,6 +202,7 @@
}
status_t removeEventListener(const sp<DispSync::Callback>& callback) {
+ if (kTraceDetailedInfo) ATRACE_CALL();
Mutex::Autolock lock(mMutex);
for (size_t i = 0; i < mEventListeners.size(); i++) {
@@ -189,6 +218,7 @@
// This method is only here to handle the kIgnorePresentFences case.
bool hasAnyEventListeners() {
+ if (kTraceDetailedInfo) ATRACE_CALL();
Mutex::Autolock lock(mMutex);
return !mEventListeners.empty();
}
@@ -196,6 +226,7 @@
private:
struct EventListener {
+ const char* mName;
nsecs_t mPhase;
nsecs_t mLastEventTime;
sp<DispSync::Callback> mCallback;
@@ -207,6 +238,8 @@
};
nsecs_t computeNextEventTimeLocked(nsecs_t now) {
+ if (kTraceDetailedInfo) ATRACE_CALL();
+ ALOGV("[%s] computeNextEventTimeLocked", mName);
nsecs_t nextEventTime = INT64_MAX;
for (size_t i = 0; i < mEventListeners.size(); i++) {
nsecs_t t = computeListenerNextEventTimeLocked(mEventListeners[i],
@@ -217,21 +250,28 @@
}
}
+ ALOGV("[%s] nextEventTime = %" PRId64, mName, ns2us(nextEventTime));
return nextEventTime;
}
Vector<CallbackInvocation> gatherCallbackInvocationsLocked(nsecs_t now) {
+ if (kTraceDetailedInfo) ATRACE_CALL();
+ ALOGV("[%s] gatherCallbackInvocationsLocked @ %" PRId64, mName,
+ ns2us(now));
+
Vector<CallbackInvocation> callbackInvocations;
- nsecs_t ref = now - mPeriod;
+ nsecs_t onePeriodAgo = now - mPeriod;
for (size_t i = 0; i < mEventListeners.size(); i++) {
nsecs_t t = computeListenerNextEventTimeLocked(mEventListeners[i],
- ref);
+ onePeriodAgo);
if (t < now) {
CallbackInvocation ci;
ci.mCallback = mEventListeners[i].mCallback;
ci.mEventTime = t;
+ ALOGV("[%s] [%s] Preparing to fire", mName,
+ mEventListeners[i].mName);
callbackInvocations.push(ci);
mEventListeners.editItemAt(i).mLastEventTime = t;
}
@@ -241,29 +281,67 @@
}
nsecs_t computeListenerNextEventTimeLocked(const EventListener& listener,
- nsecs_t ref) {
+ nsecs_t baseTime) {
+ if (kTraceDetailedInfo) ATRACE_CALL();
+ ALOGV("[%s] [%s] computeListenerNextEventTimeLocked(%" PRId64 ")",
+ mName, listener.mName, ns2us(baseTime));
- nsecs_t lastEventTime = listener.mLastEventTime;
- if (ref < lastEventTime) {
- ref = lastEventTime;
+ nsecs_t lastEventTime = listener.mLastEventTime + mWakeupLatency;
+ ALOGV("[%s] lastEventTime: %" PRId64, mName, ns2us(lastEventTime));
+ if (baseTime < lastEventTime) {
+ baseTime = lastEventTime;
+ ALOGV("[%s] Clamping baseTime to lastEventTime -> %" PRId64, mName,
+ ns2us(baseTime));
}
- nsecs_t phase = mReferenceTime + mPhase + listener.mPhase;
- nsecs_t t = (((ref - phase) / mPeriod) + 1) * mPeriod + phase;
+ baseTime -= mReferenceTime;
+ ALOGV("[%s] Relative baseTime = %" PRId64, mName, ns2us(baseTime));
+ nsecs_t phase = mPhase + listener.mPhase;
+ ALOGV("[%s] Phase = %" PRId64, mName, ns2us(phase));
+ baseTime -= phase;
+ ALOGV("[%s] baseTime - phase = %" PRId64, mName, ns2us(baseTime));
- if (t - listener.mLastEventTime < mPeriod / 2) {
+ // If our previous time is before the reference (because the reference
+ // has since been updated), the division by mPeriod will truncate
+ // towards zero instead of computing the floor. Since in all cases
+ // before the reference we want the next time to be effectively now, we
+ // set baseTime to -mPeriod so that numPeriods will be -1.
+ // When we add 1 and the phase, we will be at the correct event time for
+ // this period.
+ if (baseTime < 0) {
+ ALOGV("[%s] Correcting negative baseTime", mName);
+ baseTime = -mPeriod;
+ }
+
+ nsecs_t numPeriods = baseTime / mPeriod;
+ ALOGV("[%s] numPeriods = %" PRId64, mName, numPeriods);
+ nsecs_t t = (numPeriods + 1) * mPeriod + phase;
+ ALOGV("[%s] t = %" PRId64, mName, ns2us(t));
+ t += mReferenceTime;
+ ALOGV("[%s] Absolute t = %" PRId64, mName, ns2us(t));
+
+ // Check that it's been slightly more than half a period since the last
+ // event so that we don't accidentally fall into double-rate vsyncs
+ if (t - listener.mLastEventTime < (3 * mPeriod / 5)) {
t += mPeriod;
+ ALOGV("[%s] Modifying t -> %" PRId64, mName, ns2us(t));
}
+ t -= mWakeupLatency;
+ ALOGV("[%s] Corrected for wakeup latency -> %" PRId64, mName, ns2us(t));
+
return t;
}
void fireCallbackInvocations(const Vector<CallbackInvocation>& callbacks) {
+ if (kTraceDetailedInfo) ATRACE_CALL();
for (size_t i = 0; i < callbacks.size(); i++) {
callbacks[i].mCallback->onDispSyncEvent(callbacks[i].mEventTime);
}
}
+ const char* const mName;
+
bool mStop;
nsecs_t mPeriod;
@@ -271,12 +349,17 @@
nsecs_t mReferenceTime;
nsecs_t mWakeupLatency;
+ int64_t mFrameNumber;
+
Vector<EventListener> mEventListeners;
Mutex mMutex;
Condition mCond;
};
+#undef LOG_TAG
+#define LOG_TAG "DispSync"
+
class ZeroPhaseTracer : public DispSync::Callback {
public:
ZeroPhaseTracer() : mParity(false) {}
@@ -290,9 +373,10 @@
bool mParity;
};
-DispSync::DispSync() :
+DispSync::DispSync(const char* name) :
+ mName(name),
mRefreshSkipCount(0),
- mThread(new DispSyncThread()) {
+ mThread(new DispSyncThread(name)) {
mThread->run("DispSync", PRIORITY_URGENT_DISPLAY + PRIORITY_MORE_FAVORABLE);
@@ -305,8 +389,8 @@
// Even if we're just ignoring the fences, the zero-phase tracing is
// not needed because any time there is an event registered we will
// turn on the HW vsync events.
- if (!kIgnorePresentFences) {
- addEventListener(0, new ZeroPhaseTracer());
+ if (!kIgnorePresentFences && kEnableZeroPhaseTracer) {
+ addEventListener("ZeroPhaseTracer", 0, new ZeroPhaseTracer());
}
}
}
@@ -351,7 +435,7 @@
void DispSync::beginResync() {
Mutex::Autolock lock(mMutex);
-
+ ALOGV("[%s] beginResync", mName);
mModelUpdated = false;
mNumResyncSamples = 0;
}
@@ -359,11 +443,17 @@
bool DispSync::addResyncSample(nsecs_t timestamp) {
Mutex::Autolock lock(mMutex);
+ ALOGV("[%s] addResyncSample(%" PRId64 ")", mName, ns2us(timestamp));
+
size_t idx = (mFirstResyncSample + mNumResyncSamples) % MAX_RESYNC_SAMPLES;
mResyncSamples[idx] = timestamp;
if (mNumResyncSamples == 0) {
mPhase = 0;
mReferenceTime = timestamp;
+ ALOGV("[%s] First resync sample: mPeriod = %" PRId64 ", mPhase = 0, "
+ "mReferenceTime = %" PRId64, mName, ns2us(mPeriod),
+ ns2us(mReferenceTime));
+ mThread->updateModel(mPeriod, mPhase, mReferenceTime);
}
if (mNumResyncSamples < MAX_RESYNC_SAMPLES) {
@@ -387,17 +477,21 @@
return mThread->hasAnyEventListeners();
}
- return !mModelUpdated || mError > kErrorThreshold;
+ // Check against kErrorThreshold / 2 to add some hysteresis before having to
+ // resync again
+ bool modelLocked = mModelUpdated && mError < (kErrorThreshold / 2);
+ ALOGV("[%s] addResyncSample returning %s", mName,
+ modelLocked ? "locked" : "unlocked");
+ return !modelLocked;
}
void DispSync::endResync() {
}
-status_t DispSync::addEventListener(nsecs_t phase,
+status_t DispSync::addEventListener(const char* name, nsecs_t phase,
const sp<Callback>& callback) {
-
Mutex::Autolock lock(mMutex);
- return mThread->addEventListener(phase, callback);
+ return mThread->addEventListener(name, phase, callback);
}
void DispSync::setRefreshSkipCount(int count) {
@@ -427,20 +521,32 @@
}
void DispSync::updateModelLocked() {
+ ALOGV("[%s] updateModelLocked %zu", mName, mNumResyncSamples);
if (mNumResyncSamples >= MIN_RESYNC_SAMPLES_FOR_UPDATE) {
+ ALOGV("[%s] Computing...", mName);
nsecs_t durationSum = 0;
+ nsecs_t minDuration = INT64_MAX;
+ nsecs_t maxDuration = 0;
for (size_t i = 1; i < mNumResyncSamples; i++) {
size_t idx = (mFirstResyncSample + i) % MAX_RESYNC_SAMPLES;
size_t prev = (idx + MAX_RESYNC_SAMPLES - 1) % MAX_RESYNC_SAMPLES;
- durationSum += mResyncSamples[idx] - mResyncSamples[prev];
+ nsecs_t duration = mResyncSamples[idx] - mResyncSamples[prev];
+ durationSum += duration;
+ minDuration = min(minDuration, duration);
+ maxDuration = max(maxDuration, duration);
}
- mPeriod = durationSum / (mNumResyncSamples - 1);
+ // Exclude the min and max from the average
+ durationSum -= minDuration + maxDuration;
+ mPeriod = durationSum / (mNumResyncSamples - 3);
+
+ ALOGV("[%s] mPeriod = %" PRId64, mName, ns2us(mPeriod));
double sampleAvgX = 0;
double sampleAvgY = 0;
double scale = 2.0 * M_PI / double(mPeriod);
- for (size_t i = 0; i < mNumResyncSamples; i++) {
+ // Intentionally skip the first sample
+ for (size_t i = 1; i < mNumResyncSamples; i++) {
size_t idx = (mFirstResyncSample + i) % MAX_RESYNC_SAMPLES;
nsecs_t sample = mResyncSamples[idx] - mReferenceTime;
double samplePhase = double(sample % mPeriod) * scale;
@@ -448,18 +554,21 @@
sampleAvgY += sin(samplePhase);
}
- sampleAvgX /= double(mNumResyncSamples);
- sampleAvgY /= double(mNumResyncSamples);
+ sampleAvgX /= double(mNumResyncSamples - 1);
+ sampleAvgY /= double(mNumResyncSamples - 1);
mPhase = nsecs_t(atan2(sampleAvgY, sampleAvgX) / scale);
- if (mPhase < 0) {
+ ALOGV("[%s] mPhase = %" PRId64, mName, ns2us(mPhase));
+
+ if (mPhase < -(mPeriod / 2)) {
mPhase += mPeriod;
+ ALOGV("[%s] Adjusting mPhase -> %" PRId64, mName, ns2us(mPhase));
}
if (kTraceDetailedInfo) {
ATRACE_INT64("DispSync:Period", mPeriod);
- ATRACE_INT64("DispSync:Phase", mPhase);
+ ATRACE_INT64("DispSync:Phase", mPhase + mPeriod / 2);
}
// Artificially inflate the period if requested.
diff --git a/services/surfaceflinger/DispSync.h b/services/surfaceflinger/DispSync.h
index a8524b9..537c81b 100644
--- a/services/surfaceflinger/DispSync.h
+++ b/services/surfaceflinger/DispSync.h
@@ -26,11 +26,8 @@
namespace android {
// Ignore present (retire) fences if the device doesn't have support for the
-// sync framework, or if all phase offsets are zero. The latter is useful
-// because it allows us to avoid resync bursts on devices that don't need
-// phase-offset VSYNC events.
-#if defined(RUNNING_WITHOUT_SYNC_FRAMEWORK) || \
- (VSYNC_EVENT_PHASE_OFFSET_NS == 0 && SF_VSYNC_EVENT_PHASE_OFFSET_NS == 0)
+// sync framework
+#if defined(RUNNING_WITHOUT_SYNC_FRAMEWORK)
static const bool kIgnorePresentFences = true;
#else
static const bool kIgnorePresentFences = false;
@@ -64,7 +61,7 @@
virtual void onDispSyncEvent(nsecs_t when) = 0;
};
- DispSync();
+ DispSync(const char* name);
~DispSync();
// reset clears the resync samples and error value.
@@ -114,7 +111,8 @@
// given phase offset from the hardware vsync events. The callback is
// called from a separate thread and it should return reasonably quickly
// (i.e. within a few hundred microseconds).
- status_t addEventListener(nsecs_t phase, const sp<Callback>& callback);
+ status_t addEventListener(const char* name, nsecs_t phase,
+ const sp<Callback>& callback);
// removeEventListener removes an already-registered event callback. Once
// this method returns that callback will no longer be called by the
@@ -137,10 +135,12 @@
void resetErrorLocked();
enum { MAX_RESYNC_SAMPLES = 32 };
- enum { MIN_RESYNC_SAMPLES_FOR_UPDATE = 3 };
+ enum { MIN_RESYNC_SAMPLES_FOR_UPDATE = 6 };
enum { NUM_PRESENT_SAMPLES = 8 };
enum { MAX_RESYNC_SAMPLES_WITHOUT_PRESENT = 4 };
+ const char* const mName;
+
// mPeriod is the computed period of the modeled vsync events in
// nanoseconds.
nsecs_t mPeriod;
diff --git a/services/surfaceflinger/DisplayHardware/HWC2.cpp b/services/surfaceflinger/DisplayHardware/HWC2.cpp
index 0e97a53..5c78c68 100644
--- a/services/surfaceflinger/DisplayHardware/HWC2.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWC2.cpp
@@ -74,6 +74,7 @@
using android::Fence;
using android::FloatRect;
using android::GraphicBuffer;
+using android::HdrCapabilities;
using android::Rect;
using android::Region;
using android::sp;
@@ -100,6 +101,7 @@
mGetDisplayRequests(nullptr),
mGetDisplayType(nullptr),
mGetDozeSupport(nullptr),
+ mGetHdrCapabilities(nullptr),
mGetReleaseFences(nullptr),
mPresentDisplay(nullptr),
mSetActiveConfig(nullptr),
@@ -307,82 +309,84 @@
// loadFunctionPointer specifying which function failed to load
// Display function pointers
- if(!loadFunctionPointer(FunctionDescriptor::CreateVirtualDisplay,
+ if (!loadFunctionPointer(FunctionDescriptor::CreateVirtualDisplay,
mCreateVirtualDisplay)) return;
- if(!loadFunctionPointer(FunctionDescriptor::DestroyVirtualDisplay,
+ if (!loadFunctionPointer(FunctionDescriptor::DestroyVirtualDisplay,
mDestroyVirtualDisplay)) return;
- if(!loadFunctionPointer(FunctionDescriptor::Dump, mDump)) return;
- if(!loadFunctionPointer(FunctionDescriptor::GetMaxVirtualDisplayCount,
+ if (!loadFunctionPointer(FunctionDescriptor::Dump, mDump)) return;
+ if (!loadFunctionPointer(FunctionDescriptor::GetMaxVirtualDisplayCount,
mGetMaxVirtualDisplayCount)) return;
- if(!loadFunctionPointer(FunctionDescriptor::RegisterCallback,
+ if (!loadFunctionPointer(FunctionDescriptor::RegisterCallback,
mRegisterCallback)) return;
// Device function pointers
- if(!loadFunctionPointer(FunctionDescriptor::AcceptDisplayChanges,
+ if (!loadFunctionPointer(FunctionDescriptor::AcceptDisplayChanges,
mAcceptDisplayChanges)) return;
- if(!loadFunctionPointer(FunctionDescriptor::CreateLayer,
+ if (!loadFunctionPointer(FunctionDescriptor::CreateLayer,
mCreateLayer)) return;
- if(!loadFunctionPointer(FunctionDescriptor::DestroyLayer,
+ if (!loadFunctionPointer(FunctionDescriptor::DestroyLayer,
mDestroyLayer)) return;
- if(!loadFunctionPointer(FunctionDescriptor::GetActiveConfig,
+ if (!loadFunctionPointer(FunctionDescriptor::GetActiveConfig,
mGetActiveConfig)) return;
- if(!loadFunctionPointer(FunctionDescriptor::GetChangedCompositionTypes,
+ if (!loadFunctionPointer(FunctionDescriptor::GetChangedCompositionTypes,
mGetChangedCompositionTypes)) return;
- if(!loadFunctionPointer(FunctionDescriptor::GetDisplayAttribute,
+ if (!loadFunctionPointer(FunctionDescriptor::GetDisplayAttribute,
mGetDisplayAttribute)) return;
- if(!loadFunctionPointer(FunctionDescriptor::GetDisplayConfigs,
+ if (!loadFunctionPointer(FunctionDescriptor::GetDisplayConfigs,
mGetDisplayConfigs)) return;
- if(!loadFunctionPointer(FunctionDescriptor::GetDisplayName,
+ if (!loadFunctionPointer(FunctionDescriptor::GetDisplayName,
mGetDisplayName)) return;
- if(!loadFunctionPointer(FunctionDescriptor::GetDisplayRequests,
+ if (!loadFunctionPointer(FunctionDescriptor::GetDisplayRequests,
mGetDisplayRequests)) return;
- if(!loadFunctionPointer(FunctionDescriptor::GetDisplayType,
+ if (!loadFunctionPointer(FunctionDescriptor::GetDisplayType,
mGetDisplayType)) return;
- if(!loadFunctionPointer(FunctionDescriptor::GetDozeSupport,
+ if (!loadFunctionPointer(FunctionDescriptor::GetDozeSupport,
mGetDozeSupport)) return;
- if(!loadFunctionPointer(FunctionDescriptor::GetReleaseFences,
+ if (!loadFunctionPointer(FunctionDescriptor::GetHdrCapabilities,
+ mGetHdrCapabilities)) return;
+ if (!loadFunctionPointer(FunctionDescriptor::GetReleaseFences,
mGetReleaseFences)) return;
- if(!loadFunctionPointer(FunctionDescriptor::PresentDisplay,
+ if (!loadFunctionPointer(FunctionDescriptor::PresentDisplay,
mPresentDisplay)) return;
- if(!loadFunctionPointer(FunctionDescriptor::SetActiveConfig,
+ if (!loadFunctionPointer(FunctionDescriptor::SetActiveConfig,
mSetActiveConfig)) return;
- if(!loadFunctionPointer(FunctionDescriptor::SetClientTarget,
+ if (!loadFunctionPointer(FunctionDescriptor::SetClientTarget,
mSetClientTarget)) return;
- if(!loadFunctionPointer(FunctionDescriptor::SetOutputBuffer,
+ if (!loadFunctionPointer(FunctionDescriptor::SetOutputBuffer,
mSetOutputBuffer)) return;
- if(!loadFunctionPointer(FunctionDescriptor::SetPowerMode,
+ if (!loadFunctionPointer(FunctionDescriptor::SetPowerMode,
mSetPowerMode)) return;
- if(!loadFunctionPointer(FunctionDescriptor::SetVsyncEnabled,
+ if (!loadFunctionPointer(FunctionDescriptor::SetVsyncEnabled,
mSetVsyncEnabled)) return;
- if(!loadFunctionPointer(FunctionDescriptor::ValidateDisplay,
+ if (!loadFunctionPointer(FunctionDescriptor::ValidateDisplay,
mValidateDisplay)) return;
// Layer function pointers
- if(!loadFunctionPointer(FunctionDescriptor::SetCursorPosition,
+ if (!loadFunctionPointer(FunctionDescriptor::SetCursorPosition,
mSetCursorPosition)) return;
- if(!loadFunctionPointer(FunctionDescriptor::SetLayerBuffer,
+ if (!loadFunctionPointer(FunctionDescriptor::SetLayerBuffer,
mSetLayerBuffer)) return;
- if(!loadFunctionPointer(FunctionDescriptor::SetLayerSurfaceDamage,
+ if (!loadFunctionPointer(FunctionDescriptor::SetLayerSurfaceDamage,
mSetLayerSurfaceDamage)) return;
- if(!loadFunctionPointer(FunctionDescriptor::SetLayerBlendMode,
+ if (!loadFunctionPointer(FunctionDescriptor::SetLayerBlendMode,
mSetLayerBlendMode)) return;
- if(!loadFunctionPointer(FunctionDescriptor::SetLayerColor,
+ if (!loadFunctionPointer(FunctionDescriptor::SetLayerColor,
mSetLayerColor)) return;
- if(!loadFunctionPointer(FunctionDescriptor::SetLayerCompositionType,
+ if (!loadFunctionPointer(FunctionDescriptor::SetLayerCompositionType,
mSetLayerCompositionType)) return;
- if(!loadFunctionPointer(FunctionDescriptor::SetLayerDisplayFrame,
+ if (!loadFunctionPointer(FunctionDescriptor::SetLayerDisplayFrame,
mSetLayerDisplayFrame)) return;
- if(!loadFunctionPointer(FunctionDescriptor::SetLayerPlaneAlpha,
+ if (!loadFunctionPointer(FunctionDescriptor::SetLayerPlaneAlpha,
mSetLayerPlaneAlpha)) return;
- if(!loadFunctionPointer(FunctionDescriptor::SetLayerSidebandStream,
+ if (!loadFunctionPointer(FunctionDescriptor::SetLayerSidebandStream,
mSetLayerSidebandStream)) return;
- if(!loadFunctionPointer(FunctionDescriptor::SetLayerSourceCrop,
+ if (!loadFunctionPointer(FunctionDescriptor::SetLayerSourceCrop,
mSetLayerSourceCrop)) return;
- if(!loadFunctionPointer(FunctionDescriptor::SetLayerTransform,
+ if (!loadFunctionPointer(FunctionDescriptor::SetLayerTransform,
mSetLayerTransform)) return;
- if(!loadFunctionPointer(FunctionDescriptor::SetLayerVisibleRegion,
+ if (!loadFunctionPointer(FunctionDescriptor::SetLayerVisibleRegion,
mSetLayerVisibleRegion)) return;
- if(!loadFunctionPointer(FunctionDescriptor::SetLayerZOrder,
+ if (!loadFunctionPointer(FunctionDescriptor::SetLayerZOrder,
mSetLayerZOrder)) return;
}
@@ -637,6 +641,34 @@
return Error::None;
}
+Error Display::getHdrCapabilities(
+ std::unique_ptr<HdrCapabilities>* outCapabilities) const
+{
+ uint32_t numTypes = 0;
+ float maxLuminance = -1.0f;
+ float maxAverageLuminance = -1.0f;
+ float minLuminance = -1.0f;
+ int32_t intError = mDevice.mGetHdrCapabilities(mDevice.mHwcDevice, mId,
+ &numTypes, nullptr, &maxLuminance, &maxAverageLuminance,
+ &minLuminance);
+ auto error = static_cast<HWC2::Error>(intError);
+ if (error != Error::None) {
+ return error;
+ }
+
+ std::vector<int32_t> types(numTypes);
+ intError = mDevice.mGetHdrCapabilities(mDevice.mHwcDevice, mId, &numTypes,
+ types.data(), &maxLuminance, &maxAverageLuminance, &minLuminance);
+ error = static_cast<HWC2::Error>(intError);
+ if (error != Error::None) {
+ return error;
+ }
+
+ *outCapabilities = std::make_unique<HdrCapabilities>(std::move(types),
+ maxLuminance, maxAverageLuminance, minLuminance);
+ return Error::None;
+}
+
Error Display::getReleaseFences(
std::unordered_map<std::shared_ptr<Layer>, sp<Fence>>* outFences) const
{
diff --git a/services/surfaceflinger/DisplayHardware/HWC2.h b/services/surfaceflinger/DisplayHardware/HWC2.h
index a7bd28c..7d33a0a 100644
--- a/services/surfaceflinger/DisplayHardware/HWC2.h
+++ b/services/surfaceflinger/DisplayHardware/HWC2.h
@@ -23,6 +23,8 @@
#undef HWC2_INCLUDE_STRINGIFICATION
#undef HWC2_USE_CPP11
+#include <ui/HdrCapabilities.h>
+
#include <utils/Log.h>
#include <utils/StrongPointer.h>
#include <utils/Timers.h>
@@ -145,6 +147,7 @@
HWC2_PFN_GET_DISPLAY_REQUESTS mGetDisplayRequests;
HWC2_PFN_GET_DISPLAY_TYPE mGetDisplayType;
HWC2_PFN_GET_DOZE_SUPPORT mGetDozeSupport;
+ HWC2_PFN_GET_HDR_CAPABILITIES mGetHdrCapabilities;
HWC2_PFN_GET_RELEASE_FENCES mGetReleaseFences;
HWC2_PFN_PRESENT_DISPLAY mPresentDisplay;
HWC2_PFN_SET_ACTIVE_CONFIG mSetActiveConfig;
@@ -279,6 +282,8 @@
outLayerRequests);
[[clang::warn_unused_result]] Error getType(DisplayType* outType) const;
[[clang::warn_unused_result]] Error supportsDoze(bool* outSupport) const;
+ [[clang::warn_unused_result]] Error getHdrCapabilities(
+ std::unique_ptr<android::HdrCapabilities>* outCapabilities) const;
[[clang::warn_unused_result]] Error getReleaseFences(
std::unordered_map<std::shared_ptr<Layer>,
android::sp<android::Fence>>* outFences) const;
diff --git a/services/surfaceflinger/DisplayHardware/HWC2On1Adapter.cpp b/services/surfaceflinger/DisplayHardware/HWC2On1Adapter.cpp
index dabc77f..6ebcdfe 100644
--- a/services/surfaceflinger/DisplayHardware/HWC2On1Adapter.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWC2On1Adapter.cpp
@@ -238,6 +238,11 @@
return asFP<HWC2_PFN_GET_DOZE_SUPPORT>(
displayHook<decltype(&Display::getDozeSupport),
&Display::getDozeSupport, int32_t*>);
+ case FunctionDescriptor::GetHdrCapabilities:
+ return asFP<HWC2_PFN_GET_HDR_CAPABILITIES>(
+ displayHook<decltype(&Display::getHdrCapabilities),
+ &Display::getHdrCapabilities, uint32_t*, int32_t*, float*,
+ float*, float*>);
case FunctionDescriptor::GetReleaseFences:
return asFP<HWC2_PFN_GET_RELEASE_FENCES>(
displayHook<decltype(&Display::getReleaseFences),
@@ -709,6 +714,15 @@
return Error::None;
}
+Error HWC2On1Adapter::Display::getHdrCapabilities(uint32_t* outNumTypes,
+ int32_t* /*outTypes*/, float* /*outMaxLuminance*/,
+ float* /*outMaxAverageLuminance*/, float* /*outMinLuminance*/)
+{
+ // This isn't supported on HWC1, so per the HWC2 header, return numTypes = 0
+ *outNumTypes = 0;
+ return Error::None;
+}
+
Error HWC2On1Adapter::Display::getName(uint32_t* outSize, char* outName)
{
std::unique_lock<std::recursive_mutex> lock(mStateMutex);
diff --git a/services/surfaceflinger/DisplayHardware/HWC2On1Adapter.h b/services/surfaceflinger/DisplayHardware/HWC2On1Adapter.h
index bffeefe..6fdb184 100644
--- a/services/surfaceflinger/DisplayHardware/HWC2On1Adapter.h
+++ b/services/surfaceflinger/DisplayHardware/HWC2On1Adapter.h
@@ -194,6 +194,9 @@
HWC2::Error getConfigs(uint32_t* outNumConfigs,
hwc2_config_t* outConfigIds);
HWC2::Error getDozeSupport(int32_t* outSupport);
+ HWC2::Error getHdrCapabilities(uint32_t* outNumTypes,
+ int32_t* outTypes, float* outMaxLuminance,
+ float* outMaxAverageLuminance, float* outMinLuminance);
HWC2::Error getName(uint32_t* outSize, char* outName);
HWC2::Error getReleaseFences(uint32_t* outNumElements,
hwc2_layer_t* outLayers, int32_t* outFences);
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
index 26f9519..cd2e05f 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
@@ -736,6 +736,26 @@
mDisplayData[displayId].releaseFences.clear();
}
+std::unique_ptr<HdrCapabilities> HWComposer::getHdrCapabilities(
+ int32_t displayId) {
+ if (!isValidDisplay(displayId)) {
+ ALOGE("getHdrCapabilities: Display %d is not valid", displayId);
+ return nullptr;
+ }
+
+ auto& hwcDisplay = mDisplayData[displayId].hwcDisplay;
+ std::unique_ptr<HdrCapabilities> capabilities;
+ auto error = hwcDisplay->getHdrCapabilities(&capabilities);
+ if (error != HWC2::Error::None) {
+ ALOGE("getOutputCapabilities: Failed to get capabilities on display %d:"
+ " %s (%d)", displayId, to_string(error).c_str(),
+ static_cast<int32_t>(error));
+ return nullptr;
+ }
+
+ return capabilities;
+}
+
// Converts a PixelFormat to a human-readable string. Max 11 chars.
// (Could use a table of prefab String8 objects.)
/*
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h
index 30c8f67..d407877 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.h
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.h
@@ -130,6 +130,9 @@
// it can call this to clear the shared pointers in the release fence map
void clearReleaseFences(int32_t displayId);
+ // Returns the HDR capabilities of the given display
+ std::unique_ptr<HdrCapabilities> getHdrCapabilities(int32_t displayId);
+
// Events handling ---------------------------------------------------------
void setVsyncEnabled(int32_t disp, HWC2::Vsync enabled);
diff --git a/services/surfaceflinger/EventThread.cpp b/services/surfaceflinger/EventThread.cpp
index f760200..dd88adb 100644
--- a/services/surfaceflinger/EventThread.cpp
+++ b/services/surfaceflinger/EventThread.cpp
@@ -44,8 +44,9 @@
return;
}
-EventThread::EventThread(const sp<VSyncSource>& src)
+EventThread::EventThread(const sp<VSyncSource>& src, SurfaceFlinger& flinger)
: mVSyncSource(src),
+ mFlinger(flinger),
mUseSoftwareVSync(false),
mVsyncEnabled(false),
mDebugVsyncEnabled(false),
@@ -126,6 +127,9 @@
void EventThread::requestNextVsync(
const sp<EventThread::Connection>& connection) {
Mutex::Autolock _l(mLock);
+
+ mFlinger.resyncWithRateLimit();
+
if (connection->count < 0) {
connection->count = 0;
mCondition.broadcast();
diff --git a/services/surfaceflinger/EventThread.h b/services/surfaceflinger/EventThread.h
index 9ba179a..34654fa 100644
--- a/services/surfaceflinger/EventThread.h
+++ b/services/surfaceflinger/EventThread.h
@@ -77,7 +77,7 @@
public:
- EventThread(const sp<VSyncSource>& src);
+ EventThread(const sp<VSyncSource>& src, SurfaceFlinger& flinger);
sp<Connection> createEventConnection() const;
status_t registerDisplayEventConnection(const sp<Connection>& connection);
@@ -116,6 +116,7 @@
// constants
sp<VSyncSource> mVSyncSource;
PowerHAL mPowerHAL;
+ SurfaceFlinger& mFlinger;
mutable Mutex mLock;
mutable Condition mCondition;
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 40e9ae7..a448639 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -149,6 +149,7 @@
mLastTransactionTime(0),
mBootFinished(false),
mForceFullDamage(false),
+ mPrimaryDispSync("PrimaryDispSync"),
mPrimaryHWVsyncEnabled(false),
mHWVsyncAvailable(false),
mDaltonize(false),
@@ -331,11 +332,12 @@
class DispSyncSource : public VSyncSource, private DispSync::Callback {
public:
DispSyncSource(DispSync* dispSync, nsecs_t phaseOffset, bool traceVsync,
- const char* label) :
+ const char* name) :
+ mName(name),
mValue(0),
mTraceVsync(traceVsync),
- mVsyncOnLabel(String8::format("VsyncOn-%s", label)),
- mVsyncEventLabel(String8::format("VSYNC-%s", label)),
+ mVsyncOnLabel(String8::format("VsyncOn-%s", name)),
+ mVsyncEventLabel(String8::format("VSYNC-%s", name)),
mDispSync(dispSync),
mCallbackMutex(),
mCallback(),
@@ -348,7 +350,7 @@
virtual void setVSyncEnabled(bool enable) {
Mutex::Autolock lock(mVsyncMutex);
if (enable) {
- status_t err = mDispSync->addEventListener(mPhaseOffset,
+ status_t err = mDispSync->addEventListener(mName, mPhaseOffset,
static_cast<DispSync::Callback*>(this));
if (err != NO_ERROR) {
ALOGE("error registering vsync callback: %s (%d)",
@@ -399,7 +401,7 @@
}
// Add a listener with the new offset
- err = mDispSync->addEventListener(mPhaseOffset,
+ err = mDispSync->addEventListener(mName, mPhaseOffset,
static_cast<DispSync::Callback*>(this));
if (err != NO_ERROR) {
ALOGE("error registering vsync callback: %s (%d)",
@@ -425,6 +427,8 @@
}
}
+ const char* const mName;
+
int mValue;
const bool mTraceVsync;
@@ -455,10 +459,10 @@
// start the EventThread
sp<VSyncSource> vsyncSrc = new DispSyncSource(&mPrimaryDispSync,
vsyncPhaseOffsetNs, true, "app");
- mEventThread = new EventThread(vsyncSrc);
+ mEventThread = new EventThread(vsyncSrc, *this);
sp<VSyncSource> sfVsyncSrc = new DispSyncSource(&mPrimaryDispSync,
sfVsyncPhaseOffsetNs, true, "sf");
- mSFEventThread = new EventThread(sfVsyncSrc);
+ mSFEventThread = new EventThread(sfVsyncSrc, *this);
mEventQueue.setEventThread(mSFEventThread);
// Get a RenderEngine for the given display / config (can't fail)
@@ -715,6 +719,27 @@
return NO_ERROR;
}
+status_t SurfaceFlinger::getHdrCapabilities(const sp<IBinder>& display,
+ HdrCapabilities* outCapabilities) const {
+ Mutex::Autolock _l(mStateLock);
+
+ sp<const DisplayDevice> displayDevice(getDisplayDevice(display));
+ if (displayDevice == nullptr) {
+ ALOGE("getHdrCapabilities: Invalid display %p", displayDevice.get());
+ return BAD_VALUE;
+ }
+
+ std::unique_ptr<HdrCapabilities> capabilities =
+ mHwc->getHdrCapabilities(displayDevice->getHwcDisplayId());
+ if (capabilities) {
+ std::swap(*outCapabilities, *capabilities);
+ } else {
+ return BAD_VALUE;
+ }
+
+ return NO_ERROR;
+}
+
// ----------------------------------------------------------------------------
sp<IDisplayEventConnection> SurfaceFlinger::createDisplayEventConnection() {
@@ -806,6 +831,13 @@
}
}
+void SurfaceFlinger::resyncWithRateLimit() {
+ static constexpr nsecs_t kIgnoreDelay = ms2ns(500);
+ if (systemTime() - mLastSwapTime > kIgnoreDelay) {
+ resyncToHardwareVsync(true);
+ }
+}
+
void SurfaceFlinger::onVSyncReceived(int32_t type, nsecs_t timestamp) {
bool needsHwVsync = false;
@@ -2881,6 +2913,7 @@
case CLEAR_ANIMATION_FRAME_STATS:
case GET_ANIMATION_FRAME_STATS:
case SET_POWER_MODE:
+ case GET_HDR_CAPABILITIES:
{
// codes that require permission check
IPCThreadState* ipc = IPCThreadState::self();
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 37110b9..633e956 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -222,6 +222,8 @@
virtual status_t setActiveConfig(const sp<IBinder>& display, int id);
virtual status_t clearAnimationFrameStats();
virtual status_t getAnimationFrameStats(FrameStats* outStats) const;
+ virtual status_t getHdrCapabilities(const sp<IBinder>& display,
+ HdrCapabilities* outCapabilities) const;
/* ------------------------------------------------------------------------
* DeathRecipient interface
@@ -407,8 +409,11 @@
* VSync
*/
void enableHardwareVsync();
- void disableHardwareVsync(bool makeUnavailable);
void resyncToHardwareVsync(bool makeAvailable);
+ void disableHardwareVsync(bool makeUnavailable);
+public:
+ void resyncWithRateLimit();
+private:
/* ------------------------------------------------------------------------
* Debugging & dumpsys
@@ -520,7 +525,7 @@
static const size_t NUM_BUCKETS = 8; // < 1-7, 7+
nsecs_t mFrameBuckets[NUM_BUCKETS];
nsecs_t mTotalTime;
- nsecs_t mLastSwapTime;
+ std::atomic<nsecs_t> mLastSwapTime;
};
}; // namespace android
diff --git a/services/surfaceflinger/SurfaceFlinger_hwc1.cpp b/services/surfaceflinger/SurfaceFlinger_hwc1.cpp
index a63ec50..ea685e7 100644
--- a/services/surfaceflinger/SurfaceFlinger_hwc1.cpp
+++ b/services/surfaceflinger/SurfaceFlinger_hwc1.cpp
@@ -45,6 +45,7 @@
#include <gui/GraphicBufferAlloc.h>
#include <ui/GraphicBufferAllocator.h>
+#include <ui/HdrCapabilities.h>
#include <ui/PixelFormat.h>
#include <ui/UiConfig.h>
@@ -147,6 +148,7 @@
mLastTransactionTime(0),
mBootFinished(false),
mForceFullDamage(false),
+ mPrimaryDispSync("PrimaryDispSync"),
mPrimaryHWVsyncEnabled(false),
mHWVsyncAvailable(false),
mDaltonize(false),
@@ -328,11 +330,12 @@
class DispSyncSource : public VSyncSource, private DispSync::Callback {
public:
DispSyncSource(DispSync* dispSync, nsecs_t phaseOffset, bool traceVsync,
- const char* label) :
+ const char* name) :
+ mName(name),
mValue(0),
mTraceVsync(traceVsync),
- mVsyncOnLabel(String8::format("VsyncOn-%s", label)),
- mVsyncEventLabel(String8::format("VSYNC-%s", label)),
+ mVsyncOnLabel(String8::format("VsyncOn-%s", name)),
+ mVsyncEventLabel(String8::format("VSYNC-%s", name)),
mDispSync(dispSync),
mCallbackMutex(),
mCallback(),
@@ -345,7 +348,7 @@
virtual void setVSyncEnabled(bool enable) {
Mutex::Autolock lock(mVsyncMutex);
if (enable) {
- status_t err = mDispSync->addEventListener(mPhaseOffset,
+ status_t err = mDispSync->addEventListener(mName, mPhaseOffset,
static_cast<DispSync::Callback*>(this));
if (err != NO_ERROR) {
ALOGE("error registering vsync callback: %s (%d)",
@@ -396,7 +399,7 @@
}
// Add a listener with the new offset
- err = mDispSync->addEventListener(mPhaseOffset,
+ err = mDispSync->addEventListener(mName, mPhaseOffset,
static_cast<DispSync::Callback*>(this));
if (err != NO_ERROR) {
ALOGE("error registering vsync callback: %s (%d)",
@@ -422,6 +425,8 @@
}
}
+ const char* const mName;
+
int mValue;
const bool mTraceVsync;
@@ -451,10 +456,10 @@
// start the EventThread
sp<VSyncSource> vsyncSrc = new DispSyncSource(&mPrimaryDispSync,
vsyncPhaseOffsetNs, true, "app");
- mEventThread = new EventThread(vsyncSrc);
+ mEventThread = new EventThread(vsyncSrc, *this);
sp<VSyncSource> sfVsyncSrc = new DispSyncSource(&mPrimaryDispSync,
sfVsyncPhaseOffsetNs, true, "sf");
- mSFEventThread = new EventThread(sfVsyncSrc);
+ mSFEventThread = new EventThread(sfVsyncSrc, *this);
mEventQueue.setEventThread(mSFEventThread);
// Initialize the H/W composer object. There may or may not be an
@@ -748,6 +753,13 @@
return NO_ERROR;
}
+status_t SurfaceFlinger::getHdrCapabilities(const sp<IBinder>& /*display*/,
+ HdrCapabilities* outCapabilities) const {
+ // HWC1 does not provide HDR capabilities
+ *outCapabilities = HdrCapabilities();
+ return NO_ERROR;
+}
+
// ----------------------------------------------------------------------------
sp<IDisplayEventConnection> SurfaceFlinger::createDisplayEventConnection() {
@@ -839,6 +851,13 @@
}
}
+void SurfaceFlinger::resyncWithRateLimit() {
+ static constexpr nsecs_t kIgnoreDelay = ms2ns(500);
+ if (systemTime() - mLastSwapTime > kIgnoreDelay) {
+ resyncToHardwareVsync(true);
+ }
+}
+
void SurfaceFlinger::onVSyncReceived(int type, nsecs_t timestamp) {
bool needsHwVsync = false;
@@ -2917,6 +2936,7 @@
case CLEAR_ANIMATION_FRAME_STATS:
case GET_ANIMATION_FRAME_STATS:
case SET_POWER_MODE:
+ case GET_HDR_CAPABILITIES:
{
// codes that require permission check
IPCThreadState* ipc = IPCThreadState::self();
diff --git a/vulkan/api/platform.api b/vulkan/api/platform.api
index 980722d..7aa19e7 100644
--- a/vulkan/api/platform.api
+++ b/vulkan/api/platform.api
@@ -43,6 +43,7 @@
// VK_USE_PLATFORM_ANDROID_KHR
@internal class ANativeWindow {}
+@internal type void* buffer_handle_t
// VK_USE_PLATFORM_WIN32_KHR
@internal type void* HINSTANCE
diff --git a/vulkan/api/vulkan.api b/vulkan/api/vulkan.api
index 10565ab..ae690a3 100644
--- a/vulkan/api/vulkan.api
+++ b/vulkan/api/vulkan.api
@@ -75,6 +75,9 @@
@extension("VK_KHR_win32_surface") define VK_KHR_WIN32_SURFACE_SPEC_VERSION 5
@extension("VK_KHR_win32_surface") define VK_KHR_WIN32_SURFACE_NAME "VK_KHR_win32_surface"
+@extension("VK_ANDROID_native_buffer") define VK_ANDROID_NATIVE_BUFFER_SPEC_VERSION 5
+@extension("VK_ANDROID_native_buffer") define VK_ANDROID_NATIVE_BUFFER_NAME "VK_ANDROID_native_buffer"
+
@extension("VK_EXT_debug_report") define VK_EXT_DEBUG_REPORT_SPEC_VERSION 1
@extension("VK_EXT_debug_report") define VK_EXT_DEBUG_REPORT_NAME "VK_EXT_debug_report"
@@ -646,6 +649,9 @@
//@extension("VK_KHR_win32_surface")
VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR = 1000009000,
+ //@extension("VK_ANDROID_native_buffer")
+ VK_STRUCTURE_TYPE_NATIVE_BUFFER_ANDROID = 1000010000,
+
//@extension("VK_EXT_debug_report")
VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT = 1000011000,
}
@@ -2591,6 +2597,16 @@
platform.HWND hwnd
}
+@extension("VK_ANDROID_native_buffer")
+class VkNativeBufferANDROID {
+ VkStructureType sType
+ const void* pNext
+ platform.buffer_handle_t handle
+ int stride
+ int format
+ int usage
+}
+
@extension("VK_EXT_debug_report")
class VkDebugReportCallbackCreateInfoEXT {
VkStructureType sType
@@ -5134,6 +5150,35 @@
return ?
}
+@extension("VK_ANDROID_native_buffer")
+cmd VkResult vkGetSwapchainGrallocUsageANDROID(
+ VkDevice device,
+ VkFormat format,
+ VkImageUsageFlags imageUsage,
+ int* grallocUsage) {
+ return ?
+}
+
+@extension("VK_ANDROID_native_buffer")
+cmd VkResult vkAcquireImageANDROID(
+ VkDevice device,
+ VkImage image,
+ int nativeFenceFd,
+ VkSemaphore semaphore,
+ VkFence fence) {
+ return ?
+}
+
+@extension("VK_ANDROID_native_buffer")
+cmd VkResult vkQueueSignalReleaseImageANDROID(
+ VkQueue queue,
+ u32 waitSemaphoreCount,
+ const VkSemaphore* pWaitSemaphores,
+ VkImage image,
+ int* pNativeFenceFd) {
+ return ?
+}
+
@extension("VK_EXT_debug_report")
@external type void* PFN_vkDebugReportCallbackEXT
@extension("VK_EXT_debug_report")
diff --git a/vulkan/libvulkan/Android.mk b/vulkan/libvulkan/Android.mk
index e60d74c..7830c26 100644
--- a/vulkan/libvulkan/Android.mk
+++ b/vulkan/libvulkan/Android.mk
@@ -42,9 +42,10 @@
api.cpp \
api_gen.cpp \
debug_report.cpp \
- dispatch_gen.cpp \
+ driver.cpp \
+ driver_gen.cpp \
layers_extensions.cpp \
- loader.cpp \
+ stubhal.cpp \
swapchain.cpp \
vulkan_loader_data.cpp
LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
diff --git a/vulkan/libvulkan/api.cpp b/vulkan/libvulkan/api.cpp
index 9c5aa3b..4e19af5 100644
--- a/vulkan/libvulkan/api.cpp
+++ b/vulkan/libvulkan/api.cpp
@@ -33,7 +33,7 @@
#include <vulkan/vk_layer_interface.h>
#include "api.h"
#include "driver.h"
-#include "loader.h"
+#include "layers_extensions.h"
namespace vulkan {
namespace api {
@@ -60,8 +60,8 @@
allocator_.pfnFree(allocator_.pUserData, implicit_layers_.name_pool);
}
- VkResult parse(const char* const* names, uint32_t count) {
- add_implicit_layers();
+ VkResult Parse(const char* const* names, uint32_t count) {
+ AddImplicitLayers();
const auto& arr = implicit_layers_;
if (arr.result != VK_SUCCESS)
@@ -71,20 +71,20 @@
if (!arr.count)
return VK_SUCCESS;
- names_ = allocate_name_array(arr.count + count);
+ names_ = AllocateNameArray(arr.count + count);
if (!names_)
return VK_ERROR_OUT_OF_HOST_MEMORY;
// add implicit layer names
for (uint32_t i = 0; i < arr.count; i++)
- names_[i] = get_implicit_layer_name(i);
+ names_[i] = GetImplicitLayerName(i);
name_count_ = arr.count;
// add explicit layer names
for (uint32_t i = 0; i < count; i++) {
// ignore explicit layers that are also implicit
- if (is_implicit_layer(names[i]))
+ if (IsImplicitLayer(names[i]))
continue;
names_[name_count_++] = names[i];
@@ -93,9 +93,9 @@
return VK_SUCCESS;
}
- const char* const* names() const { return names_; }
+ const char* const* Names() const { return names_; }
- uint32_t count() const { return name_count_; }
+ uint32_t Count() const { return name_count_; }
private:
struct ImplicitLayer {
@@ -115,12 +115,12 @@
VkResult result;
};
- void add_implicit_layers() {
+ void AddImplicitLayers() {
if (!driver::Debuggable())
return;
- parse_debug_vulkan_layers();
- property_list(parse_debug_vulkan_layer, this);
+ ParseDebugVulkanLayers();
+ property_list(ParseDebugVulkanLayer, this);
// sort by priorities
auto& arr = implicit_layers_;
@@ -130,7 +130,7 @@
});
}
- void parse_debug_vulkan_layers() {
+ void ParseDebugVulkanLayers() {
// debug.vulkan.layers specifies colon-separated layer names
char prop[PROPERTY_VALUE_MAX];
if (!property_get("debug.vulkan.layers", prop, ""))
@@ -143,19 +143,19 @@
const char* delim;
while ((delim = strchr(p, ':'))) {
if (delim > p)
- add_implicit_layer(prio, p, static_cast<size_t>(delim - p));
+ AddImplicitLayer(prio, p, static_cast<size_t>(delim - p));
prio++;
p = delim + 1;
}
if (p[0] != '\0')
- add_implicit_layer(prio, p, strlen(p));
+ AddImplicitLayer(prio, p, strlen(p));
}
- static void parse_debug_vulkan_layer(const char* key,
- const char* val,
- void* user_data) {
+ static void ParseDebugVulkanLayer(const char* key,
+ const char* val,
+ void* user_data) {
static const char prefix[] = "debug.vulkan.layer.";
const size_t prefix_len = sizeof(prefix) - 1;
@@ -176,25 +176,24 @@
OverrideLayerNames& override_layers =
*reinterpret_cast<OverrideLayerNames*>(user_data);
- override_layers.add_implicit_layer(priority, val, strlen(val));
+ override_layers.AddImplicitLayer(priority, val, strlen(val));
}
- void add_implicit_layer(int priority, const char* name, size_t len) {
- if (!grow_implicit_layer_array(1, 0))
+ void AddImplicitLayer(int priority, const char* name, size_t len) {
+ if (!GrowImplicitLayerArray(1, 0))
return;
auto& arr = implicit_layers_;
auto& layer = arr.elements[arr.count++];
layer.priority = priority;
- layer.name_offset = add_implicit_layer_name(name, len);
+ layer.name_offset = AddImplicitLayerName(name, len);
- ALOGV("Added implicit layer %s",
- get_implicit_layer_name(arr.count - 1));
+ ALOGV("Added implicit layer %s", GetImplicitLayerName(arr.count - 1));
}
- size_t add_implicit_layer_name(const char* name, size_t len) {
- if (!grow_implicit_layer_array(0, len + 1))
+ size_t AddImplicitLayerName(const char* name, size_t len) {
+ if (!GrowImplicitLayerArray(0, len + 1))
return 0;
// add the name to the pool
@@ -210,7 +209,7 @@
return offset;
}
- bool grow_implicit_layer_array(uint32_t layer_count, size_t name_size) {
+ bool GrowImplicitLayerArray(uint32_t layer_count, size_t name_size) {
const uint32_t initial_max_count = 16;
const size_t initial_max_pool_size = 512;
@@ -265,25 +264,25 @@
return true;
}
- const char* get_implicit_layer_name(uint32_t index) const {
+ const char* GetImplicitLayerName(uint32_t index) const {
const auto& arr = implicit_layers_;
// this may return nullptr when arr.result is not VK_SUCCESS
return implicit_layers_.name_pool + arr.elements[index].name_offset;
}
- bool is_implicit_layer(const char* name) const {
+ bool IsImplicitLayer(const char* name) const {
const auto& arr = implicit_layers_;
for (uint32_t i = 0; i < arr.count; i++) {
- if (strcmp(name, get_implicit_layer_name(i)) == 0)
+ if (strcmp(name, GetImplicitLayerName(i)) == 0)
return true;
}
return false;
}
- const char** allocate_name_array(uint32_t count) const {
+ const char** AllocateNameArray(uint32_t count) const {
return reinterpret_cast<const char**>(allocator_.pfnAllocation(
allocator_.pUserData, sizeof(const char*) * count,
alignof(const char*), scope_));
@@ -318,12 +317,12 @@
allocator_.pfnFree(allocator_.pUserData, names_);
}
- VkResult parse(const char* const* names, uint32_t count) {
+ VkResult Parse(const char* const* names, uint32_t count) {
// this is only for debug.vulkan.enable_callback
- if (!enable_debug_callback())
+ if (!EnableDebugCallback())
return VK_SUCCESS;
- names_ = allocate_name_array(count + 1);
+ names_ = AllocateNameArray(count + 1);
if (!names_)
return VK_ERROR_OUT_OF_HOST_MEMORY;
@@ -337,19 +336,19 @@
return VK_SUCCESS;
}
- const char* const* names() const { return names_; }
+ const char* const* Names() const { return names_; }
- uint32_t count() const { return name_count_; }
+ uint32_t Count() const { return name_count_; }
- bool install_debug_callback() const { return install_debug_callback_; }
+ bool InstallDebugCallback() const { return install_debug_callback_; }
private:
- bool enable_debug_callback() const {
+ bool EnableDebugCallback() const {
return (is_instance_ && driver::Debuggable() &&
property_get_bool("debug.vulkan.enable_callback", false));
}
- const char** allocate_name_array(uint32_t count) const {
+ const char** AllocateNameArray(uint32_t count) const {
return reinterpret_cast<const char**>(allocator_.pfnAllocation(
allocator_.pUserData, sizeof(const char*) * count,
alignof(const char*), scope_));
@@ -368,20 +367,20 @@
// chaining.
class LayerChain {
public:
- static VkResult create_instance(const VkInstanceCreateInfo* create_info,
- const VkAllocationCallbacks* allocator,
- VkInstance* instance_out);
+ static VkResult CreateInstance(const VkInstanceCreateInfo* create_info,
+ const VkAllocationCallbacks* allocator,
+ VkInstance* instance_out);
- static VkResult create_device(VkPhysicalDevice physical_dev,
- const VkDeviceCreateInfo* create_info,
- const VkAllocationCallbacks* allocator,
- VkDevice* dev_out);
+ static VkResult CreateDevice(VkPhysicalDevice physical_dev,
+ const VkDeviceCreateInfo* create_info,
+ const VkAllocationCallbacks* allocator,
+ VkDevice* dev_out);
- static void destroy_instance(VkInstance instance,
- const VkAllocationCallbacks* allocator);
+ static void DestroyInstance(VkInstance instance,
+ const VkAllocationCallbacks* allocator);
- static void destroy_device(VkDevice dev,
- const VkAllocationCallbacks* allocator);
+ static void DestroyDevice(VkDevice dev,
+ const VkAllocationCallbacks* allocator);
private:
struct ActiveLayer {
@@ -395,43 +394,52 @@
LayerChain(bool is_instance, const VkAllocationCallbacks& allocator);
~LayerChain();
- VkResult activate_layers(const char* const* layer_names,
- uint32_t layer_count,
- const char* const* extension_names,
- uint32_t extension_count);
- ActiveLayer* allocate_layer_array(uint32_t count) const;
- VkResult load_layer(ActiveLayer& layer, const char* name);
- void setup_layer_links();
+ VkResult ActivateLayers(const char* const* layer_names,
+ uint32_t layer_count,
+ const char* const* extension_names,
+ uint32_t extension_count);
+ ActiveLayer* AllocateLayerArray(uint32_t count) const;
+ VkResult LoadLayer(ActiveLayer& layer, const char* name);
+ void SetupLayerLinks();
- bool empty() const;
- void modify_create_info(VkInstanceCreateInfo& info);
- void modify_create_info(VkDeviceCreateInfo& info);
+ bool Empty() const;
+ void ModifyCreateInfo(VkInstanceCreateInfo& info);
+ void ModifyCreateInfo(VkDeviceCreateInfo& info);
- VkResult create(const VkInstanceCreateInfo* create_info,
+ VkResult Create(const VkInstanceCreateInfo* create_info,
const VkAllocationCallbacks* allocator,
VkInstance* instance_out);
- VkResult create(VkPhysicalDevice physical_dev,
+ VkResult Create(VkPhysicalDevice physical_dev,
const VkDeviceCreateInfo* create_info,
const VkAllocationCallbacks* allocator,
VkDevice* dev_out);
- template <typename DataType>
- void steal_layers(DataType& data);
+ VkResult ValidateExtensions(const char* const* extension_names,
+ uint32_t extension_count);
+ VkResult ValidateExtensions(VkPhysicalDevice physical_dev,
+ const char* const* extension_names,
+ uint32_t extension_count);
+ VkExtensionProperties* AllocateDriverExtensionArray(uint32_t count) const;
+ bool IsLayerExtension(const char* name) const;
+ bool IsDriverExtension(const char* name) const;
- static void destroy_layers(ActiveLayer* layers,
- uint32_t count,
- const VkAllocationCallbacks& allocator);
+ template <typename DataType>
+ void StealLayers(DataType& data);
+
+ static void DestroyLayers(ActiveLayer* layers,
+ uint32_t count,
+ const VkAllocationCallbacks& allocator);
static VKAPI_ATTR VkBool32
- debug_report_callback(VkDebugReportFlagsEXT flags,
- VkDebugReportObjectTypeEXT obj_type,
- uint64_t obj,
- size_t location,
- int32_t msg_code,
- const char* layer_prefix,
- const char* msg,
- void* user_data);
+ DebugReportCallback(VkDebugReportFlagsEXT flags,
+ VkDebugReportObjectTypeEXT obj_type,
+ uint64_t obj,
+ size_t location,
+ int32_t msg_code,
+ const char* layer_prefix,
+ const char* msg,
+ void* user_data);
const bool is_instance_;
const VkAllocationCallbacks& allocator_;
@@ -449,6 +457,9 @@
VkLayerInstanceCreateInfo instance_chain_info_;
VkLayerDeviceCreateInfo device_chain_info_;
};
+
+ VkExtensionProperties* driver_extensions_;
+ uint32_t driver_extension_count_;
};
LayerChain::LayerChain(bool is_instance, const VkAllocationCallbacks& allocator)
@@ -459,27 +470,30 @@
layers_(nullptr),
layer_count_(0),
get_instance_proc_addr_(nullptr),
- get_device_proc_addr_(nullptr) {}
+ get_device_proc_addr_(nullptr),
+ driver_extensions_(nullptr),
+ driver_extension_count_(0) {}
LayerChain::~LayerChain() {
- destroy_layers(layers_, layer_count_, allocator_);
+ allocator_.pfnFree(allocator_.pUserData, driver_extensions_);
+ DestroyLayers(layers_, layer_count_, allocator_);
}
-VkResult LayerChain::activate_layers(const char* const* layer_names,
- uint32_t layer_count,
- const char* const* extension_names,
- uint32_t extension_count) {
- VkResult result = override_layers_.parse(layer_names, layer_count);
+VkResult LayerChain::ActivateLayers(const char* const* layer_names,
+ uint32_t layer_count,
+ const char* const* extension_names,
+ uint32_t extension_count) {
+ VkResult result = override_layers_.Parse(layer_names, layer_count);
if (result != VK_SUCCESS)
return result;
- result = override_extensions_.parse(extension_names, extension_count);
+ result = override_extensions_.Parse(extension_names, extension_count);
if (result != VK_SUCCESS)
return result;
- if (override_layers_.count()) {
- layer_names = override_layers_.names();
- layer_count = override_layers_.count();
+ if (override_layers_.Count()) {
+ layer_names = override_layers_.Names();
+ layer_count = override_layers_.Count();
}
if (!layer_count) {
@@ -491,13 +505,13 @@
return VK_SUCCESS;
}
- layers_ = allocate_layer_array(layer_count);
+ layers_ = AllocateLayerArray(layer_count);
if (!layers_)
return VK_ERROR_OUT_OF_HOST_MEMORY;
// load layers
for (uint32_t i = 0; i < layer_count; i++) {
- result = load_layer(layers_[i], layer_names[i]);
+ result = LoadLayer(layers_[i], layer_names[i]);
if (result != VK_SUCCESS)
return result;
@@ -505,13 +519,12 @@
layer_count_++;
}
- setup_layer_links();
+ SetupLayerLinks();
return VK_SUCCESS;
}
-LayerChain::ActiveLayer* LayerChain::allocate_layer_array(
- uint32_t count) const {
+LayerChain::ActiveLayer* LayerChain::AllocateLayerArray(uint32_t count) const {
VkSystemAllocationScope scope = (is_instance_)
? VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE
: VK_SYSTEM_ALLOCATION_SCOPE_DEVICE;
@@ -521,7 +534,7 @@
scope));
}
-VkResult LayerChain::load_layer(ActiveLayer& layer, const char* name) {
+VkResult LayerChain::LoadLayer(ActiveLayer& layer, const char* name) {
if (is_instance_)
new (&layer) ActiveLayer{GetInstanceLayerRef(name), {}};
else
@@ -538,7 +551,7 @@
return VK_SUCCESS;
}
-void LayerChain::setup_layer_links() {
+void LayerChain::SetupLayerLinks() {
if (is_instance_) {
for (uint32_t i = 0; i < layer_count_; i++) {
ActiveLayer& layer = layers_[i];
@@ -596,12 +609,12 @@
}
}
-bool LayerChain::empty() const {
- return (!layer_count_ && !override_layers_.count() &&
- !override_extensions_.count());
+bool LayerChain::Empty() const {
+ return (!layer_count_ && !override_layers_.Count() &&
+ !override_extensions_.Count());
}
-void LayerChain::modify_create_info(VkInstanceCreateInfo& info) {
+void LayerChain::ModifyCreateInfo(VkInstanceCreateInfo& info) {
if (layer_count_) {
const ActiveLayer& layer = layers_[0];
@@ -617,18 +630,18 @@
info.pNext = &instance_chain_info_;
}
- if (override_layers_.count()) {
- info.enabledLayerCount = override_layers_.count();
- info.ppEnabledLayerNames = override_layers_.names();
+ if (override_layers_.Count()) {
+ info.enabledLayerCount = override_layers_.Count();
+ info.ppEnabledLayerNames = override_layers_.Names();
}
- if (override_extensions_.count()) {
- info.enabledExtensionCount = override_extensions_.count();
- info.ppEnabledExtensionNames = override_extensions_.names();
+ if (override_extensions_.Count()) {
+ info.enabledExtensionCount = override_extensions_.Count();
+ info.ppEnabledExtensionNames = override_extensions_.Names();
}
}
-void LayerChain::modify_create_info(VkDeviceCreateInfo& info) {
+void LayerChain::ModifyCreateInfo(VkDeviceCreateInfo& info) {
if (layer_count_) {
const ActiveLayer& layer = layers_[0];
@@ -643,26 +656,31 @@
info.pNext = &device_chain_info_;
}
- if (override_layers_.count()) {
- info.enabledLayerCount = override_layers_.count();
- info.ppEnabledLayerNames = override_layers_.names();
+ if (override_layers_.Count()) {
+ info.enabledLayerCount = override_layers_.Count();
+ info.ppEnabledLayerNames = override_layers_.Names();
}
- if (override_extensions_.count()) {
- info.enabledExtensionCount = override_extensions_.count();
- info.ppEnabledExtensionNames = override_extensions_.names();
+ if (override_extensions_.Count()) {
+ info.enabledExtensionCount = override_extensions_.Count();
+ info.ppEnabledExtensionNames = override_extensions_.Names();
}
}
-VkResult LayerChain::create(const VkInstanceCreateInfo* create_info,
+VkResult LayerChain::Create(const VkInstanceCreateInfo* create_info,
const VkAllocationCallbacks* allocator,
VkInstance* instance_out) {
+ VkResult result = ValidateExtensions(create_info->ppEnabledExtensionNames,
+ create_info->enabledExtensionCount);
+ if (result != VK_SUCCESS)
+ return result;
+
// call down the chain
PFN_vkCreateInstance create_instance =
reinterpret_cast<PFN_vkCreateInstance>(
get_instance_proc_addr_(VK_NULL_HANDLE, "vkCreateInstance"));
VkInstance instance;
- VkResult result = create_instance(create_info, allocator, &instance);
+ result = create_instance(create_info, allocator, &instance);
if (result != VK_SUCCESS)
return result;
@@ -680,7 +698,7 @@
}
// install debug report callback
- if (override_extensions_.install_debug_callback()) {
+ if (override_extensions_.InstallDebugCallback()) {
PFN_vkCreateDebugReportCallbackEXT create_debug_report_callback =
reinterpret_cast<PFN_vkCreateDebugReportCallbackEXT>(
get_instance_proc_addr_(instance,
@@ -700,7 +718,7 @@
VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT;
debug_callback_info.flags =
VK_DEBUG_REPORT_ERROR_BIT_EXT | VK_DEBUG_REPORT_WARNING_BIT_EXT;
- debug_callback_info.pfnCallback = debug_report_callback;
+ debug_callback_info.pfnCallback = DebugReportCallback;
VkDebugReportCallbackEXT debug_callback;
result = create_debug_report_callback(instance, &debug_callback_info,
@@ -716,17 +734,23 @@
ALOGI("Installed debug report callback");
}
- steal_layers(data);
+ StealLayers(data);
*instance_out = instance;
return VK_SUCCESS;
}
-VkResult LayerChain::create(VkPhysicalDevice physical_dev,
+VkResult LayerChain::Create(VkPhysicalDevice physical_dev,
const VkDeviceCreateInfo* create_info,
const VkAllocationCallbacks* allocator,
VkDevice* dev_out) {
+ VkResult result =
+ ValidateExtensions(physical_dev, create_info->ppEnabledExtensionNames,
+ create_info->enabledExtensionCount);
+ if (result != VK_SUCCESS)
+ return result;
+
// call down the chain
//
// TODO Instance call chain available at
@@ -736,7 +760,7 @@
PFN_vkCreateDevice create_device = reinterpret_cast<PFN_vkCreateDevice>(
get_instance_proc_addr_(instance, "vkCreateDevice"));
VkDevice dev;
- VkResult result = create_device(physical_dev, create_info, allocator, &dev);
+ result = create_device(physical_dev, create_info, allocator, &dev);
if (result != VK_SUCCESS)
return result;
@@ -751,15 +775,105 @@
return VK_ERROR_INITIALIZATION_FAILED;
}
- steal_layers(data);
+ StealLayers(data);
*dev_out = dev;
return VK_SUCCESS;
}
+VkResult LayerChain::ValidateExtensions(const char* const* extension_names,
+ uint32_t extension_count) {
+ if (!extension_count)
+ return VK_SUCCESS;
+
+ // query driver instance extensions
+ uint32_t count;
+ VkResult result =
+ EnumerateInstanceExtensionProperties(nullptr, &count, nullptr);
+ if (result == VK_SUCCESS && count) {
+ driver_extensions_ = AllocateDriverExtensionArray(count);
+ result = (driver_extensions_) ? EnumerateInstanceExtensionProperties(
+ nullptr, &count, driver_extensions_)
+ : VK_ERROR_OUT_OF_HOST_MEMORY;
+ }
+ if (result != VK_SUCCESS)
+ return result;
+
+ driver_extension_count_ = count;
+
+ for (uint32_t i = 0; i < extension_count; i++) {
+ const char* name = extension_names[i];
+ if (!IsLayerExtension(name) && !IsDriverExtension(name)) {
+ ALOGE("Failed to enable missing instance extension %s", name);
+ return VK_ERROR_EXTENSION_NOT_PRESENT;
+ }
+ }
+
+ return VK_SUCCESS;
+}
+
+VkResult LayerChain::ValidateExtensions(VkPhysicalDevice physical_dev,
+ const char* const* extension_names,
+ uint32_t extension_count) {
+ if (!extension_count)
+ return VK_SUCCESS;
+
+ // query driver device extensions
+ uint32_t count;
+ VkResult result = EnumerateDeviceExtensionProperties(physical_dev, nullptr,
+ &count, nullptr);
+ if (result == VK_SUCCESS && count) {
+ driver_extensions_ = AllocateDriverExtensionArray(count);
+ result = (driver_extensions_)
+ ? EnumerateDeviceExtensionProperties(
+ physical_dev, nullptr, &count, driver_extensions_)
+ : VK_ERROR_OUT_OF_HOST_MEMORY;
+ }
+ if (result != VK_SUCCESS)
+ return result;
+
+ driver_extension_count_ = count;
+
+ for (uint32_t i = 0; i < extension_count; i++) {
+ const char* name = extension_names[i];
+ if (!IsLayerExtension(name) && !IsDriverExtension(name)) {
+ ALOGE("Failed to enable missing device extension %s", name);
+ return VK_ERROR_EXTENSION_NOT_PRESENT;
+ }
+ }
+
+ return VK_SUCCESS;
+}
+
+VkExtensionProperties* LayerChain::AllocateDriverExtensionArray(
+ uint32_t count) const {
+ return reinterpret_cast<VkExtensionProperties*>(allocator_.pfnAllocation(
+ allocator_.pUserData, sizeof(VkExtensionProperties) * count,
+ alignof(VkExtensionProperties), VK_SYSTEM_ALLOCATION_SCOPE_COMMAND));
+}
+
+bool LayerChain::IsLayerExtension(const char* name) const {
+ for (uint32_t i = 0; i < layer_count_; i++) {
+ const ActiveLayer& layer = layers_[i];
+ if (layer.ref.SupportsExtension(name))
+ return true;
+ }
+
+ return false;
+}
+
+bool LayerChain::IsDriverExtension(const char* name) const {
+ for (uint32_t i = 0; i < driver_extension_count_; i++) {
+ if (strcmp(driver_extensions_[i].extensionName, name) == 0)
+ return true;
+ }
+
+ return false;
+}
+
template <typename DataType>
-void LayerChain::steal_layers(DataType& data) {
+void LayerChain::StealLayers(DataType& data) {
data.layers = layers_;
data.layer_count = layer_count_;
@@ -767,23 +881,23 @@
layer_count_ = 0;
}
-void LayerChain::destroy_layers(ActiveLayer* layers,
- uint32_t count,
- const VkAllocationCallbacks& allocator) {
+void LayerChain::DestroyLayers(ActiveLayer* layers,
+ uint32_t count,
+ const VkAllocationCallbacks& allocator) {
for (uint32_t i = 0; i < count; i++)
layers[i].ref.~LayerRef();
allocator.pfnFree(allocator.pUserData, layers);
}
-VkBool32 LayerChain::debug_report_callback(VkDebugReportFlagsEXT flags,
- VkDebugReportObjectTypeEXT obj_type,
- uint64_t obj,
- size_t location,
- int32_t msg_code,
- const char* layer_prefix,
- const char* msg,
- void* user_data) {
+VkBool32 LayerChain::DebugReportCallback(VkDebugReportFlagsEXT flags,
+ VkDebugReportObjectTypeEXT obj_type,
+ uint64_t obj,
+ size_t location,
+ int32_t msg_code,
+ const char* layer_prefix,
+ const char* msg,
+ void* user_data) {
int prio;
if (flags & VK_DEBUG_REPORT_ERROR_BIT_EXT)
@@ -808,58 +922,58 @@
return false;
}
-VkResult LayerChain::create_instance(const VkInstanceCreateInfo* create_info,
- const VkAllocationCallbacks* allocator,
- VkInstance* instance_out) {
+VkResult LayerChain::CreateInstance(const VkInstanceCreateInfo* create_info,
+ const VkAllocationCallbacks* allocator,
+ VkInstance* instance_out) {
LayerChain chain(true,
(allocator) ? *allocator : driver::GetDefaultAllocator());
- VkResult result = chain.activate_layers(
- create_info->ppEnabledLayerNames, create_info->enabledLayerCount,
- create_info->ppEnabledExtensionNames,
- create_info->enabledExtensionCount);
+ VkResult result = chain.ActivateLayers(create_info->ppEnabledLayerNames,
+ create_info->enabledLayerCount,
+ create_info->ppEnabledExtensionNames,
+ create_info->enabledExtensionCount);
if (result != VK_SUCCESS)
return result;
// use a local create info when the chain is not empty
VkInstanceCreateInfo local_create_info;
- if (!chain.empty()) {
+ if (!chain.Empty()) {
local_create_info = *create_info;
- chain.modify_create_info(local_create_info);
+ chain.ModifyCreateInfo(local_create_info);
create_info = &local_create_info;
}
- return chain.create(create_info, allocator, instance_out);
+ return chain.Create(create_info, allocator, instance_out);
}
-VkResult LayerChain::create_device(VkPhysicalDevice physical_dev,
- const VkDeviceCreateInfo* create_info,
- const VkAllocationCallbacks* allocator,
- VkDevice* dev_out) {
+VkResult LayerChain::CreateDevice(VkPhysicalDevice physical_dev,
+ const VkDeviceCreateInfo* create_info,
+ const VkAllocationCallbacks* allocator,
+ VkDevice* dev_out) {
LayerChain chain(false, (allocator)
? *allocator
: driver::GetData(physical_dev).allocator);
- VkResult result = chain.activate_layers(
- create_info->ppEnabledLayerNames, create_info->enabledLayerCount,
- create_info->ppEnabledExtensionNames,
- create_info->enabledExtensionCount);
+ VkResult result = chain.ActivateLayers(create_info->ppEnabledLayerNames,
+ create_info->enabledLayerCount,
+ create_info->ppEnabledExtensionNames,
+ create_info->enabledExtensionCount);
if (result != VK_SUCCESS)
return result;
// use a local create info when the chain is not empty
VkDeviceCreateInfo local_create_info;
- if (!chain.empty()) {
+ if (!chain.Empty()) {
local_create_info = *create_info;
- chain.modify_create_info(local_create_info);
+ chain.ModifyCreateInfo(local_create_info);
create_info = &local_create_info;
}
- return chain.create(physical_dev, create_info, allocator, dev_out);
+ return chain.Create(physical_dev, create_info, allocator, dev_out);
}
-void LayerChain::destroy_instance(VkInstance instance,
- const VkAllocationCallbacks* allocator) {
+void LayerChain::DestroyInstance(VkInstance instance,
+ const VkAllocationCallbacks* allocator) {
InstanceData& data = GetData(instance);
if (data.debug_callback != VK_NULL_HANDLE)
@@ -875,12 +989,12 @@
// this also destroys InstanceData
data.dispatch.DestroyInstance(instance, allocator);
- destroy_layers(layers, layer_count,
- (allocator) ? *allocator : local_allocator);
+ DestroyLayers(layers, layer_count,
+ (allocator) ? *allocator : local_allocator);
}
-void LayerChain::destroy_device(VkDevice device,
- const VkAllocationCallbacks* allocator) {
+void LayerChain::DestroyDevice(VkDevice device,
+ const VkAllocationCallbacks* allocator) {
DeviceData& data = GetData(device);
ActiveLayer* layers = reinterpret_cast<ActiveLayer*>(data.layers);
@@ -893,8 +1007,8 @@
// this also destroys DeviceData
data.dispatch.DestroyDevice(device, allocator);
- destroy_layers(layers, layer_count,
- (allocator) ? *allocator : local_allocator);
+ DestroyLayers(layers, layer_count,
+ (allocator) ? *allocator : local_allocator);
}
// ----------------------------------------------------------------------------
@@ -921,26 +1035,26 @@
if (!EnsureInitialized())
return VK_ERROR_INITIALIZATION_FAILED;
- return LayerChain::create_instance(pCreateInfo, pAllocator, pInstance);
+ return LayerChain::CreateInstance(pCreateInfo, pAllocator, pInstance);
}
void DestroyInstance(VkInstance instance,
const VkAllocationCallbacks* pAllocator) {
if (instance != VK_NULL_HANDLE)
- LayerChain::destroy_instance(instance, pAllocator);
+ LayerChain::DestroyInstance(instance, pAllocator);
}
VkResult CreateDevice(VkPhysicalDevice physicalDevice,
const VkDeviceCreateInfo* pCreateInfo,
const VkAllocationCallbacks* pAllocator,
VkDevice* pDevice) {
- return LayerChain::create_device(physicalDevice, pCreateInfo, pAllocator,
- pDevice);
+ return LayerChain::CreateDevice(physicalDevice, pCreateInfo, pAllocator,
+ pDevice);
}
void DestroyDevice(VkDevice device, const VkAllocationCallbacks* pAllocator) {
if (device != VK_NULL_HANDLE)
- LayerChain::destroy_device(device, pAllocator);
+ LayerChain::DestroyDevice(device, pAllocator);
}
VkResult EnumerateInstanceLayerProperties(uint32_t* pPropertyCount,
diff --git a/vulkan/libvulkan/api_gen.cpp b/vulkan/libvulkan/api_gen.cpp
index 0c4cd9a..a8cca59 100644
--- a/vulkan/libvulkan/api_gen.cpp
+++ b/vulkan/libvulkan/api_gen.cpp
@@ -272,11 +272,14 @@
std::binary_search(
known_non_device_names, known_non_device_names + count, pName,
[](const char* a, const char* b) { return (strcmp(a, b) < 0); })) {
- ALOGE("vkGetDeviceProcAddr called with %s", pName);
+ ALOGE("vkGetDeviceProcAddr called with %s", (pName) ? pName : "(null)");
return nullptr;
}
// clang-format off
+ if (strcmp(pName, "vkGetDeviceProcAddr") == 0) return reinterpret_cast<PFN_vkVoidFunction>(vkGetDeviceProcAddr);
+ if (strcmp(pName, "vkDestroyDevice") == 0) return reinterpret_cast<PFN_vkVoidFunction>(vulkan::api::DestroyDevice);
+
return vulkan::api::GetData(device).dispatch.GetDeviceProcAddr(device, pName);
}
diff --git a/vulkan/libvulkan/code-generator.tmpl b/vulkan/libvulkan/code-generator.tmpl
index 7ebe983..7517e91 100644
--- a/vulkan/libvulkan/code-generator.tmpl
+++ b/vulkan/libvulkan/code-generator.tmpl
@@ -21,6 +21,8 @@
{{Macro "DefineGlobals" $}}
{{$ | Macro "api_gen.h" | Format (Global "clang-format") | Write "api_gen.h" }}
{{$ | Macro "api_gen.cpp" | Format (Global "clang-format") | Write "api_gen.cpp"}}
+{{$ | Macro "driver_gen.h" | Format (Global "clang-format") | Write "driver_gen.h"}}
+{{$ | Macro "driver_gen.cpp" | Format (Global "clang-format") | Write "driver_gen.cpp"}}
{{/*
-------------------------------------------------------------------------------
@@ -44,7 +46,7 @@
// clang-format off
{{range $f := AllCommands $}}
{{if (Macro "api.IsInstanceDispatchTableEntry" $f)}}
- {{Macro "C++.DeclareDispatchTableEntry" $f}};
+ {{Macro "C++.DeclareTableEntry" $f}};
{{end}}
{{end}}
// clang-format on
@@ -54,7 +56,7 @@
// clang-format off
{{range $f := AllCommands $}}
{{if (Macro "api.IsDeviceDispatchTableEntry" $f)}}
- {{Macro "C++.DeclareDispatchTableEntry" $f}};
+ {{Macro "C++.DeclareTableEntry" $f}};
{{end}}
{{end}}
// clang-format on
@@ -89,7 +91,9 @@
namespace vulkan {«
namespace api {«
¶
-{{Macro "C++.DefineInitProcMacros" "dispatch"}}
+{{Macro "C++.DefineInitProcMacro" "dispatch"}}
+¶
+{{Macro "api.C++.DefineInitProcExtMacro"}}
¶
bool InitDispatchTable(VkInstance instance, PFN_vkGetInstanceProcAddr get_proc) {
auto& data = GetData(instance);
@@ -147,11 +151,173 @@
{{/*
+-------------------------------------------------------------------------------
+ driver_gen.h
+-------------------------------------------------------------------------------
+*/}}
+{{define "driver_gen.h"}}
+{{Macro "Copyright"}}
+¶
+// WARNING: This file is generated. See ../README.md for instructions.
+¶
+#ifndef LIBVULKAN_DRIVER_GEN_H
+#define LIBVULKAN_DRIVER_GEN_H
+¶
+#include <vulkan/vulkan.h>
+#include <vulkan/vk_android_native_buffer.h>
+¶
+namespace vulkan {«
+namespace driver {«
+¶
+{{Macro "driver.C++.DefineProcHookType"}}
+¶
+struct InstanceDriverTable {
+ // clang-format off
+ {{range $f := AllCommands $}}
+ {{if (Macro "driver.IsInstanceDriverTableEntry" $f)}}
+ {{Macro "C++.DeclareTableEntry" $f}};
+ {{end}}
+ {{end}}
+ // clang-format on
+};
+¶
+struct DeviceDriverTable {
+ // clang-format off
+ {{range $f := AllCommands $}}
+ {{if (Macro "driver.IsDeviceDriverTableEntry" $f)}}
+ {{Macro "C++.DeclareTableEntry" $f}};
+ {{end}}
+ {{end}}
+ // clang-format on
+};
+¶
+const ProcHook* GetProcHook(const char* name);
+ProcHook::Extension GetProcHookExtension(const char* name);
+¶
+bool InitDriverTable(VkInstance instance, PFN_vkGetInstanceProcAddr get_proc);
+bool InitDriverTable(VkDevice dev, PFN_vkGetDeviceProcAddr get_proc);
+¶
+»} // namespace driver
+»} // namespace vulkan
+¶
+#endif // LIBVULKAN_DRIVER_TABLE_H
+¶{{end}}
+
+
+{{/*
+-------------------------------------------------------------------------------
+ driver_gen.cpp
+-------------------------------------------------------------------------------
+*/}}
+{{define "driver_gen.cpp"}}
+{{Macro "Copyright"}}
+¶
+// WARNING: This file is generated. See ../README.md for instructions.
+¶
+#include <string.h>
+#include <algorithm>
+#include <log/log.h>
+¶
+#include "driver.h"
+¶
+namespace vulkan {«
+namespace driver {«
+¶
+namespace {«
+¶
+// clang-format off
+¶
+{{range $f := AllCommands $}}
+ {{Macro "driver.C++.DefineProcHookStubs" $f}}
+{{end}}
+// clang-format on
+¶
+const ProcHook g_proc_hooks[] = {
+ // clang-format off
+ {{range $f := SortBy (AllCommands $) "FunctionName"}}
+ {{if (Macro "driver.IsIntercepted" $f)}}
+ {{ if (Macro "IsGloballyDispatched" $f)}}
+ {{Macro "driver.C++.DefineGlobalProcHook" $f}}
+ {{else if (Macro "IsInstanceDispatched" $f)}}
+ {{Macro "driver.C++.DefineInstanceProcHook" $f}}
+ {{else if (Macro "IsDeviceDispatched" $f)}}
+ {{Macro "driver.C++.DefineDeviceProcHook" $f}}
+ {{end}}
+ {{end}}
+ {{end}}
+ // clang-format on
+};
+¶
+»} // anonymous
+¶
+const ProcHook* GetProcHook(const char* name) {
+ const auto& begin = g_proc_hooks;
+ const auto& end = g_proc_hooks +
+ sizeof(g_proc_hooks) / sizeof(g_proc_hooks[0]);
+ const auto hook = std::lower_bound(begin, end, name,
+ [](const ProcHook& e, const char* n) { return strcmp(e.name, n) < 0; });
+ return (hook < end && strcmp(hook->name, name) == 0) ? hook : nullptr;
+}
+¶
+ProcHook::Extension GetProcHookExtension(const char* name) {
+ {{$exts := Strings (Macro "driver.InterceptedExtensions") | SplitOn "\n"}}
+ // clang-format off
+ {{range $e := $exts}}
+ if (strcmp(name, "{{$e}}") == 0) return ProcHook::{{TrimPrefix "VK_" $e}};
+ {{end}}
+ // clang-format on
+ return ProcHook::EXTENSION_UNKNOWN;
+}
+¶
+{{Macro "C++.DefineInitProcMacro" "driver"}}
+¶
+{{Macro "driver.C++.DefineInitProcExtMacro"}}
+¶
+bool InitDriverTable(VkInstance instance, PFN_vkGetInstanceProcAddr get_proc)
+{
+ auto& data = GetData(instance);
+ bool success = true;
+ ¶
+ // clang-format off
+ {{range $f := AllCommands $}}
+ {{if (Macro "driver.IsInstanceDriverTableEntry" $f)}}
+ {{Macro "C++.InitProc" $f}}
+ {{end}}
+ {{end}}
+ // clang-format on
+ ¶
+ return success;
+}
+¶
+bool InitDriverTable(VkDevice dev, PFN_vkGetDeviceProcAddr get_proc)
+{
+ auto& data = GetData(dev);
+ bool success = true;
+ ¶
+ // clang-format off
+ {{range $f := AllCommands $}}
+ {{if (Macro "driver.IsDeviceDriverTableEntry" $f)}}
+ {{Macro "C++.InitProc" $f}}
+ {{end}}
+ {{end}}
+ // clang-format on
+ ¶
+ return success;
+}
+¶
+»} // namespace driver
+»} // namespace vulkan
+¶
+// clang-format on
+¶{{end}}
+
+
+{{/*
------------------------------------------------------------------------------
- Emits a declaration of a dispatch table entry.
+ Emits a declaration of a dispatch/driver table entry.
------------------------------------------------------------------------------
*/}}
-{{define "C++.DeclareDispatchTableEntry"}}
+{{define "C++.DeclareTableEntry"}}
{{AssertType $ "Function"}}
{{Macro "FunctionPtrName" $}} {{Macro "BaseName" $}}
@@ -160,10 +326,10 @@
{{/*
-------------------------------------------------------------------------------
- Emits macros to help initialize dispatch tables.
+ Emits INIT_PROC macro.
-------------------------------------------------------------------------------
*/}}
-{{define "C++.DefineInitProcMacros"}}
+{{define "C++.DefineInitProcMacro"}}
#define UNLIKELY(expr) __builtin_expect((expr), 0)
¶
#define INIT_PROC(obj, proc) do { \
@@ -174,11 +340,6 @@
success = false; \
} \
} while(0)
- ¶
- // TODO do we want to point to a stub or nullptr when ext is not enabled?
- #define INIT_PROC_EXT(ext, obj, proc) do { \
- INIT_PROC(obj, proc); \
- } while(0)
{{end}}
@@ -262,6 +423,19 @@
{{/*
+-------------------------------------------------------------------------------
+ Emits INIT_PROC_EXT macro for vulkan::api.
+-------------------------------------------------------------------------------
+*/}}
+{{define "api.C++.DefineInitProcExtMacro"}}
+ // TODO do we want to point to a stub or nullptr when ext is not enabled?
+ #define INIT_PROC_EXT(ext, obj, proc) do { \
+ INIT_PROC(obj, proc); \
+ } while(0)
+{{end}}
+
+
+{{/*
------------------------------------------------------------------------------
Emits code for vkGetInstanceProcAddr for function interception.
------------------------------------------------------------------------------
@@ -355,11 +529,25 @@
std::binary_search(
known_non_device_names, known_non_device_names + count, pName,
[](const char* a, const char* b) { return (strcmp(a, b) < 0); })) {
- ALOGE("vkGetDeviceProcAddr called with %s", pName);
+ ALOGE("vkGetDeviceProcAddr called with %s", (pName) ? pName : "(null)");
return nullptr;
}
// clang-format off
¶
+ {{range $f := AllCommands $}}
+ {{if (Macro "IsDeviceDispatched" $f)}}
+ {{ if (Macro "api.IsIntercepted" $f)}}
+ if (strcmp(pName, "{{$f.Name}}") == 0) return §
+ reinterpret_cast<PFN_vkVoidFunction>(§
+ vulkan::api::{{Macro "BaseName" $f}});
+ {{else if eq $f.Name "vkGetDeviceProcAddr"}}
+ if (strcmp(pName, "{{$f.Name}}") == 0) return §
+ reinterpret_cast<PFN_vkVoidFunction>(§
+ {{$f.Name}});
+ {{end}}
+ {{end}}
+ {{end}}
+ ¶
{{end}}
@@ -386,6 +574,348 @@
{{/*
+------------------------------------------------------------------------------
+ Emits a list of extensions intercepted by vulkan::driver.
+------------------------------------------------------------------------------
+*/}}
+{{define "driver.InterceptedExtensions"}}
+VK_ANDROID_native_buffer
+VK_EXT_debug_report
+VK_KHR_android_surface
+VK_KHR_surface
+VK_KHR_swapchain
+{{end}}
+
+
+{{/*
+------------------------------------------------------------------------------
+ Emits true if an extension is intercepted by vulkan::driver.
+------------------------------------------------------------------------------
+*/}}
+{{define "driver.IsExtensionIntercepted"}}
+ {{$ext_name := index $.Arguments 0}}
+ {{$filters := Strings (Macro "driver.InterceptedExtensions") | SplitOn "\n"}}
+
+ {{range $f := $filters}}
+ {{if eq $ext_name $f}}true{{end}}
+ {{end}}
+{{end}}
+
+
+{{/*
+------------------------------------------------------------------------------
+ Emits true if a function is intercepted by vulkan::driver.
+------------------------------------------------------------------------------
+*/}}
+{{define "driver.IsIntercepted"}}
+ {{AssertType $ "Function"}}
+
+ {{if (Macro "IsFunctionSupported" $)}}
+ {{/* Create functions of dispatchable objects */}}
+ {{ if eq $.Name "vkCreateInstance"}}true
+ {{else if eq $.Name "vkCreateDevice"}}true
+ {{else if eq $.Name "vkEnumeratePhysicalDevices"}}true
+ {{else if eq $.Name "vkGetDeviceQueue"}}true
+ {{else if eq $.Name "vkAllocateCommandBuffers"}}true
+
+ {{/* Destroy functions of dispatchable objects */}}
+ {{else if eq $.Name "vkDestroyInstance"}}true
+ {{else if eq $.Name "vkDestroyDevice"}}true
+
+ {{/* Enumeration of extensions */}}
+ {{else if eq $.Name "vkEnumerateInstanceExtensionProperties"}}true
+ {{else if eq $.Name "vkEnumerateDeviceExtensionProperties"}}true
+
+ {{else if eq $.Name "vkGetInstanceProcAddr"}}true
+ {{else if eq $.Name "vkGetDeviceProcAddr"}}true
+
+ {{end}}
+
+ {{$ext := GetAnnotation $ "extension"}}
+ {{if $ext}}
+ {{Macro "driver.IsExtensionIntercepted" $ext}}
+ {{end}}
+
+ {{end}}
+{{end}}
+
+
+{{/*
+------------------------------------------------------------------------------
+ Emits true if a function needs ProcHook stubs.
+------------------------------------------------------------------------------
+*/}}
+{{define "driver.NeedProcHookStubs"}}
+ {{AssertType $ "Function"}}
+
+ {{if (Macro "driver.IsIntercepted" $)}}
+ {{$ext := GetAnnotation $ "extension"}}
+ {{if $ext}}
+ {{if not (Macro "IsExtensionInternal" $ext)}}true{{end}}
+ {{end}}
+ {{end}}
+{{end}}
+
+
+{{/*
+-------------------------------------------------------------------------------
+ Emits definition of struct ProcHook.
+-------------------------------------------------------------------------------
+*/}}
+{{define "driver.C++.DefineProcHookType"}}
+ struct ProcHook {
+ enum Type {
+ GLOBAL,
+ INSTANCE,
+ DEVICE,
+ };
+
+ enum Extension {
+ {{$exts := Strings (Macro "driver.InterceptedExtensions") | SplitOn "\n"}}
+ {{range $e := $exts}}
+ {{TrimPrefix "VK_" $e}},
+ {{end}}
+ ¶
+ EXTENSION_CORE, // valid bit
+ EXTENSION_COUNT,
+ EXTENSION_UNKNOWN,
+ };
+ ¶
+ const char* name;
+ Type type;
+ Extension extension;
+ ¶
+ PFN_vkVoidFunction proc;
+ PFN_vkVoidFunction disabled_proc; // nullptr for global hooks
+ PFN_vkVoidFunction checked_proc; // nullptr for global/instance hooks
+ };
+{{end}}
+
+
+{{/*
+-------------------------------------------------------------------------------
+ Emits INIT_PROC_EXT macro for vulkan::driver.
+-------------------------------------------------------------------------------
+*/}}
+{{define "driver.C++.DefineInitProcExtMacro"}}
+ #define INIT_PROC_EXT(ext, obj, proc) do { \
+ if (data.hal_extensions[ProcHook::ext]) \
+ INIT_PROC(obj, proc); \
+ } while(0)
+{{end}}
+
+
+{{/*
+-------------------------------------------------------------------------------
+ Emits definitions of stub functions for ProcHook.
+-------------------------------------------------------------------------------
+*/}}
+{{define "driver.C++.DefineProcHookStubs"}}
+ {{AssertType $ "Function"}}
+
+ {{if (Macro "driver.NeedProcHookStubs" $)}}
+ {{$ext := GetAnnotation $ "extension"}}
+ {{$ext_name := index $ext.Arguments 0}}
+
+ {{$base := (Macro "BaseName" $)}}
+ {{$unnamed_params := (ForEach $.CallParameters "ParameterType" | JoinWith ", ")}}
+
+ VKAPI_ATTR {{Node "Type" $.Return}} disabled{{$base}}({{$unnamed_params}}) {
+ ALOGE("{{$ext_name}} not enabled. {{$.Name}} not executed.");
+ {{if not (IsVoid $.Return.Type)}}return VK_SUCCESS;{{end}}
+ }
+ {{if (Macro "IsDeviceDispatched" $)}}
+ ¶
+ VKAPI_ATTR {{Node "Type" $.Return}} checked{{$base}}({{Macro "Parameters" $}}) {
+ {{if not (IsVoid $.Return.Type)}}return §{{end}}
+
+ {{$p0 := index $.CallParameters 0}}
+ {{$ext_hook := Strings ("ProcHook::") (Macro "BaseName" $ext)}}
+ (GetData({{$p0.Name}}).hook_extensions[{{$ext_hook}}]) ? §
+ {{$base}}({{Macro "Arguments" $}}) : §
+ disabled{{$base}}({{Macro "Arguments" $}});
+ }
+ {{end}}
+ ¶
+ {{end}}
+{{end}}
+
+
+{{/*
+-------------------------------------------------------------------------------
+ Emits definition of a global ProcHook.
+-------------------------------------------------------------------------------
+*/}}
+{{define "driver.C++.DefineGlobalProcHook"}}
+ {{AssertType $ "Function"}}
+
+ {{$base := (Macro "BaseName" $)}}
+
+ {{$ext := GetAnnotation $ "extension"}}
+ {{if $ext}}
+ {{Error "invalid global extension"}}
+ {{end}}
+
+ {
+ "{{$.Name}}",
+ ProcHook::GLOBAL,
+ ProcHook::EXTENSION_CORE,
+ reinterpret_cast<PFN_vkVoidFunction>({{$base}}),
+ nullptr,
+ nullptr,
+ },
+{{end}}
+
+
+{{/*
+-------------------------------------------------------------------------------
+ Emits definition of an instance ProcHook.
+-------------------------------------------------------------------------------
+*/}}
+{{define "driver.C++.DefineInstanceProcHook"}}
+ {{AssertType $ "Function"}}
+
+ {{$base := (Macro "BaseName" $)}}
+
+ {
+ "{{$.Name}}",
+ ProcHook::INSTANCE,
+
+ {{$ext := GetAnnotation $ "extension"}}
+ {{if $ext}}
+ ProcHook::{{Macro "BaseName" $ext}},
+
+ {{if (Macro "IsExtensionInternal" $ext)}}
+ nullptr,
+ nullptr,
+ nullptr,
+ {{else}}
+ reinterpret_cast<PFN_vkVoidFunction>({{$base}}),
+ reinterpret_cast<PFN_vkVoidFunction>(disabled{{$base}}),
+ nullptr,
+ {{end}}
+ {{else}}
+ ProcHook::EXTENSION_CORE,
+ reinterpret_cast<PFN_vkVoidFunction>({{$base}}),
+ nullptr,
+ nullptr,
+ {{end}}
+ },
+{{end}}
+
+
+{{/*
+-------------------------------------------------------------------------------
+ Emits definition of a device ProcHook.
+-------------------------------------------------------------------------------
+*/}}
+{{define "driver.C++.DefineDeviceProcHook"}}
+ {{AssertType $ "Function"}}
+
+ {{$base := (Macro "BaseName" $)}}
+
+ {
+ "{{$.Name}}",
+ ProcHook::DEVICE,
+
+ {{$ext := GetAnnotation $ "extension"}}
+ {{if $ext}}
+ ProcHook::{{Macro "BaseName" $ext}},
+
+ {{if (Macro "IsExtensionInternal" $ext)}}
+ nullptr,
+ nullptr,
+ nullptr,
+ {{else}}
+ reinterpret_cast<PFN_vkVoidFunction>({{$base}}),
+ reinterpret_cast<PFN_vkVoidFunction>(disabled{{$base}}),
+ reinterpret_cast<PFN_vkVoidFunction>(checked{{$base}}),
+ {{end}}
+ {{else}}
+ ProcHook::EXTENSION_CORE,
+ reinterpret_cast<PFN_vkVoidFunction>({{$base}}),
+ nullptr,
+ nullptr,
+ {{end}}
+ },
+{{end}}
+
+
+{{/*
+-------------------------------------------------------------------------------
+ Emits true if a function is needed by vulkan::driver.
+-------------------------------------------------------------------------------
+*/}}
+{{define "driver.IsDriverTableEntry"}}
+ {{AssertType $ "Function"}}
+
+ {{if (Macro "IsFunctionSupported" $)}}
+ {{/* Create functions of dispatchable objects */}}
+ {{ if eq $.Name "vkCreateDevice"}}true
+ {{else if eq $.Name "vkGetDeviceQueue"}}true
+ {{else if eq $.Name "vkAllocateCommandBuffers"}}true
+
+ {{/* Destroy functions of dispatchable objects */}}
+ {{else if eq $.Name "vkDestroyInstance"}}true
+ {{else if eq $.Name "vkDestroyDevice"}}true
+
+ {{else if eq $.Name "vkEnumerateDeviceLayerProperties"}}true
+
+ {{/* Enumeration of extensions */}}
+ {{else if eq $.Name "vkEnumerateDeviceExtensionProperties"}}true
+
+ {{/* We cache physical devices in loader.cpp */}}
+ {{else if eq $.Name "vkEnumeratePhysicalDevices"}}true
+
+ {{else if eq $.Name "vkGetInstanceProcAddr"}}true
+ {{else if eq $.Name "vkGetDeviceProcAddr"}}true
+
+ {{/* VK_KHR_swapchain->VK_ANDROID_native_buffer translation */}}
+ {{else if eq $.Name "vkCreateImage"}}true
+ {{else if eq $.Name "vkDestroyImage"}}true
+
+ {{end}}
+
+ {{$ext := GetAnnotation $ "extension"}}
+ {{if $ext}}
+ {{$ext_name := index $ext.Arguments 0}}
+ {{ if eq $ext_name "VK_ANDROID_native_buffer"}}true
+ {{else if eq $ext_name "VK_EXT_debug_report"}}true
+ {{end}}
+ {{end}}
+ {{end}}
+{{end}}
+
+
+{{/*
+------------------------------------------------------------------------------
+ Emits true if an instance-dispatched function is needed by vulkan::driver.
+------------------------------------------------------------------------------
+*/}}
+{{define "driver.IsInstanceDriverTableEntry"}}
+ {{AssertType $ "Function"}}
+
+ {{if and (Macro "driver.IsDriverTableEntry" $) (Macro "IsInstanceDispatched" $)}}
+ true
+ {{end}}
+{{end}}
+
+
+{{/*
+------------------------------------------------------------------------------
+ Emits true if a device-dispatched function is needed by vulkan::driver.
+------------------------------------------------------------------------------
+*/}}
+{{define "driver.IsDeviceDriverTableEntry"}}
+ {{AssertType $ "Function"}}
+
+ {{if and (Macro "driver.IsDriverTableEntry" $) (Macro "IsDeviceDispatched" $)}}
+ true
+ {{end}}
+{{end}}
+
+
+{{/*
-------------------------------------------------------------------------------
Emits a function/extension name without the "vk"/"VK_" prefix.
-------------------------------------------------------------------------------
@@ -517,3 +1047,16 @@
{{else if eq $ext "VK_KHR_android_surface"}}true
{{end}}
{{end}}
+
+
+{{/*
+------------------------------------------------------------------------------
+ Reports whether an extension is internal to the loader and drivers,
+ so the loader should not enumerate it.
+------------------------------------------------------------------------------
+*/}}
+{{define "IsExtensionInternal"}}
+ {{$ext := index $.Arguments 0}}
+ {{ if eq $ext "VK_ANDROID_native_buffer"}}true
+ {{end}}
+{{end}}
diff --git a/vulkan/libvulkan/debug_report.cpp b/vulkan/libvulkan/debug_report.cpp
index 41b6040..c4a1174 100644
--- a/vulkan/libvulkan/debug_report.cpp
+++ b/vulkan/libvulkan/debug_report.cpp
@@ -14,9 +14,10 @@
* limitations under the License.
*/
-#include "loader.h"
+#include "driver.h"
namespace vulkan {
+namespace driver {
VkResult DebugReportCallbackList::CreateCallback(
VkInstance instance,
@@ -25,24 +26,22 @@
VkDebugReportCallbackEXT* callback) {
VkDebugReportCallbackEXT driver_callback = VK_NULL_HANDLE;
- if (GetDriverDispatch(instance).CreateDebugReportCallbackEXT) {
- VkResult result =
- GetDriverDispatch(instance).CreateDebugReportCallbackEXT(
- GetDriverInstance(instance), create_info, allocator,
- &driver_callback);
+ if (GetData(instance).driver.CreateDebugReportCallbackEXT) {
+ VkResult result = GetData(instance).driver.CreateDebugReportCallbackEXT(
+ instance, create_info, allocator, &driver_callback);
if (result != VK_SUCCESS)
return result;
}
const VkAllocationCallbacks* alloc =
- allocator ? allocator : GetAllocator(instance);
+ allocator ? allocator : &GetData(instance).allocator;
void* mem =
alloc->pfnAllocation(alloc->pUserData, sizeof(Node), alignof(Node),
VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
if (!mem) {
- if (GetDriverDispatch(instance).DestroyDebugReportCallbackEXT) {
- GetDriverDispatch(instance).DestroyDebugReportCallbackEXT(
- GetDriverInstance(instance), driver_callback, allocator);
+ if (GetData(instance).driver.DestroyDebugReportCallbackEXT) {
+ GetData(instance).driver.DestroyDebugReportCallbackEXT(
+ instance, driver_callback, allocator);
}
return VK_ERROR_OUT_OF_HOST_MEMORY;
}
@@ -68,13 +67,13 @@
prev->next = node->next;
lock.unlock();
- if (GetDriverDispatch(instance).DestroyDebugReportCallbackEXT) {
- GetDriverDispatch(instance).DestroyDebugReportCallbackEXT(
- GetDriverInstance(instance), node->driver_callback, allocator);
+ if (GetData(instance).driver.DestroyDebugReportCallbackEXT) {
+ GetData(instance).driver.DestroyDebugReportCallbackEXT(
+ instance, node->driver_callback, allocator);
}
const VkAllocationCallbacks* alloc =
- allocator ? allocator : GetAllocator(instance);
+ allocator ? allocator : &GetData(instance).allocator;
alloc->pfnFree(alloc->pUserData, node);
}
@@ -95,40 +94,40 @@
}
}
-VkResult CreateDebugReportCallbackEXT_Bottom(
+VkResult CreateDebugReportCallbackEXT(
VkInstance instance,
const VkDebugReportCallbackCreateInfoEXT* create_info,
const VkAllocationCallbacks* allocator,
VkDebugReportCallbackEXT* callback) {
- return GetDebugReportCallbacks(instance).CreateCallback(
+ return GetData(instance).debug_report_callbacks.CreateCallback(
instance, create_info, allocator, callback);
}
-void DestroyDebugReportCallbackEXT_Bottom(
- VkInstance instance,
- VkDebugReportCallbackEXT callback,
- const VkAllocationCallbacks* allocator) {
+void DestroyDebugReportCallbackEXT(VkInstance instance,
+ VkDebugReportCallbackEXT callback,
+ const VkAllocationCallbacks* allocator) {
if (callback)
- GetDebugReportCallbacks(instance).DestroyCallback(instance, callback,
- allocator);
+ GetData(instance).debug_report_callbacks.DestroyCallback(
+ instance, callback, allocator);
}
-void DebugReportMessageEXT_Bottom(VkInstance instance,
- VkDebugReportFlagsEXT flags,
- VkDebugReportObjectTypeEXT object_type,
- uint64_t object,
- size_t location,
- int32_t message_code,
- const char* layer_prefix,
- const char* message) {
- if (GetDriverDispatch(instance).DebugReportMessageEXT) {
- GetDriverDispatch(instance).DebugReportMessageEXT(
- GetDriverInstance(instance), flags, object_type, object, location,
- message_code, layer_prefix, message);
+void DebugReportMessageEXT(VkInstance instance,
+ VkDebugReportFlagsEXT flags,
+ VkDebugReportObjectTypeEXT object_type,
+ uint64_t object,
+ size_t location,
+ int32_t message_code,
+ const char* layer_prefix,
+ const char* message) {
+ if (GetData(instance).driver.DebugReportMessageEXT) {
+ GetData(instance).driver.DebugReportMessageEXT(
+ instance, flags, object_type, object, location, message_code,
+ layer_prefix, message);
}
- GetDebugReportCallbacks(instance).Message(flags, object_type, object,
- location, message_code,
- layer_prefix, message);
+ GetData(instance).debug_report_callbacks.Message(flags, object_type, object,
+ location, message_code,
+ layer_prefix, message);
}
+} // namespace driver
} // namespace vulkan
diff --git a/vulkan/libvulkan/debug_report.h b/vulkan/libvulkan/debug_report.h
index c6f7570..72b1887 100644
--- a/vulkan/libvulkan/debug_report.h
+++ b/vulkan/libvulkan/debug_report.h
@@ -17,14 +17,16 @@
#ifndef LIBVULKAN_DEBUG_REPORT_H
#define LIBVULKAN_DEBUG_REPORT_H 1
+#include <vulkan/vulkan.h>
#include <shared_mutex>
namespace vulkan {
+namespace driver {
// clang-format off
-VKAPI_ATTR VkResult CreateDebugReportCallbackEXT_Bottom(VkInstance instance, const VkDebugReportCallbackCreateInfoEXT* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDebugReportCallbackEXT* pCallback);
-VKAPI_ATTR void DestroyDebugReportCallbackEXT_Bottom(VkInstance instance, VkDebugReportCallbackEXT callback, const VkAllocationCallbacks* pAllocator);
-VKAPI_ATTR void DebugReportMessageEXT_Bottom(VkInstance instance, VkDebugReportFlagsEXT flags, VkDebugReportObjectTypeEXT objectType, uint64_t object, size_t location, int32_t messageCode, const char* pLayerPrefix, const char* pMessage);
+VKAPI_ATTR VkResult CreateDebugReportCallbackEXT(VkInstance instance, const VkDebugReportCallbackCreateInfoEXT* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDebugReportCallbackEXT* pCallback);
+VKAPI_ATTR void DestroyDebugReportCallbackEXT(VkInstance instance, VkDebugReportCallbackEXT callback, const VkAllocationCallbacks* pAllocator);
+VKAPI_ATTR void DebugReportMessageEXT(VkInstance instance, VkDebugReportFlagsEXT flags, VkDebugReportObjectTypeEXT objectType, uint64_t object, size_t location, int32_t messageCode, const char* pLayerPrefix, const char* pMessage);
// clang-format on
class DebugReportCallbackList {
@@ -65,6 +67,7 @@
Node head_;
};
+} // namespace driver
} // namespace vulkan
#endif // LIBVULKAN_DEBUG_REPORT_H
diff --git a/vulkan/libvulkan/dispatch.tmpl b/vulkan/libvulkan/dispatch.tmpl
deleted file mode 100644
index 67ead4a..0000000
--- a/vulkan/libvulkan/dispatch.tmpl
+++ /dev/null
@@ -1,365 +0,0 @@
-{{/*
- * Copyright 2015 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 "../api/templates/vulkan_common.tmpl"}}
-{{Global "clang-format" (Strings "clang-format" "-style=file")}}
-{{Macro "DefineGlobals" $}}
-{{$ | Macro "dispatch_gen.h" | Format (Global "clang-format") | Write "dispatch_gen.h" }}
-{{$ | Macro "dispatch_gen.cpp" | Format (Global "clang-format") | Write "dispatch_gen.cpp"}}
-
-{{/*
--------------------------------------------------------------------------------
- dispatch_gen.h
--------------------------------------------------------------------------------
-*/}}
-{{define "dispatch_gen.h"}}
-/*
-•* Copyright 2015 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.
-•*/
-¶
-// WARNING: This file is generated. See ../README.md for instructions.
-¶
-#include <vulkan/vk_android_native_buffer.h>
-#include <vulkan/vulkan.h>
-¶
-namespace vulkan {
-¶
-struct DriverDispatchTable {«
- // clang-format off
- {{range $f := AllCommands $}}
- {{if (Macro "IsInstanceDispatched" $f)}}
- {{if not (Macro "IsLoaderFunction" $f)}}
- {{Macro "FunctionPtrName" $f}} {{Macro "BaseName" $f}};
- {{end}}
- {{end}}
- {{end}}
-
- PFN_vkGetDeviceProcAddr GetDeviceProcAddr;
-
- PFN_vkDestroyDevice DestroyDevice;
- PFN_vkGetDeviceQueue GetDeviceQueue;
- PFN_vkAllocateCommandBuffers AllocateCommandBuffers;
-
- {{/* TODO(jessehall): Needed by swapchain code. Figure out a better way of
- handling this that avoids the special case. Probably should rework
- things so the driver dispatch table has all driver functions. Probably
- need separate instance- and device-level copies, fill in all device-
- dispatched functions in the device-level copies only, and change
- GetDeviceProcAddr_Bottom to look in the already-loaded driver
- dispatch table rather than forwarding to the driver's
- vkGetDeviceProcAddr. */}}
- PFN_vkCreateImage CreateImage;
- PFN_vkDestroyImage DestroyImage;
-
- PFN_vkGetSwapchainGrallocUsageANDROID GetSwapchainGrallocUsageANDROID;
- PFN_vkAcquireImageANDROID AcquireImageANDROID;
- PFN_vkQueueSignalReleaseImageANDROID QueueSignalReleaseImageANDROID;
- // clang-format on
-»};
-¶
-} // namespace vulkan
-¶{{end}}
-
-
-{{/*
--------------------------------------------------------------------------------
- dispatch_gen.cpp
--------------------------------------------------------------------------------
-*/}}
-{{define "dispatch_gen.cpp"}}
-/*
-•* Copyright 2015 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.
-•*/
-¶
-// WARNING: This file is generated. See ../README.md for instructions.
-¶
-#include <log/log.h>
-#include <algorithm>
-#include "loader.h"
-¶
-#define UNLIKELY(expr) __builtin_expect((expr), 0)
-¶
-using namespace vulkan;
-¶
-namespace {
-¶
-struct NameProc {
- const char* name;
- PFN_vkVoidFunction proc;
-};
-¶
-PFN_vkVoidFunction Lookup(const char* name, const NameProc* begin, const NameProc* end) {
- const auto& entry = std::lower_bound(
- begin, end, name,
- [](const NameProc& e, const char* n) { return strcmp(e.name, n) < 0; });
- if (entry == end || strcmp(entry->name, name) != 0)
- return nullptr;
- return entry->proc;
-}
-¶
-template <size_t N>
-PFN_vkVoidFunction Lookup(const char* name, const NameProc (&procs)[N]) {
- return Lookup(name, procs, procs + N);
-}
-¶
-const NameProc kLoaderBottomProcs[] = {«
- // clang-format off
- {{range $f := SortBy (AllCommands $) "FunctionName"}}
- {{if (Macro "HasLoaderBottomImpl" $f)}}
- {"{{$f.Name}}", reinterpret_cast<PFN_vkVoidFunction>(§
- static_cast<{{Macro "FunctionPtrName" $f}}>(§
- {{Macro "BaseName" $f}}_Bottom))},
- {{end}}
- {{end}}
- // clang-format on
-»};
-¶
-} // anonymous namespace
-¶
-namespace vulkan {
-¶
-PFN_vkVoidFunction GetLoaderBottomProcAddr(const char* name) {
- return Lookup(name, kLoaderBottomProcs);
-}
-¶
-bool LoadDriverDispatchTable(VkInstance instance,
- PFN_vkGetInstanceProcAddr get_proc_addr,
- const InstanceExtensionSet& extensions,
- DriverDispatchTable& dispatch) {«
- bool success = true;
- // clang-format off
- {{range $f := AllCommands $}}
- {{if (Macro "IsInstanceDispatched" $f)}}
- {{if not (Macro "IsLoaderFunction" $f)}}
- {{$ext := GetAnnotation $f "extension"}}
- {{if $ext}}
- if (extensions[{{Macro "ExtensionConstant" $ext}}]) {
- {{end}}
- dispatch.{{Macro "BaseName" $f}} = §
- reinterpret_cast<{{Macro "FunctionPtrName" $f}}>(§
- get_proc_addr(instance, "{{$f.Name}}"));
- if (UNLIKELY(!dispatch.{{Macro "BaseName" $f}})) {
- ALOGE("missing driver proc: %s", "{{$f.Name}}");
- success = false;
- }
- {{if $ext}}
- }
- {{end}}
- {{end}}
- {{end}}
- {{end}}
- dispatch.GetDeviceProcAddr = reinterpret_cast<PFN_vkGetDeviceProcAddr>(get_proc_addr(instance, "vkGetDeviceProcAddr"));
- if (UNLIKELY(!dispatch.GetDeviceProcAddr)) {
- ALOGE("missing driver proc: %s", "vkGetDeviceProcAddr");
- success = false;
- }
- dispatch.DestroyDevice = reinterpret_cast<PFN_vkDestroyDevice>(get_proc_addr(instance, "vkDestroyDevice"));
- if (UNLIKELY(!dispatch.DestroyDevice)) {
- ALOGE("missing driver proc: %s", "vkDestroyDevice");
- success = false;
- }
- dispatch.GetDeviceQueue = reinterpret_cast<PFN_vkGetDeviceQueue>(get_proc_addr(instance, "vkGetDeviceQueue"));
- if (UNLIKELY(!dispatch.GetDeviceQueue)) {
- ALOGE("missing driver proc: %s", "vkGetDeviceQueue");
- success = false;
- }
- dispatch.AllocateCommandBuffers = reinterpret_cast<PFN_vkAllocateCommandBuffers>(get_proc_addr(instance, "vkAllocateCommandBuffers"));
- if (UNLIKELY(!dispatch.AllocateCommandBuffers)) {
- ALOGE("missing driver proc: %s", "vkAllocateCommandBuffers");
- success = false;
- }
- dispatch.CreateImage = reinterpret_cast<PFN_vkCreateImage>(get_proc_addr(instance, "vkCreateImage"));
- if (UNLIKELY(!dispatch.CreateImage)) {
- ALOGE("missing driver proc: %s", "vkCreateImage");
- success = false;
- }
- dispatch.DestroyImage = reinterpret_cast<PFN_vkDestroyImage>(get_proc_addr(instance, "vkDestroyImage"));
- if (UNLIKELY(!dispatch.DestroyImage)) {
- ALOGE("missing driver proc: %s", "vkDestroyImage");
- success = false;
- }
- dispatch.GetSwapchainGrallocUsageANDROID = reinterpret_cast<PFN_vkGetSwapchainGrallocUsageANDROID>(get_proc_addr(instance, "vkGetSwapchainGrallocUsageANDROID"));
- if (UNLIKELY(!dispatch.GetSwapchainGrallocUsageANDROID)) {
- ALOGE("missing driver proc: %s", "vkGetSwapchainGrallocUsageANDROID");
- success = false;
- }
- dispatch.AcquireImageANDROID = reinterpret_cast<PFN_vkAcquireImageANDROID>(get_proc_addr(instance, "vkAcquireImageANDROID"));
- if (UNLIKELY(!dispatch.AcquireImageANDROID)) {
- ALOGE("missing driver proc: %s", "vkAcquireImageANDROID");
- success = false;
- }
- dispatch.QueueSignalReleaseImageANDROID = reinterpret_cast<PFN_vkQueueSignalReleaseImageANDROID>(get_proc_addr(instance, "vkQueueSignalReleaseImageANDROID"));
- if (UNLIKELY(!dispatch.QueueSignalReleaseImageANDROID)) {
- ALOGE("missing driver proc: %s", "vkQueueSignalReleaseImageANDROID");
- success = false;
- }
- // clang-format on
- return success;
-»}
-¶
-} // namespace vulkan
-¶{{end}}
-
-
-{{/*
--------------------------------------------------------------------------------
- Map an extension name to InstanceExtension or DeviceExtension enum value
--------------------------------------------------------------------------------
-*/}}
-{{define "ExtensionConstant"}}
- {{$name := index $.Arguments 0}}
- {{ if (eq $name "VK_KHR_surface")}}kKHR_surface
- {{else if (eq $name "VK_KHR_android_surface")}}kKHR_android_surface
- {{else if (eq $name "VK_EXT_debug_report")}}kEXT_debug_report
- {{end}}
-{{end}}
-
-
-{{/*
--------------------------------------------------------------------------------
- Emits a function name without the "vk" prefix.
--------------------------------------------------------------------------------
-*/}}
-{{define "BaseName"}}
- {{AssertType $ "Function"}}
- {{TrimPrefix "vk" $.Name}}
-{{end}}
-
-
-{{/*
-------------------------------------------------------------------------------
- Emit "true" for supported functions that undergo table dispatch. Only global
- functions and functions handled in the loader top without calling into
- lower layers are not dispatched.
-------------------------------------------------------------------------------
-*/}}
-{{define "IsInstanceDispatched"}}
- {{AssertType $ "Function"}}
- {{if and (Macro "IsFunctionSupported" $) (eq (Macro "Vtbl" $) "Instance")}}
- {{if and (ne $.Name "vkEnumerateDeviceLayerProperties") (ne $.Name "vkGetInstanceProcAddr")}}true{{end}}
- {{end}}
-{{end}}
-
-
-{{/*
-------------------------------------------------------------------------------
- Emit "true" if a function is core or from a supportable extension.
-------------------------------------------------------------------------------
-*/}}
-{{define "IsFunctionSupported"}}
- {{AssertType $ "Function"}}
- {{if not (GetAnnotation $ "pfn")}}
- {{$ext := GetAnnotation $ "extension"}}
- {{if not $ext}}true
- {{else if not (Macro "IsExtensionBlacklisted" $ext)}}true
- {{end}}
- {{end}}
-{{end}}
-
-
-{{/*
-------------------------------------------------------------------------------
- Reports whether an extension function is implemented entirely by the loader,
- and not implemented by drivers.
-------------------------------------------------------------------------------
-*/}}
-{{define "IsLoaderFunction"}}
- {{AssertType $ "Function"}}
-
- {{$ext := GetAnnotation $ "extension"}}
- {{if $ext}}
- {{Macro "IsLoaderExtension" $ext}}
- {{end}}
-{{end}}
-
-
-{{/*
--------------------------------------------------------------------------------
- Emit "true" if the loader has a bottom-level implementation for the function
- which terminates the dispatch chain.
--------------------------------------------------------------------------------
-*/}}
-{{define "HasLoaderBottomImpl"}}
- {{AssertType $ "Function"}}
-
- {{if (Macro "IsFunctionSupported" $)}}
- {{ if (eq (Macro "Vtbl" $) "Instance")}}true
- {{else if (Macro "IsLoaderFunction" $)}}true
- {{else if (eq $.Name "vkCreateInstance")}}true
- {{else if (eq $.Name "vkGetDeviceProcAddr")}}true
- {{else if (eq $.Name "vkDestroyDevice")}}true
- {{else if (eq $.Name "vkGetDeviceQueue")}}true
- {{else if (eq $.Name "vkAllocateCommandBuffers")}}true
- {{end}}
- {{end}}
-{{end}}
-
-
-{{/*
-------------------------------------------------------------------------------
- Emit "true" if an extension is unsupportable on Android.
-------------------------------------------------------------------------------
-*/}}
-{{define "IsExtensionBlacklisted"}}
- {{$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_win32_surface"}}true
- {{end}}
-{{end}}
-
-
-{{/*
-------------------------------------------------------------------------------
- Reports whether an extension is implemented entirely by the loader,
- so drivers should not enumerate it.
-------------------------------------------------------------------------------
-*/}}
-{{define "IsLoaderExtension"}}
- {{$ext := index $.Arguments 0}}
- {{ if eq $ext "VK_KHR_surface"}}true
- {{else if eq $ext "VK_KHR_swapchain"}}true
- {{else if eq $ext "VK_KHR_android_surface"}}true
- {{end}}
-{{end}}
diff --git a/vulkan/libvulkan/dispatch_gen.cpp b/vulkan/libvulkan/dispatch_gen.cpp
deleted file mode 100644
index eacf1a1..0000000
--- a/vulkan/libvulkan/dispatch_gen.cpp
+++ /dev/null
@@ -1,226 +0,0 @@
-/*
- * Copyright 2015 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.
- */
-
-// WARNING: This file is generated. See ../README.md for instructions.
-
-#include <log/log.h>
-#include <algorithm>
-#include "loader.h"
-
-#define UNLIKELY(expr) __builtin_expect((expr), 0)
-
-using namespace vulkan;
-
-namespace {
-
-struct NameProc {
- const char* name;
- PFN_vkVoidFunction proc;
-};
-
-PFN_vkVoidFunction Lookup(const char* name,
- const NameProc* begin,
- const NameProc* end) {
- const auto& entry = std::lower_bound(
- begin, end, name,
- [](const NameProc& e, const char* n) { return strcmp(e.name, n) < 0; });
- if (entry == end || strcmp(entry->name, name) != 0)
- return nullptr;
- return entry->proc;
-}
-
-template <size_t N>
-PFN_vkVoidFunction Lookup(const char* name, const NameProc (&procs)[N]) {
- return Lookup(name, procs, procs + N);
-}
-
-const NameProc kLoaderBottomProcs[] = {
- // clang-format off
- {"vkAcquireNextImageKHR", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkAcquireNextImageKHR>(AcquireNextImageKHR_Bottom))},
- {"vkAllocateCommandBuffers", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkAllocateCommandBuffers>(AllocateCommandBuffers_Bottom))},
- {"vkCreateAndroidSurfaceKHR", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCreateAndroidSurfaceKHR>(CreateAndroidSurfaceKHR_Bottom))},
- {"vkCreateDebugReportCallbackEXT", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCreateDebugReportCallbackEXT>(CreateDebugReportCallbackEXT_Bottom))},
- {"vkCreateDevice", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCreateDevice>(CreateDevice_Bottom))},
- {"vkCreateInstance", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCreateInstance>(CreateInstance_Bottom))},
- {"vkCreateSwapchainKHR", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCreateSwapchainKHR>(CreateSwapchainKHR_Bottom))},
- {"vkDebugReportMessageEXT", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkDebugReportMessageEXT>(DebugReportMessageEXT_Bottom))},
- {"vkDestroyDebugReportCallbackEXT", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkDestroyDebugReportCallbackEXT>(DestroyDebugReportCallbackEXT_Bottom))},
- {"vkDestroyDevice", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkDestroyDevice>(DestroyDevice_Bottom))},
- {"vkDestroyInstance", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkDestroyInstance>(DestroyInstance_Bottom))},
- {"vkDestroySurfaceKHR", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkDestroySurfaceKHR>(DestroySurfaceKHR_Bottom))},
- {"vkDestroySwapchainKHR", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkDestroySwapchainKHR>(DestroySwapchainKHR_Bottom))},
- {"vkEnumerateDeviceExtensionProperties", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkEnumerateDeviceExtensionProperties>(EnumerateDeviceExtensionProperties_Bottom))},
- {"vkEnumerateDeviceLayerProperties", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkEnumerateDeviceLayerProperties>(EnumerateDeviceLayerProperties_Bottom))},
- {"vkEnumeratePhysicalDevices", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkEnumeratePhysicalDevices>(EnumeratePhysicalDevices_Bottom))},
- {"vkGetDeviceProcAddr", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkGetDeviceProcAddr>(GetDeviceProcAddr_Bottom))},
- {"vkGetDeviceQueue", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkGetDeviceQueue>(GetDeviceQueue_Bottom))},
- {"vkGetInstanceProcAddr", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkGetInstanceProcAddr>(GetInstanceProcAddr_Bottom))},
- {"vkGetPhysicalDeviceFeatures", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkGetPhysicalDeviceFeatures>(GetPhysicalDeviceFeatures_Bottom))},
- {"vkGetPhysicalDeviceFormatProperties", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkGetPhysicalDeviceFormatProperties>(GetPhysicalDeviceFormatProperties_Bottom))},
- {"vkGetPhysicalDeviceImageFormatProperties", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkGetPhysicalDeviceImageFormatProperties>(GetPhysicalDeviceImageFormatProperties_Bottom))},
- {"vkGetPhysicalDeviceMemoryProperties", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkGetPhysicalDeviceMemoryProperties>(GetPhysicalDeviceMemoryProperties_Bottom))},
- {"vkGetPhysicalDeviceProperties", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkGetPhysicalDeviceProperties>(GetPhysicalDeviceProperties_Bottom))},
- {"vkGetPhysicalDeviceQueueFamilyProperties", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkGetPhysicalDeviceQueueFamilyProperties>(GetPhysicalDeviceQueueFamilyProperties_Bottom))},
- {"vkGetPhysicalDeviceSparseImageFormatProperties", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkGetPhysicalDeviceSparseImageFormatProperties>(GetPhysicalDeviceSparseImageFormatProperties_Bottom))},
- {"vkGetPhysicalDeviceSurfaceCapabilitiesKHR", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkGetPhysicalDeviceSurfaceCapabilitiesKHR>(GetPhysicalDeviceSurfaceCapabilitiesKHR_Bottom))},
- {"vkGetPhysicalDeviceSurfaceFormatsKHR", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkGetPhysicalDeviceSurfaceFormatsKHR>(GetPhysicalDeviceSurfaceFormatsKHR_Bottom))},
- {"vkGetPhysicalDeviceSurfacePresentModesKHR", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkGetPhysicalDeviceSurfacePresentModesKHR>(GetPhysicalDeviceSurfacePresentModesKHR_Bottom))},
- {"vkGetPhysicalDeviceSurfaceSupportKHR", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkGetPhysicalDeviceSurfaceSupportKHR>(GetPhysicalDeviceSurfaceSupportKHR_Bottom))},
- {"vkGetSwapchainImagesKHR", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkGetSwapchainImagesKHR>(GetSwapchainImagesKHR_Bottom))},
- {"vkQueuePresentKHR", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkQueuePresentKHR>(QueuePresentKHR_Bottom))},
- // clang-format on
-};
-
-} // anonymous namespace
-
-namespace vulkan {
-
-PFN_vkVoidFunction GetLoaderBottomProcAddr(const char* name) {
- return Lookup(name, kLoaderBottomProcs);
-}
-
-bool LoadDriverDispatchTable(VkInstance instance,
- PFN_vkGetInstanceProcAddr get_proc_addr,
- const InstanceExtensionSet& extensions,
- DriverDispatchTable& dispatch) {
- bool success = true;
- // clang-format off
- dispatch.DestroyInstance = reinterpret_cast<PFN_vkDestroyInstance>(get_proc_addr(instance, "vkDestroyInstance"));
- if (UNLIKELY(!dispatch.DestroyInstance)) {
- ALOGE("missing driver proc: %s", "vkDestroyInstance");
- success = false;
- }
- dispatch.EnumeratePhysicalDevices = reinterpret_cast<PFN_vkEnumeratePhysicalDevices>(get_proc_addr(instance, "vkEnumeratePhysicalDevices"));
- if (UNLIKELY(!dispatch.EnumeratePhysicalDevices)) {
- ALOGE("missing driver proc: %s", "vkEnumeratePhysicalDevices");
- success = false;
- }
- dispatch.GetPhysicalDeviceProperties = reinterpret_cast<PFN_vkGetPhysicalDeviceProperties>(get_proc_addr(instance, "vkGetPhysicalDeviceProperties"));
- if (UNLIKELY(!dispatch.GetPhysicalDeviceProperties)) {
- ALOGE("missing driver proc: %s", "vkGetPhysicalDeviceProperties");
- success = false;
- }
- dispatch.GetPhysicalDeviceQueueFamilyProperties = reinterpret_cast<PFN_vkGetPhysicalDeviceQueueFamilyProperties>(get_proc_addr(instance, "vkGetPhysicalDeviceQueueFamilyProperties"));
- if (UNLIKELY(!dispatch.GetPhysicalDeviceQueueFamilyProperties)) {
- ALOGE("missing driver proc: %s", "vkGetPhysicalDeviceQueueFamilyProperties");
- success = false;
- }
- dispatch.GetPhysicalDeviceMemoryProperties = reinterpret_cast<PFN_vkGetPhysicalDeviceMemoryProperties>(get_proc_addr(instance, "vkGetPhysicalDeviceMemoryProperties"));
- if (UNLIKELY(!dispatch.GetPhysicalDeviceMemoryProperties)) {
- ALOGE("missing driver proc: %s", "vkGetPhysicalDeviceMemoryProperties");
- success = false;
- }
- dispatch.GetPhysicalDeviceFeatures = reinterpret_cast<PFN_vkGetPhysicalDeviceFeatures>(get_proc_addr(instance, "vkGetPhysicalDeviceFeatures"));
- if (UNLIKELY(!dispatch.GetPhysicalDeviceFeatures)) {
- ALOGE("missing driver proc: %s", "vkGetPhysicalDeviceFeatures");
- success = false;
- }
- dispatch.GetPhysicalDeviceFormatProperties = reinterpret_cast<PFN_vkGetPhysicalDeviceFormatProperties>(get_proc_addr(instance, "vkGetPhysicalDeviceFormatProperties"));
- if (UNLIKELY(!dispatch.GetPhysicalDeviceFormatProperties)) {
- ALOGE("missing driver proc: %s", "vkGetPhysicalDeviceFormatProperties");
- success = false;
- }
- dispatch.GetPhysicalDeviceImageFormatProperties = reinterpret_cast<PFN_vkGetPhysicalDeviceImageFormatProperties>(get_proc_addr(instance, "vkGetPhysicalDeviceImageFormatProperties"));
- if (UNLIKELY(!dispatch.GetPhysicalDeviceImageFormatProperties)) {
- ALOGE("missing driver proc: %s", "vkGetPhysicalDeviceImageFormatProperties");
- success = false;
- }
- dispatch.CreateDevice = reinterpret_cast<PFN_vkCreateDevice>(get_proc_addr(instance, "vkCreateDevice"));
- if (UNLIKELY(!dispatch.CreateDevice)) {
- ALOGE("missing driver proc: %s", "vkCreateDevice");
- success = false;
- }
- dispatch.EnumerateDeviceExtensionProperties = reinterpret_cast<PFN_vkEnumerateDeviceExtensionProperties>(get_proc_addr(instance, "vkEnumerateDeviceExtensionProperties"));
- if (UNLIKELY(!dispatch.EnumerateDeviceExtensionProperties)) {
- ALOGE("missing driver proc: %s", "vkEnumerateDeviceExtensionProperties");
- success = false;
- }
- dispatch.GetPhysicalDeviceSparseImageFormatProperties = reinterpret_cast<PFN_vkGetPhysicalDeviceSparseImageFormatProperties>(get_proc_addr(instance, "vkGetPhysicalDeviceSparseImageFormatProperties"));
- if (UNLIKELY(!dispatch.GetPhysicalDeviceSparseImageFormatProperties)) {
- ALOGE("missing driver proc: %s", "vkGetPhysicalDeviceSparseImageFormatProperties");
- success = false;
- }
- if (extensions[kEXT_debug_report]) {
- dispatch.CreateDebugReportCallbackEXT = reinterpret_cast<PFN_vkCreateDebugReportCallbackEXT>(get_proc_addr(instance, "vkCreateDebugReportCallbackEXT"));
- if (UNLIKELY(!dispatch.CreateDebugReportCallbackEXT)) {
- ALOGE("missing driver proc: %s", "vkCreateDebugReportCallbackEXT");
- success = false;
- }
- }
- if (extensions[kEXT_debug_report]) {
- dispatch.DestroyDebugReportCallbackEXT = reinterpret_cast<PFN_vkDestroyDebugReportCallbackEXT>(get_proc_addr(instance, "vkDestroyDebugReportCallbackEXT"));
- if (UNLIKELY(!dispatch.DestroyDebugReportCallbackEXT)) {
- ALOGE("missing driver proc: %s", "vkDestroyDebugReportCallbackEXT");
- success = false;
- }
- }
- if (extensions[kEXT_debug_report]) {
- dispatch.DebugReportMessageEXT = reinterpret_cast<PFN_vkDebugReportMessageEXT>(get_proc_addr(instance, "vkDebugReportMessageEXT"));
- if (UNLIKELY(!dispatch.DebugReportMessageEXT)) {
- ALOGE("missing driver proc: %s", "vkDebugReportMessageEXT");
- success = false;
- }
- }
- dispatch.GetDeviceProcAddr = reinterpret_cast<PFN_vkGetDeviceProcAddr>(get_proc_addr(instance, "vkGetDeviceProcAddr"));
- if (UNLIKELY(!dispatch.GetDeviceProcAddr)) {
- ALOGE("missing driver proc: %s", "vkGetDeviceProcAddr");
- success = false;
- }
- dispatch.DestroyDevice = reinterpret_cast<PFN_vkDestroyDevice>(get_proc_addr(instance, "vkDestroyDevice"));
- if (UNLIKELY(!dispatch.DestroyDevice)) {
- ALOGE("missing driver proc: %s", "vkDestroyDevice");
- success = false;
- }
- dispatch.GetDeviceQueue = reinterpret_cast<PFN_vkGetDeviceQueue>(get_proc_addr(instance, "vkGetDeviceQueue"));
- if (UNLIKELY(!dispatch.GetDeviceQueue)) {
- ALOGE("missing driver proc: %s", "vkGetDeviceQueue");
- success = false;
- }
- dispatch.AllocateCommandBuffers = reinterpret_cast<PFN_vkAllocateCommandBuffers>(get_proc_addr(instance, "vkAllocateCommandBuffers"));
- if (UNLIKELY(!dispatch.AllocateCommandBuffers)) {
- ALOGE("missing driver proc: %s", "vkAllocateCommandBuffers");
- success = false;
- }
- dispatch.CreateImage = reinterpret_cast<PFN_vkCreateImage>(get_proc_addr(instance, "vkCreateImage"));
- if (UNLIKELY(!dispatch.CreateImage)) {
- ALOGE("missing driver proc: %s", "vkCreateImage");
- success = false;
- }
- dispatch.DestroyImage = reinterpret_cast<PFN_vkDestroyImage>(get_proc_addr(instance, "vkDestroyImage"));
- if (UNLIKELY(!dispatch.DestroyImage)) {
- ALOGE("missing driver proc: %s", "vkDestroyImage");
- success = false;
- }
- dispatch.GetSwapchainGrallocUsageANDROID = reinterpret_cast<PFN_vkGetSwapchainGrallocUsageANDROID>(get_proc_addr(instance, "vkGetSwapchainGrallocUsageANDROID"));
- if (UNLIKELY(!dispatch.GetSwapchainGrallocUsageANDROID)) {
- ALOGE("missing driver proc: %s", "vkGetSwapchainGrallocUsageANDROID");
- success = false;
- }
- dispatch.AcquireImageANDROID = reinterpret_cast<PFN_vkAcquireImageANDROID>(get_proc_addr(instance, "vkAcquireImageANDROID"));
- if (UNLIKELY(!dispatch.AcquireImageANDROID)) {
- ALOGE("missing driver proc: %s", "vkAcquireImageANDROID");
- success = false;
- }
- dispatch.QueueSignalReleaseImageANDROID = reinterpret_cast<PFN_vkQueueSignalReleaseImageANDROID>(get_proc_addr(instance, "vkQueueSignalReleaseImageANDROID"));
- if (UNLIKELY(!dispatch.QueueSignalReleaseImageANDROID)) {
- ALOGE("missing driver proc: %s", "vkQueueSignalReleaseImageANDROID");
- success = false;
- }
- // clang-format on
- return success;
-}
-
-} // namespace vulkan
diff --git a/vulkan/libvulkan/dispatch_gen.h b/vulkan/libvulkan/dispatch_gen.h
deleted file mode 100644
index ca31caf..0000000
--- a/vulkan/libvulkan/dispatch_gen.h
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright 2015 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.
- */
-
-// WARNING: This file is generated. See ../README.md for instructions.
-
-#include <vulkan/vk_android_native_buffer.h>
-#include <vulkan/vulkan.h>
-
-namespace vulkan {
-
-struct DriverDispatchTable {
- // clang-format off
- PFN_vkDestroyInstance DestroyInstance;
- PFN_vkEnumeratePhysicalDevices EnumeratePhysicalDevices;
- PFN_vkGetPhysicalDeviceProperties GetPhysicalDeviceProperties;
- PFN_vkGetPhysicalDeviceQueueFamilyProperties GetPhysicalDeviceQueueFamilyProperties;
- PFN_vkGetPhysicalDeviceMemoryProperties GetPhysicalDeviceMemoryProperties;
- PFN_vkGetPhysicalDeviceFeatures GetPhysicalDeviceFeatures;
- PFN_vkGetPhysicalDeviceFormatProperties GetPhysicalDeviceFormatProperties;
- PFN_vkGetPhysicalDeviceImageFormatProperties GetPhysicalDeviceImageFormatProperties;
- PFN_vkCreateDevice CreateDevice;
- PFN_vkEnumerateDeviceExtensionProperties EnumerateDeviceExtensionProperties;
- PFN_vkGetPhysicalDeviceSparseImageFormatProperties GetPhysicalDeviceSparseImageFormatProperties;
- PFN_vkCreateDebugReportCallbackEXT CreateDebugReportCallbackEXT;
- PFN_vkDestroyDebugReportCallbackEXT DestroyDebugReportCallbackEXT;
- PFN_vkDebugReportMessageEXT DebugReportMessageEXT;
- PFN_vkGetDeviceProcAddr GetDeviceProcAddr;
- PFN_vkDestroyDevice DestroyDevice;
- PFN_vkGetDeviceQueue GetDeviceQueue;
- PFN_vkAllocateCommandBuffers AllocateCommandBuffers;
- PFN_vkCreateImage CreateImage;
- PFN_vkDestroyImage DestroyImage;
- PFN_vkGetSwapchainGrallocUsageANDROID GetSwapchainGrallocUsageANDROID;
- PFN_vkAcquireImageANDROID AcquireImageANDROID;
- PFN_vkQueueSignalReleaseImageANDROID QueueSignalReleaseImageANDROID;
- // clang-format on
-};
-
-} // namespace vulkan
diff --git a/vulkan/libvulkan/driver.cpp b/vulkan/libvulkan/driver.cpp
new file mode 100644
index 0000000..c5ea20b
--- /dev/null
+++ b/vulkan/libvulkan/driver.cpp
@@ -0,0 +1,775 @@
+/*
+ * Copyright 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 <stdlib.h>
+#include <string.h>
+#include <algorithm>
+#include <array>
+#include <new>
+#include <malloc.h>
+#include <sys/prctl.h>
+
+#include "driver.h"
+#include "stubhal.h"
+
+// #define ENABLE_ALLOC_CALLSTACKS 1
+#if ENABLE_ALLOC_CALLSTACKS
+#include <utils/CallStack.h>
+#define ALOGD_CALLSTACK(...) \
+ do { \
+ ALOGD(__VA_ARGS__); \
+ android::CallStack callstack; \
+ callstack.update(); \
+ callstack.log(LOG_TAG, ANDROID_LOG_DEBUG, " "); \
+ } while (false)
+#else
+#define ALOGD_CALLSTACK(...) \
+ do { \
+ } while (false)
+#endif
+
+namespace vulkan {
+namespace driver {
+
+namespace {
+
+class CreateInfoWrapper {
+ public:
+ CreateInfoWrapper(const hwvulkan_device_t* hw_dev,
+ const VkInstanceCreateInfo& create_info,
+ const VkAllocationCallbacks& allocator);
+ CreateInfoWrapper(VkPhysicalDevice physical_dev,
+ const VkDeviceCreateInfo& create_info,
+ const VkAllocationCallbacks& allocator);
+ ~CreateInfoWrapper();
+
+ VkResult Validate();
+
+ const std::bitset<ProcHook::EXTENSION_COUNT>& GetHookExtensions() const;
+ const std::bitset<ProcHook::EXTENSION_COUNT>& GetHalExtensions() const;
+
+ explicit operator const VkInstanceCreateInfo*() const;
+ explicit operator const VkDeviceCreateInfo*() const;
+
+ private:
+ struct ExtensionFilter {
+ VkExtensionProperties* exts;
+ uint32_t ext_count;
+
+ const char** names;
+ uint32_t name_count;
+ };
+
+ VkResult SanitizePNext();
+
+ VkResult SanitizeLayers();
+ VkResult SanitizeExtensions();
+
+ VkResult QueryExtensionCount(uint32_t& count) const;
+ VkResult EnumerateExtensions(uint32_t& count,
+ VkExtensionProperties* props) const;
+ VkResult InitExtensionFilter();
+ void FilterExtension(const char* name);
+
+ const bool is_instance_;
+ const VkAllocationCallbacks& allocator_;
+
+ union {
+ const hwvulkan_device_t* hw_dev_;
+ VkPhysicalDevice physical_dev_;
+ };
+
+ union {
+ VkInstanceCreateInfo instance_info_;
+ VkDeviceCreateInfo dev_info_;
+ };
+
+ ExtensionFilter extension_filter_;
+
+ std::bitset<ProcHook::EXTENSION_COUNT> hook_extensions_;
+ std::bitset<ProcHook::EXTENSION_COUNT> hal_extensions_;
+};
+
+CreateInfoWrapper::CreateInfoWrapper(const hwvulkan_device_t* hw_dev,
+ const VkInstanceCreateInfo& create_info,
+ const VkAllocationCallbacks& allocator)
+ : is_instance_(true),
+ allocator_(allocator),
+ hw_dev_(hw_dev),
+ instance_info_(create_info),
+ extension_filter_() {
+ hook_extensions_.set(ProcHook::EXTENSION_CORE);
+ hal_extensions_.set(ProcHook::EXTENSION_CORE);
+}
+
+CreateInfoWrapper::CreateInfoWrapper(VkPhysicalDevice physical_dev,
+ const VkDeviceCreateInfo& create_info,
+ const VkAllocationCallbacks& allocator)
+ : is_instance_(false),
+ allocator_(allocator),
+ physical_dev_(physical_dev),
+ dev_info_(create_info),
+ extension_filter_() {
+ hook_extensions_.set(ProcHook::EXTENSION_CORE);
+ hal_extensions_.set(ProcHook::EXTENSION_CORE);
+}
+
+CreateInfoWrapper::~CreateInfoWrapper() {
+ allocator_.pfnFree(allocator_.pUserData, extension_filter_.exts);
+ allocator_.pfnFree(allocator_.pUserData, extension_filter_.names);
+}
+
+VkResult CreateInfoWrapper::Validate() {
+ VkResult result = SanitizePNext();
+ if (result == VK_SUCCESS)
+ result = SanitizeLayers();
+ if (result == VK_SUCCESS)
+ result = SanitizeExtensions();
+
+ return result;
+}
+
+const std::bitset<ProcHook::EXTENSION_COUNT>&
+CreateInfoWrapper::GetHookExtensions() const {
+ return hook_extensions_;
+}
+
+const std::bitset<ProcHook::EXTENSION_COUNT>&
+CreateInfoWrapper::GetHalExtensions() const {
+ return hal_extensions_;
+}
+
+CreateInfoWrapper::operator const VkInstanceCreateInfo*() const {
+ return &instance_info_;
+}
+
+CreateInfoWrapper::operator const VkDeviceCreateInfo*() const {
+ return &dev_info_;
+}
+
+VkResult CreateInfoWrapper::SanitizePNext() {
+ const struct StructHeader {
+ VkStructureType type;
+ const void* next;
+ } * header;
+
+ if (is_instance_) {
+ header = reinterpret_cast<const StructHeader*>(instance_info_.pNext);
+
+ // skip leading VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFOs
+ while (header &&
+ header->type == VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFO)
+ header = reinterpret_cast<const StructHeader*>(header->next);
+
+ instance_info_.pNext = header;
+ } else {
+ header = reinterpret_cast<const StructHeader*>(dev_info_.pNext);
+
+ // skip leading VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFOs
+ while (header &&
+ header->type == VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFO)
+ header = reinterpret_cast<const StructHeader*>(header->next);
+
+ dev_info_.pNext = header;
+ }
+
+ return VK_SUCCESS;
+}
+
+VkResult CreateInfoWrapper::SanitizeLayers() {
+ auto& layer_names = (is_instance_) ? instance_info_.ppEnabledLayerNames
+ : dev_info_.ppEnabledLayerNames;
+ auto& layer_count = (is_instance_) ? instance_info_.enabledLayerCount
+ : dev_info_.enabledLayerCount;
+
+ // remove all layers
+ layer_names = nullptr;
+ layer_count = 0;
+
+ return VK_SUCCESS;
+}
+
+VkResult CreateInfoWrapper::SanitizeExtensions() {
+ auto& ext_names = (is_instance_) ? instance_info_.ppEnabledExtensionNames
+ : dev_info_.ppEnabledExtensionNames;
+ auto& ext_count = (is_instance_) ? instance_info_.enabledExtensionCount
+ : dev_info_.enabledExtensionCount;
+ if (!ext_count)
+ return VK_SUCCESS;
+
+ VkResult result = InitExtensionFilter();
+ if (result != VK_SUCCESS)
+ return result;
+
+ for (uint32_t i = 0; i < ext_count; i++)
+ FilterExtension(ext_names[i]);
+
+ ext_names = extension_filter_.names;
+ ext_count = extension_filter_.name_count;
+
+ return VK_SUCCESS;
+}
+
+VkResult CreateInfoWrapper::QueryExtensionCount(uint32_t& count) const {
+ if (is_instance_) {
+ return hw_dev_->EnumerateInstanceExtensionProperties(nullptr, &count,
+ nullptr);
+ } else {
+ const auto& driver = GetData(physical_dev_).driver;
+ return driver.EnumerateDeviceExtensionProperties(physical_dev_, nullptr,
+ &count, nullptr);
+ }
+}
+
+VkResult CreateInfoWrapper::EnumerateExtensions(
+ uint32_t& count,
+ VkExtensionProperties* props) const {
+ if (is_instance_) {
+ return hw_dev_->EnumerateInstanceExtensionProperties(nullptr, &count,
+ props);
+ } else {
+ const auto& driver = GetData(physical_dev_).driver;
+ return driver.EnumerateDeviceExtensionProperties(physical_dev_, nullptr,
+ &count, props);
+ }
+}
+
+VkResult CreateInfoWrapper::InitExtensionFilter() {
+ // query extension count
+ uint32_t count;
+ VkResult result = QueryExtensionCount(count);
+ if (result != VK_SUCCESS || count == 0)
+ return result;
+
+ auto& filter = extension_filter_;
+ filter.exts =
+ reinterpret_cast<VkExtensionProperties*>(allocator_.pfnAllocation(
+ allocator_.pUserData, sizeof(VkExtensionProperties) * count,
+ alignof(VkExtensionProperties),
+ VK_SYSTEM_ALLOCATION_SCOPE_COMMAND));
+ if (!filter.exts)
+ return VK_ERROR_OUT_OF_HOST_MEMORY;
+
+ // enumerate extensions
+ result = EnumerateExtensions(count, filter.exts);
+ if (result != VK_SUCCESS && result != VK_INCOMPLETE)
+ return result;
+
+ if (!count)
+ return VK_SUCCESS;
+
+ filter.ext_count = count;
+
+ // allocate name array
+ uint32_t enabled_ext_count = (is_instance_)
+ ? instance_info_.enabledExtensionCount
+ : dev_info_.enabledExtensionCount;
+ count = std::min(filter.ext_count, enabled_ext_count);
+ filter.names = reinterpret_cast<const char**>(allocator_.pfnAllocation(
+ allocator_.pUserData, sizeof(const char*) * count, alignof(const char*),
+ VK_SYSTEM_ALLOCATION_SCOPE_COMMAND));
+ if (!filter.names)
+ return VK_ERROR_OUT_OF_HOST_MEMORY;
+
+ return VK_SUCCESS;
+}
+
+void CreateInfoWrapper::FilterExtension(const char* name) {
+ auto& filter = extension_filter_;
+
+ ProcHook::Extension ext_bit = GetProcHookExtension(name);
+ if (is_instance_) {
+ switch (ext_bit) {
+ case ProcHook::KHR_android_surface:
+ case ProcHook::KHR_surface:
+ hook_extensions_.set(ext_bit);
+ // return now as these extensions do not require HAL support
+ return;
+ case ProcHook::EXT_debug_report:
+ // both we and HAL can take part in
+ hook_extensions_.set(ext_bit);
+ break;
+ case ProcHook::EXTENSION_UNKNOWN:
+ // HAL's extensions
+ break;
+ default:
+ ALOGW("Ignored invalid instance extension %s", name);
+ return;
+ }
+ } else {
+ switch (ext_bit) {
+ case ProcHook::KHR_swapchain:
+ // map VK_KHR_swapchain to VK_ANDROID_native_buffer
+ name = VK_ANDROID_NATIVE_BUFFER_EXTENSION_NAME;
+ ext_bit = ProcHook::ANDROID_native_buffer;
+ break;
+ case ProcHook::EXTENSION_UNKNOWN:
+ // HAL's extensions
+ break;
+ default:
+ ALOGW("Ignored invalid device extension %s", name);
+ return;
+ }
+ }
+
+ for (uint32_t i = 0; i < filter.ext_count; i++) {
+ const VkExtensionProperties& props = filter.exts[i];
+ // ignore unknown extensions
+ if (strcmp(name, props.extensionName) != 0)
+ continue;
+
+ filter.names[filter.name_count++] = name;
+ if (ext_bit != ProcHook::EXTENSION_UNKNOWN) {
+ if (ext_bit == ProcHook::ANDROID_native_buffer)
+ hook_extensions_.set(ProcHook::KHR_swapchain);
+
+ hal_extensions_.set(ext_bit);
+ }
+
+ break;
+ }
+}
+
+const hwvulkan_device_t* g_hwdevice = nullptr;
+
+VKAPI_ATTR void* DefaultAllocate(void*,
+ size_t size,
+ size_t alignment,
+ VkSystemAllocationScope) {
+ void* ptr = nullptr;
+ // Vulkan requires 'alignment' to be a power of two, but posix_memalign
+ // additionally requires that it be at least sizeof(void*).
+ int ret = posix_memalign(&ptr, std::max(alignment, sizeof(void*)), size);
+ ALOGD_CALLSTACK("Allocate: size=%zu align=%zu => (%d) %p", size, alignment,
+ ret, ptr);
+ return ret == 0 ? ptr : nullptr;
+}
+
+VKAPI_ATTR void* DefaultReallocate(void*,
+ void* ptr,
+ size_t size,
+ size_t alignment,
+ VkSystemAllocationScope) {
+ if (size == 0) {
+ free(ptr);
+ return nullptr;
+ }
+
+ // TODO(jessehall): Right now we never shrink allocations; if the new
+ // request is smaller than the existing chunk, we just continue using it.
+ // Right now the loader never reallocs, so this doesn't matter. If that
+ // changes, or if this code is copied into some other project, this should
+ // probably have a heuristic to allocate-copy-free when doing so will save
+ // "enough" space.
+ size_t old_size = ptr ? malloc_usable_size(ptr) : 0;
+ if (size <= old_size)
+ return ptr;
+
+ void* new_ptr = nullptr;
+ if (posix_memalign(&new_ptr, std::max(alignment, sizeof(void*)), size) != 0)
+ return nullptr;
+ if (ptr) {
+ memcpy(new_ptr, ptr, std::min(old_size, size));
+ free(ptr);
+ }
+ return new_ptr;
+}
+
+VKAPI_ATTR void DefaultFree(void*, void* ptr) {
+ ALOGD_CALLSTACK("Free: %p", ptr);
+ free(ptr);
+}
+
+InstanceData* AllocateInstanceData(const VkAllocationCallbacks& allocator) {
+ void* data_mem = allocator.pfnAllocation(
+ allocator.pUserData, sizeof(InstanceData), alignof(InstanceData),
+ VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
+ if (!data_mem)
+ return nullptr;
+
+ return new (data_mem) InstanceData(allocator);
+}
+
+void FreeInstanceData(InstanceData* data,
+ const VkAllocationCallbacks& allocator) {
+ data->~InstanceData();
+ allocator.pfnFree(allocator.pUserData, data);
+}
+
+DeviceData* AllocateDeviceData(const VkAllocationCallbacks& allocator) {
+ void* data_mem = allocator.pfnAllocation(
+ allocator.pUserData, sizeof(DeviceData), alignof(DeviceData),
+ VK_SYSTEM_ALLOCATION_SCOPE_DEVICE);
+ if (!data_mem)
+ return nullptr;
+
+ return new (data_mem) DeviceData(allocator);
+}
+
+void FreeDeviceData(DeviceData* data, const VkAllocationCallbacks& allocator) {
+ data->~DeviceData();
+ allocator.pfnFree(allocator.pUserData, data);
+}
+
+} // anonymous namespace
+
+bool Debuggable() {
+ return (prctl(PR_GET_DUMPABLE, 0, 0, 0, 0) >= 0);
+}
+
+bool OpenHAL() {
+ ALOG_ASSERT(!g_hwdevice, "OpenHAL called more than once");
+
+ // Use a stub device unless we successfully open a real HAL device.
+ g_hwdevice = &stubhal::kDevice;
+
+ const hwvulkan_module_t* module;
+ int result =
+ hw_get_module("vulkan", reinterpret_cast<const hw_module_t**>(&module));
+ if (result != 0) {
+ ALOGV("no Vulkan HAL present, using stub HAL");
+ return true;
+ }
+
+ hwvulkan_device_t* device;
+ result =
+ module->common.methods->open(&module->common, HWVULKAN_DEVICE_0,
+ reinterpret_cast<hw_device_t**>(&device));
+ if (result != 0) {
+ // Any device with a Vulkan HAL should be able to open the device.
+ ALOGE("failed to open Vulkan HAL device: %s (%d)", strerror(-result),
+ result);
+ return false;
+ }
+
+ g_hwdevice = device;
+
+ return true;
+}
+
+const VkAllocationCallbacks& GetDefaultAllocator() {
+ static const VkAllocationCallbacks kDefaultAllocCallbacks = {
+ .pUserData = nullptr,
+ .pfnAllocation = DefaultAllocate,
+ .pfnReallocation = DefaultReallocate,
+ .pfnFree = DefaultFree,
+ };
+
+ return kDefaultAllocCallbacks;
+}
+
+PFN_vkVoidFunction GetInstanceProcAddr(VkInstance instance, const char* pName) {
+ const ProcHook* hook = GetProcHook(pName);
+ if (!hook)
+ return g_hwdevice->GetInstanceProcAddr(instance, pName);
+
+ if (!instance) {
+ if (hook->type == ProcHook::GLOBAL)
+ return hook->proc;
+
+ ALOGE(
+ "Invalid use of vkGetInstanceProcAddr to query %s without an "
+ "instance",
+ pName);
+
+ // Some naughty layers expect
+ //
+ // vkGetInstanceProcAddr(VK_NULL_HANDLE, "vkCreateDevice");
+ //
+ // to work.
+ return (strcmp(pName, "vkCreateDevice") == 0) ? hook->proc : nullptr;
+ }
+
+ PFN_vkVoidFunction proc;
+
+ switch (hook->type) {
+ case ProcHook::INSTANCE:
+ proc = (GetData(instance).hook_extensions[hook->extension])
+ ? hook->proc
+ : hook->disabled_proc;
+ break;
+ case ProcHook::DEVICE:
+ proc = (hook->extension == ProcHook::EXTENSION_CORE)
+ ? hook->proc
+ : hook->checked_proc;
+ break;
+ default:
+ ALOGE(
+ "Invalid use of vkGetInstanceProcAddr to query %s with an "
+ "instance",
+ pName);
+ proc = nullptr;
+ break;
+ }
+
+ return proc;
+}
+
+PFN_vkVoidFunction GetDeviceProcAddr(VkDevice device, const char* pName) {
+ const ProcHook* hook = GetProcHook(pName);
+ if (!hook)
+ return GetData(device).driver.GetDeviceProcAddr(device, pName);
+
+ if (hook->type != ProcHook::DEVICE) {
+ ALOGE("Invalid use of vkGetDeviceProcAddr to query %s", pName);
+ return nullptr;
+ }
+
+ return (GetData(device).hook_extensions[hook->extension])
+ ? hook->proc
+ : hook->disabled_proc;
+}
+
+VkResult EnumerateInstanceExtensionProperties(
+ const char* pLayerName,
+ uint32_t* pPropertyCount,
+ VkExtensionProperties* pProperties) {
+ static const std::array<VkExtensionProperties, 2> loader_extensions = {{
+ // WSI extensions
+ {VK_KHR_SURFACE_EXTENSION_NAME, VK_KHR_SURFACE_SPEC_VERSION},
+ {VK_KHR_ANDROID_SURFACE_EXTENSION_NAME,
+ VK_KHR_ANDROID_SURFACE_SPEC_VERSION},
+ }};
+
+ // enumerate our extensions first
+ if (!pLayerName && pProperties) {
+ uint32_t count = std::min(
+ *pPropertyCount, static_cast<uint32_t>(loader_extensions.size()));
+
+ std::copy_n(loader_extensions.begin(), count, pProperties);
+
+ if (count < loader_extensions.size()) {
+ *pPropertyCount = count;
+ return VK_INCOMPLETE;
+ }
+
+ pProperties += count;
+ *pPropertyCount -= count;
+ }
+
+ VkResult result = g_hwdevice->EnumerateInstanceExtensionProperties(
+ pLayerName, pPropertyCount, pProperties);
+
+ if (!pLayerName && (result == VK_SUCCESS || result == VK_INCOMPLETE))
+ *pPropertyCount += loader_extensions.size();
+
+ return result;
+}
+
+VkResult EnumerateDeviceExtensionProperties(
+ VkPhysicalDevice physicalDevice,
+ const char* pLayerName,
+ uint32_t* pPropertyCount,
+ VkExtensionProperties* pProperties) {
+ const InstanceData& data = GetData(physicalDevice);
+
+ VkResult result = data.driver.EnumerateDeviceExtensionProperties(
+ physicalDevice, pLayerName, pPropertyCount, pProperties);
+ if (result != VK_SUCCESS && result != VK_INCOMPLETE)
+ return result;
+
+ if (!pProperties)
+ return result;
+
+ // map VK_ANDROID_native_buffer to VK_KHR_swapchain
+ for (uint32_t i = 0; i < *pPropertyCount; i++) {
+ auto& prop = pProperties[i];
+
+ if (strcmp(prop.extensionName,
+ VK_ANDROID_NATIVE_BUFFER_EXTENSION_NAME) != 0)
+ continue;
+
+ memcpy(prop.extensionName, VK_KHR_SWAPCHAIN_EXTENSION_NAME,
+ sizeof(VK_KHR_SWAPCHAIN_EXTENSION_NAME));
+ prop.specVersion = VK_KHR_SWAPCHAIN_SPEC_VERSION;
+ }
+
+ return result;
+}
+
+VkResult CreateInstance(const VkInstanceCreateInfo* pCreateInfo,
+ const VkAllocationCallbacks* pAllocator,
+ VkInstance* pInstance) {
+ const VkAllocationCallbacks& data_allocator =
+ (pAllocator) ? *pAllocator : GetDefaultAllocator();
+
+ CreateInfoWrapper wrapper(g_hwdevice, *pCreateInfo, data_allocator);
+ VkResult result = wrapper.Validate();
+ if (result != VK_SUCCESS)
+ return result;
+
+ InstanceData* data = AllocateInstanceData(data_allocator);
+ if (!data)
+ return VK_ERROR_OUT_OF_HOST_MEMORY;
+
+ data->hook_extensions |= wrapper.GetHookExtensions();
+ data->hal_extensions |= wrapper.GetHalExtensions();
+
+ // call into the driver
+ VkInstance instance;
+ result = g_hwdevice->CreateInstance(
+ static_cast<const VkInstanceCreateInfo*>(wrapper), pAllocator,
+ &instance);
+ if (result != VK_SUCCESS) {
+ FreeInstanceData(data, data_allocator);
+ return result;
+ }
+
+ // initialize InstanceDriverTable
+ if (!SetData(instance, *data) ||
+ !InitDriverTable(instance, g_hwdevice->GetInstanceProcAddr)) {
+ data->driver.DestroyInstance = reinterpret_cast<PFN_vkDestroyInstance>(
+ g_hwdevice->GetInstanceProcAddr(instance, "vkDestroyInstance"));
+ if (data->driver.DestroyInstance)
+ data->driver.DestroyInstance(instance, pAllocator);
+
+ FreeInstanceData(data, data_allocator);
+
+ return VK_ERROR_INCOMPATIBLE_DRIVER;
+ }
+
+ data->get_device_proc_addr = reinterpret_cast<PFN_vkGetDeviceProcAddr>(
+ g_hwdevice->GetInstanceProcAddr(instance, "vkGetDeviceProcAddr"));
+ if (!data->get_device_proc_addr) {
+ data->driver.DestroyInstance(instance, pAllocator);
+ FreeInstanceData(data, data_allocator);
+
+ return VK_ERROR_INCOMPATIBLE_DRIVER;
+ }
+
+ *pInstance = instance;
+
+ return VK_SUCCESS;
+}
+
+void DestroyInstance(VkInstance instance,
+ const VkAllocationCallbacks* pAllocator) {
+ InstanceData& data = GetData(instance);
+ data.driver.DestroyInstance(instance, pAllocator);
+
+ VkAllocationCallbacks local_allocator;
+ if (!pAllocator) {
+ local_allocator = data.allocator;
+ pAllocator = &local_allocator;
+ }
+
+ FreeInstanceData(&data, *pAllocator);
+}
+
+VkResult CreateDevice(VkPhysicalDevice physicalDevice,
+ const VkDeviceCreateInfo* pCreateInfo,
+ const VkAllocationCallbacks* pAllocator,
+ VkDevice* pDevice) {
+ const InstanceData& instance_data = GetData(physicalDevice);
+ const VkAllocationCallbacks& data_allocator =
+ (pAllocator) ? *pAllocator : instance_data.allocator;
+
+ CreateInfoWrapper wrapper(physicalDevice, *pCreateInfo, data_allocator);
+ VkResult result = wrapper.Validate();
+ if (result != VK_SUCCESS)
+ return result;
+
+ DeviceData* data = AllocateDeviceData(data_allocator);
+ if (!data)
+ return VK_ERROR_OUT_OF_HOST_MEMORY;
+
+ data->hook_extensions |= wrapper.GetHookExtensions();
+ data->hal_extensions |= wrapper.GetHalExtensions();
+
+ // call into the driver
+ VkDevice dev;
+ result = instance_data.driver.CreateDevice(
+ physicalDevice, static_cast<const VkDeviceCreateInfo*>(wrapper),
+ pAllocator, &dev);
+ if (result != VK_SUCCESS) {
+ FreeDeviceData(data, data_allocator);
+ return result;
+ }
+
+ // initialize DeviceDriverTable
+ if (!SetData(dev, *data) ||
+ !InitDriverTable(dev, instance_data.get_device_proc_addr)) {
+ data->driver.DestroyDevice = reinterpret_cast<PFN_vkDestroyDevice>(
+ instance_data.get_device_proc_addr(dev, "vkDestroyDevice"));
+ if (data->driver.DestroyDevice)
+ data->driver.DestroyDevice(dev, pAllocator);
+
+ FreeDeviceData(data, data_allocator);
+
+ return VK_ERROR_INCOMPATIBLE_DRIVER;
+ }
+
+ *pDevice = dev;
+
+ return VK_SUCCESS;
+}
+
+void DestroyDevice(VkDevice device, const VkAllocationCallbacks* pAllocator) {
+ DeviceData& data = GetData(device);
+ data.driver.DestroyDevice(device, pAllocator);
+
+ VkAllocationCallbacks local_allocator;
+ if (!pAllocator) {
+ local_allocator = data.allocator;
+ pAllocator = &local_allocator;
+ }
+
+ FreeDeviceData(&data, *pAllocator);
+}
+
+VkResult EnumeratePhysicalDevices(VkInstance instance,
+ uint32_t* pPhysicalDeviceCount,
+ VkPhysicalDevice* pPhysicalDevices) {
+ const auto& data = GetData(instance);
+
+ VkResult result = data.driver.EnumeratePhysicalDevices(
+ instance, pPhysicalDeviceCount, pPhysicalDevices);
+ if ((result == VK_SUCCESS || result == VK_INCOMPLETE) && pPhysicalDevices) {
+ for (uint32_t i = 0; i < *pPhysicalDeviceCount; i++)
+ SetData(pPhysicalDevices[i], data);
+ }
+
+ return result;
+}
+
+void GetDeviceQueue(VkDevice device,
+ uint32_t queueFamilyIndex,
+ uint32_t queueIndex,
+ VkQueue* pQueue) {
+ const auto& data = GetData(device);
+
+ data.driver.GetDeviceQueue(device, queueFamilyIndex, queueIndex, pQueue);
+ SetData(*pQueue, data);
+}
+
+VKAPI_ATTR VkResult
+AllocateCommandBuffers(VkDevice device,
+ const VkCommandBufferAllocateInfo* pAllocateInfo,
+ VkCommandBuffer* pCommandBuffers) {
+ const auto& data = GetData(device);
+
+ VkResult result = data.driver.AllocateCommandBuffers(device, pAllocateInfo,
+ pCommandBuffers);
+ if (result == VK_SUCCESS) {
+ for (uint32_t i = 0; i < pAllocateInfo->commandBufferCount; i++)
+ SetData(pCommandBuffers[i], data);
+ }
+
+ return result;
+}
+
+} // namespace driver
+} // namespace vulkan
diff --git a/vulkan/libvulkan/driver.h b/vulkan/libvulkan/driver.h
index de9d1c6..22db93f 100644
--- a/vulkan/libvulkan/driver.h
+++ b/vulkan/libvulkan/driver.h
@@ -18,6 +18,7 @@
#define LIBVULKAN_DRIVER_H 1
#include <inttypes.h>
+#include <bitset>
#include <type_traits>
#include <log/log.h>
@@ -25,6 +26,9 @@
#include <hardware/hwvulkan.h>
#include "api_gen.h"
+#include "driver_gen.h"
+#include "debug_report.h"
+#include "swapchain.h"
namespace vulkan {
@@ -61,15 +65,43 @@
namespace driver {
struct InstanceData {
+ InstanceData(const VkAllocationCallbacks& alloc)
+ : opaque_api_data(),
+ allocator(alloc),
+ driver(),
+ get_device_proc_addr(nullptr) {
+ hook_extensions.set(ProcHook::EXTENSION_CORE);
+ hal_extensions.set(ProcHook::EXTENSION_CORE);
+ }
+
api::InstanceData opaque_api_data;
const VkAllocationCallbacks allocator;
+
+ std::bitset<ProcHook::EXTENSION_COUNT> hook_extensions;
+ std::bitset<ProcHook::EXTENSION_COUNT> hal_extensions;
+
+ InstanceDriverTable driver;
+ PFN_vkGetDeviceProcAddr get_device_proc_addr;
+
+ DebugReportCallbackList debug_report_callbacks;
};
struct DeviceData {
+ DeviceData(const VkAllocationCallbacks& alloc)
+ : opaque_api_data(), allocator(alloc), driver() {
+ hook_extensions.set(ProcHook::EXTENSION_CORE);
+ hal_extensions.set(ProcHook::EXTENSION_CORE);
+ }
+
api::DeviceData opaque_api_data;
const VkAllocationCallbacks allocator;
+
+ std::bitset<ProcHook::EXTENSION_COUNT> hook_extensions;
+ std::bitset<ProcHook::EXTENSION_COUNT> hal_extensions;
+
+ DeviceDriverTable driver;
};
bool Debuggable();
@@ -80,6 +112,17 @@
VKAPI_ATTR PFN_vkVoidFunction GetInstanceProcAddr(VkInstance instance, const char* pName);
VKAPI_ATTR PFN_vkVoidFunction GetDeviceProcAddr(VkDevice device, const char* pName);
VKAPI_ATTR VkResult EnumerateInstanceExtensionProperties(const char* pLayerName, uint32_t* pPropertyCount, VkExtensionProperties* pProperties);
+
+VKAPI_ATTR VkResult EnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice, const char* pLayerName, uint32_t* pPropertyCount, VkExtensionProperties* pProperties);
+
+VKAPI_ATTR VkResult CreateInstance(const VkInstanceCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkInstance* pInstance);
+VKAPI_ATTR void DestroyInstance(VkInstance instance, const VkAllocationCallbacks* pAllocator);
+VKAPI_ATTR VkResult CreateDevice(VkPhysicalDevice physicalDevice, const VkDeviceCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDevice* pDevice);
+VKAPI_ATTR void DestroyDevice(VkDevice device, const VkAllocationCallbacks* pAllocator);
+
+VKAPI_ATTR VkResult EnumeratePhysicalDevices(VkInstance instance, uint32_t* pPhysicalDeviceCount, VkPhysicalDevice* pPhysicalDevices);
+VKAPI_ATTR void GetDeviceQueue(VkDevice device, uint32_t queueFamilyIndex, uint32_t queueIndex, VkQueue* pQueue);
+VKAPI_ATTR VkResult AllocateCommandBuffers(VkDevice device, const VkCommandBufferAllocateInfo* pAllocateInfo, VkCommandBuffer* pCommandBuffers);
// clang-format on
template <typename DispatchableType>
diff --git a/vulkan/libvulkan/driver_gen.cpp b/vulkan/libvulkan/driver_gen.cpp
new file mode 100644
index 0000000..8b816ba
--- /dev/null
+++ b/vulkan/libvulkan/driver_gen.cpp
@@ -0,0 +1,431 @@
+/*
+ * Copyright 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.
+ */
+
+// WARNING: This file is generated. See ../README.md for instructions.
+
+#include <string.h>
+#include <algorithm>
+#include <log/log.h>
+
+#include "driver.h"
+
+namespace vulkan {
+namespace driver {
+
+namespace {
+
+// clang-format off
+
+VKAPI_ATTR void disabledDestroySurfaceKHR(VkInstance, VkSurfaceKHR, const VkAllocationCallbacks*) {
+ ALOGE("VK_KHR_surface not enabled. vkDestroySurfaceKHR not executed.");
+}
+
+VKAPI_ATTR VkResult disabledGetPhysicalDeviceSurfaceSupportKHR(VkPhysicalDevice, uint32_t, VkSurfaceKHR, VkBool32*) {
+ ALOGE("VK_KHR_surface not enabled. vkGetPhysicalDeviceSurfaceSupportKHR not executed.");
+ return VK_SUCCESS;
+}
+
+VKAPI_ATTR VkResult disabledGetPhysicalDeviceSurfaceCapabilitiesKHR(VkPhysicalDevice, VkSurfaceKHR, VkSurfaceCapabilitiesKHR*) {
+ ALOGE("VK_KHR_surface not enabled. vkGetPhysicalDeviceSurfaceCapabilitiesKHR not executed.");
+ return VK_SUCCESS;
+}
+
+VKAPI_ATTR VkResult disabledGetPhysicalDeviceSurfaceFormatsKHR(VkPhysicalDevice, VkSurfaceKHR, uint32_t*, VkSurfaceFormatKHR*) {
+ ALOGE("VK_KHR_surface not enabled. vkGetPhysicalDeviceSurfaceFormatsKHR not executed.");
+ return VK_SUCCESS;
+}
+
+VKAPI_ATTR VkResult disabledGetPhysicalDeviceSurfacePresentModesKHR(VkPhysicalDevice, VkSurfaceKHR, uint32_t*, VkPresentModeKHR*) {
+ ALOGE("VK_KHR_surface not enabled. vkGetPhysicalDeviceSurfacePresentModesKHR not executed.");
+ return VK_SUCCESS;
+}
+
+VKAPI_ATTR VkResult disabledCreateSwapchainKHR(VkDevice, const VkSwapchainCreateInfoKHR*, const VkAllocationCallbacks*, VkSwapchainKHR*) {
+ ALOGE("VK_KHR_swapchain not enabled. vkCreateSwapchainKHR not executed.");
+ return VK_SUCCESS;
+}
+
+VKAPI_ATTR VkResult checkedCreateSwapchainKHR(VkDevice device, const VkSwapchainCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSwapchainKHR* pSwapchain) {
+ return (GetData(device).hook_extensions[ProcHook::KHR_swapchain]) ? CreateSwapchainKHR(device, pCreateInfo, pAllocator, pSwapchain) : disabledCreateSwapchainKHR(device, pCreateInfo, pAllocator, pSwapchain);
+}
+
+VKAPI_ATTR void disabledDestroySwapchainKHR(VkDevice, VkSwapchainKHR, const VkAllocationCallbacks*) {
+ ALOGE("VK_KHR_swapchain not enabled. vkDestroySwapchainKHR not executed.");
+}
+
+VKAPI_ATTR void checkedDestroySwapchainKHR(VkDevice device, VkSwapchainKHR swapchain, const VkAllocationCallbacks* pAllocator) {
+ (GetData(device).hook_extensions[ProcHook::KHR_swapchain]) ? DestroySwapchainKHR(device, swapchain, pAllocator) : disabledDestroySwapchainKHR(device, swapchain, pAllocator);
+}
+
+VKAPI_ATTR VkResult disabledGetSwapchainImagesKHR(VkDevice, VkSwapchainKHR, uint32_t*, VkImage*) {
+ ALOGE("VK_KHR_swapchain not enabled. vkGetSwapchainImagesKHR not executed.");
+ return VK_SUCCESS;
+}
+
+VKAPI_ATTR VkResult checkedGetSwapchainImagesKHR(VkDevice device, VkSwapchainKHR swapchain, uint32_t* pSwapchainImageCount, VkImage* pSwapchainImages) {
+ return (GetData(device).hook_extensions[ProcHook::KHR_swapchain]) ? GetSwapchainImagesKHR(device, swapchain, pSwapchainImageCount, pSwapchainImages) : disabledGetSwapchainImagesKHR(device, swapchain, pSwapchainImageCount, pSwapchainImages);
+}
+
+VKAPI_ATTR VkResult disabledAcquireNextImageKHR(VkDevice, VkSwapchainKHR, uint64_t, VkSemaphore, VkFence, uint32_t*) {
+ ALOGE("VK_KHR_swapchain not enabled. vkAcquireNextImageKHR not executed.");
+ return VK_SUCCESS;
+}
+
+VKAPI_ATTR VkResult checkedAcquireNextImageKHR(VkDevice device, VkSwapchainKHR swapchain, uint64_t timeout, VkSemaphore semaphore, VkFence fence, uint32_t* pImageIndex) {
+ return (GetData(device).hook_extensions[ProcHook::KHR_swapchain]) ? AcquireNextImageKHR(device, swapchain, timeout, semaphore, fence, pImageIndex) : disabledAcquireNextImageKHR(device, swapchain, timeout, semaphore, fence, pImageIndex);
+}
+
+VKAPI_ATTR VkResult disabledQueuePresentKHR(VkQueue, const VkPresentInfoKHR*) {
+ ALOGE("VK_KHR_swapchain not enabled. vkQueuePresentKHR not executed.");
+ return VK_SUCCESS;
+}
+
+VKAPI_ATTR VkResult checkedQueuePresentKHR(VkQueue queue, const VkPresentInfoKHR* pPresentInfo) {
+ return (GetData(queue).hook_extensions[ProcHook::KHR_swapchain]) ? QueuePresentKHR(queue, pPresentInfo) : disabledQueuePresentKHR(queue, pPresentInfo);
+}
+
+VKAPI_ATTR VkResult disabledCreateAndroidSurfaceKHR(VkInstance, const VkAndroidSurfaceCreateInfoKHR*, const VkAllocationCallbacks*, VkSurfaceKHR*) {
+ ALOGE("VK_KHR_android_surface not enabled. vkCreateAndroidSurfaceKHR not executed.");
+ return VK_SUCCESS;
+}
+
+VKAPI_ATTR VkResult disabledCreateDebugReportCallbackEXT(VkInstance, const VkDebugReportCallbackCreateInfoEXT*, const VkAllocationCallbacks*, VkDebugReportCallbackEXT*) {
+ ALOGE("VK_EXT_debug_report not enabled. vkCreateDebugReportCallbackEXT not executed.");
+ return VK_SUCCESS;
+}
+
+VKAPI_ATTR void disabledDestroyDebugReportCallbackEXT(VkInstance, VkDebugReportCallbackEXT, const VkAllocationCallbacks*) {
+ ALOGE("VK_EXT_debug_report not enabled. vkDestroyDebugReportCallbackEXT not executed.");
+}
+
+VKAPI_ATTR void disabledDebugReportMessageEXT(VkInstance, VkDebugReportFlagsEXT, VkDebugReportObjectTypeEXT, uint64_t, size_t, int32_t, const char*, const char*) {
+ ALOGE("VK_EXT_debug_report not enabled. vkDebugReportMessageEXT not executed.");
+}
+
+// clang-format on
+
+const ProcHook g_proc_hooks[] = {
+ // clang-format off
+ {
+ "vkAcquireImageANDROID",
+ ProcHook::DEVICE,
+ ProcHook::ANDROID_native_buffer,
+ nullptr,
+ nullptr,
+ nullptr,
+ },
+ {
+ "vkAcquireNextImageKHR",
+ ProcHook::DEVICE,
+ ProcHook::KHR_swapchain,
+ reinterpret_cast<PFN_vkVoidFunction>(AcquireNextImageKHR),
+ reinterpret_cast<PFN_vkVoidFunction>(disabledAcquireNextImageKHR),
+ reinterpret_cast<PFN_vkVoidFunction>(checkedAcquireNextImageKHR),
+ },
+ {
+ "vkAllocateCommandBuffers",
+ ProcHook::DEVICE,
+ ProcHook::EXTENSION_CORE,
+ reinterpret_cast<PFN_vkVoidFunction>(AllocateCommandBuffers),
+ nullptr,
+ nullptr,
+ },
+ {
+ "vkCreateAndroidSurfaceKHR",
+ ProcHook::INSTANCE,
+ ProcHook::KHR_android_surface,
+ reinterpret_cast<PFN_vkVoidFunction>(CreateAndroidSurfaceKHR),
+ reinterpret_cast<PFN_vkVoidFunction>(disabledCreateAndroidSurfaceKHR),
+ nullptr,
+ },
+ {
+ "vkCreateDebugReportCallbackEXT",
+ ProcHook::INSTANCE,
+ ProcHook::EXT_debug_report,
+ reinterpret_cast<PFN_vkVoidFunction>(CreateDebugReportCallbackEXT),
+ reinterpret_cast<PFN_vkVoidFunction>(disabledCreateDebugReportCallbackEXT),
+ nullptr,
+ },
+ {
+ "vkCreateDevice",
+ ProcHook::INSTANCE,
+ ProcHook::EXTENSION_CORE,
+ reinterpret_cast<PFN_vkVoidFunction>(CreateDevice),
+ nullptr,
+ nullptr,
+ },
+ {
+ "vkCreateInstance",
+ ProcHook::GLOBAL,
+ ProcHook::EXTENSION_CORE,
+ reinterpret_cast<PFN_vkVoidFunction>(CreateInstance),
+ nullptr,
+ nullptr,
+ },
+ {
+ "vkCreateSwapchainKHR",
+ ProcHook::DEVICE,
+ ProcHook::KHR_swapchain,
+ reinterpret_cast<PFN_vkVoidFunction>(CreateSwapchainKHR),
+ reinterpret_cast<PFN_vkVoidFunction>(disabledCreateSwapchainKHR),
+ reinterpret_cast<PFN_vkVoidFunction>(checkedCreateSwapchainKHR),
+ },
+ {
+ "vkDebugReportMessageEXT",
+ ProcHook::INSTANCE,
+ ProcHook::EXT_debug_report,
+ reinterpret_cast<PFN_vkVoidFunction>(DebugReportMessageEXT),
+ reinterpret_cast<PFN_vkVoidFunction>(disabledDebugReportMessageEXT),
+ nullptr,
+ },
+ {
+ "vkDestroyDebugReportCallbackEXT",
+ ProcHook::INSTANCE,
+ ProcHook::EXT_debug_report,
+ reinterpret_cast<PFN_vkVoidFunction>(DestroyDebugReportCallbackEXT),
+ reinterpret_cast<PFN_vkVoidFunction>(disabledDestroyDebugReportCallbackEXT),
+ nullptr,
+ },
+ {
+ "vkDestroyDevice",
+ ProcHook::DEVICE,
+ ProcHook::EXTENSION_CORE,
+ reinterpret_cast<PFN_vkVoidFunction>(DestroyDevice),
+ nullptr,
+ nullptr,
+ },
+ {
+ "vkDestroyInstance",
+ ProcHook::INSTANCE,
+ ProcHook::EXTENSION_CORE,
+ reinterpret_cast<PFN_vkVoidFunction>(DestroyInstance),
+ nullptr,
+ nullptr,
+ },
+ {
+ "vkDestroySurfaceKHR",
+ ProcHook::INSTANCE,
+ ProcHook::KHR_surface,
+ reinterpret_cast<PFN_vkVoidFunction>(DestroySurfaceKHR),
+ reinterpret_cast<PFN_vkVoidFunction>(disabledDestroySurfaceKHR),
+ nullptr,
+ },
+ {
+ "vkDestroySwapchainKHR",
+ ProcHook::DEVICE,
+ ProcHook::KHR_swapchain,
+ reinterpret_cast<PFN_vkVoidFunction>(DestroySwapchainKHR),
+ reinterpret_cast<PFN_vkVoidFunction>(disabledDestroySwapchainKHR),
+ reinterpret_cast<PFN_vkVoidFunction>(checkedDestroySwapchainKHR),
+ },
+ {
+ "vkEnumerateDeviceExtensionProperties",
+ ProcHook::INSTANCE,
+ ProcHook::EXTENSION_CORE,
+ reinterpret_cast<PFN_vkVoidFunction>(EnumerateDeviceExtensionProperties),
+ nullptr,
+ nullptr,
+ },
+ {
+ "vkEnumerateInstanceExtensionProperties",
+ ProcHook::GLOBAL,
+ ProcHook::EXTENSION_CORE,
+ reinterpret_cast<PFN_vkVoidFunction>(EnumerateInstanceExtensionProperties),
+ nullptr,
+ nullptr,
+ },
+ {
+ "vkEnumeratePhysicalDevices",
+ ProcHook::INSTANCE,
+ ProcHook::EXTENSION_CORE,
+ reinterpret_cast<PFN_vkVoidFunction>(EnumeratePhysicalDevices),
+ nullptr,
+ nullptr,
+ },
+ {
+ "vkGetDeviceProcAddr",
+ ProcHook::DEVICE,
+ ProcHook::EXTENSION_CORE,
+ reinterpret_cast<PFN_vkVoidFunction>(GetDeviceProcAddr),
+ nullptr,
+ nullptr,
+ },
+ {
+ "vkGetDeviceQueue",
+ ProcHook::DEVICE,
+ ProcHook::EXTENSION_CORE,
+ reinterpret_cast<PFN_vkVoidFunction>(GetDeviceQueue),
+ nullptr,
+ nullptr,
+ },
+ {
+ "vkGetInstanceProcAddr",
+ ProcHook::INSTANCE,
+ ProcHook::EXTENSION_CORE,
+ reinterpret_cast<PFN_vkVoidFunction>(GetInstanceProcAddr),
+ nullptr,
+ nullptr,
+ },
+ {
+ "vkGetPhysicalDeviceSurfaceCapabilitiesKHR",
+ ProcHook::INSTANCE,
+ ProcHook::KHR_surface,
+ reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceSurfaceCapabilitiesKHR),
+ reinterpret_cast<PFN_vkVoidFunction>(disabledGetPhysicalDeviceSurfaceCapabilitiesKHR),
+ nullptr,
+ },
+ {
+ "vkGetPhysicalDeviceSurfaceFormatsKHR",
+ ProcHook::INSTANCE,
+ ProcHook::KHR_surface,
+ reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceSurfaceFormatsKHR),
+ reinterpret_cast<PFN_vkVoidFunction>(disabledGetPhysicalDeviceSurfaceFormatsKHR),
+ nullptr,
+ },
+ {
+ "vkGetPhysicalDeviceSurfacePresentModesKHR",
+ ProcHook::INSTANCE,
+ ProcHook::KHR_surface,
+ reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceSurfacePresentModesKHR),
+ reinterpret_cast<PFN_vkVoidFunction>(disabledGetPhysicalDeviceSurfacePresentModesKHR),
+ nullptr,
+ },
+ {
+ "vkGetPhysicalDeviceSurfaceSupportKHR",
+ ProcHook::INSTANCE,
+ ProcHook::KHR_surface,
+ reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceSurfaceSupportKHR),
+ reinterpret_cast<PFN_vkVoidFunction>(disabledGetPhysicalDeviceSurfaceSupportKHR),
+ nullptr,
+ },
+ {
+ "vkGetSwapchainGrallocUsageANDROID",
+ ProcHook::DEVICE,
+ ProcHook::ANDROID_native_buffer,
+ nullptr,
+ nullptr,
+ nullptr,
+ },
+ {
+ "vkGetSwapchainImagesKHR",
+ ProcHook::DEVICE,
+ ProcHook::KHR_swapchain,
+ reinterpret_cast<PFN_vkVoidFunction>(GetSwapchainImagesKHR),
+ reinterpret_cast<PFN_vkVoidFunction>(disabledGetSwapchainImagesKHR),
+ reinterpret_cast<PFN_vkVoidFunction>(checkedGetSwapchainImagesKHR),
+ },
+ {
+ "vkQueuePresentKHR",
+ ProcHook::DEVICE,
+ ProcHook::KHR_swapchain,
+ reinterpret_cast<PFN_vkVoidFunction>(QueuePresentKHR),
+ reinterpret_cast<PFN_vkVoidFunction>(disabledQueuePresentKHR),
+ reinterpret_cast<PFN_vkVoidFunction>(checkedQueuePresentKHR),
+ },
+ {
+ "vkQueueSignalReleaseImageANDROID",
+ ProcHook::DEVICE,
+ ProcHook::ANDROID_native_buffer,
+ nullptr,
+ nullptr,
+ nullptr,
+ },
+ // clang-format on
+};
+
+} // anonymous
+
+const ProcHook* GetProcHook(const char* name) {
+ const auto& begin = g_proc_hooks;
+ const auto& end =
+ g_proc_hooks + sizeof(g_proc_hooks) / sizeof(g_proc_hooks[0]);
+ const auto hook = std::lower_bound(
+ begin, end, name,
+ [](const ProcHook& e, const char* n) { return strcmp(e.name, n) < 0; });
+ return (hook < end && strcmp(hook->name, name) == 0) ? hook : nullptr;
+}
+
+ProcHook::Extension GetProcHookExtension(const char* name) {
+ // clang-format off
+ if (strcmp(name, "VK_ANDROID_native_buffer") == 0) return ProcHook::ANDROID_native_buffer;
+ if (strcmp(name, "VK_EXT_debug_report") == 0) return ProcHook::EXT_debug_report;
+ if (strcmp(name, "VK_KHR_android_surface") == 0) return ProcHook::KHR_android_surface;
+ if (strcmp(name, "VK_KHR_surface") == 0) return ProcHook::KHR_surface;
+ if (strcmp(name, "VK_KHR_swapchain") == 0) return ProcHook::KHR_swapchain;
+ // clang-format on
+ return ProcHook::EXTENSION_UNKNOWN;
+}
+
+#define UNLIKELY(expr) __builtin_expect((expr), 0)
+
+#define INIT_PROC(obj, proc) \
+ do { \
+ data.driver.proc = \
+ reinterpret_cast<PFN_vk##proc>(get_proc(obj, "vk" #proc)); \
+ if (UNLIKELY(!data.driver.proc)) { \
+ ALOGE("missing " #obj " proc: vk" #proc); \
+ success = false; \
+ } \
+ } while (0)
+
+#define INIT_PROC_EXT(ext, obj, proc) \
+ do { \
+ if (data.hal_extensions[ProcHook::ext]) \
+ INIT_PROC(obj, proc); \
+ } while (0)
+
+bool InitDriverTable(VkInstance instance, PFN_vkGetInstanceProcAddr get_proc) {
+ auto& data = GetData(instance);
+ bool success = true;
+
+ // clang-format off
+ INIT_PROC(instance, DestroyInstance);
+ INIT_PROC(instance, EnumeratePhysicalDevices);
+ INIT_PROC(instance, GetInstanceProcAddr);
+ INIT_PROC(instance, CreateDevice);
+ INIT_PROC(instance, EnumerateDeviceLayerProperties);
+ INIT_PROC(instance, EnumerateDeviceExtensionProperties);
+ INIT_PROC_EXT(EXT_debug_report, instance, CreateDebugReportCallbackEXT);
+ INIT_PROC_EXT(EXT_debug_report, instance, DestroyDebugReportCallbackEXT);
+ INIT_PROC_EXT(EXT_debug_report, instance, DebugReportMessageEXT);
+ // clang-format on
+
+ return success;
+}
+
+bool InitDriverTable(VkDevice dev, PFN_vkGetDeviceProcAddr get_proc) {
+ auto& data = GetData(dev);
+ bool success = true;
+
+ // clang-format off
+ INIT_PROC(dev, GetDeviceProcAddr);
+ INIT_PROC(dev, DestroyDevice);
+ INIT_PROC(dev, GetDeviceQueue);
+ INIT_PROC(dev, CreateImage);
+ INIT_PROC(dev, DestroyImage);
+ INIT_PROC(dev, AllocateCommandBuffers);
+ INIT_PROC_EXT(ANDROID_native_buffer, dev, GetSwapchainGrallocUsageANDROID);
+ INIT_PROC_EXT(ANDROID_native_buffer, dev, AcquireImageANDROID);
+ INIT_PROC_EXT(ANDROID_native_buffer, dev, QueueSignalReleaseImageANDROID);
+ // clang-format on
+
+ return success;
+}
+
+} // namespace driver
+} // namespace vulkan
+
+// clang-format on
diff --git a/vulkan/libvulkan/driver_gen.h b/vulkan/libvulkan/driver_gen.h
new file mode 100644
index 0000000..1eb7d79
--- /dev/null
+++ b/vulkan/libvulkan/driver_gen.h
@@ -0,0 +1,92 @@
+/*
+ * Copyright 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.
+ */
+
+// WARNING: This file is generated. See ../README.md for instructions.
+
+#ifndef LIBVULKAN_DRIVER_GEN_H
+#define LIBVULKAN_DRIVER_GEN_H
+
+#include <vulkan/vulkan.h>
+#include <vulkan/vk_android_native_buffer.h>
+
+namespace vulkan {
+namespace driver {
+
+struct ProcHook {
+ enum Type {
+ GLOBAL,
+ INSTANCE,
+ DEVICE,
+ };
+ enum Extension {
+ ANDROID_native_buffer,
+ EXT_debug_report,
+ KHR_android_surface,
+ KHR_surface,
+ KHR_swapchain,
+
+ EXTENSION_CORE, // valid bit
+ EXTENSION_COUNT,
+ EXTENSION_UNKNOWN,
+ };
+
+ const char* name;
+ Type type;
+ Extension extension;
+
+ PFN_vkVoidFunction proc;
+ PFN_vkVoidFunction disabled_proc; // nullptr for global hooks
+ PFN_vkVoidFunction checked_proc; // nullptr for global/instance hooks
+};
+
+struct InstanceDriverTable {
+ // clang-format off
+ PFN_vkDestroyInstance DestroyInstance;
+ PFN_vkEnumeratePhysicalDevices EnumeratePhysicalDevices;
+ PFN_vkGetInstanceProcAddr GetInstanceProcAddr;
+ PFN_vkCreateDevice CreateDevice;
+ PFN_vkEnumerateDeviceLayerProperties EnumerateDeviceLayerProperties;
+ PFN_vkEnumerateDeviceExtensionProperties EnumerateDeviceExtensionProperties;
+ PFN_vkCreateDebugReportCallbackEXT CreateDebugReportCallbackEXT;
+ PFN_vkDestroyDebugReportCallbackEXT DestroyDebugReportCallbackEXT;
+ PFN_vkDebugReportMessageEXT DebugReportMessageEXT;
+ // clang-format on
+};
+
+struct DeviceDriverTable {
+ // clang-format off
+ PFN_vkGetDeviceProcAddr GetDeviceProcAddr;
+ PFN_vkDestroyDevice DestroyDevice;
+ PFN_vkGetDeviceQueue GetDeviceQueue;
+ PFN_vkCreateImage CreateImage;
+ PFN_vkDestroyImage DestroyImage;
+ PFN_vkAllocateCommandBuffers AllocateCommandBuffers;
+ PFN_vkGetSwapchainGrallocUsageANDROID GetSwapchainGrallocUsageANDROID;
+ PFN_vkAcquireImageANDROID AcquireImageANDROID;
+ PFN_vkQueueSignalReleaseImageANDROID QueueSignalReleaseImageANDROID;
+ // clang-format on
+};
+
+const ProcHook* GetProcHook(const char* name);
+ProcHook::Extension GetProcHookExtension(const char* name);
+
+bool InitDriverTable(VkInstance instance, PFN_vkGetInstanceProcAddr get_proc);
+bool InitDriverTable(VkDevice dev, PFN_vkGetDeviceProcAddr get_proc);
+
+} // namespace driver
+} // namespace vulkan
+
+#endif // LIBVULKAN_DRIVER_TABLE_H
diff --git a/vulkan/libvulkan/layers_extensions.cpp b/vulkan/libvulkan/layers_extensions.cpp
index aec0fd0..6b53a9a 100644
--- a/vulkan/libvulkan/layers_extensions.cpp
+++ b/vulkan/libvulkan/layers_extensions.cpp
@@ -16,7 +16,7 @@
// #define LOG_NDEBUG 0
-#include "loader.h"
+#include "layers_extensions.h"
#include <alloca.h>
#include <dirent.h>
#include <dlfcn.h>
@@ -28,8 +28,6 @@
#include <log/log.h>
#include <vulkan/vulkan_loader_data.h>
-using namespace vulkan;
-
// TODO(jessehall): The whole way we deal with extensions is pretty hokey, and
// not a good long-term solution. Having a hard-coded enum of extensions is
// bad, of course. Representing sets of extensions (requested, supported, etc.)
@@ -50,12 +48,13 @@
// with a mask saying what kind(s) it is.
namespace vulkan {
+namespace api {
+
struct Layer {
VkLayerProperties properties;
size_t library_idx;
std::vector<VkExtensionProperties> extensions;
};
-} // namespace vulkan
namespace {
@@ -341,8 +340,6 @@
} // anonymous namespace
-namespace vulkan {
-
void DiscoverLayers() {
if (prctl(PR_GET_DUMPABLE, 0, 0, 0, 0))
DiscoverLayersInDirectory("/data/local/debug/vulkan");
@@ -425,22 +422,5 @@
}) != layer_->extensions.cend();
}
-InstanceExtension InstanceExtensionFromName(const char* name) {
- if (strcmp(name, VK_KHR_SURFACE_EXTENSION_NAME) == 0)
- return kKHR_surface;
- if (strcmp(name, VK_KHR_ANDROID_SURFACE_EXTENSION_NAME) == 0)
- return kKHR_android_surface;
- if (strcmp(name, VK_EXT_DEBUG_REPORT_EXTENSION_NAME) == 0)
- return kEXT_debug_report;
- return kInstanceExtensionCount;
-}
-
-DeviceExtension DeviceExtensionFromName(const char* name) {
- if (strcmp(name, VK_KHR_SWAPCHAIN_EXTENSION_NAME) == 0)
- return kKHR_swapchain;
- if (strcmp(name, VK_ANDROID_NATIVE_BUFFER_EXTENSION_NAME) == 0)
- return kANDROID_native_buffer;
- return kDeviceExtensionCount;
-}
-
+} // namespace api
} // namespace vulkan
diff --git a/vulkan/libvulkan/layers_extensions.h b/vulkan/libvulkan/layers_extensions.h
new file mode 100644
index 0000000..7e7bfd3
--- /dev/null
+++ b/vulkan/libvulkan/layers_extensions.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2015 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 LIBVULKAN_LAYERS_EXTENSIONS_H
+#define LIBVULKAN_LAYERS_EXTENSIONS_H 1
+
+#include <vulkan/vulkan.h>
+
+namespace vulkan {
+namespace api {
+
+struct Layer;
+class LayerRef {
+ public:
+ LayerRef(Layer* layer);
+ LayerRef(LayerRef&& other);
+ ~LayerRef();
+ LayerRef(const LayerRef&) = delete;
+ LayerRef& operator=(const LayerRef&) = delete;
+
+ const char* GetName() const;
+ uint32_t GetSpecVersion();
+
+ // provides bool-like behavior
+ operator const Layer*() const { return layer_; }
+
+ PFN_vkGetInstanceProcAddr GetGetInstanceProcAddr() const;
+ PFN_vkGetDeviceProcAddr GetGetDeviceProcAddr() const;
+
+ bool SupportsExtension(const char* name) const;
+
+ private:
+ Layer* layer_;
+};
+
+void DiscoverLayers();
+uint32_t EnumerateInstanceLayers(uint32_t count, VkLayerProperties* properties);
+uint32_t EnumerateDeviceLayers(uint32_t count, VkLayerProperties* properties);
+void GetInstanceLayerExtensions(const char* name,
+ const VkExtensionProperties** properties,
+ uint32_t* count);
+void GetDeviceLayerExtensions(const char* name,
+ const VkExtensionProperties** properties,
+ uint32_t* count);
+LayerRef GetInstanceLayerRef(const char* name);
+LayerRef GetDeviceLayerRef(const char* name);
+
+} // namespace api
+} // namespace vulkan
+
+#endif // LIBVULKAN_LAYERS_EXTENSIONS_H
diff --git a/vulkan/libvulkan/loader.cpp b/vulkan/libvulkan/loader.cpp
deleted file mode 100644
index 65b09db..0000000
--- a/vulkan/libvulkan/loader.cpp
+++ /dev/null
@@ -1,1045 +0,0 @@
-/*
- * Copyright 2015 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.
- */
-
-// module header
-#include "loader.h"
-#include "driver.h"
-// standard C headers
-#include <dirent.h>
-#include <dlfcn.h>
-#include <inttypes.h>
-#include <pthread.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/prctl.h>
-// standard C++ headers
-#include <algorithm>
-#include <mutex>
-#include <sstream>
-#include <string>
-#include <unordered_map>
-#include <vector>
-// platform/library headers
-#include <cutils/properties.h>
-#include <hardware/hwvulkan.h>
-#include <log/log.h>
-#include <vulkan/vulkan_loader_data.h>
-#include <vulkan/vk_layer_interface.h>
-
-// #define ENABLE_ALLOC_CALLSTACKS 1
-#if ENABLE_ALLOC_CALLSTACKS
-#include <utils/CallStack.h>
-#define ALOGD_CALLSTACK(...) \
- do { \
- ALOGD(__VA_ARGS__); \
- android::CallStack callstack; \
- callstack.update(); \
- callstack.log(LOG_TAG, ANDROID_LOG_DEBUG, " "); \
- } while (false)
-#else
-#define ALOGD_CALLSTACK(...) \
- do { \
- } while (false)
-#endif
-
-using namespace vulkan;
-
-static const uint32_t kMaxPhysicalDevices = 4;
-
-namespace {
-
-// ----------------------------------------------------------------------------
-
-// Standard-library allocator that delegates to VkAllocationCallbacks.
-//
-// TODO(jessehall): This class currently always uses
-// VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE. The scope to use could be a template
-// parameter or a constructor parameter. The former would help catch bugs
-// where we use the wrong scope, e.g. adding a command-scope string to an
-// instance-scope vector. But that might also be pretty annoying to deal with.
-template <class T>
-class CallbackAllocator {
- public:
- typedef T value_type;
-
- CallbackAllocator(const VkAllocationCallbacks* alloc_input)
- : alloc(alloc_input) {}
-
- template <class T2>
- CallbackAllocator(const CallbackAllocator<T2>& other)
- : alloc(other.alloc) {}
-
- T* allocate(std::size_t n) {
- void* mem =
- alloc->pfnAllocation(alloc->pUserData, n * sizeof(T), alignof(T),
- VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
- if (!mem)
- throw std::bad_alloc();
- return static_cast<T*>(mem);
- }
-
- void deallocate(T* array, std::size_t /*n*/) noexcept {
- alloc->pfnFree(alloc->pUserData, array);
- }
-
- const VkAllocationCallbacks* alloc;
-};
-// These are needed in order to move Strings
-template <class T>
-bool operator==(const CallbackAllocator<T>& alloc1,
- const CallbackAllocator<T>& alloc2) {
- return alloc1.alloc == alloc2.alloc;
-}
-template <class T>
-bool operator!=(const CallbackAllocator<T>& alloc1,
- const CallbackAllocator<T>& alloc2) {
- return !(alloc1 == alloc2);
-}
-
-template <class T>
-using Vector = std::vector<T, CallbackAllocator<T>>;
-
-typedef std::basic_string<char, std::char_traits<char>, CallbackAllocator<char>>
- String;
-
-// ----------------------------------------------------------------------------
-
-VKAPI_ATTR void* DefaultAllocate(void*,
- size_t size,
- size_t alignment,
- VkSystemAllocationScope) {
- void* ptr = nullptr;
- // Vulkan requires 'alignment' to be a power of two, but posix_memalign
- // additionally requires that it be at least sizeof(void*).
- int ret = posix_memalign(&ptr, std::max(alignment, sizeof(void*)), size);
- ALOGD_CALLSTACK("Allocate: size=%zu align=%zu => (%d) %p", size, alignment,
- ret, ptr);
- return ret == 0 ? ptr : nullptr;
-}
-
-VKAPI_ATTR void* DefaultReallocate(void*,
- void* ptr,
- size_t size,
- size_t alignment,
- VkSystemAllocationScope) {
- if (size == 0) {
- free(ptr);
- return nullptr;
- }
-
- // TODO(jessehall): Right now we never shrink allocations; if the new
- // request is smaller than the existing chunk, we just continue using it.
- // Right now the loader never reallocs, so this doesn't matter. If that
- // changes, or if this code is copied into some other project, this should
- // probably have a heuristic to allocate-copy-free when doing so will save
- // "enough" space.
- size_t old_size = ptr ? malloc_usable_size(ptr) : 0;
- if (size <= old_size)
- return ptr;
-
- void* new_ptr = nullptr;
- if (posix_memalign(&new_ptr, std::max(alignment, sizeof(void*)), size) != 0)
- return nullptr;
- if (ptr) {
- memcpy(new_ptr, ptr, std::min(old_size, size));
- free(ptr);
- }
- return new_ptr;
-}
-
-VKAPI_ATTR void DefaultFree(void*, void* ptr) {
- ALOGD_CALLSTACK("Free: %p", ptr);
- free(ptr);
-}
-
-const VkAllocationCallbacks kDefaultAllocCallbacks = {
- .pUserData = nullptr,
- .pfnAllocation = DefaultAllocate,
- .pfnReallocation = DefaultReallocate,
- .pfnFree = DefaultFree,
-};
-
-// ----------------------------------------------------------------------------
-// Global Data and Initialization
-
-hwvulkan_device_t* g_hwdevice = nullptr;
-InstanceExtensionSet g_driver_instance_extensions;
-
-void LoadVulkanHAL() {
- static const hwvulkan_module_t* module;
- int result =
- hw_get_module("vulkan", reinterpret_cast<const hw_module_t**>(&module));
- if (result != 0) {
- ALOGE("failed to load vulkan hal: %s (%d)", strerror(-result), result);
- return;
- }
- result = module->common.methods->open(
- &module->common, HWVULKAN_DEVICE_0,
- reinterpret_cast<hw_device_t**>(&g_hwdevice));
- if (result != 0) {
- ALOGE("failed to open vulkan driver: %s (%d)", strerror(-result),
- result);
- module = nullptr;
- return;
- }
-
- VkResult vkresult;
- uint32_t count;
- if ((vkresult = g_hwdevice->EnumerateInstanceExtensionProperties(
- nullptr, &count, nullptr)) != VK_SUCCESS) {
- ALOGE("driver EnumerateInstanceExtensionProperties failed: %d",
- vkresult);
- g_hwdevice->common.close(&g_hwdevice->common);
- g_hwdevice = nullptr;
- module = nullptr;
- return;
- }
- VkExtensionProperties* extensions = static_cast<VkExtensionProperties*>(
- alloca(count * sizeof(VkExtensionProperties)));
- if ((vkresult = g_hwdevice->EnumerateInstanceExtensionProperties(
- nullptr, &count, extensions)) != VK_SUCCESS) {
- ALOGE("driver EnumerateInstanceExtensionProperties failed: %d",
- vkresult);
- g_hwdevice->common.close(&g_hwdevice->common);
- g_hwdevice = nullptr;
- module = nullptr;
- return;
- }
- ALOGV_IF(count > 0, "Driver-supported instance extensions:");
- for (uint32_t i = 0; i < count; i++) {
- ALOGV(" %s (v%u)", extensions[i].extensionName,
- extensions[i].specVersion);
- InstanceExtension id =
- InstanceExtensionFromName(extensions[i].extensionName);
- if (id != kInstanceExtensionCount)
- g_driver_instance_extensions.set(id);
- }
- // Ignore driver attempts to support loader extensions
- g_driver_instance_extensions.reset(kKHR_surface);
- g_driver_instance_extensions.reset(kKHR_android_surface);
-}
-
-// -----------------------------------------------------------------------------
-
-struct Instance {
- Instance(const VkAllocationCallbacks* alloc_callbacks)
- : base{{}, *alloc_callbacks},
- alloc(&base.allocator),
- num_physical_devices(0) {
- memset(physical_devices, 0, sizeof(physical_devices));
- enabled_extensions.reset();
- memset(&drv.dispatch, 0, sizeof(drv.dispatch));
- }
-
- ~Instance() {}
-
- driver::InstanceData base;
-
- const VkAllocationCallbacks* alloc;
- uint32_t num_physical_devices;
- VkPhysicalDevice physical_devices_top[kMaxPhysicalDevices];
- VkPhysicalDevice physical_devices[kMaxPhysicalDevices];
- DeviceExtensionSet physical_device_driver_extensions[kMaxPhysicalDevices];
-
- DebugReportCallbackList debug_report_callbacks;
- InstanceExtensionSet enabled_extensions;
-
- struct {
- DriverDispatchTable dispatch;
- } drv; // may eventually be an array
-};
-
-struct Device {
- Device(Instance* instance_)
- : base{{}, *instance_->alloc}, instance(instance_) {
- enabled_extensions.reset();
- }
-
- driver::DeviceData base;
-
- Instance* instance;
- PFN_vkGetDeviceProcAddr get_device_proc_addr;
- DeviceExtensionSet enabled_extensions;
-};
-
-template <typename THandle>
-struct HandleTraits {};
-template <>
-struct HandleTraits<VkInstance> {
- typedef Instance LoaderObjectType;
-};
-template <>
-struct HandleTraits<VkPhysicalDevice> {
- typedef Instance LoaderObjectType;
-};
-template <>
-struct HandleTraits<VkDevice> {
- typedef Device LoaderObjectType;
-};
-template <>
-struct HandleTraits<VkQueue> {
- typedef Device LoaderObjectType;
-};
-template <>
-struct HandleTraits<VkCommandBuffer> {
- typedef Device LoaderObjectType;
-};
-
-template <typename THandle>
-typename HandleTraits<THandle>::LoaderObjectType& GetDispatchParent(
- THandle handle) {
- // TODO(jessehall): Make Instance and Device POD types (by removing the
- // non-default constructors), so that offsetof is actually legal to use.
- // The specific case we're using here is safe in gcc/clang (and probably
- // most other C++ compilers), but isn't guaranteed by C++.
- typedef typename HandleTraits<THandle>::LoaderObjectType ObjectType;
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Winvalid-offsetof"
- const size_t kBaseOffset = offsetof(ObjectType, base);
-#pragma clang diagnostic pop
-
- const auto& base = driver::GetData(handle);
- uintptr_t base_addr = reinterpret_cast<uintptr_t>(&base);
- uintptr_t object_addr = base_addr - kBaseOffset;
- return *reinterpret_cast<ObjectType*>(object_addr);
-}
-
-// -----------------------------------------------------------------------------
-
-void DestroyDevice(Device* device, VkDevice vkdevice) {
- const auto& instance = *device->instance;
-
- if (vkdevice != VK_NULL_HANDLE)
- instance.drv.dispatch.DestroyDevice(vkdevice, instance.alloc);
-
- device->~Device();
- instance.alloc->pfnFree(instance.alloc->pUserData, device);
-}
-
-/*
- * This function will return the pNext pointer of any
- * CreateInfo extensions that are not loader extensions.
- * This is used to skip past the loader extensions prepended
- * to the list during CreateInstance and CreateDevice.
- */
-void* StripCreateExtensions(const void* pNext) {
- VkLayerInstanceCreateInfo* create_info =
- const_cast<VkLayerInstanceCreateInfo*>(
- static_cast<const VkLayerInstanceCreateInfo*>(pNext));
-
- while (
- create_info &&
- (create_info->sType == VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFO ||
- create_info->sType == VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFO)) {
- create_info = const_cast<VkLayerInstanceCreateInfo*>(
- static_cast<const VkLayerInstanceCreateInfo*>(create_info->pNext));
- }
-
- return create_info;
-}
-
-// Clean up and deallocate an Instance; called from both the failure paths in
-// CreateInstance_Top as well as from DestroyInstance_Top. This function does
-// not call down the dispatch chain; that should be done before calling this
-// function, iff the lower vkCreateInstance call has been made and returned
-// successfully.
-void DestroyInstance(Instance* instance,
- const VkAllocationCallbacks* allocator,
- VkInstance vkinstance) {
- if (vkinstance != VK_NULL_HANDLE && instance->drv.dispatch.DestroyInstance)
- instance->drv.dispatch.DestroyInstance(vkinstance, allocator);
-
- instance->~Instance();
- allocator->pfnFree(allocator->pUserData, instance);
-}
-
-} // anonymous namespace
-
-namespace vulkan {
-
-// -----------------------------------------------------------------------------
-// "Bottom" functions. These are called at the end of the instance dispatch
-// chain.
-
-VkResult CreateInstance_Bottom(const VkInstanceCreateInfo* create_info,
- const VkAllocationCallbacks* allocator,
- VkInstance* vkinstance) {
- VkResult result;
-
- if (!allocator)
- allocator = &kDefaultAllocCallbacks;
-
- void* instance_mem = allocator->pfnAllocation(
- allocator->pUserData, sizeof(Instance), alignof(Instance),
- VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
- if (!instance_mem)
- return VK_ERROR_OUT_OF_HOST_MEMORY;
- Instance& instance = *new (instance_mem) Instance(allocator);
-
- // Check that all enabled extensions are supported
- uint32_t num_driver_extensions = 0;
- for (uint32_t i = 0; i < create_info->enabledExtensionCount; i++) {
- const char* name = create_info->ppEnabledExtensionNames[i];
- InstanceExtension id = InstanceExtensionFromName(name);
- if (id != kInstanceExtensionCount) {
- if (g_driver_instance_extensions[id]) {
- num_driver_extensions++;
- instance.enabled_extensions.set(id);
- continue;
- }
- if (id == kKHR_surface || id == kKHR_android_surface) {
- instance.enabled_extensions.set(id);
- continue;
- }
- // The loader natively supports debug report.
- if (id == kEXT_debug_report) {
- continue;
- }
- }
- }
-
- VkInstanceCreateInfo driver_create_info = *create_info;
- driver_create_info.pNext = StripCreateExtensions(create_info->pNext);
- driver_create_info.enabledLayerCount = 0;
- driver_create_info.ppEnabledLayerNames = nullptr;
- driver_create_info.enabledExtensionCount = 0;
- driver_create_info.ppEnabledExtensionNames = nullptr;
- if (num_driver_extensions > 0) {
- const char** names = static_cast<const char**>(
- alloca(num_driver_extensions * sizeof(char*)));
- for (uint32_t i = 0; i < create_info->enabledExtensionCount; i++) {
- const char* name = create_info->ppEnabledExtensionNames[i];
- InstanceExtension id = InstanceExtensionFromName(name);
- if (id != kInstanceExtensionCount) {
- if (g_driver_instance_extensions[id]) {
- names[driver_create_info.enabledExtensionCount++] = name;
- continue;
- }
- }
- }
- driver_create_info.ppEnabledExtensionNames = names;
- ALOG_ASSERT(
- driver_create_info.enabledExtensionCount == num_driver_extensions,
- "counted enabled driver instance extensions twice and got "
- "different answers!");
- }
-
- VkInstance drv_instance;
- result = g_hwdevice->CreateInstance(&driver_create_info, instance.alloc,
- &drv_instance);
- if (result != VK_SUCCESS) {
- DestroyInstance(&instance, allocator, VK_NULL_HANDLE);
- return result;
- }
-
- if (!driver::SetData(drv_instance, instance.base)) {
- DestroyInstance(&instance, allocator, drv_instance);
- return VK_ERROR_INITIALIZATION_FAILED;
- }
-
- if (!LoadDriverDispatchTable(drv_instance, g_hwdevice->GetInstanceProcAddr,
- instance.enabled_extensions,
- instance.drv.dispatch)) {
- DestroyInstance(&instance, allocator, drv_instance);
- return VK_ERROR_INITIALIZATION_FAILED;
- }
-
- uint32_t num_physical_devices = 0;
- result = instance.drv.dispatch.EnumeratePhysicalDevices(
- drv_instance, &num_physical_devices, nullptr);
- if (result != VK_SUCCESS) {
- DestroyInstance(&instance, allocator, drv_instance);
- return VK_ERROR_INITIALIZATION_FAILED;
- }
- num_physical_devices = std::min(num_physical_devices, kMaxPhysicalDevices);
- result = instance.drv.dispatch.EnumeratePhysicalDevices(
- drv_instance, &num_physical_devices, instance.physical_devices);
- if (result != VK_SUCCESS) {
- DestroyInstance(&instance, allocator, drv_instance);
- return VK_ERROR_INITIALIZATION_FAILED;
- }
-
- Vector<VkExtensionProperties> extensions(
- Vector<VkExtensionProperties>::allocator_type(instance.alloc));
- for (uint32_t i = 0; i < num_physical_devices; i++) {
- if (!driver::SetData(instance.physical_devices[i], instance.base)) {
- DestroyInstance(&instance, allocator, drv_instance);
- return VK_ERROR_INITIALIZATION_FAILED;
- }
-
- uint32_t count;
- if ((result = instance.drv.dispatch.EnumerateDeviceExtensionProperties(
- instance.physical_devices[i], nullptr, &count, nullptr)) !=
- VK_SUCCESS) {
- ALOGW("driver EnumerateDeviceExtensionProperties(%u) failed: %d", i,
- result);
- continue;
- }
- try {
- extensions.resize(count);
- } catch (std::bad_alloc&) {
- ALOGE("instance creation failed: out of memory");
- DestroyInstance(&instance, allocator, drv_instance);
- return VK_ERROR_OUT_OF_HOST_MEMORY;
- }
- if ((result = instance.drv.dispatch.EnumerateDeviceExtensionProperties(
- instance.physical_devices[i], nullptr, &count,
- extensions.data())) != VK_SUCCESS) {
- ALOGW("driver EnumerateDeviceExtensionProperties(%u) failed: %d", i,
- result);
- continue;
- }
- ALOGV_IF(count > 0, "driver gpu[%u] supports extensions:", i);
- for (const auto& extension : extensions) {
- ALOGV(" %s (v%u)", extension.extensionName, extension.specVersion);
- DeviceExtension id =
- DeviceExtensionFromName(extension.extensionName);
- if (id == kDeviceExtensionCount) {
- ALOGW("driver gpu[%u] extension '%s' unknown to loader", i,
- extension.extensionName);
- } else {
- instance.physical_device_driver_extensions[i].set(id);
- }
- }
- // Ignore driver attempts to support loader extensions
- instance.physical_device_driver_extensions[i].reset(kKHR_swapchain);
- }
- instance.num_physical_devices = num_physical_devices;
-
- *vkinstance = drv_instance;
-
- return VK_SUCCESS;
-}
-
-VkResult CreateAndroidSurfaceKHR_Disabled(VkInstance,
- const VkAndroidSurfaceCreateInfoKHR*,
- const VkAllocationCallbacks*,
- VkSurfaceKHR*) {
- ALOGE(
- "VK_KHR_android_surface not enabled. vkCreateAndroidSurfaceKHR not "
- "executed.");
-
- return VK_SUCCESS;
-}
-
-void DestroySurfaceKHR_Disabled(VkInstance,
- VkSurfaceKHR,
- const VkAllocationCallbacks*) {
- ALOGE("VK_KHR_surface not enabled. vkDestroySurfaceKHR not executed.");
-}
-
-VkResult GetPhysicalDeviceSurfaceSupportKHR_Disabled(VkPhysicalDevice,
- uint32_t,
- VkSurfaceKHR,
- VkBool32*) {
- ALOGE(
- "VK_KHR_surface not enabled. vkGetPhysicalDeviceSurfaceSupportKHR not "
- "executed.");
-
- return VK_SUCCESS;
-}
-
-VkResult GetPhysicalDeviceSurfaceCapabilitiesKHR_Disabled(
- VkPhysicalDevice,
- VkSurfaceKHR,
- VkSurfaceCapabilitiesKHR*) {
- ALOGE(
- "VK_KHR_surface not enabled. vkGetPhysicalDeviceSurfaceapabilitiesKHR "
- "not executed.");
-
- return VK_SUCCESS;
-}
-
-VkResult GetPhysicalDeviceSurfaceFormatsKHR_Disabled(VkPhysicalDevice,
- VkSurfaceKHR,
- uint32_t*,
- VkSurfaceFormatKHR*) {
- ALOGE(
- "VK_KHR_surface not enabled. vkGetPhysicalDeviceSurfaceFormatsKHR not "
- "executed.");
-
- return VK_SUCCESS;
-}
-
-VkResult GetPhysicalDeviceSurfacePresentModesKHR_Disabled(VkPhysicalDevice,
- VkSurfaceKHR,
- uint32_t*,
- VkPresentModeKHR*) {
- ALOGE(
- "VK_KHR_surface not enabled. vkGetPhysicalDeviceSurfacePresentModesKHR "
- "not executed.");
-
- return VK_SUCCESS;
-}
-
-PFN_vkVoidFunction GetInstanceProcAddr_Bottom(VkInstance vkinstance,
- const char* name) {
- PFN_vkVoidFunction pfn;
-
- if (vkinstance) {
- Instance& instance = GetDispatchParent(vkinstance);
- if (!instance.enabled_extensions[kKHR_android_surface]) {
- // KHR_android_surface is not enabled, use error stubs instead
- if (strcmp(name, "vkCreateAndroidSurfaceKHR") == 0) {
- return reinterpret_cast<PFN_vkVoidFunction>(
- CreateAndroidSurfaceKHR_Disabled);
- }
- }
- if (!instance.enabled_extensions[kKHR_surface]) {
- // KHR_surface is not enabled, use error stubs instead
- if (strcmp(name, "vkDestroySurfaceKHR") == 0) {
- return reinterpret_cast<PFN_vkVoidFunction>(
- DestroySurfaceKHR_Disabled);
- }
- if (strcmp(name, "vkGetPhysicalDeviceSurfaceSupportKHR") == 0) {
- return reinterpret_cast<PFN_vkVoidFunction>(
- GetPhysicalDeviceSurfaceSupportKHR_Disabled);
- }
- if (strcmp(name, "vkGetPhysicalDeviceSurfaceCapabilitiesKHR") ==
- 0) {
- return reinterpret_cast<PFN_vkVoidFunction>(
- GetPhysicalDeviceSurfaceCapabilitiesKHR_Disabled);
- }
- if (strcmp(name, "vkGetPhysicalDeviceSurfaceFormatsKHR") == 0) {
- return reinterpret_cast<PFN_vkVoidFunction>(
- GetPhysicalDeviceSurfaceFormatsKHR_Disabled);
- }
- if (strcmp(name, "vkGetPhysicalDeviceSurfacePresentModesKHR") ==
- 0) {
- return reinterpret_cast<PFN_vkVoidFunction>(
- GetPhysicalDeviceSurfacePresentModesKHR_Disabled);
- }
- }
- }
- if ((pfn = GetLoaderBottomProcAddr(name)))
- return pfn;
- return g_hwdevice->GetInstanceProcAddr(vkinstance, name);
-}
-
-VkResult EnumeratePhysicalDevices_Bottom(VkInstance vkinstance,
- uint32_t* pdev_count,
- VkPhysicalDevice* pdevs) {
- Instance& instance = GetDispatchParent(vkinstance);
- uint32_t count = instance.num_physical_devices;
- if (pdevs) {
- count = std::min(count, *pdev_count);
- std::copy(instance.physical_devices, instance.physical_devices + count,
- pdevs);
- }
- *pdev_count = count;
- return VK_SUCCESS;
-}
-
-void GetPhysicalDeviceProperties_Bottom(
- VkPhysicalDevice pdev,
- VkPhysicalDeviceProperties* properties) {
- GetDispatchParent(pdev).drv.dispatch.GetPhysicalDeviceProperties(
- pdev, properties);
-}
-
-void GetPhysicalDeviceFeatures_Bottom(VkPhysicalDevice pdev,
- VkPhysicalDeviceFeatures* features) {
- GetDispatchParent(pdev).drv.dispatch.GetPhysicalDeviceFeatures(pdev,
- features);
-}
-
-void GetPhysicalDeviceMemoryProperties_Bottom(
- VkPhysicalDevice pdev,
- VkPhysicalDeviceMemoryProperties* properties) {
- GetDispatchParent(pdev).drv.dispatch.GetPhysicalDeviceMemoryProperties(
- pdev, properties);
-}
-
-void GetPhysicalDeviceQueueFamilyProperties_Bottom(
- VkPhysicalDevice pdev,
- uint32_t* pCount,
- VkQueueFamilyProperties* properties) {
- GetDispatchParent(pdev).drv.dispatch.GetPhysicalDeviceQueueFamilyProperties(
- pdev, pCount, properties);
-}
-
-void GetPhysicalDeviceFormatProperties_Bottom(VkPhysicalDevice pdev,
- VkFormat format,
- VkFormatProperties* properties) {
- GetDispatchParent(pdev).drv.dispatch.GetPhysicalDeviceFormatProperties(
- pdev, format, properties);
-}
-
-VkResult GetPhysicalDeviceImageFormatProperties_Bottom(
- VkPhysicalDevice pdev,
- VkFormat format,
- VkImageType type,
- VkImageTiling tiling,
- VkImageUsageFlags usage,
- VkImageCreateFlags flags,
- VkImageFormatProperties* properties) {
- return GetDispatchParent(pdev)
- .drv.dispatch.GetPhysicalDeviceImageFormatProperties(
- pdev, format, type, tiling, usage, flags, properties);
-}
-
-void GetPhysicalDeviceSparseImageFormatProperties_Bottom(
- VkPhysicalDevice pdev,
- VkFormat format,
- VkImageType type,
- VkSampleCountFlagBits samples,
- VkImageUsageFlags usage,
- VkImageTiling tiling,
- uint32_t* properties_count,
- VkSparseImageFormatProperties* properties) {
- GetDispatchParent(pdev)
- .drv.dispatch.GetPhysicalDeviceSparseImageFormatProperties(
- pdev, format, type, samples, usage, tiling, properties_count,
- properties);
-}
-
-VKAPI_ATTR
-VkResult EnumerateDeviceExtensionProperties_Bottom(
- VkPhysicalDevice pdev,
- const char* layer_name,
- uint32_t* properties_count,
- VkExtensionProperties* properties) {
- (void)layer_name;
-
- Instance& instance = GetDispatchParent(pdev);
-
- size_t gpu_idx = 0;
- while (instance.physical_devices[gpu_idx] != pdev)
- gpu_idx++;
- const DeviceExtensionSet driver_extensions =
- instance.physical_device_driver_extensions[gpu_idx];
-
- // We only support VK_KHR_swapchain if the GPU supports
- // VK_ANDROID_native_buffer
- VkExtensionProperties* available = static_cast<VkExtensionProperties*>(
- alloca(kDeviceExtensionCount * sizeof(VkExtensionProperties)));
- uint32_t num_extensions = 0;
- if (driver_extensions[kANDROID_native_buffer]) {
- available[num_extensions++] = VkExtensionProperties{
- VK_KHR_SWAPCHAIN_EXTENSION_NAME, VK_KHR_SWAPCHAIN_SPEC_VERSION};
- }
-
- if (!properties || *properties_count > num_extensions)
- *properties_count = num_extensions;
- if (properties)
- std::copy(available, available + *properties_count, properties);
-
- return *properties_count < num_extensions ? VK_INCOMPLETE : VK_SUCCESS;
-}
-
-// This is a no-op, the Top function returns the aggregate layer property
-// data. This is to keep the dispatch generator happy.
-VKAPI_ATTR
-VkResult EnumerateDeviceLayerProperties_Bottom(
- VkPhysicalDevice /*pdev*/,
- uint32_t* /*properties_count*/,
- VkLayerProperties* /*properties*/) {
- return VK_SUCCESS;
-}
-
-VKAPI_ATTR
-VkResult CreateDevice_Bottom(VkPhysicalDevice gpu,
- const VkDeviceCreateInfo* create_info,
- const VkAllocationCallbacks* allocator,
- VkDevice* device_out) {
- Instance& instance = GetDispatchParent(gpu);
-
- // FIXME(jessehall): We don't have good conventions or infrastructure yet to
- // do better than just using the instance allocator and scope for
- // everything. See b/26732122.
- if (true /*!allocator*/)
- allocator = instance.alloc;
-
- void* mem = allocator->pfnAllocation(allocator->pUserData, sizeof(Device),
- alignof(Device),
- VK_SYSTEM_ALLOCATION_SCOPE_DEVICE);
- if (!mem)
- return VK_ERROR_OUT_OF_HOST_MEMORY;
- Device* device = new (mem) Device(&instance);
-
- size_t gpu_idx = 0;
- while (instance.physical_devices[gpu_idx] != gpu)
- gpu_idx++;
-
- VkDeviceCreateInfo driver_create_info = *create_info;
- driver_create_info.pNext = StripCreateExtensions(create_info->pNext);
- driver_create_info.enabledLayerCount = 0;
- driver_create_info.ppEnabledLayerNames = nullptr;
-
- uint32_t num_driver_extensions = 0;
- const char** driver_extensions = static_cast<const char**>(
- alloca(create_info->enabledExtensionCount * sizeof(const char*)));
- for (uint32_t i = 0; i < create_info->enabledExtensionCount; i++) {
- const char* name = create_info->ppEnabledExtensionNames[i];
- DeviceExtension id = DeviceExtensionFromName(name);
- if (id != kDeviceExtensionCount) {
- if (instance.physical_device_driver_extensions[gpu_idx][id]) {
- driver_extensions[num_driver_extensions++] = name;
- device->enabled_extensions.set(id);
- continue;
- }
- // Add the VK_ANDROID_native_buffer extension to the list iff
- // the VK_KHR_swapchain extension was requested
- if (id == kKHR_swapchain &&
- instance.physical_device_driver_extensions
- [gpu_idx][kANDROID_native_buffer]) {
- driver_extensions[num_driver_extensions++] =
- VK_ANDROID_NATIVE_BUFFER_EXTENSION_NAME;
- device->enabled_extensions.set(id);
- continue;
- }
- }
- }
-
- driver_create_info.enabledExtensionCount = num_driver_extensions;
- driver_create_info.ppEnabledExtensionNames = driver_extensions;
- VkDevice drv_device;
- VkResult result = instance.drv.dispatch.CreateDevice(
- gpu, &driver_create_info, allocator, &drv_device);
- if (result != VK_SUCCESS) {
- DestroyDevice(device, VK_NULL_HANDLE);
- return VK_ERROR_INITIALIZATION_FAILED;
- }
-
- if (!driver::SetData(drv_device, device->base)) {
- DestroyDevice(device, drv_device);
- return VK_ERROR_INITIALIZATION_FAILED;
- }
-
- device->get_device_proc_addr = reinterpret_cast<PFN_vkGetDeviceProcAddr>(
- instance.drv.dispatch.GetDeviceProcAddr(drv_device,
- "vkGetDeviceProcAddr"));
- *device_out = drv_device;
- return VK_SUCCESS;
-}
-
-void DestroyInstance_Bottom(VkInstance vkinstance,
- const VkAllocationCallbacks* allocator) {
- Instance& instance = GetDispatchParent(vkinstance);
-
- VkAllocationCallbacks local_allocator;
- if (!allocator) {
- local_allocator = *instance.alloc;
- allocator = &local_allocator;
- }
-
- DestroyInstance(&instance, allocator, vkinstance);
-}
-
-VkResult CreateSwapchainKHR_Disabled(VkDevice,
- const VkSwapchainCreateInfoKHR*,
- const VkAllocationCallbacks*,
- VkSwapchainKHR*) {
- ALOGE("VK_KHR_swapchain not enabled. vkCreateSwapchainKHR not executed.");
-
- return VK_SUCCESS;
-}
-
-void DestroySwapchainKHR_Disabled(VkDevice,
- VkSwapchainKHR,
- const VkAllocationCallbacks*) {
- ALOGE("VK_KHR_swapchain not enabled. vkDestroySwapchainKHR not executed.");
-}
-
-VkResult GetSwapchainImagesKHR_Disabled(VkDevice,
- VkSwapchainKHR,
- uint32_t*,
- VkImage*) {
- ALOGE(
- "VK_KHR_swapchain not enabled. vkGetSwapchainImagesKHR not executed.");
-
- return VK_SUCCESS;
-}
-
-VkResult AcquireNextImageKHR_Disabled(VkDevice,
- VkSwapchainKHR,
- uint64_t,
- VkSemaphore,
- VkFence,
- uint32_t*) {
- ALOGE("VK_KHR_swapchain not enabled. vkAcquireNextImageKHR not executed.");
-
- return VK_SUCCESS;
-}
-
-VkResult QueuePresentKHR_Disabled(VkQueue, const VkPresentInfoKHR*) {
- ALOGE("VK_KHR_swapchain not enabled. vkQueuePresentKHR not executed.");
-
- return VK_SUCCESS;
-}
-
-PFN_vkVoidFunction GetDeviceProcAddr_Bottom(VkDevice vkdevice,
- const char* name) {
- if (strcmp(name, "vkCreateDevice") == 0) {
- return reinterpret_cast<PFN_vkVoidFunction>(CreateDevice_Bottom);
- }
-
- Device& device = GetDispatchParent(vkdevice);
- if (!device.enabled_extensions[kKHR_swapchain]) {
- if (strcmp(name, "vkCreateSwapchainKHR") == 0) {
- return reinterpret_cast<PFN_vkVoidFunction>(
- CreateSwapchainKHR_Disabled);
- }
- if (strcmp(name, "vkDestroySwapchainKHR") == 0) {
- return reinterpret_cast<PFN_vkVoidFunction>(
- DestroySwapchainKHR_Disabled);
- }
- if (strcmp(name, "vkGetSwapchainImagesKHR") == 0) {
- return reinterpret_cast<PFN_vkVoidFunction>(
- GetSwapchainImagesKHR_Disabled);
- }
- if (strcmp(name, "vkAcquireNextSwapchainImageKHR") == 0) {
- return reinterpret_cast<PFN_vkVoidFunction>(
- AcquireNextImageKHR_Disabled);
- }
- if (strcmp(name, "vkQueuePresentKHR") == 0) {
- return reinterpret_cast<PFN_vkVoidFunction>(
- QueuePresentKHR_Disabled);
- }
- }
-
- // VK_ANDROID_native_buffer should be hidden from applications and layers.
- // TODO(jessehall): Generate this as part of GetLoaderBottomProcAddr.
- PFN_vkVoidFunction pfn;
- if (strcmp(name, "vkGetSwapchainGrallocUsageANDROID") == 0 ||
- strcmp(name, "vkAcquireImageANDROID") == 0 ||
- strcmp(name, "vkQueueSignalReleaseImageANDROID") == 0) {
- return nullptr;
- }
- if ((pfn = GetLoaderBottomProcAddr(name)))
- return pfn;
- return GetDispatchParent(vkdevice).get_device_proc_addr(vkdevice, name);
-}
-
-void DestroyDevice_Bottom(VkDevice vkdevice, const VkAllocationCallbacks*) {
- DestroyDevice(&GetDispatchParent(vkdevice), vkdevice);
-}
-
-void GetDeviceQueue_Bottom(VkDevice vkdevice,
- uint32_t family,
- uint32_t index,
- VkQueue* queue_out) {
- const auto& device = GetDispatchParent(vkdevice);
- const auto& instance = *device.instance;
-
- instance.drv.dispatch.GetDeviceQueue(vkdevice, family, index, queue_out);
- driver::SetData(*queue_out, device.base);
-}
-
-VkResult AllocateCommandBuffers_Bottom(
- VkDevice vkdevice,
- const VkCommandBufferAllocateInfo* alloc_info,
- VkCommandBuffer* cmdbufs) {
- const auto& device = GetDispatchParent(vkdevice);
- const auto& instance = *device.instance;
-
- VkResult result = instance.drv.dispatch.AllocateCommandBuffers(
- vkdevice, alloc_info, cmdbufs);
- if (result == VK_SUCCESS) {
- for (uint32_t i = 0; i < alloc_info->commandBufferCount; i++)
- driver::SetData(cmdbufs[i], device.base);
- }
-
- return result;
-}
-
-// -----------------------------------------------------------------------------
-
-const VkAllocationCallbacks* GetAllocator(VkInstance vkinstance) {
- return GetDispatchParent(vkinstance).alloc;
-}
-
-const VkAllocationCallbacks* GetAllocator(VkDevice vkdevice) {
- return GetDispatchParent(vkdevice).instance->alloc;
-}
-
-VkInstance GetDriverInstance(VkInstance instance) {
- return instance;
-}
-
-const DriverDispatchTable& GetDriverDispatch(VkInstance instance) {
- return GetDispatchParent(instance).drv.dispatch;
-}
-
-const DriverDispatchTable& GetDriverDispatch(VkDevice device) {
- return GetDispatchParent(device).instance->drv.dispatch;
-}
-
-const DriverDispatchTable& GetDriverDispatch(VkQueue queue) {
- return GetDispatchParent(queue).instance->drv.dispatch;
-}
-
-DebugReportCallbackList& GetDebugReportCallbacks(VkInstance instance) {
- return GetDispatchParent(instance).debug_report_callbacks;
-}
-
-namespace driver {
-
-bool Debuggable() {
- return (prctl(PR_GET_DUMPABLE, 0, 0, 0, 0) >= 0);
-}
-
-bool OpenHAL() {
- if (!g_hwdevice)
- LoadVulkanHAL();
-
- return (g_hwdevice != nullptr);
-}
-
-const VkAllocationCallbacks& GetDefaultAllocator() {
- return kDefaultAllocCallbacks;
-}
-
-PFN_vkVoidFunction GetInstanceProcAddr(VkInstance instance, const char* pName) {
- return GetInstanceProcAddr_Bottom(instance, pName);
-}
-
-PFN_vkVoidFunction GetDeviceProcAddr(VkDevice device, const char* pName) {
- return GetDeviceProcAddr_Bottom(device, pName);
-}
-
-VkResult EnumerateInstanceExtensionProperties(
- const char* pLayerName,
- uint32_t* pPropertyCount,
- VkExtensionProperties* pProperties) {
- (void)pLayerName;
-
- VkExtensionProperties* available = static_cast<VkExtensionProperties*>(
- alloca(kInstanceExtensionCount * sizeof(VkExtensionProperties)));
- uint32_t num_extensions = 0;
-
- available[num_extensions++] = VkExtensionProperties{
- VK_KHR_SURFACE_EXTENSION_NAME, VK_KHR_SURFACE_SPEC_VERSION};
- available[num_extensions++] =
- VkExtensionProperties{VK_KHR_ANDROID_SURFACE_EXTENSION_NAME,
- VK_KHR_ANDROID_SURFACE_SPEC_VERSION};
- if (g_driver_instance_extensions[kEXT_debug_report]) {
- available[num_extensions++] =
- VkExtensionProperties{VK_EXT_DEBUG_REPORT_EXTENSION_NAME,
- VK_EXT_DEBUG_REPORT_SPEC_VERSION};
- }
-
- if (!pProperties || *pPropertyCount > num_extensions)
- *pPropertyCount = num_extensions;
- if (pProperties)
- std::copy(available, available + *pPropertyCount, pProperties);
-
- return *pPropertyCount < num_extensions ? VK_INCOMPLETE : VK_SUCCESS;
-}
-
-} // namespace driver
-
-} // namespace vulkan
diff --git a/vulkan/libvulkan/loader.h b/vulkan/libvulkan/loader.h
deleted file mode 100644
index 0ec08b2..0000000
--- a/vulkan/libvulkan/loader.h
+++ /dev/null
@@ -1,155 +0,0 @@
-/*
- * Copyright 2015 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 LIBVULKAN_LOADER_H
-#define LIBVULKAN_LOADER_H 1
-
-#include <bitset>
-#include "dispatch_gen.h"
-#include "debug_report.h"
-
-namespace vulkan {
-
-enum InstanceExtension {
- kKHR_surface,
- kKHR_android_surface,
- kEXT_debug_report,
- kInstanceExtensionCount
-};
-typedef std::bitset<kInstanceExtensionCount> InstanceExtensionSet;
-
-enum DeviceExtension {
- kKHR_swapchain,
- kANDROID_native_buffer,
- kDeviceExtensionCount
-};
-typedef std::bitset<kDeviceExtensionCount> DeviceExtensionSet;
-
-// -----------------------------------------------------------------------------
-// dispatch_gen.cpp
-
-PFN_vkVoidFunction GetLoaderBottomProcAddr(const char* name);
-bool LoadDriverDispatchTable(VkInstance instance,
- PFN_vkGetInstanceProcAddr get_proc_addr,
- const InstanceExtensionSet& extensions,
- DriverDispatchTable& dispatch);
-
-// -----------------------------------------------------------------------------
-// loader.cpp
-
-// clang-format off
-VKAPI_ATTR VkResult CreateInstance_Bottom(const VkInstanceCreateInfo* create_info, const VkAllocationCallbacks* allocator, VkInstance* vkinstance);
-VKAPI_ATTR PFN_vkVoidFunction GetInstanceProcAddr_Bottom(VkInstance, const char* name);
-VKAPI_ATTR VkResult EnumeratePhysicalDevices_Bottom(VkInstance vkinstance, uint32_t* pdev_count, VkPhysicalDevice* pdevs);
-VKAPI_ATTR void GetPhysicalDeviceProperties_Bottom(VkPhysicalDevice pdev, VkPhysicalDeviceProperties* properties);
-VKAPI_ATTR void GetPhysicalDeviceFeatures_Bottom(VkPhysicalDevice pdev, VkPhysicalDeviceFeatures* features);
-VKAPI_ATTR void GetPhysicalDeviceMemoryProperties_Bottom(VkPhysicalDevice pdev, VkPhysicalDeviceMemoryProperties* properties);
-VKAPI_ATTR void GetPhysicalDeviceQueueFamilyProperties_Bottom(VkPhysicalDevice pdev, uint32_t* properties_count, VkQueueFamilyProperties* properties);
-VKAPI_ATTR void GetPhysicalDeviceFormatProperties_Bottom(VkPhysicalDevice pdev, VkFormat format, VkFormatProperties* properties);
-VKAPI_ATTR VkResult GetPhysicalDeviceImageFormatProperties_Bottom(VkPhysicalDevice pdev, VkFormat format, VkImageType type, VkImageTiling tiling, VkImageUsageFlags usage, VkImageCreateFlags flags, VkImageFormatProperties* properties);
-VKAPI_ATTR void GetPhysicalDeviceSparseImageFormatProperties_Bottom(VkPhysicalDevice pdev, VkFormat format, VkImageType type, VkSampleCountFlagBits samples, VkImageUsageFlags usage, VkImageTiling tiling, uint32_t* properties_count, VkSparseImageFormatProperties* properties);
-VKAPI_ATTR VkResult EnumerateDeviceExtensionProperties_Bottom(VkPhysicalDevice pdev, const char* layer_name, uint32_t* properties_count, VkExtensionProperties* properties);
-VKAPI_ATTR VkResult EnumerateDeviceLayerProperties_Bottom(VkPhysicalDevice pdev, uint32_t* properties_count, VkLayerProperties* properties);
-VKAPI_ATTR VkResult CreateDevice_Bottom(VkPhysicalDevice pdev, const VkDeviceCreateInfo* create_info, const VkAllocationCallbacks* allocator, VkDevice* device_out);
-VKAPI_ATTR void DestroyInstance_Bottom(VkInstance vkinstance, const VkAllocationCallbacks* allocator);
-VKAPI_ATTR PFN_vkVoidFunction GetDeviceProcAddr_Bottom(VkDevice vkdevice, const char* name);
-VKAPI_ATTR void DestroyDevice_Bottom(VkDevice device, const VkAllocationCallbacks* pAllocator);
-VKAPI_ATTR void GetDeviceQueue_Bottom(VkDevice device, uint32_t queueFamilyIndex, uint32_t queueIndex, VkQueue* pQueue);
-VKAPI_ATTR VkResult AllocateCommandBuffers_Bottom(VkDevice device, const VkCommandBufferAllocateInfo* pAllocateInfo, VkCommandBuffer* pCommandBuffers);
-// clang-format on
-
-const VkAllocationCallbacks* GetAllocator(VkInstance instance);
-const VkAllocationCallbacks* GetAllocator(VkDevice device);
-VkInstance GetDriverInstance(VkInstance instance);
-const DriverDispatchTable& GetDriverDispatch(VkInstance instance);
-const DriverDispatchTable& GetDriverDispatch(VkDevice device);
-const DriverDispatchTable& GetDriverDispatch(VkQueue queue);
-DebugReportCallbackList& GetDebugReportCallbacks(VkInstance instance);
-
-// -----------------------------------------------------------------------------
-// swapchain.cpp
-
-// clang-format off
-VKAPI_ATTR VkResult CreateAndroidSurfaceKHR_Bottom(VkInstance instance, const VkAndroidSurfaceCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* allocator, VkSurfaceKHR* surface);
-VKAPI_ATTR void DestroySurfaceKHR_Bottom(VkInstance instance, VkSurfaceKHR surface, const VkAllocationCallbacks* allocator);
-VKAPI_ATTR VkResult GetPhysicalDeviceSurfaceSupportKHR_Bottom(VkPhysicalDevice pdev, uint32_t queue_family, VkSurfaceKHR surface, VkBool32* pSupported);
-VKAPI_ATTR VkResult GetPhysicalDeviceSurfaceCapabilitiesKHR_Bottom(VkPhysicalDevice pdev, VkSurfaceKHR surface, VkSurfaceCapabilitiesKHR* capabilities);
-VKAPI_ATTR VkResult GetPhysicalDeviceSurfaceFormatsKHR_Bottom(VkPhysicalDevice pdev, VkSurfaceKHR surface, uint32_t* count, VkSurfaceFormatKHR* formats);
-VKAPI_ATTR VkResult GetPhysicalDeviceSurfacePresentModesKHR_Bottom(VkPhysicalDevice pdev, VkSurfaceKHR surface, uint32_t* count, VkPresentModeKHR* modes);
-VKAPI_ATTR VkResult CreateSwapchainKHR_Bottom(VkDevice device, const VkSwapchainCreateInfoKHR* create_info, const VkAllocationCallbacks* allocator, VkSwapchainKHR* swapchain_handle);
-VKAPI_ATTR void DestroySwapchainKHR_Bottom(VkDevice device, VkSwapchainKHR swapchain_handle, const VkAllocationCallbacks* allocator);
-VKAPI_ATTR VkResult GetSwapchainImagesKHR_Bottom(VkDevice device, VkSwapchainKHR swapchain_handle, uint32_t* count, VkImage* images);
-VKAPI_ATTR VkResult AcquireNextImageKHR_Bottom(VkDevice device, VkSwapchainKHR swapchain_handle, uint64_t timeout, VkSemaphore semaphore, VkFence fence, uint32_t* image_index);
-VKAPI_ATTR VkResult QueuePresentKHR_Bottom(VkQueue queue, const VkPresentInfoKHR* present_info);
-
-VKAPI_ATTR VkResult CreateAndroidSurfaceKHR_Disabled(VkInstance instance, const VkAndroidSurfaceCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* allocator, VkSurfaceKHR* surface);
-VKAPI_ATTR void DestroySurfaceKHR_Disabled(VkInstance, VkSurfaceKHR, const VkAllocationCallbacks*);
-VKAPI_ATTR VkResult GetPhysicalDeviceSurfaceSupportKHR_Disabled(VkPhysicalDevice, uint32_t, VkSurfaceKHR, VkBool32*);
-VKAPI_ATTR VkResult GetPhysicalDeviceSurfaceCapabilitiesKHR_Disabled(VkPhysicalDevice, VkSurfaceKHR, VkSurfaceCapabilitiesKHR*);
-VKAPI_ATTR VkResult GetPhysicalDeviceSurfaceFormatsKHR_Disabled(VkPhysicalDevice, VkSurfaceKHR, uint32_t*, VkSurfaceFormatKHR*);
-VKAPI_ATTR VkResult GetPhysicalDeviceSurfacePresentModesKHR_Disabled(VkPhysicalDevice, VkSurfaceKHR, uint32_t*, VkPresentModeKHR*);
-VKAPI_ATTR VkResult CreateSwapchainKHR_Disabled(VkDevice device, const VkSwapchainCreateInfoKHR* create_info, const VkAllocationCallbacks* allocator, VkSwapchainKHR* swapchain_handle);
-VKAPI_ATTR void DestroySwapchainKHR_Disabled(VkDevice device, VkSwapchainKHR swapchain_handle, const VkAllocationCallbacks* allocator);
-VKAPI_ATTR VkResult GetSwapchainImagesKHR_Disabled(VkDevice device, VkSwapchainKHR swapchain_handle, uint32_t* count, VkImage* images);
-VKAPI_ATTR VkResult AcquireNextImageKHR_Disabled(VkDevice device, VkSwapchainKHR swapchain_handle, uint64_t timeout, VkSemaphore semaphore, VkFence fence, uint32_t* image_index);
-VKAPI_ATTR VkResult QueuePresentKHR_Disabled(VkQueue queue, const VkPresentInfoKHR* present_info);
-// clang-format on
-
-// -----------------------------------------------------------------------------
-// layers_extensions.cpp
-
-struct Layer;
-class LayerRef {
- public:
- LayerRef(Layer* layer);
- LayerRef(LayerRef&& other);
- ~LayerRef();
- LayerRef(const LayerRef&) = delete;
- LayerRef& operator=(const LayerRef&) = delete;
-
- const char* GetName() const;
- uint32_t GetSpecVersion();
-
- // provides bool-like behavior
- operator const Layer*() const { return layer_; }
-
- PFN_vkGetInstanceProcAddr GetGetInstanceProcAddr() const;
- PFN_vkGetDeviceProcAddr GetGetDeviceProcAddr() const;
-
- bool SupportsExtension(const char* name) const;
-
- private:
- Layer* layer_;
-};
-
-void DiscoverLayers();
-uint32_t EnumerateInstanceLayers(uint32_t count, VkLayerProperties* properties);
-uint32_t EnumerateDeviceLayers(uint32_t count, VkLayerProperties* properties);
-void GetInstanceLayerExtensions(const char* name,
- const VkExtensionProperties** properties,
- uint32_t* count);
-void GetDeviceLayerExtensions(const char* name,
- const VkExtensionProperties** properties,
- uint32_t* count);
-LayerRef GetInstanceLayerRef(const char* name);
-LayerRef GetDeviceLayerRef(const char* name);
-
-InstanceExtension InstanceExtensionFromName(const char* name);
-DeviceExtension DeviceExtensionFromName(const char* name);
-
-} // namespace vulkan
-
-#endif // LIBVULKAN_LOADER_H
diff --git a/vulkan/libvulkan/stubhal.cpp b/vulkan/libvulkan/stubhal.cpp
new file mode 100644
index 0000000..89fcebb
--- /dev/null
+++ b/vulkan/libvulkan/stubhal.cpp
@@ -0,0 +1,134 @@
+/*
+ * Copyright 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.
+ */
+
+/* NOTE:
+ * This stub HAL is only used internally by the loader when a real HAL
+ * implementation is not present, in order to avoid needing "null HAL" checks
+ * throughout the loader. It does not enumerate any physical devices, and is
+ * only as conformant to the Vulkan and Android HAL interfaces as the loader
+ * needs it to be. Do not use it as an example of a correct implementation; the
+ * code in ../null_driver is better for that.
+ */
+
+#undef LOG_TAG
+#define LOG_TAG "vkstub"
+
+#include <array>
+#include <bitset>
+#include <mutex>
+#include <hardware/hwvulkan.h>
+#include <log/log.h>
+#include "stubhal.h"
+
+namespace vulkan {
+namespace stubhal {
+
+namespace {
+
+const size_t kMaxInstances = 32;
+static std::mutex g_instance_mutex;
+static std::bitset<kMaxInstances> g_instance_used(false);
+static std::array<hwvulkan_dispatch_t, kMaxInstances> g_instances;
+
+[[noreturn]] void NoOp() {
+ LOG_ALWAYS_FATAL("invalid stub function called");
+}
+
+VKAPI_ATTR VkResult
+EnumerateInstanceExtensionProperties(const char* /*layer_name*/,
+ uint32_t* count,
+ VkExtensionProperties* /*properties*/) {
+ *count = 0;
+ return VK_SUCCESS;
+}
+
+VKAPI_ATTR VkResult
+EnumerateInstanceLayerProperties(uint32_t* count,
+ VkLayerProperties* /*properties*/) {
+ *count = 0;
+ return VK_SUCCESS;
+}
+
+VKAPI_ATTR VkResult CreateInstance(const VkInstanceCreateInfo* /*create_info*/,
+ const VkAllocationCallbacks* /*allocator*/,
+ VkInstance* instance) {
+ std::lock_guard<std::mutex> lock(g_instance_mutex);
+ for (size_t i = 0; i < kMaxInstances; i++) {
+ if (!g_instance_used[i]) {
+ g_instance_used[i] = true;
+ g_instances[i].magic = HWVULKAN_DISPATCH_MAGIC;
+ *instance = reinterpret_cast<VkInstance>(&g_instances[i]);
+ return VK_SUCCESS;
+ }
+ }
+ ALOGE("no more instances available (max=%zu)", kMaxInstances);
+ return VK_ERROR_INITIALIZATION_FAILED;
+}
+
+VKAPI_ATTR void DestroyInstance(VkInstance instance,
+ const VkAllocationCallbacks* /*allocator*/) {
+ std::lock_guard<std::mutex> lock(g_instance_mutex);
+ ssize_t idx =
+ reinterpret_cast<hwvulkan_dispatch_t*>(instance) - &g_instances[0];
+ ALOG_ASSERT(idx >= 0 && idx < g_instance_used.size(),
+ "DestroyInstance: invalid instance handle");
+ g_instance_used[static_cast<size_t>(idx)] = false;
+}
+
+VKAPI_ATTR VkResult EnumeratePhysicalDevices(VkInstance /*instance*/,
+ uint32_t* count,
+ VkPhysicalDevice* /*gpus*/) {
+ *count = 0;
+ return VK_SUCCESS;
+}
+
+VKAPI_ATTR PFN_vkVoidFunction GetInstanceProcAddr(VkInstance /*instance*/,
+ const char* name) {
+ if (strcmp(name, "vkCreateInstance") == 0)
+ return reinterpret_cast<PFN_vkVoidFunction>(CreateInstance);
+ if (strcmp(name, "vkDestroyInstance") == 0)
+ return reinterpret_cast<PFN_vkVoidFunction>(DestroyInstance);
+ if (strcmp(name, "vkEnumerateInstanceExtensionProperties") == 0)
+ return reinterpret_cast<PFN_vkVoidFunction>(
+ EnumerateInstanceExtensionProperties);
+ if (strcmp(name, "vkEnumeratePhysicalDevices") == 0)
+ return reinterpret_cast<PFN_vkVoidFunction>(EnumeratePhysicalDevices);
+ if (strcmp(name, "vkGetInstanceProcAddr") == 0)
+ return reinterpret_cast<PFN_vkVoidFunction>(GetInstanceProcAddr);
+
+ // None of the other Vulkan functions should ever be called, as they all
+ // take a VkPhysicalDevice or other object obtained from a physical device.
+ return reinterpret_cast<PFN_vkVoidFunction>(NoOp);
+}
+
+} // anonymous namespace
+
+const hwvulkan_device_t kDevice = {
+ .common =
+ {
+ .tag = HARDWARE_DEVICE_TAG,
+ .version = HWVULKAN_DEVICE_API_VERSION_0_1,
+ .module = nullptr,
+ .close = nullptr,
+ },
+ .EnumerateInstanceExtensionProperties =
+ EnumerateInstanceExtensionProperties,
+ .CreateInstance = CreateInstance,
+ .GetInstanceProcAddr = GetInstanceProcAddr,
+};
+
+} // namespace stubhal
+} // namespace vulkan
diff --git a/vulkan/libvulkan/stubhal.h b/vulkan/libvulkan/stubhal.h
new file mode 100644
index 0000000..9ba7d04
--- /dev/null
+++ b/vulkan/libvulkan/stubhal.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright 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 LIBVULKAN_STUBHAL_H
+#define LIBVULKAN_STUBHAL_H 1
+
+struct hwvulkan_device_t;
+
+namespace vulkan {
+namespace stubhal {
+
+extern const hwvulkan_device_t kDevice;
+
+} // namespace stubhal
+} // namespace vulkan
+
+#endif // LIBVULKAN_STUBHAL_H
diff --git a/vulkan/libvulkan/swapchain.cpp b/vulkan/libvulkan/swapchain.cpp
index 7f944cf..320a2ac 100644
--- a/vulkan/libvulkan/swapchain.cpp
+++ b/vulkan/libvulkan/swapchain.cpp
@@ -21,14 +21,14 @@
#include <log/log.h>
#include <sync/sync.h>
-#include "loader.h"
-
-using namespace vulkan;
+#include "driver.h"
// TODO(jessehall): Currently we don't have a good error code for when a native
// window operation fails. Just returning INITIALIZATION_FAILED for now. Later
// versions (post SDK 0.9) of the API/extension have a better error code.
// When updating to that version, audit all error returns.
+namespace vulkan {
+namespace driver {
namespace {
@@ -98,11 +98,10 @@
std::shared_ptr<T> InitSharedPtr(Host host, T* obj) {
try {
obj->common.incRef(&obj->common);
- return std::shared_ptr<T>(
- obj, NativeBaseDeleter<T>(),
- VulkanAllocator<T>(*GetAllocator(host), AllocScope<Host>::kScope));
+ return std::shared_ptr<T>(obj, NativeBaseDeleter<T>(),
+ VulkanAllocator<T>(GetData(host).allocator,
+ AllocScope<Host>::kScope));
} catch (std::bad_alloc&) {
- obj->common.decRef(&obj->common);
return nullptr;
}
}
@@ -224,16 +223,14 @@
} // anonymous namespace
-namespace vulkan {
-
VKAPI_ATTR
-VkResult CreateAndroidSurfaceKHR_Bottom(
+VkResult CreateAndroidSurfaceKHR(
VkInstance instance,
const VkAndroidSurfaceCreateInfoKHR* pCreateInfo,
const VkAllocationCallbacks* allocator,
VkSurfaceKHR* out_surface) {
if (!allocator)
- allocator = GetAllocator(instance);
+ allocator = &GetData(instance).allocator;
void* mem = allocator->pfnAllocation(allocator->pUserData, sizeof(Surface),
alignof(Surface),
VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
@@ -267,30 +264,30 @@
}
VKAPI_ATTR
-void DestroySurfaceKHR_Bottom(VkInstance instance,
- VkSurfaceKHR surface_handle,
- const VkAllocationCallbacks* allocator) {
+void DestroySurfaceKHR(VkInstance instance,
+ VkSurfaceKHR surface_handle,
+ const VkAllocationCallbacks* allocator) {
Surface* surface = SurfaceFromHandle(surface_handle);
if (!surface)
return;
native_window_api_disconnect(surface->window.get(), NATIVE_WINDOW_API_EGL);
surface->~Surface();
if (!allocator)
- allocator = GetAllocator(instance);
+ allocator = &GetData(instance).allocator;
allocator->pfnFree(allocator->pUserData, surface);
}
VKAPI_ATTR
-VkResult GetPhysicalDeviceSurfaceSupportKHR_Bottom(VkPhysicalDevice /*pdev*/,
- uint32_t /*queue_family*/,
- VkSurfaceKHR /*surface*/,
- VkBool32* supported) {
+VkResult GetPhysicalDeviceSurfaceSupportKHR(VkPhysicalDevice /*pdev*/,
+ uint32_t /*queue_family*/,
+ VkSurfaceKHR /*surface*/,
+ VkBool32* supported) {
*supported = VK_TRUE;
return VK_SUCCESS;
}
VKAPI_ATTR
-VkResult GetPhysicalDeviceSurfaceCapabilitiesKHR_Bottom(
+VkResult GetPhysicalDeviceSurfaceCapabilitiesKHR(
VkPhysicalDevice /*pdev*/,
VkSurfaceKHR surface,
VkSurfaceCapabilitiesKHR* capabilities) {
@@ -357,11 +354,10 @@
}
VKAPI_ATTR
-VkResult GetPhysicalDeviceSurfaceFormatsKHR_Bottom(
- VkPhysicalDevice /*pdev*/,
- VkSurfaceKHR /*surface*/,
- uint32_t* count,
- VkSurfaceFormatKHR* formats) {
+VkResult GetPhysicalDeviceSurfaceFormatsKHR(VkPhysicalDevice /*pdev*/,
+ VkSurfaceKHR /*surface*/,
+ uint32_t* count,
+ VkSurfaceFormatKHR* formats) {
// TODO(jessehall): Fill out the set of supported formats. Longer term, add
// a new gralloc method to query whether a (format, usage) pair is
// supported, and check that for each gralloc format that corresponds to a
@@ -386,11 +382,10 @@
}
VKAPI_ATTR
-VkResult GetPhysicalDeviceSurfacePresentModesKHR_Bottom(
- VkPhysicalDevice /*pdev*/,
- VkSurfaceKHR /*surface*/,
- uint32_t* count,
- VkPresentModeKHR* modes) {
+VkResult GetPhysicalDeviceSurfacePresentModesKHR(VkPhysicalDevice /*pdev*/,
+ VkSurfaceKHR /*surface*/,
+ uint32_t* count,
+ VkPresentModeKHR* modes) {
const VkPresentModeKHR kModes[] = {
VK_PRESENT_MODE_MAILBOX_KHR, VK_PRESENT_MODE_FIFO_KHR,
};
@@ -407,15 +402,15 @@
}
VKAPI_ATTR
-VkResult CreateSwapchainKHR_Bottom(VkDevice device,
- const VkSwapchainCreateInfoKHR* create_info,
- const VkAllocationCallbacks* allocator,
- VkSwapchainKHR* swapchain_handle) {
+VkResult CreateSwapchainKHR(VkDevice device,
+ const VkSwapchainCreateInfoKHR* create_info,
+ const VkAllocationCallbacks* allocator,
+ VkSwapchainKHR* swapchain_handle) {
int err;
VkResult result = VK_SUCCESS;
if (!allocator)
- allocator = GetAllocator(device);
+ allocator = &GetData(device).allocator;
ALOGV_IF(create_info->imageArrayLayers != 1,
"Swapchain imageArrayLayers (%u) != 1 not supported",
@@ -436,7 +431,7 @@
// -- Configure the native window --
Surface& surface = *SurfaceFromHandle(create_info->surface);
- const DriverDispatchTable& dispatch = GetDriverDispatch(device);
+ const auto& dispatch = GetData(device).driver;
int native_format = HAL_PIXEL_FORMAT_RGBA_8888;
switch (create_info->imageFormat) {
@@ -681,10 +676,10 @@
}
VKAPI_ATTR
-void DestroySwapchainKHR_Bottom(VkDevice device,
- VkSwapchainKHR swapchain_handle,
- const VkAllocationCallbacks* allocator) {
- const DriverDispatchTable& dispatch = GetDriverDispatch(device);
+void DestroySwapchainKHR(VkDevice device,
+ VkSwapchainKHR swapchain_handle,
+ const VkAllocationCallbacks* allocator) {
+ const auto& dispatch = GetData(device).driver;
Swapchain* swapchain = SwapchainFromHandle(swapchain_handle);
const std::shared_ptr<ANativeWindow>& window = swapchain->surface.window;
@@ -702,16 +697,16 @@
}
if (!allocator)
- allocator = GetAllocator(device);
+ allocator = &GetData(device).allocator;
swapchain->~Swapchain();
allocator->pfnFree(allocator->pUserData, swapchain);
}
VKAPI_ATTR
-VkResult GetSwapchainImagesKHR_Bottom(VkDevice,
- VkSwapchainKHR swapchain_handle,
- uint32_t* count,
- VkImage* images) {
+VkResult GetSwapchainImagesKHR(VkDevice,
+ VkSwapchainKHR swapchain_handle,
+ uint32_t* count,
+ VkImage* images) {
Swapchain& swapchain = *SwapchainFromHandle(swapchain_handle);
VkResult result = VK_SUCCESS;
if (images) {
@@ -728,12 +723,12 @@
}
VKAPI_ATTR
-VkResult AcquireNextImageKHR_Bottom(VkDevice device,
- VkSwapchainKHR swapchain_handle,
- uint64_t timeout,
- VkSemaphore semaphore,
- VkFence vk_fence,
- uint32_t* image_index) {
+VkResult AcquireNextImageKHR(VkDevice device,
+ VkSwapchainKHR swapchain_handle,
+ uint64_t timeout,
+ VkSemaphore semaphore,
+ VkFence vk_fence,
+ uint32_t* image_index) {
Swapchain& swapchain = *SwapchainFromHandle(swapchain_handle);
ANativeWindow* window = swapchain.surface.window.get();
VkResult result;
@@ -777,7 +772,7 @@
}
}
- result = GetDriverDispatch(device).AcquireImageANDROID(
+ result = GetData(device).driver.AcquireImageANDROID(
device, swapchain.images[idx].image, fence_clone, semaphore, vk_fence);
if (result != VK_SUCCESS) {
// NOTE: we're relying on AcquireImageANDROID to close fence_clone,
@@ -798,14 +793,13 @@
}
VKAPI_ATTR
-VkResult QueuePresentKHR_Bottom(VkQueue queue,
- const VkPresentInfoKHR* present_info) {
+VkResult QueuePresentKHR(VkQueue queue, const VkPresentInfoKHR* present_info) {
ALOGV_IF(present_info->sType != VK_STRUCTURE_TYPE_PRESENT_INFO_KHR,
"vkQueuePresentKHR: invalid VkPresentInfoKHR structure type %d",
present_info->sType);
ALOGV_IF(present_info->pNext, "VkPresentInfo::pNext != NULL");
- const DriverDispatchTable& dispatch = GetDriverDispatch(queue);
+ const auto& dispatch = GetData(queue).driver;
VkResult final_result = VK_SUCCESS;
for (uint32_t sc = 0; sc < present_info->swapchainCount; sc++) {
Swapchain& swapchain =
@@ -858,4 +852,5 @@
return final_result;
}
+} // namespace driver
} // namespace vulkan
diff --git a/vulkan/libvulkan/swapchain.h b/vulkan/libvulkan/swapchain.h
new file mode 100644
index 0000000..2c60c49
--- /dev/null
+++ b/vulkan/libvulkan/swapchain.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2015 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 LIBVULKAN_SWAPCHAIN_H
+#define LIBVULKAN_SWAPCHAIN_H 1
+
+#include <vulkan/vulkan.h>
+
+namespace vulkan {
+namespace driver {
+
+// clang-format off
+VKAPI_ATTR VkResult CreateAndroidSurfaceKHR(VkInstance instance, const VkAndroidSurfaceCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* allocator, VkSurfaceKHR* surface);
+VKAPI_ATTR void DestroySurfaceKHR(VkInstance instance, VkSurfaceKHR surface, const VkAllocationCallbacks* allocator);
+VKAPI_ATTR VkResult GetPhysicalDeviceSurfaceSupportKHR(VkPhysicalDevice pdev, uint32_t queue_family, VkSurfaceKHR surface, VkBool32* pSupported);
+VKAPI_ATTR VkResult GetPhysicalDeviceSurfaceCapabilitiesKHR(VkPhysicalDevice pdev, VkSurfaceKHR surface, VkSurfaceCapabilitiesKHR* capabilities);
+VKAPI_ATTR VkResult GetPhysicalDeviceSurfaceFormatsKHR(VkPhysicalDevice pdev, VkSurfaceKHR surface, uint32_t* count, VkSurfaceFormatKHR* formats);
+VKAPI_ATTR VkResult GetPhysicalDeviceSurfacePresentModesKHR(VkPhysicalDevice pdev, VkSurfaceKHR surface, uint32_t* count, VkPresentModeKHR* modes);
+VKAPI_ATTR VkResult CreateSwapchainKHR(VkDevice device, const VkSwapchainCreateInfoKHR* create_info, const VkAllocationCallbacks* allocator, VkSwapchainKHR* swapchain_handle);
+VKAPI_ATTR void DestroySwapchainKHR(VkDevice device, VkSwapchainKHR swapchain_handle, const VkAllocationCallbacks* allocator);
+VKAPI_ATTR VkResult GetSwapchainImagesKHR(VkDevice device, VkSwapchainKHR swapchain_handle, uint32_t* count, VkImage* images);
+VKAPI_ATTR VkResult AcquireNextImageKHR(VkDevice device, VkSwapchainKHR swapchain_handle, uint64_t timeout, VkSemaphore semaphore, VkFence fence, uint32_t* image_index);
+VKAPI_ATTR VkResult QueuePresentKHR(VkQueue queue, const VkPresentInfoKHR* present_info);
+// clang-format on
+
+} // namespace driver
+} // namespace vulkan
+
+#endif // LIBVULKAN_SWAPCHAIN_H