Remove GCC-specific pragma am: 020c6ead1a am: 795c8c1d88
am: f3c3e9a946
Change-Id: If83e29c47e08bbf615a2240eb38b84400dfa653a
diff --git a/cmds/atrace/atrace.cpp b/cmds/atrace/atrace.cpp
index 9dbbb77..1b90579 100644
--- a/cmds/atrace/atrace.cpp
+++ b/cmds/atrace/atrace.cpp
@@ -130,6 +130,14 @@
{ REQ, "events/irq/enable" },
{ OPT, "events/ipi/enable" },
} },
+ { "irqoff", "IRQ-disabled code section tracing", 0, {
+ { REQ, "events/preemptirq/irq_enable/enable" },
+ { REQ, "events/preemptirq/irq_disable/enable" },
+ } },
+ { "preemptoff", "Preempt-disabled code section tracing", 0, {
+ { REQ, "events/preemptirq/preempt_enable/enable" },
+ { REQ, "events/preemptirq/preempt_disable/enable" },
+ } },
{ "i2c", "I2C Events", 0, {
{ REQ, "events/i2c/enable" },
{ REQ, "events/i2c/i2c_read/enable" },
@@ -144,6 +152,8 @@
{ "freq", "CPU Frequency", 0, {
{ REQ, "events/power/cpu_frequency/enable" },
{ OPT, "events/power/clock_set_rate/enable" },
+ { OPT, "events/power/clock_disable/enable" },
+ { OPT, "events/power/clock_enable/enable" },
{ OPT, "events/power/cpu_frequency_limits/enable" },
} },
{ "membus", "Memory Bus Utilization", 0, {
diff --git a/cmds/cmd/cmd.cpp b/cmds/cmd/cmd.cpp
index 014c995..40dbbf5 100644
--- a/cmds/cmd/cmd.cpp
+++ b/cmds/cmd/cmd.cpp
@@ -61,7 +61,8 @@
public:
bool mActive = true;
- virtual int openOutputFile(const String16& path, const String16& seLinuxContext) {
+ virtual int openFile(const String16& path, const String16& seLinuxContext,
+ const String16& mode) {
String8 path8(path);
char cwd[256];
getcwd(cwd, 256);
@@ -71,7 +72,26 @@
aerr << "Open attempt after active for: " << fullPath << endl;
return -EPERM;
}
- int fd = open(fullPath.string(), O_WRONLY|O_CREAT|O_TRUNC, S_IRWXU|S_IRWXG);
+ int flags = 0;
+ bool checkRead = false;
+ bool checkWrite = false;
+ if (mode == String16("w")) {
+ flags = O_WRONLY|O_CREAT|O_TRUNC;
+ checkWrite = true;
+ } else if (mode == String16("w+")) {
+ flags = O_RDWR|O_CREAT|O_TRUNC;
+ checkRead = checkWrite = true;
+ } else if (mode == String16("r")) {
+ flags = O_RDONLY;
+ checkRead = true;
+ } else if (mode == String16("r+")) {
+ flags = O_RDWR;
+ checkRead = checkWrite = true;
+ } else {
+ aerr << "Invalid mode requested: " << mode.string() << endl;
+ return -EINVAL;
+ }
+ int fd = open(fullPath.string(), flags, S_IRWXU|S_IRWXG);
if (fd < 0) {
return fd;
}
@@ -80,14 +100,27 @@
security_context_t tmp = NULL;
int ret = getfilecon(fullPath.string(), &tmp);
Unique_SecurityContext context(tmp);
- int accessGranted = selinux_check_access(seLinuxContext8.string(), context.get(),
- "file", "write", NULL);
- if (accessGranted != 0) {
- close(fd);
- aerr << "System server has no access to file context " << context.get()
- << " (from path " << fullPath.string() << ", context "
- << seLinuxContext8.string() << ")" << endl;
- return -EPERM;
+ if (checkWrite) {
+ int accessGranted = selinux_check_access(seLinuxContext8.string(), context.get(),
+ "file", "write", NULL);
+ if (accessGranted != 0) {
+ close(fd);
+ aerr << "System server has no access to write file context " << context.get()
+ << " (from path " << fullPath.string() << ", context "
+ << seLinuxContext8.string() << ")" << endl;
+ return -EPERM;
+ }
+ }
+ if (checkRead) {
+ int accessGranted = selinux_check_access(seLinuxContext8.string(), context.get(),
+ "file", "read", NULL);
+ if (accessGranted != 0) {
+ close(fd);
+ aerr << "System server has no access to read file context " << context.get()
+ << " (from path " << fullPath.string() << ", context "
+ << seLinuxContext8.string() << ")" << endl;
+ return -EPERM;
+ }
}
}
return fd;
diff --git a/cmds/dumpstate/bugreport-format.md b/cmds/dumpstate/bugreport-format.md
index b995b80..dee89cf 100644
--- a/cmds/dumpstate/bugreport-format.md
+++ b/cmds/dumpstate/bugreport-format.md
@@ -56,8 +56,20 @@
- `description.txt`: whose value is a multi-line, detailed description of the problem.
## Android O versions
-On _Android O (OhMightyAndroidWhatsYourNextReleaseName?)_, the following changes were made:
-- The ANR traces are added to the `FS` folder, typically under `FS/data/anr` (version `2.0-dev-1`).
+On _Android O (Oreo)_, the following changes were made:
+- The ANR traces are added to the `FS` folder, typically under `FS/data/anr` (version `2.0-dev-split-anr`).
+
+## Android P versions
+On _Android P (PleaseMightyAndroidWhatsYourNextReleaseName?)_, the following changes were made:
+- Dumpsys sections are dumped by priority (version `2.0-dev-priority-dumps`).
+ Supported priorities can be specified when registering framework services. Section headers are
+ changed to contain priority info.
+ `DUMPSYS` -> `DUMPSYS CRITICAL/HIGH/NORMAL`
+ `DUMP OF SERVICE <servicename>` -> `DUMP OF SERVICE CRITICAL/HIGH/NORMAL <servicename>`
+ Supported Priorities:
+ - CRITICAL - services that must dump first, and fast (under 100ms). Ex: cpuinfo.
+ - HIGH - services that also must dump first, but can take longer (under 250ms) to dump. Ex: meminfo.
+ - NORMAL - services that have no rush to dump and can take a long time (under 10s).
## Intermediate versions
During development, the versions will be suffixed with _-devX_ or
diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp
index e792942..201b5a3 100644
--- a/cmds/dumpstate/dumpstate.cpp
+++ b/cmds/dumpstate/dumpstate.cpp
@@ -1055,6 +1055,40 @@
RunCommand("IP RULES v6", {"ip", "-6", "rule", "show"});
}
+// Runs dumpsys on services that must dump first and and will take less than 100ms to dump.
+static void RunDumpsysCritical() {
+ if (ds.CurrentVersionSupportsPriorityDumps()) {
+ RunDumpsys("DUMPSYS CRITICAL", {"--priority", "CRITICAL"},
+ CommandOptions::WithTimeout(5).DropRoot().Build());
+ } else {
+ RunDumpsys("DUMPSYS MEMINFO", {"meminfo", "-a"},
+ CommandOptions::WithTimeout(90).DropRoot().Build());
+ RunDumpsys("DUMPSYS CPUINFO", {"cpuinfo", "-a"},
+ CommandOptions::WithTimeout(10).DropRoot().Build());
+ }
+}
+
+// Runs dumpsys on services that must dump first but can take up to 250ms to dump.
+static void RunDumpsysHigh() {
+ if (ds.CurrentVersionSupportsPriorityDumps()) {
+ RunDumpsys("DUMPSYS HIGH", {"--priority", "HIGH"},
+ CommandOptions::WithTimeout(20).DropRoot().Build());
+ } else {
+ RunDumpsys("NETWORK DIAGNOSTICS", {"connectivity", "--diag"});
+ }
+}
+
+// Runs dumpsys on services that must dump but can take up to 10s to dump.
+static void RunDumpsysNormal() {
+ if (ds.CurrentVersionSupportsPriorityDumps()) {
+ RunDumpsys("DUMPSYS NORMAL", {"--priority", "NORMAL"},
+ CommandOptions::WithTimeout(90).DropRoot().Build());
+ } else {
+ RunDumpsys("DUMPSYS", {"--skip", "meminfo", "cpuinfo"},
+ CommandOptions::WithTimeout(90).Build(), 10);
+ }
+}
+
static void dumpstate() {
DurationReporter duration_reporter("DUMPSTATE");
@@ -1080,7 +1114,7 @@
DumpFile("KERNEL SYNC", "/d/sync");
RunCommand("PROCESSES AND THREADS",
- {"ps", "-A", "-T", "-Z", "-O", "pri,nice,rtprio,sched,pcy"});
+ {"ps", "-A", "-T", "-Z", "-O", "pri,nice,rtprio,sched,pcy,time"});
RunCommand("LIBRANK", {"librank"}, CommandOptions::AS_ROOT);
if (ds.IsZipping()) {
@@ -1146,15 +1180,11 @@
RunCommand("IPv6 ND CACHE", {"ip", "-6", "neigh", "show"});
RunCommand("MULTICAST ADDRESSES", {"ip", "maddr"});
- RunDumpsys("NETWORK DIAGNOSTICS", {"connectivity", "--diag"},
- CommandOptions::WithTimeout(10).Build());
+ RunDumpsysHigh();
RunCommand("SYSTEM PROPERTIES", {"getprop"});
- RunCommand("VOLD DUMP", {"vdc", "dump"});
- RunCommand("SECURE CONTAINERS", {"vdc", "asec", "list"});
-
- RunCommand("STORAGED TASKIOINFO", {"storaged", "-u"}, CommandOptions::WithTimeout(10).Build());
+ RunCommand("STORAGED IO INFO", {"storaged", "-u", "-p"});
RunCommand("FILESYSTEMS & FREE SPACE", {"df"});
@@ -1200,8 +1230,7 @@
printf("== Android Framework Services\n");
printf("========================================================\n");
- RunDumpsys("DUMPSYS", {"--skip", "meminfo", "cpuinfo"}, CommandOptions::WithTimeout(90).Build(),
- 10);
+ RunDumpsysNormal();
printf("========================================================\n");
printf("== Checkins\n");
@@ -1599,6 +1628,7 @@
do_fb = 0;
} else if (ds.extra_options_ == "bugreportwear") {
ds.update_progress_ = true;
+ do_zip_file = 1;
} else if (ds.extra_options_ == "bugreporttelephony") {
telephony_only = true;
} else {
@@ -1642,10 +1672,12 @@
ds.version_ = VERSION_CURRENT;
}
- if (ds.version_ != VERSION_CURRENT && ds.version_ != VERSION_SPLIT_ANR) {
- MYLOGE("invalid version requested ('%s'); suppported values are: ('%s', '%s', '%s')\n",
- ds.version_.c_str(), VERSION_DEFAULT.c_str(), VERSION_CURRENT.c_str(),
- VERSION_SPLIT_ANR.c_str());
+ if (ds.version_ != VERSION_CURRENT && ds.version_ != VERSION_SPLIT_ANR &&
+ ds.version_ != VERSION_PRIORITY_DUMPS) {
+ MYLOGE(
+ "invalid version requested ('%s'); suppported values are: ('%s', '%s', '%s', '%s')\n",
+ ds.version_.c_str(), VERSION_DEFAULT.c_str(), VERSION_CURRENT.c_str(),
+ VERSION_SPLIT_ANR.c_str(), VERSION_PRIORITY_DUMPS.c_str());
exit(1);
}
@@ -1836,10 +1868,7 @@
// Invoking the following dumpsys calls before dump_traces() to try and
// keep the system stats as close to its initial state as possible.
- RunDumpsys("DUMPSYS MEMINFO", {"meminfo", "-a"},
- CommandOptions::WithTimeout(90).DropRoot().Build());
- RunDumpsys("DUMPSYS CPUINFO", {"cpuinfo", "-a"},
- CommandOptions::WithTimeout(10).DropRoot().Build());
+ RunDumpsysCritical();
// TODO: Drop root user and move into dumpstate() once b/28633932 is fixed.
dump_raft();
@@ -1869,6 +1898,9 @@
RunCommand("DETAILED SOCKET STATE", {"ss", "-eionptu"},
CommandOptions::WithTimeout(10).Build());
+ // Run iotop as root to show top 100 IO threads
+ RunCommand("IOTOP", {"iotop", "-n", "1", "-m", "100"});
+
if (!DropRootUser()) {
return -1;
}
diff --git a/cmds/dumpstate/dumpstate.h b/cmds/dumpstate/dumpstate.h
index 7757c1e..1bfafba 100644
--- a/cmds/dumpstate/dumpstate.h
+++ b/cmds/dumpstate/dumpstate.h
@@ -149,9 +149,15 @@
/*
* Temporary version that adds a anr-traces.txt entry. Once tools support it, the current version
- * will be bumped to 2.0-dev-1.
+ * will be bumped to 2.0.
*/
-static std::string VERSION_SPLIT_ANR = "2.0-dev-1";
+static std::string VERSION_SPLIT_ANR = "2.0-dev-split-anr";
+
+/*
+ * Temporary version that adds priority based dumps. Once tools support it, the current version
+ * will be bumped to 2.0.
+ */
+static std::string VERSION_PRIORITY_DUMPS = "2.0-dev-priority-dumps";
/*
* "Alias" for the current version.
@@ -266,6 +272,9 @@
/* Gets the path of a bugreport file with the given suffix. */
std::string GetPath(const std::string& suffix) const;
+ /* Returns true if the current version supports priority dump feature. */
+ bool CurrentVersionSupportsPriorityDumps() const;
+
// TODO: initialize fields on constructor
// dumpstate id - unique after each device reboot.
diff --git a/cmds/dumpstate/utils.cpp b/cmds/dumpstate/utils.cpp
index a96a69d..6ff0dae 100644
--- a/cmds/dumpstate/utils.cpp
+++ b/cmds/dumpstate/utils.cpp
@@ -257,6 +257,10 @@
name_.c_str(), suffix.c_str());
}
+bool Dumpstate::CurrentVersionSupportsPriorityDumps() const {
+ return (version_ == VERSION_PRIORITY_DUMPS);
+}
+
void Dumpstate::SetProgress(std::unique_ptr<Progress> progress) {
progress_ = std::move(progress);
}
diff --git a/cmds/dumpsys/Android.bp b/cmds/dumpsys/Android.bp
index 3476964..f68b862 100644
--- a/cmds/dumpsys/Android.bp
+++ b/cmds/dumpsys/Android.bp
@@ -17,6 +17,10 @@
"libbinder",
],
+ static_libs: [
+ "libserviceutils",
+ ],
+
clang: true,
}
diff --git a/cmds/dumpsys/dumpsys.cpp b/cmds/dumpsys/dumpsys.cpp
index 3227749..c36ab08 100644
--- a/cmds/dumpsys/dumpsys.cpp
+++ b/cmds/dumpsys/dumpsys.cpp
@@ -25,6 +25,7 @@
#include <binder/Parcel.h>
#include <binder/ProcessState.h>
#include <binder/TextOutput.h>
+#include <serviceutils/PriorityDumper.h>
#include <utils/Log.h>
#include <utils/Vector.h>
@@ -53,13 +54,18 @@
static void usage() {
fprintf(stderr,
- "usage: dumpsys\n"
+ "usage: dumpsys\n"
" To dump all services.\n"
"or:\n"
- " dumpsys [-t TIMEOUT] [--help | -l | --skip SERVICES | SERVICE [ARGS]]\n"
+ " dumpsys [-t TIMEOUT] [--priority LEVEL] [--help | -l | --skip SERVICES | "
+ "SERVICE [ARGS]]\n"
" --help: shows this help\n"
" -l: only list services, do not dump them\n"
" -t TIMEOUT: TIMEOUT to use in seconds instead of default 10 seconds\n"
+ " --proto: filter services that support dumping data in proto format. Dumps"
+ " will be in proto format.\n"
+ " --priority LEVEL: filter services based on specified priority\n"
+ " LEVEL must be one of CRITICAL | HIGH | NORMAL\n"
" --skip SERVICES: dumps all services but SERVICES (comma-separated list)\n"
" SERVICE [ARGS]: dumps only service SERVICE, optionally passing ARGS to it\n");
}
@@ -73,18 +79,38 @@
return false;
}
+static bool ConvertPriorityTypeToBitmask(const String16& type, int& bitmask) {
+ if (type == PriorityDumper::PRIORITY_ARG_CRITICAL) {
+ bitmask = IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL;
+ return true;
+ }
+ if (type == PriorityDumper::PRIORITY_ARG_HIGH) {
+ bitmask = IServiceManager::DUMP_FLAG_PRIORITY_HIGH;
+ return true;
+ }
+ if (type == PriorityDumper::PRIORITY_ARG_NORMAL) {
+ bitmask = IServiceManager::DUMP_FLAG_PRIORITY_NORMAL;
+ return true;
+ }
+ return false;
+}
+
int Dumpsys::main(int argc, char* const argv[]) {
Vector<String16> services;
Vector<String16> args;
+ String16 priorityType;
Vector<String16> skippedServices;
+ Vector<String16> protoServices;
bool showListOnly = false;
bool skipServices = false;
+ bool filterByProto = false;
int timeoutArg = 10;
- static struct option longOptions[] = {
- {"skip", no_argument, 0, 0 },
- {"help", no_argument, 0, 0 },
- { 0, 0, 0, 0 }
- };
+ int dumpPriorityFlags = IServiceManager::DUMP_FLAG_PRIORITY_ALL;
+ static struct option longOptions[] = {{"priority", required_argument, 0, 0},
+ {"proto", no_argument, 0, 0},
+ {"skip", no_argument, 0, 0},
+ {"help", no_argument, 0, 0},
+ {0, 0, 0, 0}};
// Must reset optind, otherwise subsequent calls will fail (wouldn't happen on main.cpp, but
// happens on test cases).
@@ -103,9 +129,18 @@
case 0:
if (!strcmp(longOptions[optionIndex].name, "skip")) {
skipServices = true;
+ } else if (!strcmp(longOptions[optionIndex].name, "proto")) {
+ filterByProto = true;
} else if (!strcmp(longOptions[optionIndex].name, "help")) {
usage();
return 0;
+ } else if (!strcmp(longOptions[optionIndex].name, "priority")) {
+ priorityType = String16(String8(optarg));
+ if (!ConvertPriorityTypeToBitmask(priorityType, dumpPriorityFlags)) {
+ fprintf(stderr, "\n");
+ usage();
+ return -1;
+ }
}
break;
@@ -151,9 +186,23 @@
if (services.empty() || showListOnly) {
// gets all services
- services = sm_->listServices();
+ services = sm_->listServices(dumpPriorityFlags);
services.sort(sort_func);
- args.add(String16("-a"));
+ if (filterByProto) {
+ protoServices = sm_->listServices(IServiceManager::DUMP_FLAG_PROTO);
+ protoServices.sort(sort_func);
+ Vector<String16> intersection;
+ std::set_intersection(services.begin(), services.end(), protoServices.begin(),
+ protoServices.end(), std::back_inserter(intersection));
+ services = std::move(intersection);
+ args.insertAt(String16(PriorityDumper::PROTO_ARG), 0);
+ }
+ if (dumpPriorityFlags != IServiceManager::DUMP_FLAG_PRIORITY_ALL) {
+ args.insertAt(String16(PriorityDumper::PRIORITY_ARG), 0);
+ args.insertAt(priorityType, 1);
+ } else {
+ args.add(String16("-a"));
+ }
}
const size_t N = services.size();
@@ -197,7 +246,11 @@
if (N > 1) {
aout << "------------------------------------------------------------"
"-------------------" << endl;
- aout << "DUMP OF SERVICE " << service_name << ":" << endl;
+ if (dumpPriorityFlags == IServiceManager::DUMP_FLAG_PRIORITY_ALL) {
+ aout << "DUMP OF SERVICE " << service_name << ":" << endl;
+ } else {
+ aout << "DUMP OF SERVICE " << priorityType << " " << service_name << ":" << endl;
+ }
}
// dump blocks until completion, so spawn a thread..
diff --git a/cmds/dumpsys/tests/Android.bp b/cmds/dumpsys/tests/Android.bp
index 39fcb80..e182b9d 100644
--- a/cmds/dumpsys/tests/Android.bp
+++ b/cmds/dumpsys/tests/Android.bp
@@ -15,6 +15,7 @@
static_libs: [
"libdumpsys",
"libgmock",
+ "libserviceutils",
],
clang: true,
diff --git a/cmds/dumpsys/tests/dumpsys_test.cpp b/cmds/dumpsys/tests/dumpsys_test.cpp
index 16fefe6..18a4da9 100644
--- a/cmds/dumpsys/tests/dumpsys_test.cpp
+++ b/cmds/dumpsys/tests/dumpsys_test.cpp
@@ -22,6 +22,7 @@
#include <gtest/gtest.h>
#include <android-base/file.h>
+#include <serviceutils/PriorityDumper.h>
#include <utils/String16.h>
#include <utils/String8.h>
#include <utils/Vector.h>
@@ -50,8 +51,8 @@
public:
MOCK_CONST_METHOD1(getService, sp<IBinder>(const String16&));
MOCK_CONST_METHOD1(checkService, sp<IBinder>(const String16&));
- MOCK_METHOD3(addService, status_t(const String16&, const sp<IBinder>&, bool));
- MOCK_METHOD0(listServices, Vector<String16>());
+ MOCK_METHOD4(addService, status_t(const String16&, const sp<IBinder>&, bool, int));
+ MOCK_METHOD1(listServices, Vector<String16>(int));
protected:
MOCK_METHOD0(onAsBinder, IBinder*());
@@ -131,7 +132,16 @@
for (auto& service : services) {
services16.add(String16(service.c_str()));
}
- EXPECT_CALL(sm_, listServices()).WillRepeatedly(Return(services16));
+ EXPECT_CALL(sm_, listServices(IServiceManager::DUMP_FLAG_PRIORITY_ALL))
+ .WillRepeatedly(Return(services16));
+ }
+
+ void ExpectListServicesWithPriority(std::vector<std::string> services, int dumpFlags) {
+ Vector<String16> services16;
+ for (auto& service : services) {
+ services16.add(String16(service.c_str()));
+ }
+ EXPECT_CALL(sm_, listServices(dumpFlags)).WillRepeatedly(Return(services16));
}
sp<BinderMock> ExpectCheckService(const char* name, bool running = true) {
@@ -179,7 +189,10 @@
}
void AssertRunningServices(const std::vector<std::string>& services) {
- std::string expected("Currently running services:\n");
+ std::string expected;
+ if (services.size() > 1) {
+ expected.append("Currently running services:\n");
+ }
for (const std::string& service : services) {
expected.append(" ").append(service).append("\n");
}
@@ -198,6 +211,13 @@
EXPECT_THAT(stdout_, HasSubstr("DUMP OF SERVICE " + service + ":\n" + dump));
}
+ void AssertDumpedWithPriority(const std::string& service, const std::string& dump,
+ const char16_t* priorityType) {
+ std::string priority = String8(priorityType).c_str();
+ EXPECT_THAT(stdout_,
+ HasSubstr("DUMP OF SERVICE " + priority + " " + service + ":\n" + dump));
+ }
+
void AssertNotDumped(const std::string& dump) {
EXPECT_THAT(stdout_, Not(HasSubstr(dump)));
}
@@ -236,6 +256,39 @@
AssertNotDumped({"Valet"});
}
+// Tests 'dumpsys -l --priority HIGH'
+TEST_F(DumpsysTest, ListAllServicesWithPriority) {
+ ExpectListServicesWithPriority({"Locksmith", "Valet"}, IServiceManager::DUMP_FLAG_PRIORITY_HIGH);
+ ExpectCheckService("Locksmith");
+ ExpectCheckService("Valet");
+
+ CallMain({"-l", "--priority", "HIGH"});
+
+ AssertRunningServices({"Locksmith", "Valet"});
+}
+
+// Tests 'dumpsys -l --priority HIGH' with and empty list
+TEST_F(DumpsysTest, ListEmptyServicesWithPriority) {
+ ExpectListServicesWithPriority({}, IServiceManager::DUMP_FLAG_PRIORITY_HIGH);
+
+ CallMain({"-l", "--priority", "HIGH"});
+
+ AssertRunningServices({});
+}
+
+// Tests 'dumpsys -l --proto'
+TEST_F(DumpsysTest, ListAllServicesWithProto) {
+ ExpectListServicesWithPriority({"Locksmith", "Valet", "Car"},
+ IServiceManager::DUMP_FLAG_PRIORITY_ALL);
+ ExpectListServicesWithPriority({"Valet", "Car"}, IServiceManager::DUMP_FLAG_PROTO);
+ ExpectCheckService("Car");
+ ExpectCheckService("Valet");
+
+ CallMain({"-l", "--proto"});
+
+ AssertRunningServices({"Car", "Valet"});
+}
+
// Tests 'dumpsys service_name' on a service is running
TEST_F(DumpsysTest, DumpRunningService) {
ExpectDump("Valet", "Here's your car");
@@ -300,3 +353,98 @@
AssertNotDumped("dump3");
AssertNotDumped("dump5");
}
+
+// Tests 'dumpsys --skip skipped3 skipped5 --priority CRITICAL', which should skip these services
+TEST_F(DumpsysTest, DumpWithSkipAndPriority) {
+ ExpectListServicesWithPriority({"running1", "stopped2", "skipped3", "running4", "skipped5"},
+ IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL);
+ ExpectDump("running1", "dump1");
+ ExpectCheckService("stopped2", false);
+ ExpectDump("skipped3", "dump3");
+ ExpectDump("running4", "dump4");
+ ExpectDump("skipped5", "dump5");
+
+ CallMain({"--priority", "CRITICAL", "--skip", "skipped3", "skipped5"});
+
+ AssertRunningServices({"running1", "running4", "skipped3 (skipped)", "skipped5 (skipped)"});
+ AssertDumpedWithPriority("running1", "dump1", PriorityDumper::PRIORITY_ARG_CRITICAL);
+ AssertDumpedWithPriority("running4", "dump4", PriorityDumper::PRIORITY_ARG_CRITICAL);
+ AssertStopped("stopped2");
+ AssertNotDumped("dump3");
+ AssertNotDumped("dump5");
+}
+
+// Tests 'dumpsys --priority CRITICAL'
+TEST_F(DumpsysTest, DumpWithPriorityCritical) {
+ ExpectListServicesWithPriority({"runningcritical1", "runningcritical2"},
+ IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL);
+ ExpectDump("runningcritical1", "dump1");
+ ExpectDump("runningcritical2", "dump2");
+
+ CallMain({"--priority", "CRITICAL"});
+
+ AssertRunningServices({"runningcritical1", "runningcritical2"});
+ AssertDumpedWithPriority("runningcritical1", "dump1", PriorityDumper::PRIORITY_ARG_CRITICAL);
+ AssertDumpedWithPriority("runningcritical2", "dump2", PriorityDumper::PRIORITY_ARG_CRITICAL);
+}
+
+// Tests 'dumpsys --priority HIGH'
+TEST_F(DumpsysTest, DumpWithPriorityHigh) {
+ ExpectListServicesWithPriority({"runninghigh1", "runninghigh2"},
+ IServiceManager::DUMP_FLAG_PRIORITY_HIGH);
+ ExpectDump("runninghigh1", "dump1");
+ ExpectDump("runninghigh2", "dump2");
+
+ CallMain({"--priority", "HIGH"});
+
+ AssertRunningServices({"runninghigh1", "runninghigh2"});
+ AssertDumpedWithPriority("runninghigh1", "dump1", PriorityDumper::PRIORITY_ARG_HIGH);
+ AssertDumpedWithPriority("runninghigh2", "dump2", PriorityDumper::PRIORITY_ARG_HIGH);
+}
+
+// Tests 'dumpsys --priority NORMAL'
+TEST_F(DumpsysTest, DumpWithPriorityNormal) {
+ ExpectListServicesWithPriority({"runningnormal1", "runningnormal2"},
+ IServiceManager::DUMP_FLAG_PRIORITY_NORMAL);
+ ExpectDump("runningnormal1", "dump1");
+ ExpectDump("runningnormal2", "dump2");
+
+ CallMain({"--priority", "NORMAL"});
+
+ AssertRunningServices({"runningnormal1", "runningnormal2"});
+ AssertDumpedWithPriority("runningnormal1", "dump1", PriorityDumper::PRIORITY_ARG_NORMAL);
+ AssertDumpedWithPriority("runningnormal2", "dump2", PriorityDumper::PRIORITY_ARG_NORMAL);
+}
+
+// Tests 'dumpsys --proto'
+TEST_F(DumpsysTest, DumpWithProto) {
+ ExpectListServicesWithPriority({"run8", "run1", "run2", "run5"},
+ IServiceManager::DUMP_FLAG_PRIORITY_ALL);
+ ExpectListServicesWithPriority({"run3", "run2", "run4", "run8"},
+ IServiceManager::DUMP_FLAG_PROTO);
+ ExpectDump("run2", "dump1");
+ ExpectDump("run8", "dump2");
+
+ CallMain({"--proto"});
+
+ AssertRunningServices({"run2", "run8"});
+ AssertDumped("run2", "dump1");
+ AssertDumped("run8", "dump2");
+}
+
+// Tests 'dumpsys --priority HIGH --proto'
+TEST_F(DumpsysTest, DumpWithPriorityHighAndProto) {
+ ExpectListServicesWithPriority({"runninghigh1", "runninghigh2"},
+ IServiceManager::DUMP_FLAG_PRIORITY_HIGH);
+ ExpectListServicesWithPriority({"runninghigh1", "runninghigh2", "runninghigh3"},
+ IServiceManager::DUMP_FLAG_PROTO);
+
+ ExpectDump("runninghigh1", "dump1");
+ ExpectDump("runninghigh2", "dump2");
+
+ CallMain({"--priority", "HIGH", "--proto"});
+
+ AssertRunningServices({"runninghigh1", "runninghigh2"});
+ AssertDumpedWithPriority("runninghigh1", "dump1", PriorityDumper::PRIORITY_ARG_HIGH);
+ AssertDumpedWithPriority("runninghigh2", "dump2", PriorityDumper::PRIORITY_ARG_HIGH);
+}
diff --git a/cmds/flatland/GLHelper.cpp b/cmds/flatland/GLHelper.cpp
index dfc3e58..d5b3372 100644
--- a/cmds/flatland/GLHelper.cpp
+++ b/cmds/flatland/GLHelper.cpp
@@ -269,24 +269,10 @@
return false;
}
- SurfaceComposerClient::openGlobalTransaction();
- err = sc->setLayer(0x7FFFFFFF);
- if (err != NO_ERROR) {
- fprintf(stderr, "SurfaceComposer::setLayer error: %#x\n", err);
- return false;
- }
- err = sc->setMatrix(scale, 0.0f, 0.0f, scale);
- if (err != NO_ERROR) {
- fprintf(stderr, "SurfaceComposer::setMatrix error: %#x\n", err);
- return false;
- }
-
- err = sc->show();
- if (err != NO_ERROR) {
- fprintf(stderr, "SurfaceComposer::show error: %#x\n", err);
- return false;
- }
- SurfaceComposerClient::closeGlobalTransaction();
+ SurfaceComposerClient::Transaction{}.setLayer(sc, 0x7FFFFFFF)
+ .setMatrix(sc, scale, 0.0f, 0.0f, scale)
+ .show(sc)
+ .apply();
sp<ANativeWindow> anw = sc->getSurface();
EGLSurface s = eglCreateWindowSurface(mDisplay, mConfig, anw.get(), NULL);
diff --git a/cmds/installd/dexopt.cpp b/cmds/installd/dexopt.cpp
index 20b7728..af2c527 100644
--- a/cmds/installd/dexopt.cpp
+++ b/cmds/installd/dexopt.cpp
@@ -1385,6 +1385,8 @@
oat_dir.c_str(),
is_secondary_dex,
oat_path)) {
+ LOG(ERROR) << "Could not create oat out path for "
+ << apk_path << " with oat dir " << oat_dir;
return false;
}
oat_file_fd->reset(open(oat_path, O_RDONLY));
@@ -1489,7 +1491,7 @@
// Prepares the oat dir for the secondary dex files.
static bool prepare_secondary_dex_oat_dir(const std::string& dex_path, int uid,
- const char* instruction_set, std::string* oat_dir_out) {
+ const char* instruction_set) {
unsigned long dirIndex = dex_path.rfind('/');
if (dirIndex == std::string::npos) {
LOG(ERROR ) << "Unexpected dir structure for secondary dex " << dex_path;
@@ -1506,10 +1508,8 @@
char oat_dir[PKG_PATH_MAX];
snprintf(oat_dir, PKG_PATH_MAX, "%s/oat", dex_dir.c_str());
- oat_dir_out->assign(oat_dir);
- // Create oat/isa output directory.
- if (prepare_app_cache_dir(*oat_dir_out, instruction_set, oat_dir_mode, uid, uid) != 0) {
+ if (prepare_app_cache_dir(oat_dir, instruction_set, oat_dir_mode, uid, uid) != 0) {
LOG(ERROR) << "Could not prepare oat/isa dir for secondary dex: " << dex_path;
return false;
}
@@ -1517,39 +1517,128 @@
return true;
}
-static int constexpr DEXOPTANALYZER_BIN_EXEC_ERROR = 200;
+// Return codes for identifying the reason why dexoptanalyzer was not invoked when processing
+// secondary dex files. This return codes are returned by the child process created for
+// analyzing secondary dex files in process_secondary_dex_dexopt.
-// Verifies the result of dexoptanalyzer executed for the apk_path.
+// The dexoptanalyzer was not invoked because of validation or IO errors.
+static int constexpr SECONDARY_DEX_DEXOPTANALYZER_SKIPPED = 200;
+// The dexoptanalyzer was not invoked because the dex file does not exist anymore.
+static int constexpr SECONDARY_DEX_DEXOPTANALYZER_SKIPPED_NO_FILE = 201;
+
+// Verifies the result of analyzing secondary dex files from process_secondary_dex_dexopt.
// If the result is valid returns true and sets dexopt_needed_out to a valid value.
// Returns false for errors or unexpected result values.
-static bool process_dexoptanalyzer_result(const std::string& dex_path, int result,
+// The result is expected to be either one of SECONDARY_DEX_* codes or a valid exit code
+// of dexoptanalyzer.
+static bool process_secondary_dexoptanalyzer_result(const std::string& dex_path, int result,
int* dexopt_needed_out) {
// The result values are defined in dexoptanalyzer.
switch (result) {
- case 0: // no_dexopt_needed
+ case 0: // dexoptanalyzer: no_dexopt_needed
*dexopt_needed_out = NO_DEXOPT_NEEDED; return true;
- case 1: // dex2oat_from_scratch
+ case 1: // dexoptanalyzer: dex2oat_from_scratch
*dexopt_needed_out = DEX2OAT_FROM_SCRATCH; return true;
- case 5: // dex2oat_for_bootimage_odex
+ case 5: // dexoptanalyzer: dex2oat_for_bootimage_odex
*dexopt_needed_out = -DEX2OAT_FOR_BOOT_IMAGE; return true;
- case 6: // dex2oat_for_filter_odex
+ case 6: // dexoptanalyzer: dex2oat_for_filter_odex
*dexopt_needed_out = -DEX2OAT_FOR_FILTER; return true;
- case 7: // dex2oat_for_relocation_odex
+ case 7: // dexoptanalyzer: dex2oat_for_relocation_odex
*dexopt_needed_out = -DEX2OAT_FOR_RELOCATION; return true;
- case 2: // dex2oat_for_bootimage_oat
- case 3: // dex2oat_for_filter_oat
- case 4: // dex2oat_for_relocation_oat
+ case 2: // dexoptanalyzer: dex2oat_for_bootimage_oat
+ case 3: // dexoptanalyzer: dex2oat_for_filter_oat
+ case 4: // dexoptanalyzer: dex2oat_for_relocation_oat
LOG(ERROR) << "Dexoptnalyzer return the status of an oat file."
<< " Expected odex file status for secondary dex " << dex_path
<< " : dexoptanalyzer result=" << result;
return false;
+ case SECONDARY_DEX_DEXOPTANALYZER_SKIPPED_NO_FILE:
+ // If the file does not exist there's no need for dexopt.
+ *dexopt_needed_out = NO_DEXOPT_NEEDED;
+ return true;
+ case SECONDARY_DEX_DEXOPTANALYZER_SKIPPED:
+ return false;
default:
- LOG(ERROR) << "Unexpected result for dexoptanalyzer " << dex_path
- << " exec_dexoptanalyzer result=" << result;
+ LOG(ERROR) << "Unexpected result from analyzing secondary dex " << dex_path
+ << " result=" << result;
return false;
}
}
+enum SecondaryDexAccess {
+ kSecondaryDexAccessReadOk = 0,
+ kSecondaryDexAccessDoesNotExist = 1,
+ kSecondaryDexAccessPermissionError = 2,
+ kSecondaryDexAccessIOError = 3
+};
+
+static SecondaryDexAccess check_secondary_dex_access(const std::string& dex_path) {
+ // Check if the path exists and can be read. If not, there's nothing to do.
+ if (access(dex_path.c_str(), R_OK) == 0) {
+ return kSecondaryDexAccessReadOk;
+ } else {
+ if (errno == ENOENT) {
+ LOG(INFO) << "Secondary dex does not exist: " << dex_path;
+ return kSecondaryDexAccessDoesNotExist;
+ } else {
+ PLOG(ERROR) << "Could not access secondary dex " << dex_path;
+ return errno == EACCES
+ ? kSecondaryDexAccessPermissionError
+ : kSecondaryDexAccessIOError;
+ }
+ }
+}
+
+static bool is_file_public(const std::string& filename) {
+ struct stat file_stat;
+ if (stat(filename.c_str(), &file_stat) == 0) {
+ return (file_stat.st_mode & S_IROTH) != 0;
+ }
+ return false;
+}
+
+// Create the oat file structure for the secondary dex 'dex_path' and assign
+// the individual path component to the 'out_' parameters.
+static bool create_secondary_dex_oat_layout(const std::string& dex_path, const std::string& isa,
+ char* out_oat_dir, char* out_oat_isa_dir, char* out_oat_path) {
+ size_t dirIndex = dex_path.rfind('/');
+ if (dirIndex == std::string::npos) {
+ LOG(ERROR) << "Unexpected dir structure for dex file " << dex_path;
+ return false;
+ }
+ // TODO(calin): we have similar computations in at lest 3 other places
+ // (InstalldNativeService, otapropt and dexopt). Unify them and get rid of snprintf by
+ // using string append.
+ std::string apk_dir = dex_path.substr(0, dirIndex);
+ snprintf(out_oat_dir, PKG_PATH_MAX, "%s/oat", apk_dir.c_str());
+ snprintf(out_oat_isa_dir, PKG_PATH_MAX, "%s/%s", out_oat_dir, isa.c_str());
+
+ if (!create_oat_out_path(dex_path.c_str(), isa.c_str(), out_oat_dir,
+ /*is_secondary_dex*/true, out_oat_path)) {
+ LOG(ERROR) << "Could not create oat path for secondary dex " << dex_path;
+ return false;
+ }
+ return true;
+}
+
+// Validate that the dexopt_flags contain a valid storage flag and convert that to an installd
+// recognized storage flags (FLAG_STORAGE_CE or FLAG_STORAGE_DE).
+static bool validate_dexopt_storage_flags(int dexopt_flags, int* out_storage_flag) {
+ if ((dexopt_flags & DEXOPT_STORAGE_CE) != 0) {
+ *out_storage_flag = FLAG_STORAGE_CE;
+ if ((dexopt_flags & DEXOPT_STORAGE_DE) != 0) {
+ LOG(ERROR) << "Ambiguous secondary dex storage flag. Both, CE and DE, flags are set";
+ return false;
+ }
+ } else if ((dexopt_flags & DEXOPT_STORAGE_DE) != 0) {
+ *out_storage_flag = FLAG_STORAGE_DE;
+ } else {
+ LOG(ERROR) << "Secondary dex storage flag must be set";
+ return false;
+ }
+ return true;
+}
+
// Processes the dex_path as a secondary dex files and return true if the path dex file should
// be compiled. Returns false for errors (logged) or true if the secondary dex path was process
// successfully.
@@ -1557,126 +1646,107 @@
// - is_public_out: whether or not the oat file should not be made public
// - dexopt_needed_out: valid OatFileAsssitant::DexOptNeeded
// - oat_dir_out: the oat dir path where the oat file should be stored
-// - dex_path_out: the real path of the dex file
-static bool process_secondary_dex_dexopt(const char* original_dex_path, const char* pkgname,
+static bool process_secondary_dex_dexopt(const std::string& dex_path, const char* pkgname,
int dexopt_flags, const char* volume_uuid, int uid, const char* instruction_set,
const char* compiler_filter, bool* is_public_out, int* dexopt_needed_out,
- std::string* oat_dir_out, std::string* dex_path_out, bool downgrade,
- const char* class_loader_context) {
+ std::string* oat_dir_out, bool downgrade, const char* class_loader_context) {
+ LOG(DEBUG) << "Processing secondary dex path " << dex_path;
int storage_flag;
-
- if ((dexopt_flags & DEXOPT_STORAGE_CE) != 0) {
- storage_flag = FLAG_STORAGE_CE;
- if ((dexopt_flags & DEXOPT_STORAGE_DE) != 0) {
- LOG(ERROR) << "Ambiguous secondary dex storage flag. Both, CE and DE, flags are set";
- return false;
- }
- } else if ((dexopt_flags & DEXOPT_STORAGE_DE) != 0) {
- storage_flag = FLAG_STORAGE_DE;
- } else {
- LOG(ERROR) << "Secondary dex storage flag must be set";
+ if (!validate_dexopt_storage_flags(dexopt_flags, &storage_flag)) {
return false;
}
-
- {
- // As opposed to the primary apk, secondary dex files might contain symlinks.
- // Resolve the path before passing it to the validate method to
- // make sure the verification is done on the real location.
- UniqueCPtr<char> dex_real_path_cstr(realpath(original_dex_path, nullptr));
- if (dex_real_path_cstr == nullptr) {
- PLOG(ERROR) << "Could not get the real path of the secondary dex file "
- << original_dex_path;
- return false;
- } else {
- dex_path_out->assign(dex_real_path_cstr.get());
- }
- }
- const std::string& dex_path = *dex_path_out;
- if (!validate_dex_path_size(dex_path)) {
+ // Compute the oat dir as it's not easy to extract it from the child computation.
+ char oat_path[PKG_PATH_MAX];
+ char oat_dir[PKG_PATH_MAX];
+ char oat_isa_dir[PKG_PATH_MAX];
+ if (!create_secondary_dex_oat_layout(
+ dex_path, instruction_set, oat_dir, oat_isa_dir, oat_path)) {
+ LOG(ERROR) << "Could not create secondary odex layout: " << dex_path;
return false;
}
- if (!validate_secondary_dex_path(pkgname, dex_path, volume_uuid, uid, storage_flag)) {
- LOG(ERROR) << "Could not validate secondary dex path " << dex_path;
- return false;
- }
-
- // Check if the path exist. If not, there's nothing to do.
- struct stat dex_path_stat;
- if (stat(dex_path.c_str(), &dex_path_stat) != 0) {
- if (errno == ENOENT) {
- // Secondary dex files might be deleted any time by the app.
- // Nothing to do if that's the case
- ALOGV("Secondary dex does not exist %s", dex_path.c_str());
- return NO_DEXOPT_NEEDED;
- } else {
- PLOG(ERROR) << "Could not access secondary dex " << dex_path;
- }
- }
-
- // Check if we should make the oat file public.
- // Note that if the dex file is not public the compiled code cannot be made public.
- *is_public_out = ((dexopt_flags & DEXOPT_PUBLIC) != 0) &&
- ((dex_path_stat.st_mode & S_IROTH) != 0);
-
- // Prepare the oat directories.
- if (!prepare_secondary_dex_oat_dir(dex_path, uid, instruction_set, oat_dir_out)) {
- return false;
- }
-
- // Analyze profiles.
- bool profile_was_updated = analyze_profiles(uid, dex_path, /*is_secondary_dex*/true);
-
- unique_fd oat_file_fd;
- unique_fd vdex_file_fd;
- unique_fd zip_fd;
- zip_fd.reset(open(dex_path.c_str(), O_RDONLY));
- if (zip_fd.get() < 0) {
- PLOG(ERROR) << "installd cannot open " << dex_path << " for input during dexopt";
- return false;
- }
- if (!maybe_open_oat_and_vdex_file(dex_path,
- *oat_dir_out,
- instruction_set,
- true /* is_secondary_dex */,
- &oat_file_fd,
- &vdex_file_fd)) {
- return false;
- }
+ oat_dir_out->assign(oat_dir);
pid_t pid = fork();
if (pid == 0) {
// child -- drop privileges before continuing.
drop_capabilities(uid);
- // Run dexoptanalyzer to get dexopt_needed code.
+
+ // Validate the path structure.
+ if (!validate_secondary_dex_path(pkgname, dex_path, volume_uuid, uid, storage_flag)) {
+ LOG(ERROR) << "Could not validate secondary dex path " << dex_path;
+ _exit(SECONDARY_DEX_DEXOPTANALYZER_SKIPPED);
+ }
+
+ // Open the dex file.
+ unique_fd zip_fd;
+ zip_fd.reset(open(dex_path.c_str(), O_RDONLY));
+ if (zip_fd.get() < 0) {
+ if (errno == ENOENT) {
+ _exit(SECONDARY_DEX_DEXOPTANALYZER_SKIPPED_NO_FILE);
+ } else {
+ _exit(SECONDARY_DEX_DEXOPTANALYZER_SKIPPED);
+ }
+ }
+
+ // Prepare the oat directories.
+ if (!prepare_secondary_dex_oat_dir(dex_path, uid, instruction_set)) {
+ _exit(SECONDARY_DEX_DEXOPTANALYZER_SKIPPED);
+ }
+
+ // Open the vdex/oat files if any.
+ unique_fd oat_file_fd;
+ unique_fd vdex_file_fd;
+ if (!maybe_open_oat_and_vdex_file(dex_path,
+ *oat_dir_out,
+ instruction_set,
+ true /* is_secondary_dex */,
+ &oat_file_fd,
+ &vdex_file_fd)) {
+ _exit(SECONDARY_DEX_DEXOPTANALYZER_SKIPPED);
+ }
+
+ // Analyze profiles.
+ bool profile_was_updated = analyze_profiles(uid, dex_path, /*is_secondary_dex*/true);
+
+ // Run dexoptanalyzer to get dexopt_needed code. This is not expected to return.
exec_dexoptanalyzer(dex_path,
vdex_file_fd.get(),
oat_file_fd.get(),
zip_fd.get(),
instruction_set,
- compiler_filter,
- profile_was_updated,
- downgrade, class_loader_context);
- exit(DEXOPTANALYZER_BIN_EXEC_ERROR);
+ compiler_filter, profile_was_updated,
+ downgrade,
+ class_loader_context);
+ PLOG(ERROR) << "Failed to exec dexoptanalyzer";
+ _exit(SECONDARY_DEX_DEXOPTANALYZER_SKIPPED);
}
/* parent */
-
int result = wait_child(pid);
if (!WIFEXITED(result)) {
LOG(ERROR) << "dexoptanalyzer failed for path " << dex_path << ": " << result;
return false;
}
result = WEXITSTATUS(result);
- bool success = process_dexoptanalyzer_result(dex_path, result, dexopt_needed_out);
+ // Check that we successfully executed dexoptanalyzer.
+ bool success = process_secondary_dexoptanalyzer_result(dex_path, result, dexopt_needed_out);
+
+ LOG(DEBUG) << "Processed secondary dex file " << dex_path << " result=" << result;
+
// Run dexopt only if needed or forced.
- // Note that dexoptanalyzer is executed even if force compilation is enabled.
- // We ignore its valid dexopNeeded result, but still check (in process_dexoptanalyzer_result)
- // that we only get results for odex files (apk_dir/oat/isa/code.odex) and not
- // for oat files from dalvik-cache.
- if (success && ((dexopt_flags & DEXOPT_FORCE) != 0)) {
+ // Note that dexoptanalyzer is executed even if force compilation is enabled (because it
+ // makes the code simpler; force compilation is only needed during tests).
+ if (success &&
+ (result != SECONDARY_DEX_DEXOPTANALYZER_SKIPPED_NO_FILE) &&
+ ((dexopt_flags & DEXOPT_FORCE) != 0)) {
*dexopt_needed_out = DEX2OAT_FROM_SCRATCH;
}
+ // Check if we should make the oat file public.
+ // Note that if the dex file is not public the compiled code cannot be made public.
+ // It is ok to check this flag outside in the parent process.
+ *is_public_out = ((dexopt_flags & DEXOPT_PUBLIC) != 0) && is_file_public(dex_path);
+
return success;
}
@@ -1708,13 +1778,11 @@
// Check if we're dealing with a secondary dex file and if we need to compile it.
std::string oat_dir_str;
- std::string dex_real_path;
if (is_secondary_dex) {
if (process_secondary_dex_dexopt(dex_path, pkgname, dexopt_flags, volume_uuid, uid,
instruction_set, compiler_filter, &is_public, &dexopt_needed, &oat_dir_str,
- &dex_real_path, downgrade, class_loader_context)) {
+ downgrade, class_loader_context)) {
oat_dir = oat_dir_str.c_str();
- dex_path = dex_real_path.c_str();
if (dexopt_needed == NO_DEXOPT_NEEDED) {
return 0; // Nothing to do, report success.
}
@@ -1852,29 +1920,13 @@
return false;
}
-// Create the oat file structure for the secondary dex 'dex_path' and assign
-// the individual path component to the 'out_' parameters.
-static bool create_secondary_dex_oat_layout(const std::string& dex_path, const std::string& isa,
- /*out*/char* out_oat_dir, /*out*/char* out_oat_isa_dir, /*out*/char* out_oat_path) {
- size_t dirIndex = dex_path.rfind('/');
- if (dirIndex == std::string::npos) {
- LOG(ERROR) << "Unexpected dir structure for dex file " << dex_path;
- return false;
- }
- // TODO(calin): we have similar computations in at lest 3 other places
- // (InstalldNativeService, otapropt and dexopt). Unify them and get rid of snprintf by
- // use string append.
- std::string apk_dir = dex_path.substr(0, dirIndex);
- snprintf(out_oat_dir, PKG_PATH_MAX, "%s/oat", apk_dir.c_str());
- snprintf(out_oat_isa_dir, PKG_PATH_MAX, "%s/%s", out_oat_dir, isa.c_str());
-
- if (!create_oat_out_path(dex_path.c_str(), isa.c_str(), out_oat_dir,
- /*is_secondary_dex*/true, out_oat_path)) {
- LOG(ERROR) << "Could not create oat path for secondary dex " << dex_path;
- return false;
- }
- return true;
-}
+enum ReconcileSecondaryDexResult {
+ kReconcileSecondaryDexExists = 0,
+ kReconcileSecondaryDexCleanedUp = 1,
+ kReconcileSecondaryDexValidationError = 2,
+ kReconcileSecondaryDexCleanUpError = 3,
+ kReconcileSecondaryDexAccessIOError = 4,
+};
// Reconcile the secondary dex 'dex_path' and its generated oat files.
// Return true if all the parameters are valid and the secondary dex file was
@@ -1888,36 +1940,15 @@
const std::string& pkgname, int uid, const std::vector<std::string>& isas,
const std::unique_ptr<std::string>& volume_uuid, int storage_flag,
/*out*/bool* out_secondary_dex_exists) {
- // Set out to false to start with, just in case we have validation errors.
- *out_secondary_dex_exists = false;
- if (!validate_dex_path_size(dex_path)) {
- return false;
- }
-
+ *out_secondary_dex_exists = false; // start by assuming the file does not exist.
if (isas.size() == 0) {
LOG(ERROR) << "reconcile_secondary_dex_file called with empty isas vector";
return false;
}
- const char* volume_uuid_cstr = volume_uuid == nullptr ? nullptr : volume_uuid->c_str();
-
- // Note that we cannot validate the package path here because the file might not exist
- // and we cannot call realpath to resolve system symlinks. Since /data/user/0 symlinks to
- // /data/data/ a lot of validations will fail if we attempt to check the package path.
- // It is still ok to be more relaxed because any file removal is done after forking and
- // dropping capabilities.
- if (!validate_secondary_dex_path(pkgname.c_str(), dex_path.c_str(), volume_uuid_cstr,
- uid, storage_flag, /*validate_package_path*/ false)) {
- LOG(ERROR) << "Could not validate secondary dex path " << dex_path;
- return false;
- }
-
- if (access(dex_path.c_str(), F_OK) == 0) {
- // The path exists, nothing to do. The odex files (if any) will be left untouched.
- *out_secondary_dex_exists = true;
- return true;
- } else if (errno != ENOENT) {
- PLOG(ERROR) << "Failed to check access to secondary dex " << dex_path;
+ if (storage_flag != FLAG_STORAGE_CE && storage_flag != FLAG_STORAGE_DE) {
+ LOG(ERROR) << "reconcile_secondary_dex_file called with invalid storage_flag: "
+ << storage_flag;
return false;
}
@@ -1925,23 +1956,39 @@
// of the package user id. So we fork and drop capabilities in the child.
pid_t pid = fork();
if (pid == 0) {
- // The secondary dex does not exist anymore. Clear any generated files.
+ /* child -- drop privileges before continuing */
+ drop_capabilities(uid);
+
+ const char* volume_uuid_cstr = volume_uuid == nullptr ? nullptr : volume_uuid->c_str();
+ if (!validate_secondary_dex_path(pkgname.c_str(), dex_path.c_str(), volume_uuid_cstr,
+ uid, storage_flag)) {
+ LOG(ERROR) << "Could not validate secondary dex path " << dex_path;
+ _exit(kReconcileSecondaryDexValidationError);
+ }
+
+ SecondaryDexAccess access_check = check_secondary_dex_access(dex_path);
+ switch (access_check) {
+ case kSecondaryDexAccessDoesNotExist:
+ // File does not exist. Proceed with cleaning.
+ break;
+ case kSecondaryDexAccessReadOk: _exit(kReconcileSecondaryDexExists);
+ case kSecondaryDexAccessIOError: _exit(kReconcileSecondaryDexAccessIOError);
+ case kSecondaryDexAccessPermissionError: _exit(kReconcileSecondaryDexValidationError);
+ default:
+ LOG(ERROR) << "Unexpected result from check_secondary_dex_access: " << access_check;
+ _exit(kReconcileSecondaryDexValidationError);
+ }
+
+ // The secondary dex does not exist anymore or it's. Clear any generated files.
char oat_path[PKG_PATH_MAX];
char oat_dir[PKG_PATH_MAX];
char oat_isa_dir[PKG_PATH_MAX];
bool result = true;
- /* child -- drop privileges before continuing */
- drop_capabilities(uid);
for (size_t i = 0; i < isas.size(); i++) {
- if (!create_secondary_dex_oat_layout(dex_path,
- isas[i],
- oat_dir,
- oat_isa_dir,
- oat_path)) {
- LOG(ERROR) << "Could not create secondary odex layout: "
- << dex_path;
- result = false;
- continue;
+ if (!create_secondary_dex_oat_layout(
+ dex_path,isas[i], oat_dir, oat_isa_dir, oat_path)) {
+ LOG(ERROR) << "Could not create secondary odex layout: " << dex_path;
+ _exit(kReconcileSecondaryDexValidationError);
}
// Delete oat/vdex/art files.
@@ -1966,11 +2013,43 @@
result = rmdir_if_empty(oat_isa_dir) && result;
result = rmdir_if_empty(oat_dir) && result;
}
- result ? _exit(0) : _exit(1);
+ if (!result) {
+ PLOG(ERROR) << "Failed to clean secondary dex artifacts for location " << dex_path;
+ }
+ _exit(result ? kReconcileSecondaryDexCleanedUp : kReconcileSecondaryDexAccessIOError);
}
int return_code = wait_child(pid);
- return return_code == 0;
+ if (!WIFEXITED(return_code)) {
+ LOG(WARNING) << "reconcile dex failed for location " << dex_path << ": " << return_code;
+ } else {
+ return_code = WEXITSTATUS(return_code);
+ }
+
+ LOG(DEBUG) << "Reconcile secondary dex path " << dex_path << " result=" << return_code;
+
+ switch (return_code) {
+ case kReconcileSecondaryDexCleanedUp:
+ case kReconcileSecondaryDexValidationError:
+ // If we couldn't validate assume the dex file does not exist.
+ // This will purge the entry from the PM records.
+ *out_secondary_dex_exists = false;
+ return true;
+ case kReconcileSecondaryDexExists:
+ *out_secondary_dex_exists = true;
+ return true;
+ case kReconcileSecondaryDexAccessIOError:
+ // We had an access IO error.
+ // Return false so that we can try again.
+ // The value of out_secondary_dex_exists does not matter in this case and by convention
+ // is set to false.
+ *out_secondary_dex_exists = false;
+ return false;
+ default:
+ LOG(ERROR) << "Unexpected code from reconcile_secondary_dex_file: " << return_code;
+ *out_secondary_dex_exists = false;
+ return false;
+ }
}
// Helper for move_ab, so that we can have common failure-case cleanup.
diff --git a/cmds/installd/tests/Android.bp b/cmds/installd/tests/Android.bp
index 89c11aa..1a22992 100644
--- a/cmds/installd/tests/Android.bp
+++ b/cmds/installd/tests/Android.bp
@@ -55,3 +55,23 @@
"liblogwrap",
],
}
+
+cc_test {
+ name: "installd_dexopt_test",
+ clang: true,
+ srcs: ["installd_dexopt_test.cpp"],
+ cflags: ["-Wall", "-Werror"],
+ shared_libs: [
+ "libbase",
+ "libbinder",
+ "libcutils",
+ "libselinux",
+ "libutils",
+ ],
+ static_libs: [
+ "libdiskusage",
+ "libinstalld",
+ "liblog",
+ "liblogwrap",
+ ],
+}
diff --git a/cmds/installd/tests/installd_dexopt_test.cpp b/cmds/installd/tests/installd_dexopt_test.cpp
new file mode 100644
index 0000000..821b96f
--- /dev/null
+++ b/cmds/installd/tests/installd_dexopt_test.cpp
@@ -0,0 +1,359 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <android-base/logging.h>
+#include <android-base/stringprintf.h>
+#include <cutils/properties.h>
+#include <gtest/gtest.h>
+
+#include "dexopt.h"
+#include "InstalldNativeService.h"
+#include "globals.h"
+#include "tests/test_utils.h"
+#include "utils.h"
+
+namespace android {
+namespace installd {
+
+// TODO(calin): try to dedup this code.
+#if defined(__arm__)
+static const std::string kRuntimeIsa = "arm";
+#elif defined(__aarch64__)
+static const std::string kRuntimeIsa = "arm64";
+#elif defined(__mips__) && !defined(__LP64__)
+static const std::string kRuntimeIsa = "mips";
+#elif defined(__mips__) && defined(__LP64__)
+static const std::string kRuntimeIsa = "mips64";
+#elif defined(__i386__)
+static const std::string kRuntimeIsa = "x86";
+#elif defined(__x86_64__)
+static const std::string kRuntimeIsa = "x86_64";
+#else
+static const std::string kRuntimeIsa = "none";
+#endif
+
+int get_property(const char *key, char *value, const char *default_value) {
+ return property_get(key, value, default_value);
+}
+
+bool calculate_oat_file_path(char path[PKG_PATH_MAX], const char *oat_dir, const char *apk_path,
+ const char *instruction_set) {
+ return calculate_oat_file_path_default(path, oat_dir, apk_path, instruction_set);
+}
+
+bool calculate_odex_file_path(char path[PKG_PATH_MAX], const char *apk_path,
+ const char *instruction_set) {
+ return calculate_odex_file_path_default(path, apk_path, instruction_set);
+}
+
+bool create_cache_path(char path[PKG_PATH_MAX], const char *src, const char *instruction_set) {
+ return create_cache_path_default(path, src, instruction_set);
+}
+
+static void run_cmd(const std::string& cmd) {
+ system(cmd.c_str());
+}
+
+static void mkdir(const std::string& path, uid_t owner, gid_t group, mode_t mode) {
+ ::mkdir(path.c_str(), mode);
+ ::chown(path.c_str(), owner, group);
+ ::chmod(path.c_str(), mode);
+}
+
+// Base64 encoding of a simple dex files with 2 methods.
+static const char kDexFile[] =
+ "UEsDBBQAAAAIAOiOYUs9y6BLCgEAABQCAAALABwAY2xhc3Nlcy5kZXhVVAkAA/Ns+lkOHv1ZdXgL"
+ "AAEEI+UCAASIEwAAS0mt4DIwNmX4qpn7j/2wA7v7N+ZvoQpCJRlVx5SWa4YaiDAxMBQwMDBUhJkI"
+ "MUBBDyMDAzsDRJwFxAdioBDDHAYEYAbiFUAM1M5wAIhFGCGKDIDYAogdgNgDiH2BOAiI0xghekDm"
+ "sQIxGxQzM6ACRijNhCbOhCZfyohdPYyuh8szgtVkMkLsLhAAqeCDi+ejibPZZOZlltgxsDnqZSWW"
+ "JTKwOUFoZh9HayDhZM0g5AMS0M9JzEvX90/KSk0usWZgDAMaws5nAyXBzmpoYGlgAjsAyJoBMp0b"
+ "zQ8gGhbOTEhhzYwU3qxIYc2GFN6MClC/AhUyKUDMAYU9M1Qc5F8GKBscVgIQM0FxCwBQSwECHgMU"
+ "AAAACADojmFLPcugSwoBAAAUAgAACwAYAAAAAAAAAAAAoIEAAAAAY2xhc3Nlcy5kZXhVVAUAA/Ns"
+ "+ll1eAsAAQQj5QIABIgTAABQSwUGAAAAAAEAAQBRAAAATwEAAAAA";
+
+
+class DexoptTest : public testing::Test {
+protected:
+ static constexpr bool kDebug = false;
+ static constexpr uid_t kSystemUid = 1000;
+ static constexpr uid_t kSystemGid = 1000;
+ static constexpr int32_t kOSdkVersion = 25;
+ static constexpr int32_t kAppDataFlags = FLAG_STORAGE_CE | FLAG_STORAGE_DE;
+ static constexpr uid_t kTestAppUid = 19999;
+ static constexpr gid_t kTestAppGid = 19999;
+ static constexpr int32_t kTestUserId = 0;
+
+ InstalldNativeService* service_;
+ std::unique_ptr<std::string> volume_uuid_;
+ std::string package_name_;
+ std::string app_apk_dir_;
+ std::string app_private_dir_ce_;
+ std::string app_private_dir_de_;
+ std::string se_info_;
+
+ int64_t ce_data_inode_;
+
+ std::string secondary_dex_ce_;
+ std::string secondary_dex_ce_link_;
+ std::string secondary_dex_de_;
+
+ virtual void SetUp() {
+ setenv("ANDROID_LOG_TAGS", "*:v", 1);
+ android::base::InitLogging(nullptr);
+
+ service_ = new InstalldNativeService();
+
+ volume_uuid_ = nullptr;
+ package_name_ = "com.installd.test.dexopt";
+ se_info_ = "default";
+
+ init_globals_from_data_and_root();
+
+ app_apk_dir_ = android_app_dir + package_name_;
+
+ create_mock_app();
+ }
+
+ virtual void TearDown() {
+ if (!kDebug) {
+ service_->destroyAppData(
+ volume_uuid_, package_name_, kTestUserId, kAppDataFlags, ce_data_inode_);
+ run_cmd("rm -rf " + app_apk_dir_);
+ run_cmd("rm -rf " + app_private_dir_ce_);
+ run_cmd("rm -rf " + app_private_dir_de_);
+ }
+ delete service_;
+ }
+
+ void create_mock_app() {
+ // Create the oat dir.
+ std::string app_oat_dir = app_apk_dir_ + "/oat";
+ mkdir(app_apk_dir_, kSystemUid, kSystemGid, 0755);
+ service_->createOatDir(app_oat_dir, kRuntimeIsa);
+
+ // Copy the primary apk.
+ std::string apk_path = app_apk_dir_ + "/base.jar";
+ ASSERT_TRUE(WriteBase64ToFile(kDexFile, apk_path, kSystemUid, kSystemGid, 0644));
+
+ // Create the app user data.
+ ASSERT_TRUE(service_->createAppData(
+ volume_uuid_,
+ package_name_,
+ kTestUserId,
+ kAppDataFlags,
+ kTestAppUid,
+ se_info_,
+ kOSdkVersion,
+ &ce_data_inode_).isOk());
+
+ // Create a secondary dex file on CE storage
+ const char* volume_uuid_cstr = volume_uuid_ == nullptr ? nullptr : volume_uuid_->c_str();
+ app_private_dir_ce_ = create_data_user_ce_package_path(
+ volume_uuid_cstr, kTestUserId, package_name_.c_str());
+ secondary_dex_ce_ = app_private_dir_ce_ + "/secondary_ce.jar";
+ ASSERT_TRUE(WriteBase64ToFile(kDexFile, secondary_dex_ce_, kTestAppUid, kTestAppGid, 0600));
+ std::string app_private_dir_ce_link = create_data_user_ce_package_path_as_user_link(
+ volume_uuid_cstr, kTestUserId, package_name_.c_str());
+ secondary_dex_ce_link_ = app_private_dir_ce_link + "/secondary_ce.jar";
+
+ // Create a secondary dex file on DE storage.
+ app_private_dir_de_ = create_data_user_de_package_path(
+ volume_uuid_cstr, kTestUserId, package_name_.c_str());
+ secondary_dex_de_ = app_private_dir_de_ + "/secondary_de.jar";
+ ASSERT_TRUE(WriteBase64ToFile(kDexFile, secondary_dex_de_, kTestAppUid, kTestAppGid, 0600));
+
+ // Fix app data uid.
+ ASSERT_TRUE(service_->fixupAppData(volume_uuid_, kTestUserId).isOk());
+ }
+
+
+ std::string get_secondary_dex_artifact(const std::string& path, const std::string& type) {
+ std::string::size_type end = path.rfind('.');
+ std::string::size_type start = path.rfind('/', end);
+ return path.substr(0, start) + "/oat/" + kRuntimeIsa + "/" +
+ path.substr(start + 1, end - start) + type;
+ }
+
+ void compile_secondary_dex(const std::string& path, int32_t dex_storage_flag,
+ bool should_binder_call_succeed, bool should_dex_be_compiled = true,
+ int uid = kTestAppUid) {
+ std::unique_ptr<std::string> package_name_ptr(new std::string(package_name_));
+ int32_t dexopt_needed = 0; // does not matter;
+ std::unique_ptr<std::string> out_path = nullptr; // does not matter
+ int32_t dex_flags = DEXOPT_SECONDARY_DEX | dex_storage_flag;
+ std::string compiler_filter = "speed-profile";
+ std::unique_ptr<std::string> class_loader_context_ptr(new std::string("&"));
+ std::unique_ptr<std::string> se_info_ptr(new std::string(se_info_));
+ bool downgrade = false;
+
+ binder::Status result = service_->dexopt(path,
+ uid,
+ package_name_ptr,
+ kRuntimeIsa,
+ dexopt_needed,
+ out_path,
+ dex_flags,
+ compiler_filter,
+ volume_uuid_,
+ class_loader_context_ptr,
+ se_info_ptr,
+ downgrade);
+ ASSERT_EQ(should_binder_call_succeed, result.isOk());
+ int expected_access = should_dex_be_compiled ? 0 : -1;
+ std::string odex = get_secondary_dex_artifact(path, "odex");
+ std::string vdex = get_secondary_dex_artifact(path, "vdex");
+ std::string art = get_secondary_dex_artifact(path, "art");
+ ASSERT_EQ(expected_access, access(odex.c_str(), R_OK));
+ ASSERT_EQ(expected_access, access(vdex.c_str(), R_OK));
+ ASSERT_EQ(-1, access(art.c_str(), R_OK)); // empty profiles do not generate an image.
+ }
+
+ void reconcile_secondary_dex(const std::string& path, int32_t storage_flag,
+ bool should_binder_call_succeed, bool should_dex_exist, bool should_dex_be_deleted,
+ int uid = kTestAppUid, std::string* package_override = nullptr) {
+ std::vector<std::string> isas;
+ isas.push_back(kRuntimeIsa);
+ bool out_secondary_dex_exists = false;
+ binder::Status result = service_->reconcileSecondaryDexFile(
+ path,
+ package_override == nullptr ? package_name_ : *package_override,
+ uid,
+ isas,
+ volume_uuid_,
+ storage_flag,
+ &out_secondary_dex_exists);
+
+ ASSERT_EQ(should_binder_call_succeed, result.isOk());
+ ASSERT_EQ(should_dex_exist, out_secondary_dex_exists);
+
+ int expected_access = should_dex_be_deleted ? -1 : 0;
+ std::string odex = get_secondary_dex_artifact(path, "odex");
+ std::string vdex = get_secondary_dex_artifact(path, "vdex");
+ std::string art = get_secondary_dex_artifact(path, "art");
+ ASSERT_EQ(expected_access, access(odex.c_str(), F_OK));
+ ASSERT_EQ(expected_access, access(vdex.c_str(), F_OK));
+ ASSERT_EQ(-1, access(art.c_str(), R_OK)); // empty profiles do not generate an image.
+ }
+};
+
+
+TEST_F(DexoptTest, DexoptSecondaryCe) {
+ LOG(INFO) << "DexoptSecondaryCe";
+ compile_secondary_dex(secondary_dex_ce_, DEXOPT_STORAGE_CE,
+ /*binder_ok*/ true, /*compile_ok*/ true);
+}
+
+TEST_F(DexoptTest, DexoptSecondaryCeLink) {
+ LOG(INFO) << "DexoptSecondaryCeLink";
+ compile_secondary_dex(secondary_dex_ce_link_, DEXOPT_STORAGE_CE,
+ /*binder_ok*/ true, /*compile_ok*/ true);
+}
+
+TEST_F(DexoptTest, DexoptSecondaryDe) {
+ LOG(INFO) << "DexoptSecondaryDe";
+ compile_secondary_dex(secondary_dex_de_, DEXOPT_STORAGE_DE,
+ /*binder_ok*/ true, /*compile_ok*/ true);
+}
+
+TEST_F(DexoptTest, DexoptSecondaryDoesNotExist) {
+ LOG(INFO) << "DexoptSecondaryDoesNotExist";
+ // If the file validates but does not exist we do not treat it as an error.
+ compile_secondary_dex(secondary_dex_ce_ + "not.there", DEXOPT_STORAGE_CE,
+ /*binder_ok*/ true, /*compile_ok*/ false);
+}
+
+TEST_F(DexoptTest, DexoptSecondaryStorageValidationError) {
+ LOG(INFO) << "DexoptSecondaryStorageValidationError";
+ compile_secondary_dex(secondary_dex_ce_, DEXOPT_STORAGE_DE,
+ /*binder_ok*/ false, /*compile_ok*/ false);
+}
+
+TEST_F(DexoptTest, DexoptSecondaryAppOwnershipValidationError) {
+ LOG(INFO) << "DexoptSecondaryAppOwnershipValidationError";
+ compile_secondary_dex("/data/data/random.app/secondary.jar", DEXOPT_STORAGE_CE,
+ /*binder_ok*/ false, /*compile_ok*/ false);
+}
+
+TEST_F(DexoptTest, DexoptSecondaryAcessViaDifferentUidError) {
+ LOG(INFO) << "DexoptSecondaryAcessViaDifferentUidError";
+ compile_secondary_dex(secondary_dex_ce_, DEXOPT_STORAGE_CE,
+ /*binder_ok*/ false, /*compile_ok*/ false, kSystemUid);
+}
+
+
+class ReconcileTest : public DexoptTest {
+ virtual void SetUp() {
+ DexoptTest::SetUp();
+ compile_secondary_dex(secondary_dex_ce_, DEXOPT_STORAGE_CE,
+ /*binder_ok*/ true, /*compile_ok*/ true);
+ compile_secondary_dex(secondary_dex_de_, DEXOPT_STORAGE_DE,
+ /*binder_ok*/ true, /*compile_ok*/ true);
+ }
+};
+
+TEST_F(ReconcileTest, ReconcileSecondaryCeExists) {
+ LOG(INFO) << "ReconcileSecondaryCeExists";
+ reconcile_secondary_dex(secondary_dex_ce_, FLAG_STORAGE_CE,
+ /*binder_ok*/ true, /*dex_ok */ true, /*odex_deleted*/ false);
+}
+
+TEST_F(ReconcileTest, ReconcileSecondaryCeLinkExists) {
+ LOG(INFO) << "ReconcileSecondaryCeLinkExists";
+ reconcile_secondary_dex(secondary_dex_ce_link_, FLAG_STORAGE_CE,
+ /*binder_ok*/ true, /*dex_ok */ true, /*odex_deleted*/ false);
+}
+
+TEST_F(ReconcileTest, ReconcileSecondaryDeExists) {
+ LOG(INFO) << "ReconcileSecondaryDeExists";
+ reconcile_secondary_dex(secondary_dex_de_, FLAG_STORAGE_DE,
+ /*binder_ok*/ true, /*dex_ok */ true, /*odex_deleted*/ false);
+}
+
+TEST_F(ReconcileTest, ReconcileSecondaryDeDoesNotExist) {
+ LOG(INFO) << "ReconcileSecondaryDeDoesNotExist";
+ run_cmd("rm -rf " + secondary_dex_de_);
+ reconcile_secondary_dex(secondary_dex_de_, FLAG_STORAGE_DE,
+ /*binder_ok*/ true, /*dex_ok */ false, /*odex_deleted*/ true);
+}
+
+TEST_F(ReconcileTest, ReconcileSecondaryStorageValidationError) {
+ // Validation errors will not clean the odex/vdex/art files but will mark
+ // the file as non existent so that the PM knows it should purge it from its
+ // records.
+ LOG(INFO) << "ReconcileSecondaryStorageValidationError";
+ reconcile_secondary_dex(secondary_dex_ce_, FLAG_STORAGE_DE,
+ /*binder_ok*/ true, /*dex_ok */ false, /*odex_deleted*/ false);
+}
+
+TEST_F(ReconcileTest, ReconcileSecondaryAppOwnershipValidationError) {
+ LOG(INFO) << "ReconcileSecondaryAppOwnershipValidationError";
+ // Attempt to reconcile the dex files of the test app from a different app.
+ std::string another_app = "another.app";
+ reconcile_secondary_dex(secondary_dex_ce_, FLAG_STORAGE_CE,
+ /*binder_ok*/ true, /*dex_ok */ false, /*odex_deleted*/ false, kSystemUid, &another_app);
+}
+
+TEST_F(ReconcileTest, ReconcileSecondaryAcessViaDifferentUidError) {
+ LOG(INFO) << "ReconcileSecondaryAcessViaDifferentUidError";
+ reconcile_secondary_dex(secondary_dex_ce_, FLAG_STORAGE_CE,
+ /*binder_ok*/ true, /*dex_ok */ false, /*odex_deleted*/ false, kSystemUid);
+}
+
+} // namespace installd
+} // namespace android
diff --git a/cmds/installd/tests/installd_utils_test.cpp b/cmds/installd/tests/installd_utils_test.cpp
index 2ca7ac2..a6a4451 100644
--- a/cmds/installd/tests/installd_utils_test.cpp
+++ b/cmds/installd/tests/installd_utils_test.cpp
@@ -379,6 +379,7 @@
TEST_F(UtilsTest, ValidateSecondaryDexFilesPath) {
std::string package_name = "com.test.app";
std::string app_dir_ce_user_0 = "/data/data/" + package_name;
+ std::string app_dir_ce_user_0_link = "/data/user/0/" + package_name;
std::string app_dir_ce_user_10 = "/data/user/10/" + package_name;
std::string app_dir_de_user_0 = "/data/user_de/0/" + package_name;
@@ -400,6 +401,8 @@
// Standard path for user 0 on CE storage.
pass_secondary_dex_validation(
package_name, app_dir_ce_user_0 + "/ce0.dex", app_uid_for_user_0, FLAG_STORAGE_CE);
+ pass_secondary_dex_validation(
+ package_name, app_dir_ce_user_0_link + "/ce0.dex", app_uid_for_user_0, FLAG_STORAGE_CE);
// Standard path for user 10 on CE storage.
pass_secondary_dex_validation(
package_name, app_dir_ce_user_10 + "/ce10.dex", app_uid_for_user_10, FLAG_STORAGE_CE);
diff --git a/cmds/installd/tests/test_utils.h b/cmds/installd/tests/test_utils.h
new file mode 100644
index 0000000..7d1162e
--- /dev/null
+++ b/cmds/installd/tests/test_utils.h
@@ -0,0 +1,107 @@
+#include <android-base/logging.h>
+#include <stdlib.h>
+#include <string.h>
+
+uint8_t kBase64Map[256] = {
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 62, 255, 255, 255, 63,
+ 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 255, 255,
+ 255, 254, 255, 255, 255, 0, 1, 2, 3, 4, 5, 6,
+ 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18,
+ 19, 20, 21, 22, 23, 24, 25, 255, 255, 255, 255, 255,
+ 255, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36,
+ 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
+ 49, 50, 51, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255
+};
+
+uint8_t* DecodeBase64(const char* src, size_t* dst_size) {
+ CHECK(dst_size != nullptr);
+ std::vector<uint8_t> tmp;
+ uint32_t t = 0, y = 0;
+ int g = 3;
+ for (size_t i = 0; src[i] != '\0'; ++i) {
+ uint8_t c = kBase64Map[src[i] & 0xFF];
+ if (c == 255) continue;
+ // the final = symbols are read and used to trim the remaining bytes
+ if (c == 254) {
+ c = 0;
+ // prevent g < 0 which would potentially allow an overflow later
+ if (--g < 0) {
+ *dst_size = 0;
+ return nullptr;
+ }
+ } else if (g != 3) {
+ // we only allow = to be at the end
+ *dst_size = 0;
+ return nullptr;
+ }
+ t = (t << 6) | c;
+ if (++y == 4) {
+ tmp.push_back((t >> 16) & 255);
+ if (g > 1) {
+ tmp.push_back((t >> 8) & 255);
+ }
+ if (g > 2) {
+ tmp.push_back(t & 255);
+ }
+ y = t = 0;
+ }
+ }
+ if (y != 0) {
+ *dst_size = 0;
+ return nullptr;
+ }
+ std::unique_ptr<uint8_t[]> dst(new uint8_t[tmp.size()]);
+ *dst_size = tmp.size();
+ std::copy(tmp.begin(), tmp.end(), dst.get());
+ return dst.release();
+}
+
+bool WriteBase64ToFile(const char* base64, const std::string& file,
+ uid_t uid, gid_t gid, int mode) {
+ CHECK(base64 != nullptr);
+ size_t length;
+ std::unique_ptr<uint8_t[]> bytes(DecodeBase64(base64, &length));
+ CHECK(bytes != nullptr);
+
+
+ int fd = open(file.c_str(), O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR);
+
+ if (fd < 0) {
+ PLOG(ERROR) << "Could not open file " << file;
+ return false;
+ }
+
+ size_t wrote = 0;
+ while (wrote < length) {
+ ssize_t cur = write(fd, bytes.get() + wrote, length - wrote);
+ if (cur == -1) {
+ PLOG(ERROR) << "Could not write file " << file;
+ return false;
+ }
+ wrote += cur;
+ }
+
+ if (::chown(file.c_str(), uid, gid) != 0) {
+ PLOG(ERROR) << "Could not chown file " << file;
+ return false;
+ }
+ if (::chmod(file.c_str(), mode) != 0) {
+ PLOG(ERROR) << "Could not chmod file " << file;
+ return false;
+ }
+ return true;
+}
diff --git a/cmds/installd/utils.cpp b/cmds/installd/utils.cpp
index ca0a82e..7dca7c6 100644
--- a/cmds/installd/utils.cpp
+++ b/cmds/installd/utils.cpp
@@ -87,6 +87,20 @@
create_data_user_ce_path(volume_uuid, user).c_str(), package_name);
}
+/**
+ * Create the path name where package data should be stored for the given
+ * volume UUID, package name, and user ID. An empty UUID is assumed to be
+ * internal storage.
+ * Compared to create_data_user_ce_package_path this method always return the
+ * ".../user/..." directory.
+ */
+std::string create_data_user_ce_package_path_as_user_link(
+ const char* volume_uuid, userid_t userid, const char* package_name) {
+ check_package_name(package_name);
+ std::string data(create_data_path(volume_uuid));
+ return StringPrintf("%s/user/%u/%s", data.c_str(), userid, 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
@@ -786,7 +800,7 @@
}
bool validate_secondary_dex_path(const std::string& pkgname, const std::string& dex_path,
- const char* volume_uuid, int uid, int storage_flag, bool validate_package_path) {
+ const char* volume_uuid, int uid, int storage_flag) {
CHECK(storage_flag == FLAG_STORAGE_CE || storage_flag == FLAG_STORAGE_DE);
// Empty paths are not allowed.
@@ -800,16 +814,20 @@
// The path should be at most PKG_PATH_MAX long.
if (dex_path.size() > PKG_PATH_MAX) { return false; }
- if (validate_package_path) {
- // If we are asked to validate the package path check that
- // the dex_path is under the app data directory.
- std::string app_private_dir = storage_flag == FLAG_STORAGE_CE
+ // The dex_path should be under the app data directory.
+ std::string app_private_dir = storage_flag == FLAG_STORAGE_CE
? create_data_user_ce_package_path(
volume_uuid, multiuser_get_user_id(uid), pkgname.c_str())
: create_data_user_de_package_path(
volume_uuid, multiuser_get_user_id(uid), pkgname.c_str());
- if (strncmp(dex_path.c_str(), app_private_dir.c_str(), app_private_dir.size()) != 0) {
+ if (strncmp(dex_path.c_str(), app_private_dir.c_str(), app_private_dir.size()) != 0) {
+ // The check above might fail if the dex file is accessed via the /data/user/0 symlink.
+ // If that's the case, attempt to validate against the user data link.
+ std::string app_private_dir_symlink = create_data_user_ce_package_path_as_user_link(
+ volume_uuid, multiuser_get_user_id(uid), pkgname.c_str());
+ if (strncmp(dex_path.c_str(), app_private_dir_symlink.c_str(),
+ app_private_dir_symlink.size()) != 0) {
return false;
}
}
diff --git a/cmds/installd/utils.h b/cmds/installd/utils.h
index 3e04af9..b90caf9 100644
--- a/cmds/installd/utils.h
+++ b/cmds/installd/utils.h
@@ -60,6 +60,8 @@
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);
+std::string create_data_user_ce_package_path_as_user_link(
+ const char* volume_uuid, userid_t userid, const char* package_name);
std::string create_data_media_path(const char* volume_uuid, userid_t userid);
std::string create_data_media_obb_path(const char* volume_uuid, const char* package_name);
@@ -114,7 +116,7 @@
int validate_system_app_path(const char* path);
bool validate_secondary_dex_path(const std::string& pkgname, const std::string& dex_path,
- const char* volume_uuid, int uid, int storage_flag, bool validate_package_path = true);
+ const char* volume_uuid, int uid, int storage_flag);
int validate_apk_path(const char *path);
int validate_apk_path_subdirs(const char *path);
diff --git a/cmds/servicemanager/service_manager.c b/cmds/servicemanager/service_manager.c
index 31cd0cb..6b340a8 100644
--- a/cmds/servicemanager/service_manager.c
+++ b/cmds/servicemanager/service_manager.c
@@ -138,6 +138,7 @@
uint32_t handle;
struct binder_death death;
int allow_isolated;
+ uint32_t dumpsys_priority;
size_t len;
uint16_t name[0];
};
@@ -198,11 +199,8 @@
return si->handle;
}
-int do_add_service(struct binder_state *bs,
- const uint16_t *s, size_t len,
- uint32_t handle, uid_t uid, int allow_isolated,
- pid_t spid)
-{
+int do_add_service(struct binder_state *bs, const uint16_t *s, size_t len, uint32_t handle,
+ uid_t uid, int allow_isolated, uint32_t dumpsys_priority, pid_t spid) {
struct svcinfo *si;
//ALOGI("add_service('%s',%x,%s) uid=%d\n", str8(s, len), handle,
@@ -239,6 +237,7 @@
si->death.func = (void*) svcinfo_death;
si->death.ptr = si;
si->allow_isolated = allow_isolated;
+ si->dumpsys_priority = dumpsys_priority;
si->next = svclist;
svclist = si;
}
@@ -259,6 +258,7 @@
uint32_t handle;
uint32_t strict_policy;
int allow_isolated;
+ uint32_t dumpsys_priority;
//ALOGI("target=%p code=%d pid=%d uid=%d\n",
// (void*) txn->target.ptr, txn->code, txn->sender_pid, txn->sender_euid);
@@ -317,13 +317,15 @@
}
handle = bio_get_ref(msg);
allow_isolated = bio_get_uint32(msg) ? 1 : 0;
- if (do_add_service(bs, s, len, handle, txn->sender_euid,
- allow_isolated, txn->sender_pid))
+ dumpsys_priority = bio_get_uint32(msg);
+ if (do_add_service(bs, s, len, handle, txn->sender_euid, allow_isolated, dumpsys_priority,
+ txn->sender_pid))
return -1;
break;
case SVC_MGR_LIST_SERVICES: {
uint32_t n = bio_get_uint32(msg);
+ uint32_t req_dumpsys_priority = bio_get_uint32(msg);
if (!svc_can_list(txn->sender_pid, txn->sender_euid)) {
ALOGE("list_service() uid=%d - PERMISSION DENIED\n",
@@ -331,8 +333,15 @@
return -1;
}
si = svclist;
- while ((n-- > 0) && si)
+ // walk through the list of services n times skipping services that
+ // do not support the requested priority
+ while (si) {
+ if (si->dumpsys_priority & req_dumpsys_priority) {
+ if (n == 0) break;
+ n--;
+ }
si = si->next;
+ }
if (si) {
bio_put_string16(reply, si->name);
return 0;
diff --git a/cmds/surfacereplayer/replayer/Replayer.cpp b/cmds/surfacereplayer/replayer/Replayer.cpp
index 2b5389b..4140f40 100644
--- a/cmds/surfacereplayer/replayer/Replayer.cpp
+++ b/cmds/surfacereplayer/replayer/Replayer.cpp
@@ -24,9 +24,9 @@
#include <gui/BufferQueue.h>
#include <gui/ISurfaceComposer.h>
+#include <gui/LayerState.h>
#include <gui/Surface.h>
#include <private/gui/ComposerService.h>
-#include <private/gui/LayerState.h>
#include <ui/DisplayInfo.h>
#include <utils/Log.h>
@@ -338,27 +338,29 @@
status_t Replayer::doTransaction(const Transaction& t, const std::shared_ptr<Event>& event) {
ALOGV("Started Transaction");
- SurfaceComposerClient::openGlobalTransaction();
+ SurfaceComposerClient::Transaction liveTransaction;
status_t status = NO_ERROR;
- status = doSurfaceTransaction(t.surface_change());
- doDisplayTransaction(t.display_change());
+ status = doSurfaceTransaction(liveTransaction, t.surface_change());
+ doDisplayTransaction(liveTransaction, t.display_change());
if (t.animation()) {
- SurfaceComposerClient::setAnimationTransaction();
+ liveTransaction.setAnimationTransaction();
}
event->readyToExecute();
- SurfaceComposerClient::closeGlobalTransaction(t.synchronous());
+ liveTransaction.apply(t.synchronous());
ALOGV("Ended Transaction");
return status;
}
-status_t Replayer::doSurfaceTransaction(const SurfaceChanges& surfaceChanges) {
+status_t Replayer::doSurfaceTransaction(
+ SurfaceComposerClient::Transaction& transaction,
+ const SurfaceChanges& surfaceChanges) {
status_t status = NO_ERROR;
for (const SurfaceChange& change : surfaceChanges) {
@@ -369,62 +371,66 @@
switch (change.SurfaceChange_case()) {
case SurfaceChange::SurfaceChangeCase::kPosition:
- status = setPosition(change.id(), change.position());
+ setPosition(transaction, change.id(), change.position());
break;
case SurfaceChange::SurfaceChangeCase::kSize:
- status = setSize(change.id(), change.size());
+ setSize(transaction, change.id(), change.size());
break;
case SurfaceChange::SurfaceChangeCase::kAlpha:
- status = setAlpha(change.id(), change.alpha());
+ setAlpha(transaction, change.id(), change.alpha());
break;
case SurfaceChange::SurfaceChangeCase::kLayer:
- status = setLayer(change.id(), change.layer());
+ setLayer(transaction, change.id(), change.layer());
break;
case SurfaceChange::SurfaceChangeCase::kCrop:
- status = setCrop(change.id(), change.crop());
+ setCrop(transaction, change.id(), change.crop());
break;
case SurfaceChange::SurfaceChangeCase::kMatrix:
- status = setMatrix(change.id(), change.matrix());
+ setMatrix(transaction, change.id(), change.matrix());
break;
case SurfaceChange::SurfaceChangeCase::kFinalCrop:
- status = setFinalCrop(change.id(), change.final_crop());
+ setFinalCrop(transaction, change.id(), change.final_crop());
break;
case SurfaceChange::SurfaceChangeCase::kOverrideScalingMode:
- status = setOverrideScalingMode(change.id(), change.override_scaling_mode());
+ setOverrideScalingMode(transaction, change.id(),
+ change.override_scaling_mode());
break;
case SurfaceChange::SurfaceChangeCase::kTransparentRegionHint:
- status = setTransparentRegionHint(change.id(), change.transparent_region_hint());
+ setTransparentRegionHint(transaction, change.id(),
+ change.transparent_region_hint());
break;
case SurfaceChange::SurfaceChangeCase::kLayerStack:
- status = setLayerStack(change.id(), change.layer_stack());
+ setLayerStack(transaction, change.id(), change.layer_stack());
break;
case SurfaceChange::SurfaceChangeCase::kHiddenFlag:
- status = setHiddenFlag(change.id(), change.hidden_flag());
+ setHiddenFlag(transaction, change.id(), change.hidden_flag());
break;
case SurfaceChange::SurfaceChangeCase::kOpaqueFlag:
- status = setOpaqueFlag(change.id(), change.opaque_flag());
+ setOpaqueFlag(transaction, change.id(), change.opaque_flag());
break;
case SurfaceChange::SurfaceChangeCase::kSecureFlag:
- status = setSecureFlag(change.id(), change.secure_flag());
+ setSecureFlag(transaction, change.id(), change.secure_flag());
break;
case SurfaceChange::SurfaceChangeCase::kDeferredTransaction:
waitUntilDeferredTransactionLayerExists(change.deferred_transaction(), lock);
- status = setDeferredTransaction(change.id(), change.deferred_transaction());
+ setDeferredTransaction(transaction, change.id(),
+ change.deferred_transaction());
break;
default:
- status = NO_ERROR;
+ status = 1;
break;
}
if (status != NO_ERROR) {
- ALOGE("SET TRANSACTION FAILED");
+ ALOGE("Unknown Transaction Code");
return status;
}
}
return status;
}
-void Replayer::doDisplayTransaction(const DisplayChanges& displayChanges) {
+void Replayer::doDisplayTransaction(SurfaceComposerClient::Transaction& t,
+ const DisplayChanges& displayChanges) {
for (const DisplayChange& change : displayChanges) {
ALOGV("Doing display transaction");
std::unique_lock<std::mutex> lock(mDisplayLock);
@@ -434,16 +440,16 @@
switch (change.DisplayChange_case()) {
case DisplayChange::DisplayChangeCase::kSurface:
- setDisplaySurface(change.id(), change.surface());
+ setDisplaySurface(t, change.id(), change.surface());
break;
case DisplayChange::DisplayChangeCase::kLayerStack:
- setDisplayLayerStack(change.id(), change.layer_stack());
+ setDisplayLayerStack(t, change.id(), change.layer_stack());
break;
case DisplayChange::DisplayChangeCase::kSize:
- setDisplaySize(change.id(), change.size());
+ setDisplaySize(t, change.id(), change.size());
break;
case DisplayChange::DisplayChangeCase::kProjection:
- setDisplayProjection(change.id(), change.projection());
+ setDisplayProjection(t, change.id(), change.projection());
break;
default:
break;
@@ -451,57 +457,66 @@
}
}
-status_t Replayer::setPosition(layer_id id, const PositionChange& pc) {
+void Replayer::setPosition(SurfaceComposerClient::Transaction& t,
+ layer_id id, const PositionChange& pc) {
ALOGV("Layer %d: Setting Position -- x=%f, y=%f", id, pc.x(), pc.y());
- return mLayers[id]->setPosition(pc.x(), pc.y());
+ t.setPosition(mLayers[id], pc.x(), pc.y());
}
-status_t Replayer::setSize(layer_id id, const SizeChange& sc) {
+void Replayer::setSize(SurfaceComposerClient::Transaction& t,
+ layer_id id, const SizeChange& sc) {
ALOGV("Layer %d: Setting Size -- w=%u, h=%u", id, sc.w(), sc.h());
- return mLayers[id]->setSize(sc.w(), sc.h());
+ t.setSize(mLayers[id], sc.w(), sc.h());
}
-status_t Replayer::setLayer(layer_id id, const LayerChange& lc) {
+void Replayer::setLayer(SurfaceComposerClient::Transaction& t,
+ layer_id id, const LayerChange& lc) {
ALOGV("Layer %d: Setting Layer -- layer=%d", id, lc.layer());
- return mLayers[id]->setLayer(lc.layer());
+ t.setLayer(mLayers[id], lc.layer());
}
-status_t Replayer::setAlpha(layer_id id, const AlphaChange& ac) {
+void Replayer::setAlpha(SurfaceComposerClient::Transaction& t,
+ layer_id id, const AlphaChange& ac) {
ALOGV("Layer %d: Setting Alpha -- alpha=%f", id, ac.alpha());
- return mLayers[id]->setAlpha(ac.alpha());
+ t.setAlpha(mLayers[id], ac.alpha());
}
-status_t Replayer::setCrop(layer_id id, const CropChange& cc) {
+void Replayer::setCrop(SurfaceComposerClient::Transaction& t,
+ layer_id id, const CropChange& cc) {
ALOGV("Layer %d: Setting Crop -- left=%d, top=%d, right=%d, bottom=%d", id,
cc.rectangle().left(), cc.rectangle().top(), cc.rectangle().right(),
cc.rectangle().bottom());
Rect r = Rect(cc.rectangle().left(), cc.rectangle().top(), cc.rectangle().right(),
cc.rectangle().bottom());
- return mLayers[id]->setCrop(r);
+ t.setCrop(mLayers[id], r);
}
-status_t Replayer::setFinalCrop(layer_id id, const FinalCropChange& fcc) {
+void Replayer::setFinalCrop(SurfaceComposerClient::Transaction& t,
+ layer_id id, const FinalCropChange& fcc) {
ALOGV("Layer %d: Setting Final Crop -- left=%d, top=%d, right=%d, bottom=%d", id,
fcc.rectangle().left(), fcc.rectangle().top(), fcc.rectangle().right(),
fcc.rectangle().bottom());
Rect r = Rect(fcc.rectangle().left(), fcc.rectangle().top(), fcc.rectangle().right(),
fcc.rectangle().bottom());
- return mLayers[id]->setFinalCrop(r);
+ t.setFinalCrop(mLayers[id], r);
}
-status_t Replayer::setMatrix(layer_id id, const MatrixChange& mc) {
+void Replayer::setMatrix(SurfaceComposerClient::Transaction& t,
+ layer_id id, const MatrixChange& mc) {
ALOGV("Layer %d: Setting Matrix -- dsdx=%f, dtdx=%f, dsdy=%f, dtdy=%f", id, mc.dsdx(),
mc.dtdx(), mc.dsdy(), mc.dtdy());
- return mLayers[id]->setMatrix(mc.dsdx(), mc.dtdx(), mc.dsdy(), mc.dtdy());
+ t.setMatrix(mLayers[id], mc.dsdx(), mc.dtdx(), mc.dsdy(), mc.dtdy());
}
-status_t Replayer::setOverrideScalingMode(layer_id id, const OverrideScalingModeChange& osmc) {
+void Replayer::setOverrideScalingMode(SurfaceComposerClient::Transaction& t,
+ layer_id id, const OverrideScalingModeChange& osmc) {
ALOGV("Layer %d: Setting Override Scaling Mode -- mode=%d", id, osmc.override_scaling_mode());
- return mLayers[id]->setOverrideScalingMode(osmc.override_scaling_mode());
+ t.setOverrideScalingMode(mLayers[id], osmc.override_scaling_mode());
}
-status_t Replayer::setTransparentRegionHint(layer_id id, const TransparentRegionHintChange& trhc) {
+void Replayer::setTransparentRegionHint(SurfaceComposerClient::Transaction& t,
+ layer_id id, const TransparentRegionHintChange& trhc) {
ALOGV("Setting Transparent Region Hint");
Region re = Region();
@@ -510,71 +525,80 @@
re.merge(rect);
}
- return mLayers[id]->setTransparentRegionHint(re);
+ t.setTransparentRegionHint(mLayers[id], re);
}
-status_t Replayer::setLayerStack(layer_id id, const LayerStackChange& lsc) {
+void Replayer::setLayerStack(SurfaceComposerClient::Transaction& t,
+ layer_id id, const LayerStackChange& lsc) {
ALOGV("Layer %d: Setting LayerStack -- layer_stack=%d", id, lsc.layer_stack());
- return mLayers[id]->setLayerStack(lsc.layer_stack());
+ t.setLayerStack(mLayers[id], lsc.layer_stack());
}
-status_t Replayer::setHiddenFlag(layer_id id, const HiddenFlagChange& hfc) {
+void Replayer::setHiddenFlag(SurfaceComposerClient::Transaction& t,
+ layer_id id, const HiddenFlagChange& hfc) {
ALOGV("Layer %d: Setting Hidden Flag -- hidden_flag=%d", id, hfc.hidden_flag());
layer_id flag = hfc.hidden_flag() ? layer_state_t::eLayerHidden : 0;
- return mLayers[id]->setFlags(flag, layer_state_t::eLayerHidden);
+ t.setFlags(mLayers[id], flag, layer_state_t::eLayerHidden);
}
-status_t Replayer::setOpaqueFlag(layer_id id, const OpaqueFlagChange& ofc) {
+void Replayer::setOpaqueFlag(SurfaceComposerClient::Transaction& t,
+ layer_id id, const OpaqueFlagChange& ofc) {
ALOGV("Layer %d: Setting Opaque Flag -- opaque_flag=%d", id, ofc.opaque_flag());
layer_id flag = ofc.opaque_flag() ? layer_state_t::eLayerOpaque : 0;
- return mLayers[id]->setFlags(flag, layer_state_t::eLayerOpaque);
+ t.setFlags(mLayers[id], flag, layer_state_t::eLayerOpaque);
}
-status_t Replayer::setSecureFlag(layer_id id, const SecureFlagChange& sfc) {
+void Replayer::setSecureFlag(SurfaceComposerClient::Transaction& t,
+ layer_id id, const SecureFlagChange& sfc) {
ALOGV("Layer %d: Setting Secure Flag -- secure_flag=%d", id, sfc.secure_flag());
layer_id flag = sfc.secure_flag() ? layer_state_t::eLayerSecure : 0;
- return mLayers[id]->setFlags(flag, layer_state_t::eLayerSecure);
+ t.setFlags(mLayers[id], flag, layer_state_t::eLayerSecure);
}
-status_t Replayer::setDeferredTransaction(layer_id id, const DeferredTransactionChange& dtc) {
+void Replayer::setDeferredTransaction(SurfaceComposerClient::Transaction& t,
+ layer_id id, const DeferredTransactionChange& dtc) {
ALOGV("Layer %d: Setting Deferred Transaction -- layer_id=%d, "
"frame_number=%llu",
id, dtc.layer_id(), dtc.frame_number());
if (mLayers.count(dtc.layer_id()) == 0 || mLayers[dtc.layer_id()] == nullptr) {
ALOGE("Layer %d not found in Deferred Transaction", dtc.layer_id());
- return BAD_VALUE;
+ return;
}
auto handle = mLayers[dtc.layer_id()]->getHandle();
- return mLayers[id]->deferTransactionUntil(handle, dtc.frame_number());
+ t.deferTransactionUntil(mLayers[id], handle, dtc.frame_number());
}
-void Replayer::setDisplaySurface(display_id id, const DispSurfaceChange& /*dsc*/) {
+void Replayer::setDisplaySurface(SurfaceComposerClient::Transaction& t,
+ display_id id, const DispSurfaceChange& /*dsc*/) {
sp<IGraphicBufferProducer> outProducer;
sp<IGraphicBufferConsumer> outConsumer;
BufferQueue::createBufferQueue(&outProducer, &outConsumer);
- SurfaceComposerClient::setDisplaySurface(mDisplays[id], outProducer);
+ t.setDisplaySurface(mDisplays[id], outProducer);
}
-void Replayer::setDisplayLayerStack(display_id id, const LayerStackChange& lsc) {
- SurfaceComposerClient::setDisplayLayerStack(mDisplays[id], lsc.layer_stack());
+void Replayer::setDisplayLayerStack(SurfaceComposerClient::Transaction& t,
+ display_id id, const LayerStackChange& lsc) {
+ t.setDisplayLayerStack(mDisplays[id], lsc.layer_stack());
}
-void Replayer::setDisplaySize(display_id id, const SizeChange& sc) {
- SurfaceComposerClient::setDisplaySize(mDisplays[id], sc.w(), sc.h());
+void Replayer::setDisplaySize(SurfaceComposerClient::Transaction& t,
+ display_id id, const SizeChange& sc) {
+ t.setDisplaySize(mDisplays[id], sc.w(), sc.h());
}
-void Replayer::setDisplayProjection(display_id id, const ProjectionChange& pc) {
+void Replayer::setDisplayProjection(SurfaceComposerClient::Transaction& t,
+ display_id id, const ProjectionChange& pc) {
Rect viewport = Rect(pc.viewport().left(), pc.viewport().top(), pc.viewport().right(),
pc.viewport().bottom());
Rect frame = Rect(pc.frame().left(), pc.frame().top(), pc.frame().right(), pc.frame().bottom());
- SurfaceComposerClient::setDisplayProjection(mDisplays[id], pc.orientation(), viewport, frame);
+ t.setDisplayProjection(mDisplays[id], pc.orientation(), viewport, frame);
}
status_t Replayer::createSurfaceControl(
diff --git a/cmds/surfacereplayer/replayer/Replayer.h b/cmds/surfacereplayer/replayer/Replayer.h
index f36c9fd..295403e 100644
--- a/cmds/surfacereplayer/replayer/Replayer.h
+++ b/cmds/surfacereplayer/replayer/Replayer.h
@@ -77,28 +77,48 @@
void deleteDisplay(const DisplayDeletion& delete_, const std::shared_ptr<Event>& event);
void updatePowerMode(const PowerModeUpdate& update, const std::shared_ptr<Event>& event);
- status_t doSurfaceTransaction(const SurfaceChanges& surfaceChange);
- void doDisplayTransaction(const DisplayChanges& displayChange);
+ status_t doSurfaceTransaction(SurfaceComposerClient::Transaction& transaction,
+ const SurfaceChanges& surfaceChange);
+ void doDisplayTransaction(SurfaceComposerClient::Transaction& transaction,
+ const DisplayChanges& displayChange);
- status_t setPosition(layer_id id, const PositionChange& pc);
- status_t setSize(layer_id id, const SizeChange& sc);
- status_t setAlpha(layer_id id, const AlphaChange& ac);
- status_t setLayer(layer_id id, const LayerChange& lc);
- status_t setCrop(layer_id id, const CropChange& cc);
- status_t setFinalCrop(layer_id id, const FinalCropChange& fcc);
- status_t setMatrix(layer_id id, const MatrixChange& mc);
- status_t setOverrideScalingMode(layer_id id, const OverrideScalingModeChange& osmc);
- status_t setTransparentRegionHint(layer_id id, const TransparentRegionHintChange& trgc);
- status_t setLayerStack(layer_id id, const LayerStackChange& lsc);
- status_t setHiddenFlag(layer_id id, const HiddenFlagChange& hfc);
- status_t setOpaqueFlag(layer_id id, const OpaqueFlagChange& ofc);
- status_t setSecureFlag(layer_id id, const SecureFlagChange& sfc);
- status_t setDeferredTransaction(layer_id id, const DeferredTransactionChange& dtc);
+ void setPosition(SurfaceComposerClient::Transaction& t,
+ layer_id id, const PositionChange& pc);
+ void setSize(SurfaceComposerClient::Transaction& t,
+ layer_id id, const SizeChange& sc);
+ void setAlpha(SurfaceComposerClient::Transaction& t,
+ layer_id id, const AlphaChange& ac);
+ void setLayer(SurfaceComposerClient::Transaction& t,
+ layer_id id, const LayerChange& lc);
+ void setCrop(SurfaceComposerClient::Transaction& t,
+ layer_id id, const CropChange& cc);
+ void setFinalCrop(SurfaceComposerClient::Transaction& t,
+ layer_id id, const FinalCropChange& fcc);
+ void setMatrix(SurfaceComposerClient::Transaction& t,
+ layer_id id, const MatrixChange& mc);
+ void setOverrideScalingMode(SurfaceComposerClient::Transaction& t,
+ layer_id id, const OverrideScalingModeChange& osmc);
+ void setTransparentRegionHint(SurfaceComposerClient::Transaction& t,
+ layer_id id, const TransparentRegionHintChange& trgc);
+ void setLayerStack(SurfaceComposerClient::Transaction& t,
+ layer_id id, const LayerStackChange& lsc);
+ void setHiddenFlag(SurfaceComposerClient::Transaction& t,
+ layer_id id, const HiddenFlagChange& hfc);
+ void setOpaqueFlag(SurfaceComposerClient::Transaction& t,
+ layer_id id, const OpaqueFlagChange& ofc);
+ void setSecureFlag(SurfaceComposerClient::Transaction& t,
+ layer_id id, const SecureFlagChange& sfc);
+ void setDeferredTransaction(SurfaceComposerClient::Transaction& t,
+ layer_id id, const DeferredTransactionChange& dtc);
- void setDisplaySurface(display_id id, const DispSurfaceChange& dsc);
- void setDisplayLayerStack(display_id id, const LayerStackChange& lsc);
- void setDisplaySize(display_id id, const SizeChange& sc);
- void setDisplayProjection(display_id id, const ProjectionChange& pc);
+ void setDisplaySurface(SurfaceComposerClient::Transaction& t,
+ display_id id, const DispSurfaceChange& dsc);
+ void setDisplayLayerStack(SurfaceComposerClient::Transaction& t,
+ display_id id, const LayerStackChange& lsc);
+ void setDisplaySize(SurfaceComposerClient::Transaction& t,
+ display_id id, const SizeChange& sc);
+ void setDisplayProjection(SurfaceComposerClient::Transaction& t,
+ display_id id, const ProjectionChange& pc);
void doDeleteSurfaceControls();
void waitUntilTimestamp(int64_t timestamp);
diff --git a/data/etc/android.hardware.wifi.rtt.xml b/data/etc/android.hardware.wifi.rtt.xml
new file mode 100644
index 0000000..60529ea
--- /dev/null
+++ b/data/etc/android.hardware.wifi.rtt.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<!-- This is the standard feature indicating that the device supports WiFi RTT (IEEE 802.11mc). -->
+<permissions>
+ <feature name="android.hardware.wifi.rtt" />
+</permissions>
diff --git a/data/etc/handheld_core_hardware.xml b/data/etc/handheld_core_hardware.xml
index ec7be53..b6abc1b 100644
--- a/data/etc/handheld_core_hardware.xml
+++ b/data/etc/handheld_core_hardware.xml
@@ -55,7 +55,7 @@
<feature name="android.software.device_admin" />
<!-- Feature to specify if the device support managed users. -->
- <feature name="android.software.managed_users" />
+ <feature name="android.software.managed_users" notLowRam="true"/>
<!-- Feature to specify if the device supports a VR mode.
feature name="android.software.vr.mode" -->
diff --git a/docs/Doxyfile b/docs/Doxyfile
index bb0ca32..0ec4551 100644
--- a/docs/Doxyfile
+++ b/docs/Doxyfile
@@ -677,7 +677,7 @@
# directories like "/usr/src/myproject". Separate the files or directories
# with spaces.
-INPUT = ../include/android ../../av/include/ndk ../../av/include/camera/ndk
+INPUT = ../include/android ../../av/media/ndk/include ../../av/camera/ndk/include
# This tag can be used to specify the character encoding of the source files
# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is
diff --git a/include/android/sensor.h b/include/android/sensor.h
index a88733c..2db0ee7 100644
--- a/include/android/sensor.h
+++ b/include/android/sensor.h
@@ -197,7 +197,7 @@
* A sensor event.
*/
-/* NOTE: Must match hardware/sensors.h */
+/* NOTE: changes to these structs have to be backward compatible */
typedef struct ASensorVector {
union {
float v[3];
@@ -259,7 +259,7 @@
};
} AAdditionalInfoEvent;
-/* NOTE: Must match hardware/sensors.h */
+/* NOTE: changes to this struct has to be backward compatible */
typedef struct ASensorEvent {
int32_t version; /* sizeof(struct ASensorEvent) */
int32_t sensor;
diff --git a/include/audiomanager/IPlayer.h b/include/audiomanager/IPlayer.h
deleted file mode 100644
index de5c1c7..0000000
--- a/include/audiomanager/IPlayer.h
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ANDROID_IPLAYER_H
-#define ANDROID_IPLAYER_H
-
-#include <stdint.h>
-#include <sys/types.h>
-
-#include <media/VolumeShaper.h>
-#include <utils/RefBase.h>
-#include <utils/Errors.h>
-#include <binder/IInterface.h>
-
-namespace android {
-
-// ----------------------------------------------------------------------------
-
-class IPlayer : public IInterface
-{
-public:
- DECLARE_META_INTERFACE(Player);
-
- virtual void start() = 0;
-
- virtual void pause() = 0;
-
- virtual void stop() = 0;
-
- virtual void setVolume(float vol) = 0;
-
- virtual void setPan(float pan) = 0;
-
- virtual void setStartDelayMs(int delayMs) = 0;
-
- virtual void applyVolumeShaper(
- const sp<VolumeShaper::Configuration>& configuration,
- const sp<VolumeShaper::Operation>& operation) = 0;
-};
-
-// ----------------------------------------------------------------------------
-
-class BnPlayer : public BnInterface<IPlayer>
-{
-public:
- virtual status_t onTransact( uint32_t code,
- const Parcel& data,
- Parcel* reply,
- uint32_t flags = 0);
-};
-
-// ----------------------------------------------------------------------------
-
-}; // namespace android
-
-#endif // ANDROID_IPLAYER_H
diff --git a/include/input/InputTransport.h b/include/input/InputTransport.h
index 9449474..c4b5dca 100644
--- a/include/input/InputTransport.h
+++ b/include/input/InputTransport.h
@@ -455,7 +455,6 @@
int32_t* displayId);
void updateTouchState(InputMessage& msg);
- bool rewriteMessage(const TouchState& state, InputMessage& msg);
void resampleTouchState(nsecs_t frameTime, MotionEvent* event,
const InputMessage *next);
@@ -464,6 +463,7 @@
status_t sendUnchainedFinishedSignal(uint32_t seq, bool handled);
+ static bool rewriteMessage(const TouchState& state, InputMessage& msg);
static void initializeKeyEvent(KeyEvent* event, const InputMessage* msg);
static void initializeMotionEvent(MotionEvent* event, const InputMessage* msg);
static void addSample(MotionEvent* event, const InputMessage* msg);
diff --git a/include/input/VelocityTracker.h b/include/input/VelocityTracker.h
index 795f575..ffa1614 100644
--- a/include/input/VelocityTracker.h
+++ b/include/input/VelocityTracker.h
@@ -264,6 +264,40 @@
Movement mMovements[HISTORY_SIZE];
};
+class ImpulseVelocityTrackerStrategy : public VelocityTrackerStrategy {
+public:
+ ImpulseVelocityTrackerStrategy();
+ virtual ~ImpulseVelocityTrackerStrategy();
+
+ virtual void clear();
+ virtual void clearPointers(BitSet32 idBits);
+ virtual void addMovement(nsecs_t eventTime, BitSet32 idBits,
+ const VelocityTracker::Position* positions);
+ virtual bool getEstimator(uint32_t id, VelocityTracker::Estimator* outEstimator) const;
+
+private:
+ // Sample horizon.
+ // We don't use too much history by default since we want to react to quick
+ // changes in direction.
+ static constexpr nsecs_t HORIZON = 100 * 1000000; // 100 ms
+
+ // Number of samples to keep.
+ static constexpr size_t HISTORY_SIZE = 20;
+
+ struct Movement {
+ nsecs_t eventTime;
+ BitSet32 idBits;
+ VelocityTracker::Position positions[MAX_POINTERS];
+
+ inline const VelocityTracker::Position& getPosition(uint32_t id) const {
+ return positions[idBits.getIndexOfBit(id)];
+ }
+ };
+
+ size_t mIndex;
+ Movement mMovements[HISTORY_SIZE];
+};
+
} // namespace android
#endif // _LIBINPUT_VELOCITY_TRACKER_H
diff --git a/include/layerproto b/include/layerproto
new file mode 120000
index 0000000..ef21a4e
--- /dev/null
+++ b/include/layerproto
@@ -0,0 +1 @@
+../services/surfaceflinger/layerproto/include/layerproto/
\ No newline at end of file
diff --git a/libs/binder/BpBinder.cpp b/libs/binder/BpBinder.cpp
index c0e0296..289433b 100644
--- a/libs/binder/BpBinder.cpp
+++ b/libs/binder/BpBinder.cpp
@@ -21,6 +21,7 @@
#include <binder/IPCThreadState.h>
#include <binder/IResultReceiver.h>
+#include <cutils/compiler.h>
#include <utils/Log.h>
#include <stdio.h>
@@ -32,6 +33,23 @@
// ---------------------------------------------------------------------------
+Mutex BpBinder::sTrackingLock;
+std::unordered_map<int32_t,uint32_t> BpBinder::sTrackingMap;
+int BpBinder::sNumTrackedUids = 0;
+std::atomic_bool BpBinder::sCountByUidEnabled(false);
+binder_proxy_limit_callback BpBinder::sLimitCallback;
+bool BpBinder::sBinderProxyThrottleCreate = false;
+
+// Arbitrarily high value that probably distinguishes a bad behaving app
+uint32_t BpBinder::sBinderProxyCountHighWatermark = 2500;
+// Another arbitrary value a binder count needs to drop below before another callback will be called
+uint32_t BpBinder::sBinderProxyCountLowWatermark = 2000;
+
+enum {
+ CALLBACK_TRIGGERED_MASK = 0x80000000, // A flag denoting that the callback has been called
+ COUNTING_VALUE_MASK = 0x7FFFFFFF, // A mask of the remaining bits for the count value
+};
+
BpBinder::ObjectManager::ObjectManager()
{
}
@@ -87,11 +105,47 @@
// ---------------------------------------------------------------------------
-BpBinder::BpBinder(int32_t handle)
+
+BpBinder* BpBinder::create(int32_t handle) {
+ int32_t trackedUid = -1;
+ if (sCountByUidEnabled) {
+ BpBinder* out;
+ trackedUid = IPCThreadState::self()->getCallingUid();
+ AutoMutex _l(sTrackingLock);
+ if ((sTrackingMap[trackedUid] & COUNTING_VALUE_MASK) >= sBinderProxyCountHighWatermark) {
+ ALOGE("Too many binder proxy objects sent to uid %d from uid %d (over %d proxies held)",
+ getuid(), trackedUid, sBinderProxyCountHighWatermark);
+
+ if (sBinderProxyThrottleCreate) {
+ ALOGE("Returning Null Binder Proxy Object to uid %d", trackedUid);
+ out = nullptr;
+ } else {
+ // increment and construct here in case callback has an async kill causing a race
+ sTrackingMap[trackedUid]++;
+ out = new BpBinder(handle, trackedUid);
+ }
+
+ if (sLimitCallback && !(sTrackingMap[trackedUid] & CALLBACK_TRIGGERED_MASK)) {
+ sTrackingMap[trackedUid] |= CALLBACK_TRIGGERED_MASK;
+ sLimitCallback(trackedUid);
+ }
+ } else {
+ sTrackingMap[trackedUid]++;
+ out = new BpBinder(handle, trackedUid);
+ }
+
+ return out;
+ } else {
+ return new BpBinder(handle, trackedUid);
+ }
+}
+
+BpBinder::BpBinder(int32_t handle, int32_t trackedUid)
: mHandle(handle)
, mAlive(1)
, mObitsSent(0)
, mObituaries(NULL)
+ , mTrackedUid(trackedUid)
{
ALOGV("Creating BpBinder %p handle %d\n", this, mHandle);
@@ -315,6 +369,24 @@
IPCThreadState* ipc = IPCThreadState::self();
+ if (mTrackedUid >= 0) {
+ AutoMutex _l(sTrackingLock);
+ if (CC_UNLIKELY(sTrackingMap[mTrackedUid] == 0)) {
+ ALOGE("Unexpected Binder Proxy tracking decrement in %p handle %d\n", this, mHandle);
+ } else {
+ if (CC_UNLIKELY(
+ (sTrackingMap[mTrackedUid] & CALLBACK_TRIGGERED_MASK) &&
+ ((sTrackingMap[mTrackedUid] & COUNTING_VALUE_MASK) <= sBinderProxyCountLowWatermark)
+ )) {
+ // Clear the Callback Triggered bit when crossing below the low watermark
+ sTrackingMap[mTrackedUid] &= ~CALLBACK_TRIGGERED_MASK;
+ }
+ if (--sTrackingMap[mTrackedUid] == 0) {
+ sTrackingMap.erase(mTrackedUid);
+ }
+ }
+ }
+
mLock.lock();
Vector<Obituary>* obits = mObituaries;
if(obits != NULL) {
@@ -360,6 +432,42 @@
return ipc ? ipc->attemptIncStrongHandle(mHandle) == NO_ERROR : false;
}
+uint32_t BpBinder::getBinderProxyCount(uint32_t uid)
+{
+ AutoMutex _l(sTrackingLock);
+ auto it = sTrackingMap.find(uid);
+ if (it != sTrackingMap.end()) {
+ return it->second & COUNTING_VALUE_MASK;
+ }
+ return 0;
+}
+
+void BpBinder::getCountByUid(Vector<uint32_t>& uids, Vector<uint32_t>& counts)
+{
+ AutoMutex _l(sTrackingLock);
+ uids.setCapacity(sTrackingMap.size());
+ counts.setCapacity(sTrackingMap.size());
+ for (const auto& it : sTrackingMap) {
+ uids.push_back(it.first);
+ counts.push_back(it.second & COUNTING_VALUE_MASK);
+ }
+}
+
+void BpBinder::enableCountByUid() { sCountByUidEnabled.store(true); }
+void BpBinder::disableCountByUid() { sCountByUidEnabled.store(false); }
+void BpBinder::setCountByUidEnabled(bool enable) { sCountByUidEnabled.store(enable); }
+
+void BpBinder::setLimitCallback(binder_proxy_limit_callback cb) {
+ AutoMutex _l(sTrackingLock);
+ sLimitCallback = cb;
+}
+
+void BpBinder::setBinderProxyCountWatermarks(int high, int low) {
+ AutoMutex _l(sTrackingLock);
+ sBinderProxyCountHighWatermark = high;
+ sBinderProxyCountLowWatermark = low;
+}
+
// ---------------------------------------------------------------------------
}; // namespace android
diff --git a/libs/binder/IServiceManager.cpp b/libs/binder/IServiceManager.cpp
index c7a0f43..70f5108 100644
--- a/libs/binder/IServiceManager.cpp
+++ b/libs/binder/IServiceManager.cpp
@@ -161,19 +161,18 @@
}
virtual status_t addService(const String16& name, const sp<IBinder>& service,
- bool allowIsolated)
- {
+ bool allowIsolated, int dumpsysPriority) {
Parcel data, reply;
data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor());
data.writeString16(name);
data.writeStrongBinder(service);
data.writeInt32(allowIsolated ? 1 : 0);
+ data.writeInt32(dumpsysPriority);
status_t err = remote()->transact(ADD_SERVICE_TRANSACTION, data, &reply);
return err == NO_ERROR ? reply.readExceptionCode() : err;
}
- virtual Vector<String16> listServices()
- {
+ virtual Vector<String16> listServices(int dumpsysPriority) {
Vector<String16> res;
int n = 0;
@@ -181,6 +180,7 @@
Parcel data, reply;
data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor());
data.writeInt32(n++);
+ data.writeInt32(dumpsysPriority);
status_t err = remote()->transact(LIST_SERVICES_TRANSACTION, data, &reply);
if (err != NO_ERROR)
break;
diff --git a/libs/binder/IShellCallback.cpp b/libs/binder/IShellCallback.cpp
index c793df3..23b83a6 100644
--- a/libs/binder/IShellCallback.cpp
+++ b/libs/binder/IShellCallback.cpp
@@ -39,11 +39,13 @@
{
}
- virtual int openOutputFile(const String16& path, const String16& seLinuxContext) {
+ virtual int openFile(const String16& path, const String16& seLinuxContext,
+ const String16& mode) {
Parcel data, reply;
data.writeInterfaceToken(IShellCallback::getInterfaceDescriptor());
data.writeString16(path);
data.writeString16(seLinuxContext);
+ data.writeString16(mode);
remote()->transact(OP_OPEN_OUTPUT_FILE, data, &reply, 0);
reply.readExceptionCode();
int fd = reply.readParcelFileDescriptor();
@@ -64,7 +66,8 @@
CHECK_INTERFACE(IShellCallback, data, reply);
String16 path(data.readString16());
String16 seLinuxContext(data.readString16());
- int fd = openOutputFile(path, seLinuxContext);
+ String16 mode(data.readString16());
+ int fd = openFile(path, seLinuxContext, mode);
if (reply != NULL) {
reply->writeNoException();
if (fd >= 0) {
diff --git a/libs/binder/ProcessState.cpp b/libs/binder/ProcessState.cpp
index 11dd525..44039f8 100644
--- a/libs/binder/ProcessState.cpp
+++ b/libs/binder/ProcessState.cpp
@@ -276,7 +276,7 @@
return NULL;
}
- b = new BpBinder(handle);
+ b = BpBinder::create(handle);
e->binder = b;
if (b) e->refs = b->getWeakRefs();
result = b;
@@ -310,7 +310,7 @@
// arriving from the driver.
IBinder* b = e->binder;
if (b == NULL || !e->refs->attemptIncWeak(this)) {
- b = new BpBinder(handle);
+ b = BpBinder::create(handle);
result = b;
e->binder = b;
if (b) e->refs = b->getWeakRefs();
diff --git a/libs/binder/include/binder/BinderService.h b/libs/binder/include/binder/BinderService.h
index ef703bd..4ce82a1 100644
--- a/libs/binder/include/binder/BinderService.h
+++ b/libs/binder/include/binder/BinderService.h
@@ -34,15 +34,17 @@
class BinderService
{
public:
- static status_t publish(bool allowIsolated = false) {
+ static status_t publish(bool allowIsolated = false,
+ int dumpFlags = IServiceManager::DUMP_FLAG_PRIORITY_NORMAL) {
sp<IServiceManager> sm(defaultServiceManager());
- return sm->addService(
- String16(SERVICE::getServiceName()),
- new SERVICE(), allowIsolated);
+ return sm->addService(String16(SERVICE::getServiceName()), new SERVICE(), allowIsolated,
+ dumpFlags);
}
- static void publishAndJoinThreadPool(bool allowIsolated = false) {
- publish(allowIsolated);
+ static void publishAndJoinThreadPool(
+ bool allowIsolated = false,
+ int dumpFlags = IServiceManager::DUMP_FLAG_PRIORITY_NORMAL) {
+ publish(allowIsolated, dumpFlags);
joinThreadPool();
}
diff --git a/libs/binder/include/binder/BpBinder.h b/libs/binder/include/binder/BpBinder.h
index 7ef93aa..8bd297b 100644
--- a/libs/binder/include/binder/BpBinder.h
+++ b/libs/binder/include/binder/BpBinder.h
@@ -19,15 +19,20 @@
#include <binder/IBinder.h>
#include <utils/KeyedVector.h>
+#include <utils/Mutex.h>
#include <utils/threads.h>
+#include <unordered_map>
+
// ---------------------------------------------------------------------------
namespace android {
+using binder_proxy_limit_callback = void(*)(int);
+
class BpBinder : public IBinder
{
public:
- BpBinder(int32_t handle);
+ static BpBinder* create(int32_t handle);
inline int32_t handle() const { return mHandle; }
@@ -61,6 +66,14 @@
status_t setConstantData(const void* data, size_t size);
void sendObituary();
+ static uint32_t getBinderProxyCount(uint32_t uid);
+ static void getCountByUid(Vector<uint32_t>& uids, Vector<uint32_t>& counts);
+ static void enableCountByUid();
+ static void disableCountByUid();
+ static void setCountByUidEnabled(bool enable);
+ static void setLimitCallback(binder_proxy_limit_callback cb);
+ static void setBinderProxyCountWatermarks(int high, int low);
+
class ObjectManager
{
public:
@@ -91,6 +104,7 @@
};
protected:
+ BpBinder(int32_t handle,int32_t trackedUid);
virtual ~BpBinder();
virtual void onFirstRef();
virtual void onLastStrongRef(const void* id);
@@ -115,6 +129,16 @@
ObjectManager mObjects;
Parcel* mConstantData;
mutable String16 mDescriptorCache;
+ int32_t mTrackedUid;
+
+ static Mutex sTrackingLock;
+ static std::unordered_map<int32_t,uint32_t> sTrackingMap;
+ static int sNumTrackedUids;
+ static std::atomic_bool sCountByUidEnabled;
+ static binder_proxy_limit_callback sLimitCallback;
+ static uint32_t sBinderProxyCountHighWatermark;
+ static uint32_t sBinderProxyCountLowWatermark;
+ static bool sBinderProxyThrottleCreate;
};
}; // namespace android
diff --git a/libs/binder/include/binder/IServiceManager.h b/libs/binder/include/binder/IServiceManager.h
index 3b23f81..19e841a 100644
--- a/libs/binder/include/binder/IServiceManager.h
+++ b/libs/binder/include/binder/IServiceManager.h
@@ -31,6 +31,15 @@
{
public:
DECLARE_META_INTERFACE(ServiceManager)
+ /*
+ * Must match values in IServiceManager.java
+ */
+ static const int DUMP_FLAG_PRIORITY_CRITICAL = 1 << 0;
+ static const int DUMP_FLAG_PRIORITY_HIGH = 1 << 1;
+ static const int DUMP_FLAG_PRIORITY_NORMAL = 1 << 2;
+ static const int DUMP_FLAG_PRIORITY_ALL =
+ DUMP_FLAG_PRIORITY_CRITICAL | DUMP_FLAG_PRIORITY_HIGH | DUMP_FLAG_PRIORITY_NORMAL;
+ static const int DUMP_FLAG_PROTO = 1 << 3;
/**
* Retrieve an existing service, blocking for a few seconds
@@ -46,14 +55,14 @@
/**
* Register a service.
*/
- virtual status_t addService( const String16& name,
- const sp<IBinder>& service,
- bool allowIsolated = false) = 0;
+ virtual status_t addService(const String16& name, const sp<IBinder>& service,
+ bool allowIsolated = false,
+ int dumpsysFlags = DUMP_FLAG_PRIORITY_NORMAL) = 0;
/**
* Return list of all existing services.
*/
- virtual Vector<String16> listServices() = 0;
+ virtual Vector<String16> listServices(int dumpsysFlags = DUMP_FLAG_PRIORITY_ALL) = 0;
enum {
GET_SERVICE_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION,
diff --git a/libs/binder/include/binder/IShellCallback.h b/libs/binder/include/binder/IShellCallback.h
index fda9ee6..b47e995 100644
--- a/libs/binder/include/binder/IShellCallback.h
+++ b/libs/binder/include/binder/IShellCallback.h
@@ -29,7 +29,8 @@
public:
DECLARE_META_INTERFACE(ShellCallback);
- virtual int openOutputFile(const String16& path, const String16& seLinuxContext) = 0;
+ virtual int openFile(const String16& path, const String16& seLinuxContext,
+ const String16& mode) = 0;
enum {
OP_OPEN_OUTPUT_FILE = IBinder::FIRST_CALL_TRANSACTION
diff --git a/libs/binder/tests/binderThroughputTest.cpp b/libs/binder/tests/binderThroughputTest.cpp
index 455f2c4..bf41e0b 100644
--- a/libs/binder/tests/binderThroughputTest.cpp
+++ b/libs/binder/tests/binderThroughputTest.cpp
@@ -215,7 +215,7 @@
int target = cs_pair ? num % server_count : rand() % workers.size();
int sz = payload_size;
- while (sz > sizeof(uint32_t)) {
+ while (sz >= sizeof(uint32_t)) {
data.writeInt32(0);
sz -= sizeof(uint32_t);
}
@@ -381,6 +381,7 @@
// No need to run training round in this case.
if (atoi(argv[i+1]) > 0) {
max_time_bucket = strtoull(argv[i+1], (char **)NULL, 10) * 1000;
+ time_per_bucket = max_time_bucket / num_buckets;
i++;
} else {
cout << "Max latency -m must be positive." << endl;
diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp
index 8e7f814..973302c 100644
--- a/libs/gui/ISurfaceComposer.cpp
+++ b/libs/gui/ISurfaceComposer.cpp
@@ -29,8 +29,7 @@
#include <gui/ISurfaceComposer.h>
#include <gui/ISurfaceComposerClient.h>
#include <gui/LayerDebugInfo.h>
-
-#include <private/gui/LayerState.h>
+#include <gui/LayerState.h>
#include <system/graphics.h>
@@ -123,6 +122,18 @@
return reply.readInt32();
}
+ virtual status_t captureLayers(const sp<IBinder>& layerHandleBinder,
+ const sp<IGraphicBufferProducer>& producer,
+ ISurfaceComposer::Rotation rotation) {
+ Parcel data, reply;
+ data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
+ data.writeStrongBinder(layerHandleBinder);
+ data.writeStrongBinder(IInterface::asBinder(producer));
+ data.writeInt32(static_cast<int32_t>(rotation));
+ remote()->transact(BnSurfaceComposer::CAPTURE_LAYERS, data, &reply);
+ return reply.readInt32();
+ }
+
virtual bool authenticateSurfaceTexture(
const sp<IGraphicBufferProducer>& bufferProducer) const
{
@@ -589,6 +600,18 @@
reply->writeInt32(res);
return NO_ERROR;
}
+ case CAPTURE_LAYERS: {
+ CHECK_INTERFACE(ISurfaceComposer, data, reply);
+ sp<IBinder> layerHandleBinder = data.readStrongBinder();
+ sp<IGraphicBufferProducer> producer =
+ interface_cast<IGraphicBufferProducer>(data.readStrongBinder());
+ int32_t rotation = data.readInt32();
+
+ status_t res = captureLayers(layerHandleBinder, producer,
+ static_cast<ISurfaceComposer::Rotation>(rotation));
+ reply->writeInt32(res);
+ return NO_ERROR;
+ }
case AUTHENTICATE_SURFACE: {
CHECK_INTERFACE(ISurfaceComposer, data, reply);
sp<IGraphicBufferProducer> bufferProducer =
diff --git a/libs/gui/LayerDebugInfo.cpp b/libs/gui/LayerDebugInfo.cpp
index 57ddde0..d3dc16d 100644
--- a/libs/gui/LayerDebugInfo.cpp
+++ b/libs/gui/LayerDebugInfo.cpp
@@ -43,7 +43,10 @@
RETURN_ON_ERROR(parcel->writeInt32(mHeight));
RETURN_ON_ERROR(parcel->write(mCrop));
RETURN_ON_ERROR(parcel->write(mFinalCrop));
- RETURN_ON_ERROR(parcel->writeFloat(mAlpha));
+ RETURN_ON_ERROR(parcel->writeFloat(mColor.r));
+ RETURN_ON_ERROR(parcel->writeFloat(mColor.g));
+ RETURN_ON_ERROR(parcel->writeFloat(mColor.b));
+ RETURN_ON_ERROR(parcel->writeFloat(mColor.a));
RETURN_ON_ERROR(parcel->writeUint32(mFlags));
RETURN_ON_ERROR(parcel->writeInt32(mPixelFormat));
RETURN_ON_ERROR(parcel->writeUint32(static_cast<uint32_t>(mDataSpace)));
@@ -79,7 +82,14 @@
RETURN_ON_ERROR(parcel->readInt32(&mHeight));
RETURN_ON_ERROR(parcel->read(mCrop));
RETURN_ON_ERROR(parcel->read(mFinalCrop));
- RETURN_ON_ERROR(parcel->readFloat(&mAlpha));
+ mColor.r = parcel->readFloat();
+ RETURN_ON_ERROR(parcel->errorCheck());
+ mColor.g = parcel->readFloat();
+ RETURN_ON_ERROR(parcel->errorCheck());
+ mColor.b = parcel->readFloat();
+ RETURN_ON_ERROR(parcel->errorCheck());
+ mColor.a = parcel->readFloat();
+ RETURN_ON_ERROR(parcel->errorCheck());
RETURN_ON_ERROR(parcel->readUint32(&mFlags));
RETURN_ON_ERROR(parcel->readInt32(&mPixelFormat));
// \todo [2017-07-25 kraita]: Static casting mDataSpace pointer to an uint32 does work. Better ways?
@@ -116,8 +126,10 @@
result.appendFormat("isOpaque=%1d, invalidate=%1d, ", info.mIsOpaque, info.mContentDirty);
result.appendFormat("dataspace=%s, ", dataspaceDetails(info.mDataSpace).c_str());
result.appendFormat("pixelformat=%s, ", decodePixelFormat(info.mPixelFormat).c_str());
- result.appendFormat("alpha=%.3f, flags=0x%08x, ",
- static_cast<double>(info.mAlpha), info.mFlags);
+ result.appendFormat("color=(%.3f,%.3f,%.3f,%.3f), flags=0x%08x, ",
+ static_cast<double>(info.mColor.r), static_cast<double>(info.mColor.g),
+ static_cast<double>(info.mColor.b), static_cast<double>(info.mColor.a),
+ info.mFlags);
result.appendFormat("tr=[%.2f, %.2f][%.2f, %.2f]",
static_cast<double>(info.mMatrix[0][0]), static_cast<double>(info.mMatrix[0][1]),
static_cast<double>(info.mMatrix[1][0]), static_cast<double>(info.mMatrix[1][1]));
diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp
index 9b06e63..b5295f2 100644
--- a/libs/gui/LayerState.cpp
+++ b/libs/gui/LayerState.cpp
@@ -18,7 +18,7 @@
#include <binder/Parcel.h>
#include <gui/ISurfaceComposerClient.h>
#include <gui/IGraphicBufferProducer.h>
-#include <private/gui/LayerState.h>
+#include <gui/LayerState.h>
namespace android {
@@ -45,6 +45,10 @@
output.writeInt32(overrideScalingMode);
output.writeStrongBinder(IInterface::asBinder(barrierGbp));
output.writeStrongBinder(relativeLayerHandle);
+ output.writeStrongBinder(parentHandleForChild);
+ output.writeFloat(color.r);
+ output.writeFloat(color.g);
+ output.writeFloat(color.b);
output.write(transparentRegion);
return NO_ERROR;
}
@@ -77,6 +81,10 @@
barrierGbp =
interface_cast<IGraphicBufferProducer>(input.readStrongBinder());
relativeLayerHandle = input.readStrongBinder();
+ parentHandleForChild = input.readStrongBinder();
+ color.r = input.readFloat();
+ color.g = input.readFloat();
+ color.b = input.readFloat();
input.read(transparentRegion);
return NO_ERROR;
}
@@ -128,5 +136,101 @@
return NO_ERROR;
}
+void DisplayState::merge(const DisplayState& other) {
+ if (other.what & eSurfaceChanged) {
+ what |= eSurfaceChanged;
+ surface = other.surface;
+ }
+ if (other.what & eLayerStackChanged) {
+ what |= eLayerStackChanged;
+ layerStack = other.layerStack;
+ }
+ if (other.what & eDisplayProjectionChanged) {
+ what |= eDisplayProjectionChanged;
+ orientation = other.orientation;
+ viewport = other.viewport;
+ frame = other.frame;
+ }
+ if (other.what & eDisplaySizeChanged) {
+ what |= eDisplaySizeChanged;
+ width = other.width;
+ height = other.height;
+ }
+}
+
+void layer_state_t::merge(const layer_state_t& other) {
+ if (other.what & ePositionChanged) {
+ what |= ePositionChanged;
+ x = other.x;
+ y = other.y;
+ }
+ if (other.what & eLayerChanged) {
+ what |= eLayerChanged;
+ z = other.z;
+ }
+ if (other.what & eSizeChanged) {
+ what |= eSizeChanged;
+ w = other.w;
+ h = other.h;
+ }
+ if (other.what & eAlphaChanged) {
+ what |= eAlphaChanged;
+ alpha = other.alpha;
+ }
+ if (other.what & eMatrixChanged) {
+ what |= eMatrixChanged;
+ matrix = other.matrix;
+ }
+ if (other.what & eTransparentRegionChanged) {
+ what |= eTransparentRegionChanged;
+ transparentRegion = other.transparentRegion;
+ }
+ if (other.what & eFlagsChanged) {
+ what |= eFlagsChanged;
+ flags = other.flags;
+ mask = other.mask;
+ }
+ if (other.what & eLayerStackChanged) {
+ what |= eLayerStackChanged;
+ layerStack = other.layerStack;
+ }
+ if (other.what & eCropChanged) {
+ what |= eCropChanged;
+ crop = other.crop;
+ }
+ if (other.what & eDeferTransaction) {
+ what |= eDeferTransaction;
+ barrierHandle = other.barrierHandle;
+ barrierGbp = other.barrierGbp;
+ frameNumber = other.frameNumber;
+ }
+ if (other.what & eFinalCropChanged) {
+ what |= eFinalCropChanged;
+ finalCrop = other.finalCrop;
+ }
+ if (other.what & eOverrideScalingModeChanged) {
+ what |= eOverrideScalingModeChanged;
+ overrideScalingMode = other.overrideScalingMode;
+ }
+ if (other.what & eGeometryAppliesWithResize) {
+ what |= eGeometryAppliesWithResize;
+ }
+ if (other.what & eReparentChildren) {
+ what |= eReparentChildren;
+ reparentHandle = other.reparentHandle;
+ }
+ if (other.what & eDetachChildren) {
+ what |= eDetachChildren;
+ }
+ if (other.what & eRelativeLayerChanged) {
+ what |= eRelativeLayerChanged;
+ z = other.z;
+ relativeLayerHandle = other.relativeLayerHandle;
+ }
+ if (other.what & eReparent) {
+ what |= eReparent;
+ parentHandleForChild = other.parentHandleForChild;
+ }
+}
}; // namespace android
diff --git a/libs/gui/Surface.cpp b/libs/gui/Surface.cpp
index d9d945d..e939383 100644
--- a/libs/gui/Surface.cpp
+++ b/libs/gui/Surface.cpp
@@ -1512,6 +1512,12 @@
return NO_ERROR;
}
+android_dataspace_t Surface::getBuffersDataSpace() {
+ ALOGV("Surface::getBuffersDataSpace");
+ Mutex::Autolock lock(mMutex);
+ return mDataSpace;
+}
+
void Surface::freeAllBuffers() {
for (int i = 0; i < NUM_BUFFER_SLOTS; i++) {
mSlots[i].buffer = 0;
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index 7ae2672..2adc273 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -21,7 +21,6 @@
#include <utils/Errors.h>
#include <utils/Log.h>
-#include <utils/Singleton.h>
#include <utils/SortedVector.h>
#include <utils/String8.h>
#include <utils/threads.h>
@@ -37,11 +36,11 @@
#include <gui/IGraphicBufferProducer.h>
#include <gui/ISurfaceComposer.h>
#include <gui/ISurfaceComposerClient.h>
+#include <gui/LayerState.h>
#include <gui/Surface.h>
#include <gui/SurfaceComposerClient.h>
#include <private/gui/ComposerService.h>
-#include <private/gui/LayerState.h>
namespace android {
// ---------------------------------------------------------------------------
@@ -97,204 +96,95 @@
// ---------------------------------------------------------------------------
-static inline
-int compare_type(const ComposerState& lhs, const ComposerState& rhs) {
- if (lhs.client < rhs.client) return -1;
- if (lhs.client > rhs.client) return 1;
- if (lhs.state.surface < rhs.state.surface) return -1;
- if (lhs.state.surface > rhs.state.surface) return 1;
- return 0;
+SurfaceComposerClient::Transaction::Transaction(const Transaction& other) :
+ mForceSynchronous(other.mForceSynchronous),
+ mTransactionNestCount(other.mTransactionNestCount),
+ mAnimation(other.mAnimation) {
+ mDisplayStates = other.mDisplayStates;
+ mComposerStates = other.mComposerStates;
}
-static inline
-int compare_type(const DisplayState& lhs, const DisplayState& rhs) {
- return compare_type(lhs.token, rhs.token);
+SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::merge(Transaction&& other) {
+ for (auto const& state : other.mComposerStates) {
+ ssize_t index = mComposerStates.indexOf(state);
+ if (index < 0) {
+ mComposerStates.add(state);
+ } else {
+ mComposerStates.editItemAt(static_cast<size_t>(index)).state.merge(state.state);
+ }
+ }
+ other.mComposerStates.clear();
+
+ for (auto const& state : other.mDisplayStates) {
+ ssize_t index = mDisplayStates.indexOf(state);
+ if (index < 0) {
+ mDisplayStates.add(state);
+ } else {
+ mDisplayStates.editItemAt(static_cast<size_t>(index)).merge(state);
+ }
+ }
+ other.mDisplayStates.clear();
+
+ return *this;
}
-class Composer : public Singleton<Composer>
-{
- friend class Singleton<Composer>;
-
- mutable Mutex mLock;
- SortedVector<ComposerState> mComposerStates;
- SortedVector<DisplayState > mDisplayStates;
- uint32_t mForceSynchronous;
- uint32_t mTransactionNestCount;
- bool mAnimation;
-
- Composer() : Singleton<Composer>(),
- mForceSynchronous(0), mTransactionNestCount(0),
- mAnimation(false)
- { }
-
- void openGlobalTransactionImpl();
- void closeGlobalTransactionImpl(bool synchronous);
- void setAnimationTransactionImpl();
- status_t enableVSyncInjectionsImpl(bool enable);
- status_t injectVSyncImpl(nsecs_t when);
-
- layer_state_t* getLayerStateLocked(
- const sp<SurfaceComposerClient>& client, const sp<IBinder>& id);
-
- DisplayState& getDisplayStateLocked(const sp<IBinder>& token);
-
-public:
- sp<IBinder> createDisplay(const String8& displayName, bool secure);
- void destroyDisplay(const sp<IBinder>& display);
- sp<IBinder> getBuiltInDisplay(int32_t id);
-
- status_t setPosition(const sp<SurfaceComposerClient>& client, const sp<IBinder>& id,
- float x, float y);
- status_t setSize(const sp<SurfaceComposerClient>& client, const sp<IBinder>& id,
- uint32_t w, uint32_t h);
- status_t setLayer(const sp<SurfaceComposerClient>& client, const sp<IBinder>& id,
- int32_t z);
- status_t setRelativeLayer(const sp<SurfaceComposerClient>& client, const sp<IBinder>& id,
- const sp<IBinder>& relativeTo, int32_t z);
- status_t setFlags(const sp<SurfaceComposerClient>& client, const sp<IBinder>& id,
- uint32_t flags, uint32_t mask);
- status_t setTransparentRegionHint(
- const sp<SurfaceComposerClient>& client, const sp<IBinder>& id,
- const Region& transparentRegion);
- status_t setAlpha(const sp<SurfaceComposerClient>& client, const sp<IBinder>& id,
- float alpha);
- status_t setMatrix(const sp<SurfaceComposerClient>& client, const sp<IBinder>& id,
- float dsdx, float dtdx, float dtdy, float dsdy);
- status_t setOrientation(int orientation);
- status_t setCrop(const sp<SurfaceComposerClient>& client, const sp<IBinder>& id,
- const Rect& crop);
- status_t setFinalCrop(const sp<SurfaceComposerClient>& client,
- const sp<IBinder>& id, const Rect& crop);
- status_t setLayerStack(const sp<SurfaceComposerClient>& client,
- const sp<IBinder>& id, uint32_t layerStack);
- status_t deferTransactionUntil(const sp<SurfaceComposerClient>& client,
- const sp<IBinder>& id, const sp<IBinder>& handle,
- uint64_t frameNumber);
- status_t deferTransactionUntil(const sp<SurfaceComposerClient>& client,
- const sp<IBinder>& id, const sp<Surface>& barrierSurface,
- uint64_t frameNumber);
- status_t reparentChildren(const sp<SurfaceComposerClient>& client,
- const sp<IBinder>& id,
- const sp<IBinder>& newParentHandle);
- status_t detachChildren(const sp<SurfaceComposerClient>& client,
- const sp<IBinder>& id);
- status_t setOverrideScalingMode(const sp<SurfaceComposerClient>& client,
- const sp<IBinder>& id, int32_t overrideScalingMode);
- status_t setGeometryAppliesWithResize(const sp<SurfaceComposerClient>& client,
- const sp<IBinder>& id);
-
- status_t setDisplaySurface(const sp<IBinder>& token,
- sp<IGraphicBufferProducer> bufferProducer);
- void setDisplayLayerStack(const sp<IBinder>& token, uint32_t layerStack);
- void setDisplayProjection(const sp<IBinder>& token,
- uint32_t orientation,
- const Rect& layerStackRect,
- const Rect& displayRect);
- void setDisplaySize(const sp<IBinder>& token, uint32_t width, uint32_t height);
-
- static void setAnimationTransaction() {
- Composer::getInstance().setAnimationTransactionImpl();
+status_t SurfaceComposerClient::Transaction::apply(bool synchronous) {
+ if (mStatus != NO_ERROR) {
+ return mStatus;
}
- static void openGlobalTransaction() {
- Composer::getInstance().openGlobalTransactionImpl();
+ sp<ISurfaceComposer> sf(ComposerService::getComposerService());
+
+ Vector<ComposerState> composerStates;
+ Vector<DisplayState> displayStates;
+ uint32_t flags = 0;
+
+ mForceSynchronous |= synchronous;
+
+ composerStates = mComposerStates;
+ mComposerStates.clear();
+
+ displayStates = mDisplayStates;
+ mDisplayStates.clear();
+
+ if (mForceSynchronous) {
+ flags |= ISurfaceComposer::eSynchronous;
+ }
+ if (mAnimation) {
+ flags |= ISurfaceComposer::eAnimation;
}
- static void closeGlobalTransaction(bool synchronous) {
- Composer::getInstance().closeGlobalTransactionImpl(synchronous);
- }
+ mForceSynchronous = false;
+ mAnimation = false;
- static status_t enableVSyncInjections(bool enable) {
- return Composer::getInstance().enableVSyncInjectionsImpl(enable);
- }
-
- static status_t injectVSync(nsecs_t when) {
- return Composer::getInstance().injectVSyncImpl(when);
- }
-};
-
-ANDROID_SINGLETON_STATIC_INSTANCE(Composer);
+ sf->setTransactionState(composerStates, displayStates, flags);
+ mStatus = NO_ERROR;
+ return NO_ERROR;
+}
// ---------------------------------------------------------------------------
-sp<IBinder> Composer::createDisplay(const String8& displayName, bool secure) {
+sp<IBinder> SurfaceComposerClient::createDisplay(const String8& displayName, bool secure) {
return ComposerService::getComposerService()->createDisplay(displayName,
secure);
}
-void Composer::destroyDisplay(const sp<IBinder>& display) {
+void SurfaceComposerClient::destroyDisplay(const sp<IBinder>& display) {
return ComposerService::getComposerService()->destroyDisplay(display);
}
-sp<IBinder> Composer::getBuiltInDisplay(int32_t id) {
+sp<IBinder> SurfaceComposerClient::getBuiltInDisplay(int32_t id) {
return ComposerService::getComposerService()->getBuiltInDisplay(id);
}
-void Composer::openGlobalTransactionImpl() {
- { // scope for the lock
- Mutex::Autolock _l(mLock);
- mTransactionNestCount += 1;
- }
-}
-
-void Composer::closeGlobalTransactionImpl(bool synchronous) {
- sp<ISurfaceComposer> sm(ComposerService::getComposerService());
-
- Vector<ComposerState> transaction;
- Vector<DisplayState> displayTransaction;
- uint32_t flags = 0;
-
- { // scope for the lock
- Mutex::Autolock _l(mLock);
- mForceSynchronous |= synchronous;
- if (!mTransactionNestCount) {
- ALOGW("At least one call to closeGlobalTransaction() was not matched by a prior "
- "call to openGlobalTransaction().");
- } else if (--mTransactionNestCount) {
- return;
- }
-
- transaction = mComposerStates;
- mComposerStates.clear();
-
- displayTransaction = mDisplayStates;
- mDisplayStates.clear();
-
- if (mForceSynchronous) {
- flags |= ISurfaceComposer::eSynchronous;
- }
- if (mAnimation) {
- flags |= ISurfaceComposer::eAnimation;
- }
-
- mForceSynchronous = false;
- mAnimation = false;
- }
-
- sm->setTransactionState(transaction, displayTransaction, flags);
-}
-
-status_t Composer::enableVSyncInjectionsImpl(bool enable) {
- sp<ISurfaceComposer> sm(ComposerService::getComposerService());
- return sm->enableVSyncInjections(enable);
-}
-
-status_t Composer::injectVSyncImpl(nsecs_t when) {
- sp<ISurfaceComposer> sm(ComposerService::getComposerService());
- return sm->injectVSync(when);
-}
-
-void Composer::setAnimationTransactionImpl() {
- Mutex::Autolock _l(mLock);
+void SurfaceComposerClient::Transaction::setAnimationTransaction() {
mAnimation = true;
}
-layer_state_t* Composer::getLayerStateLocked(
- const sp<SurfaceComposerClient>& client, const sp<IBinder>& id) {
-
+layer_state_t* SurfaceComposerClient::Transaction::getLayerStateLocked(const sp<SurfaceControl>& sc) {
ComposerState s;
- s.client = client->mClient;
- s.state.surface = id;
+ s.client = sc->getClient()->mClient;
+ s.state.surface = sc->getHandle();
ssize_t index = mComposerStates.indexOf(s);
if (index < 0) {
@@ -306,24 +196,36 @@
return &(out[index].state);
}
-status_t Composer::setPosition(const sp<SurfaceComposerClient>& client,
- const sp<IBinder>& id, float x, float y) {
- Mutex::Autolock _l(mLock);
- layer_state_t* s = getLayerStateLocked(client, id);
- if (!s)
- return BAD_INDEX;
+SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setPosition(
+ const sp<SurfaceControl>& sc, float x, float y) {
+ layer_state_t* s = getLayerStateLocked(sc);
+ if (!s) {
+ mStatus = BAD_INDEX;
+ return *this;
+ }
s->what |= layer_state_t::ePositionChanged;
s->x = x;
s->y = y;
- return NO_ERROR;
+ return *this;
}
-status_t Composer::setSize(const sp<SurfaceComposerClient>& client,
- const sp<IBinder>& id, uint32_t w, uint32_t h) {
- Mutex::Autolock _l(mLock);
- layer_state_t* s = getLayerStateLocked(client, id);
- if (!s)
- return BAD_INDEX;
+SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::show(
+ const sp<SurfaceControl>& sc) {
+ return setFlags(sc, 0, layer_state_t::eLayerHidden);
+}
+
+SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::hide(
+ const sp<SurfaceControl>& sc) {
+ return setFlags(sc, layer_state_t::eLayerHidden, layer_state_t::eLayerHidden);
+}
+
+SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setSize(
+ const sp<SurfaceControl>& sc, uint32_t w, uint32_t h) {
+ layer_state_t* s = getLayerStateLocked(sc);
+ if (!s) {
+ mStatus = BAD_INDEX;
+ return *this;
+ }
s->what |= layer_state_t::eSizeChanged;
s->w = w;
s->h = h;
@@ -331,41 +233,41 @@
// Resizing a surface makes the transaction synchronous.
mForceSynchronous = true;
- return NO_ERROR;
+ return *this;
}
-status_t Composer::setLayer(const sp<SurfaceComposerClient>& client,
- const sp<IBinder>& id, int32_t z) {
- Mutex::Autolock _l(mLock);
- layer_state_t* s = getLayerStateLocked(client, id);
- if (!s)
- return BAD_INDEX;
+SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setLayer(
+ const sp<SurfaceControl>& sc, int32_t z) {
+ layer_state_t* s = getLayerStateLocked(sc);
+ if (!s) {
+ mStatus = BAD_INDEX;
+ return *this;
+ }
s->what |= layer_state_t::eLayerChanged;
s->z = z;
- return NO_ERROR;
+ return *this;
}
-status_t Composer::setRelativeLayer(const sp<SurfaceComposerClient>& client,
- const sp<IBinder>& id, const sp<IBinder>& relativeTo,
+SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setRelativeLayer(const sp<SurfaceControl>& sc, const sp<IBinder>& relativeTo,
int32_t z) {
- Mutex::Autolock _l(mLock);
- layer_state_t* s = getLayerStateLocked(client, id);
+ layer_state_t* s = getLayerStateLocked(sc);
if (!s) {
- return BAD_INDEX;
+ mStatus = BAD_INDEX;
}
s->what |= layer_state_t::eRelativeLayerChanged;
s->relativeLayerHandle = relativeTo;
s->z = z;
- return NO_ERROR;
+ return *this;
}
-status_t Composer::setFlags(const sp<SurfaceComposerClient>& client,
- const sp<IBinder>& id, uint32_t flags,
+SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setFlags(
+ const sp<SurfaceControl>& sc, uint32_t flags,
uint32_t mask) {
- Mutex::Autolock _l(mLock);
- layer_state_t* s = getLayerStateLocked(client, id);
- if (!s)
- return BAD_INDEX;
+ layer_state_t* s = getLayerStateLocked(sc);
+ if (!s) {
+ mStatus = BAD_INDEX;
+ return *this;
+ }
if ((mask & layer_state_t::eLayerOpaque) ||
(mask & layer_state_t::eLayerHidden) ||
(mask & layer_state_t::eLayerSecure)) {
@@ -374,50 +276,54 @@
s->flags &= ~mask;
s->flags |= (flags & mask);
s->mask |= mask;
- return NO_ERROR;
+ return *this;
}
-status_t Composer::setTransparentRegionHint(
- const sp<SurfaceComposerClient>& client, const sp<IBinder>& id,
+SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setTransparentRegionHint(
+ const sp<SurfaceControl>& sc,
const Region& transparentRegion) {
- Mutex::Autolock _l(mLock);
- layer_state_t* s = getLayerStateLocked(client, id);
- if (!s)
- return BAD_INDEX;
+ layer_state_t* s = getLayerStateLocked(sc);
+ if (!s) {
+ mStatus = BAD_INDEX;
+ return *this;
+ }
s->what |= layer_state_t::eTransparentRegionChanged;
s->transparentRegion = transparentRegion;
- return NO_ERROR;
+ return *this;
}
-status_t Composer::setAlpha(const sp<SurfaceComposerClient>& client,
- const sp<IBinder>& id, float alpha) {
- Mutex::Autolock _l(mLock);
- layer_state_t* s = getLayerStateLocked(client, id);
- if (!s)
- return BAD_INDEX;
+SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setAlpha(
+ const sp<SurfaceControl>& sc, float alpha) {
+ layer_state_t* s = getLayerStateLocked(sc);
+ if (!s) {
+ mStatus = BAD_INDEX;
+ return *this;
+ }
s->what |= layer_state_t::eAlphaChanged;
s->alpha = alpha;
- return NO_ERROR;
+ return *this;
}
-status_t Composer::setLayerStack(const sp<SurfaceComposerClient>& client,
- const sp<IBinder>& id, uint32_t layerStack) {
- Mutex::Autolock _l(mLock);
- layer_state_t* s = getLayerStateLocked(client, id);
- if (!s)
- return BAD_INDEX;
+SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setLayerStack(
+ const sp<SurfaceControl>& sc, uint32_t layerStack) {
+ layer_state_t* s = getLayerStateLocked(sc);
+ if (!s) {
+ mStatus = BAD_INDEX;
+ return *this;
+ }
s->what |= layer_state_t::eLayerStackChanged;
s->layerStack = layerStack;
- return NO_ERROR;
+ return *this;
}
-status_t Composer::setMatrix(const sp<SurfaceComposerClient>& client,
- const sp<IBinder>& id, float dsdx, float dtdx,
+SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setMatrix(
+ const sp<SurfaceControl>& sc, float dsdx, float dtdx,
float dtdy, float dsdy) {
- Mutex::Autolock _l(mLock);
- layer_state_t* s = getLayerStateLocked(client, id);
- if (!s)
- return BAD_INDEX;
+ layer_state_t* s = getLayerStateLocked(sc);
+ if (!s) {
+ mStatus = BAD_INDEX;
+ return *this;
+ }
s->what |= layer_state_t::eMatrixChanged;
layer_state_t::matrix22_t matrix;
matrix.dsdx = dsdx;
@@ -425,93 +331,115 @@
matrix.dsdy = dsdy;
matrix.dtdy = dtdy;
s->matrix = matrix;
- return NO_ERROR;
+ return *this;
}
-status_t Composer::setCrop(const sp<SurfaceComposerClient>& client,
- const sp<IBinder>& id, const Rect& crop) {
- Mutex::Autolock _l(mLock);
- layer_state_t* s = getLayerStateLocked(client, id);
- if (!s)
- return BAD_INDEX;
+SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setCrop(
+ const sp<SurfaceControl>& sc, const Rect& crop) {
+ layer_state_t* s = getLayerStateLocked(sc);
+ if (!s) {
+ mStatus = BAD_INDEX;
+ return *this;
+ }
s->what |= layer_state_t::eCropChanged;
s->crop = crop;
- return NO_ERROR;
+ return *this;
}
-status_t Composer::setFinalCrop(const sp<SurfaceComposerClient>& client,
- const sp<IBinder>& id, const Rect& crop) {
- Mutex::Autolock _l(mLock);
- layer_state_t* s = getLayerStateLocked(client, id);
+SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setFinalCrop(const sp<SurfaceControl>& sc, const Rect& crop) {
+ layer_state_t* s = getLayerStateLocked(sc);
if (!s) {
- return BAD_INDEX;
+ mStatus = BAD_INDEX;
+ return *this;
}
s->what |= layer_state_t::eFinalCropChanged;
s->finalCrop = crop;
- return NO_ERROR;
+ return *this;
}
-status_t Composer::deferTransactionUntil(
- const sp<SurfaceComposerClient>& client, const sp<IBinder>& id,
+SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::deferTransactionUntil(
+ const sp<SurfaceControl>& sc,
const sp<IBinder>& handle, uint64_t frameNumber) {
- Mutex::Autolock lock(mLock);
- layer_state_t* s = getLayerStateLocked(client, id);
+ layer_state_t* s = getLayerStateLocked(sc);
if (!s) {
- return BAD_INDEX;
+ mStatus = BAD_INDEX;
+ return *this;
}
s->what |= layer_state_t::eDeferTransaction;
s->barrierHandle = handle;
s->frameNumber = frameNumber;
- return NO_ERROR;
+ return *this;
}
-status_t Composer::deferTransactionUntil(
- const sp<SurfaceComposerClient>& client, const sp<IBinder>& id,
+SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::deferTransactionUntil(
+ const sp<SurfaceControl>& sc,
const sp<Surface>& barrierSurface, uint64_t frameNumber) {
- Mutex::Autolock lock(mLock);
- layer_state_t* s = getLayerStateLocked(client, id);
+ layer_state_t* s = getLayerStateLocked(sc);
if (!s) {
- return BAD_INDEX;
+ mStatus = BAD_INDEX;
+ return *this;
}
s->what |= layer_state_t::eDeferTransaction;
s->barrierGbp = barrierSurface->getIGraphicBufferProducer();
s->frameNumber = frameNumber;
- return NO_ERROR;
+ return *this;
}
-status_t Composer::reparentChildren(
- const sp<SurfaceComposerClient>& client,
- const sp<IBinder>& id,
+SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::reparentChildren(
+ const sp<SurfaceControl>& sc,
const sp<IBinder>& newParentHandle) {
- Mutex::Autolock lock(mLock);
- layer_state_t* s = getLayerStateLocked(client, id);
+ layer_state_t* s = getLayerStateLocked(sc);
if (!s) {
- return BAD_INDEX;
+ mStatus = BAD_INDEX;
+ return *this;
}
s->what |= layer_state_t::eReparentChildren;
s->reparentHandle = newParentHandle;
- return NO_ERROR;
+ return *this;
}
-status_t Composer::detachChildren(
- const sp<SurfaceComposerClient>& client,
- const sp<IBinder>& id) {
- Mutex::Autolock lock(mLock);
- layer_state_t* s = getLayerStateLocked(client, id);
+SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::reparent(
+ const sp<SurfaceControl>& sc,
+ const sp<IBinder>& newParentHandle) {
+ layer_state_t* s = getLayerStateLocked(sc);
if (!s) {
- return BAD_INDEX;
+ mStatus = BAD_INDEX;
+ return *this;
+ }
+ s->what |= layer_state_t::eReparent;
+ s->parentHandleForChild = newParentHandle;
+ return *this;
+}
+
+SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setColor(
+ const sp<SurfaceControl>& sc,
+ const half3& color) {
+ layer_state_t* s = getLayerStateLocked(sc);
+ if (!s) {
+ mStatus = BAD_INDEX;
+ return *this;
+ }
+ s->what |= layer_state_t::eColorChanged;
+ s->color = color;
+ return *this;
+}
+
+SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::detachChildren(
+ const sp<SurfaceControl>& sc) {
+ layer_state_t* s = getLayerStateLocked(sc);
+ if (!s) {
+ mStatus = BAD_INDEX;
}
s->what |= layer_state_t::eDetachChildren;
- return NO_ERROR;
+ return *this;
}
-status_t Composer::setOverrideScalingMode(
- const sp<SurfaceComposerClient>& client,
- const sp<IBinder>& id, int32_t overrideScalingMode) {
- Mutex::Autolock lock(mLock);
- layer_state_t* s = getLayerStateLocked(client, id);
+SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setOverrideScalingMode(
+ const sp<SurfaceControl>& sc, int32_t overrideScalingMode) {
+ layer_state_t* s = getLayerStateLocked(sc);
if (!s) {
- return BAD_INDEX;
+ mStatus = BAD_INDEX;
+ return *this;
}
switch (overrideScalingMode) {
@@ -524,29 +452,29 @@
default:
ALOGE("unknown scaling mode: %d",
overrideScalingMode);
- return BAD_VALUE;
+ mStatus = BAD_VALUE;
+ return *this;
}
s->what |= layer_state_t::eOverrideScalingModeChanged;
s->overrideScalingMode = overrideScalingMode;
- return NO_ERROR;
+ return *this;
}
-status_t Composer::setGeometryAppliesWithResize(
- const sp<SurfaceComposerClient>& client,
- const sp<IBinder>& id) {
- Mutex::Autolock lock(mLock);
- layer_state_t* s = getLayerStateLocked(client, id);
+SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setGeometryAppliesWithResize(
+ const sp<SurfaceControl>& sc) {
+ layer_state_t* s = getLayerStateLocked(sc);
if (!s) {
- return BAD_INDEX;
+ mStatus = BAD_INDEX;
+ return *this;
}
s->what |= layer_state_t::eGeometryAppliesWithResize;
- return NO_ERROR;
+ return *this;
}
// ---------------------------------------------------------------------------
-DisplayState& Composer::getDisplayStateLocked(const sp<IBinder>& token) {
+DisplayState& SurfaceComposerClient::Transaction::getDisplayStateLocked(const sp<IBinder>& token) {
DisplayState s;
s.token = token;
ssize_t index = mDisplayStates.indexOf(s);
@@ -558,8 +486,8 @@
return mDisplayStates.editItemAt(static_cast<size_t>(index));
}
-status_t Composer::setDisplaySurface(const sp<IBinder>& token,
- sp<IGraphicBufferProducer> bufferProducer) {
+status_t SurfaceComposerClient::Transaction::setDisplaySurface(const sp<IBinder>& token,
+ const sp<IGraphicBufferProducer>& bufferProducer) {
if (bufferProducer.get() != nullptr) {
// Make sure that composition can never be stalled by a virtual display
// consumer that isn't processing buffers fast enough.
@@ -571,26 +499,23 @@
return err;
}
}
- Mutex::Autolock _l(mLock);
DisplayState& s(getDisplayStateLocked(token));
s.surface = bufferProducer;
s.what |= DisplayState::eSurfaceChanged;
return NO_ERROR;
}
-void Composer::setDisplayLayerStack(const sp<IBinder>& token,
+void SurfaceComposerClient::Transaction::setDisplayLayerStack(const sp<IBinder>& token,
uint32_t layerStack) {
- Mutex::Autolock _l(mLock);
DisplayState& s(getDisplayStateLocked(token));
s.layerStack = layerStack;
s.what |= DisplayState::eLayerStackChanged;
}
-void Composer::setDisplayProjection(const sp<IBinder>& token,
+void SurfaceComposerClient::Transaction::setDisplayProjection(const sp<IBinder>& token,
uint32_t orientation,
const Rect& layerStackRect,
const Rect& displayRect) {
- Mutex::Autolock _l(mLock);
DisplayState& s(getDisplayStateLocked(token));
s.orientation = orientation;
s.viewport = layerStackRect;
@@ -599,8 +524,7 @@
mForceSynchronous = true; // TODO: do we actually still need this?
}
-void Composer::setDisplaySize(const sp<IBinder>& token, uint32_t width, uint32_t height) {
- Mutex::Autolock _l(mLock);
+void SurfaceComposerClient::Transaction::setDisplaySize(const sp<IBinder>& token, uint32_t width, uint32_t height) {
DisplayState& s(getDisplayStateLocked(token));
s.width = width;
s.height = height;
@@ -610,22 +534,22 @@
// ---------------------------------------------------------------------------
SurfaceComposerClient::SurfaceComposerClient()
- : mStatus(NO_INIT), mComposer(Composer::getInstance())
+ : mStatus(NO_INIT)
{
}
SurfaceComposerClient::SurfaceComposerClient(const sp<IGraphicBufferProducer>& root)
- : mStatus(NO_INIT), mComposer(Composer::getInstance()), mParent(root)
+ : mStatus(NO_INIT), mParent(root)
{
}
void SurfaceComposerClient::onFirstRef() {
- sp<ISurfaceComposer> sm(ComposerService::getComposerService());
- if (sm != 0) {
+ sp<ISurfaceComposer> sf(ComposerService::getComposerService());
+ if (sf != 0) {
auto rootProducer = mParent.promote();
sp<ISurfaceComposerClient> conn;
- conn = (rootProducer != nullptr) ? sm->createScopedConnection(rootProducer) :
- sm->createConnection();
+ conn = (rootProducer != nullptr) ? sf->createScopedConnection(rootProducer) :
+ sf->createConnection();
if (conn != 0) {
mClient = conn;
mStatus = NO_ERROR;
@@ -648,8 +572,8 @@
status_t SurfaceComposerClient::linkToComposerDeath(
const sp<IBinder::DeathRecipient>& recipient,
void* cookie, uint32_t flags) {
- sp<ISurfaceComposer> sm(ComposerService::getComposerService());
- return IInterface::asBinder(sm)->linkToDeath(recipient, cookie, flags);
+ sp<ISurfaceComposer> sf(ComposerService::getComposerService());
+ return IInterface::asBinder(sf)->linkToDeath(recipient, cookie, flags);
}
void SurfaceComposerClient::dispose() {
@@ -692,19 +616,6 @@
return sur;
}
-sp<IBinder> SurfaceComposerClient::createDisplay(const String8& displayName,
- bool secure) {
- return Composer::getInstance().createDisplay(displayName, secure);
-}
-
-void SurfaceComposerClient::destroyDisplay(const sp<IBinder>& display) {
- Composer::getInstance().destroyDisplay(display);
-}
-
-sp<IBinder> SurfaceComposerClient::getBuiltInDisplay(int32_t id) {
- return Composer::getInstance().getBuiltInDisplay(id);
-}
-
status_t SurfaceComposerClient::destroySurface(const sp<IBinder>& sid) {
if (mStatus != NO_ERROR)
return mStatus;
@@ -727,152 +638,18 @@
return mClient->getLayerFrameStats(token, outStats);
}
-inline Composer& SurfaceComposerClient::getComposer() {
- return mComposer;
-}
-
// ----------------------------------------------------------------------------
-void SurfaceComposerClient::openGlobalTransaction() {
- Composer::openGlobalTransaction();
-}
-
-void SurfaceComposerClient::closeGlobalTransaction(bool synchronous) {
- Composer::closeGlobalTransaction(synchronous);
-}
-
-void SurfaceComposerClient::setAnimationTransaction() {
- Composer::setAnimationTransaction();
-}
-
status_t SurfaceComposerClient::enableVSyncInjections(bool enable) {
- return Composer::enableVSyncInjections(enable);
+ sp<ISurfaceComposer> sf(ComposerService::getComposerService());
+ return sf->enableVSyncInjections(enable);
}
status_t SurfaceComposerClient::injectVSync(nsecs_t when) {
- return Composer::injectVSync(when);
+ sp<ISurfaceComposer> sf(ComposerService::getComposerService());
+ return sf->injectVSync(when);
}
-// ----------------------------------------------------------------------------
-
-status_t SurfaceComposerClient::setCrop(const sp<IBinder>& id, const Rect& crop) {
- return getComposer().setCrop(this, id, crop);
-}
-
-status_t SurfaceComposerClient::setFinalCrop(const sp<IBinder>& id,
- const Rect& crop) {
- return getComposer().setFinalCrop(this, id, crop);
-}
-
-status_t SurfaceComposerClient::setPosition(const sp<IBinder>& id, float x, float y) {
- return getComposer().setPosition(this, id, x, y);
-}
-
-status_t SurfaceComposerClient::setSize(const sp<IBinder>& id, uint32_t w, uint32_t h) {
- return getComposer().setSize(this, id, w, h);
-}
-
-status_t SurfaceComposerClient::setLayer(const sp<IBinder>& id, int32_t z) {
- return getComposer().setLayer(this, id, z);
-}
-
-status_t SurfaceComposerClient::setRelativeLayer(const sp<IBinder>& id,
- const sp<IBinder>& relativeTo, int32_t z) {
- return getComposer().setRelativeLayer(this, id, relativeTo, z);
-}
-
-status_t SurfaceComposerClient::hide(const sp<IBinder>& id) {
- return getComposer().setFlags(this, id,
- layer_state_t::eLayerHidden,
- layer_state_t::eLayerHidden);
-}
-
-status_t SurfaceComposerClient::show(const sp<IBinder>& id) {
- return getComposer().setFlags(this, id,
- 0,
- layer_state_t::eLayerHidden);
-}
-
-status_t SurfaceComposerClient::setFlags(const sp<IBinder>& id, uint32_t flags,
- uint32_t mask) {
- return getComposer().setFlags(this, id, flags, mask);
-}
-
-status_t SurfaceComposerClient::setTransparentRegionHint(const sp<IBinder>& id,
- const Region& transparentRegion) {
- return getComposer().setTransparentRegionHint(this, id, transparentRegion);
-}
-
-status_t SurfaceComposerClient::setAlpha(const sp<IBinder>& id, float alpha) {
- return getComposer().setAlpha(this, id, alpha);
-}
-
-status_t SurfaceComposerClient::setLayerStack(const sp<IBinder>& id, uint32_t layerStack) {
- return getComposer().setLayerStack(this, id, layerStack);
-}
-
-status_t SurfaceComposerClient::setMatrix(const sp<IBinder>& id, float dsdx, float dtdx,
- float dtdy, float dsdy) {
- return getComposer().setMatrix(this, id, dsdx, dtdx, dtdy, dsdy);
-}
-
-status_t SurfaceComposerClient::deferTransactionUntil(const sp<IBinder>& id,
- const sp<IBinder>& handle, uint64_t frameNumber) {
- return getComposer().deferTransactionUntil(this, id, handle, frameNumber);
-}
-
-status_t SurfaceComposerClient::deferTransactionUntil(const sp<IBinder>& id,
- const sp<Surface>& barrierSurface, uint64_t frameNumber) {
- return getComposer().deferTransactionUntil(this, id, barrierSurface, frameNumber);
-}
-
-status_t SurfaceComposerClient::reparentChildren(const sp<IBinder>& id,
- const sp<IBinder>& newParentHandle) {
- return getComposer().reparentChildren(this, id, newParentHandle);
-}
-
-status_t SurfaceComposerClient::detachChildren(const sp<IBinder>& id) {
- return getComposer().detachChildren(this, id);
-}
-
-status_t SurfaceComposerClient::setOverrideScalingMode(
- const sp<IBinder>& id, int32_t overrideScalingMode) {
- return getComposer().setOverrideScalingMode(
- this, id, overrideScalingMode);
-}
-
-status_t SurfaceComposerClient::setGeometryAppliesWithResize(
- const sp<IBinder>& id) {
- return getComposer().setGeometryAppliesWithResize(this, id);
-}
-
-// ----------------------------------------------------------------------------
-
-status_t SurfaceComposerClient::setDisplaySurface(const sp<IBinder>& token,
- sp<IGraphicBufferProducer> bufferProducer) {
- return Composer::getInstance().setDisplaySurface(token, bufferProducer);
-}
-
-void SurfaceComposerClient::setDisplayLayerStack(const sp<IBinder>& token,
- uint32_t layerStack) {
- Composer::getInstance().setDisplayLayerStack(token, layerStack);
-}
-
-void SurfaceComposerClient::setDisplayProjection(const sp<IBinder>& token,
- uint32_t orientation,
- const Rect& layerStackRect,
- const Rect& displayRect) {
- Composer::getInstance().setDisplayProjection(token, orientation,
- layerStackRect, displayRect);
-}
-
-void SurfaceComposerClient::setDisplaySize(const sp<IBinder>& token,
- uint32_t width, uint32_t height) {
- Composer::getInstance().setDisplaySize(token, width, height);
-}
-
-// ----------------------------------------------------------------------------
-
status_t SurfaceComposerClient::getDisplayConfigs(
const sp<IBinder>& display, Vector<DisplayInfo>* configs)
{
@@ -978,6 +755,15 @@
return ret;
}
+status_t ScreenshotClient::captureLayers(const sp<IBinder>& layerHandle,
+ const sp<IGraphicBufferProducer>& producer,
+ uint32_t rotation) {
+ sp<ISurfaceComposer> s(ComposerService::getComposerService());
+ if (s == NULL) return NO_INIT;
+ return s->captureLayers(layerHandle, producer,
+ static_cast<ISurfaceComposer::Rotation>(rotation));
+}
+
ScreenshotClient::ScreenshotClient()
: mHaveBuffer(false) {
memset(&mBuffer, 0, sizeof(mBuffer));
diff --git a/libs/gui/SurfaceControl.cpp b/libs/gui/SurfaceControl.cpp
index 58bd273..f6a2b8f 100644
--- a/libs/gui/SurfaceControl.cpp
+++ b/libs/gui/SurfaceControl.cpp
@@ -97,112 +97,6 @@
return lhs->mHandle == rhs->mHandle;
}
-status_t SurfaceControl::setLayerStack(uint32_t layerStack) {
- status_t err = validate();
- if (err < 0) return err;
- return mClient->setLayerStack(mHandle, layerStack);
-}
-
-status_t SurfaceControl::setLayer(int32_t layer) {
- status_t err = validate();
- if (err < 0) return err;
- return mClient->setLayer(mHandle, layer);
-}
-
-status_t SurfaceControl::setRelativeLayer(const sp<IBinder>& relativeTo, int32_t layer) {
- status_t err = validate();
- if (err < 0) return err;
- return mClient->setRelativeLayer(mHandle, relativeTo, layer);
-}
-
-status_t SurfaceControl::setPosition(float x, float y) {
- status_t err = validate();
- if (err < 0) return err;
- return mClient->setPosition(mHandle, x, y);
-}
-status_t SurfaceControl::setGeometryAppliesWithResize() {
- status_t err = validate();
- if (err < 0) return err;
- return mClient->setGeometryAppliesWithResize(mHandle);
-}
-status_t SurfaceControl::setSize(uint32_t w, uint32_t h) {
- status_t err = validate();
- if (err < 0) return err;
- return mClient->setSize(mHandle, w, h);
-}
-status_t SurfaceControl::hide() {
- status_t err = validate();
- if (err < 0) return err;
- return mClient->hide(mHandle);
-}
-status_t SurfaceControl::show() {
- status_t err = validate();
- if (err < 0) return err;
- return mClient->show(mHandle);
-}
-status_t SurfaceControl::setFlags(uint32_t flags, uint32_t mask) {
- status_t err = validate();
- if (err < 0) return err;
- return mClient->setFlags(mHandle, flags, mask);
-}
-status_t SurfaceControl::setTransparentRegionHint(const Region& transparent) {
- status_t err = validate();
- if (err < 0) return err;
- return mClient->setTransparentRegionHint(mHandle, transparent);
-}
-status_t SurfaceControl::setAlpha(float alpha) {
- status_t err = validate();
- if (err < 0) return err;
- return mClient->setAlpha(mHandle, alpha);
-}
-status_t SurfaceControl::setMatrix(float dsdx, float dtdx, float dtdy, float dsdy) {
- status_t err = validate();
- if (err < 0) return err;
- return mClient->setMatrix(mHandle, dsdx, dtdx, dtdy, dsdy);
-}
-status_t SurfaceControl::setCrop(const Rect& crop) {
- status_t err = validate();
- if (err < 0) return err;
- return mClient->setCrop(mHandle, crop);
-}
-status_t SurfaceControl::setFinalCrop(const Rect& crop) {
- status_t err = validate();
- if (err < 0) return err;
- return mClient->setFinalCrop(mHandle, crop);
-}
-
-status_t SurfaceControl::deferTransactionUntil(const sp<IBinder>& handle,
- uint64_t frameNumber) {
- status_t err = validate();
- if (err < 0) return err;
- return mClient->deferTransactionUntil(mHandle, handle, frameNumber);
-}
-
-status_t SurfaceControl::deferTransactionUntil(const sp<Surface>& handle,
- uint64_t frameNumber) {
- status_t err = validate();
- if (err < 0) return err;
- return mClient->deferTransactionUntil(mHandle, handle, frameNumber);
-}
-
-status_t SurfaceControl::reparentChildren(const sp<IBinder>& newParentHandle) {
- status_t err = validate();
- if (err < 0) return err;
- return mClient->reparentChildren(mHandle, newParentHandle);
-}
-
-status_t SurfaceControl::detachChildren() {
- status_t err = validate();
- if (err < 0) return err;
- return mClient->detachChildren(mHandle);
-}
-
-status_t SurfaceControl::setOverrideScalingMode(int32_t overrideScalingMode) {
- status_t err = validate();
- if (err < 0) return err;
- return mClient->setOverrideScalingMode(mHandle, overrideScalingMode);
-}
-
status_t SurfaceControl::clearLayerFrameStats() const {
status_t err = validate();
if (err < 0) return err;
@@ -267,5 +161,10 @@
return mHandle;
}
+sp<SurfaceComposerClient> SurfaceControl::getClient() const
+{
+ return mClient;
+}
+
// ----------------------------------------------------------------------------
}; // namespace android
diff --git a/libs/gui/include/gui/ISurfaceComposer.h b/libs/gui/include/gui/ISurfaceComposer.h
index b226742..13e7473 100644
--- a/libs/gui/include/gui/ISurfaceComposer.h
+++ b/libs/gui/include/gui/ISurfaceComposer.h
@@ -174,6 +174,10 @@
bool useIdentityTransform,
Rotation rotation = eRotateNone) = 0;
+ virtual status_t captureLayers(const sp<IBinder>& layerHandleBinder,
+ const sp<IGraphicBufferProducer>& producer,
+ Rotation rotation = eRotateNone) = 0;
+
/* Clears the frame statistics for animations.
*
* Requires the ACCESS_SURFACE_FLINGER permission.
@@ -226,6 +230,7 @@
SET_ACTIVE_CONFIG,
CONNECT_DISPLAY,
CAPTURE_SCREEN,
+ CAPTURE_LAYERS,
CLEAR_ANIMATION_FRAME_STATS,
GET_ANIMATION_FRAME_STATS,
SET_POWER_MODE,
diff --git a/libs/gui/include/gui/ISurfaceComposerClient.h b/libs/gui/include/gui/ISurfaceComposerClient.h
index 2c613ea..d5bbef2 100644
--- a/libs/gui/include/gui/ISurfaceComposerClient.h
+++ b/libs/gui/include/gui/ISurfaceComposerClient.h
@@ -41,7 +41,7 @@
eCursorWindow = 0x00002000,
eFXSurfaceNormal = 0x00000000,
- eFXSurfaceDim = 0x00020000,
+ eFXSurfaceColor = 0x00020000,
eFXSurfaceMask = 0x000F0000,
};
diff --git a/libs/gui/include/gui/LayerDebugInfo.h b/libs/gui/include/gui/LayerDebugInfo.h
index 8453e04..92bd8c5 100644
--- a/libs/gui/include/gui/LayerDebugInfo.h
+++ b/libs/gui/include/gui/LayerDebugInfo.h
@@ -22,6 +22,7 @@
#include <ui/Region.h>
#include <string>
+#include <math/vec4.h>
namespace android {
@@ -52,7 +53,7 @@
int32_t mHeight = -1;
Rect mCrop = Rect::INVALID_RECT;
Rect mFinalCrop = Rect::INVALID_RECT;
- float mAlpha = 0.f;
+ half4 mColor = half4(1.0_hf, 1.0_hf, 1.0_hf, 0.0_hf);
uint32_t mFlags = 0;
PixelFormat mPixelFormat = PIXEL_FORMAT_NONE;
android_dataspace mDataSpace = HAL_DATASPACE_UNKNOWN;
diff --git a/libs/gui/include/private/gui/LayerState.h b/libs/gui/include/gui/LayerState.h
similarity index 85%
rename from libs/gui/include/private/gui/LayerState.h
rename to libs/gui/include/gui/LayerState.h
index 307c764..f3fb82f 100644
--- a/libs/gui/include/private/gui/LayerState.h
+++ b/libs/gui/include/gui/LayerState.h
@@ -25,6 +25,7 @@
#include <ui/Region.h>
#include <ui/Rect.h>
#include <gui/IGraphicBufferProducer.h>
+#include <math/vec3.h>
namespace android {
@@ -59,7 +60,9 @@
eGeometryAppliesWithResize = 0x00001000,
eReparentChildren = 0x00002000,
eDetachChildren = 0x00004000,
- eRelativeLayerChanged = 0x00008000
+ eRelativeLayerChanged = 0x00008000,
+ eReparent = 0x00010000,
+ eColorChanged = 0x00020000
};
layer_state_t()
@@ -74,6 +77,7 @@
matrix.dsdy = matrix.dtdx = 0.0f;
}
+ void merge(const layer_state_t& other);
status_t write(Parcel& output) const;
status_t read(const Parcel& input);
@@ -107,6 +111,10 @@
sp<IBinder> relativeLayerHandle;
+ sp<IBinder> parentHandleForChild;
+
+ half3 color;
+
// non POD must be last. see write/read
Region transparentRegion;
};
@@ -137,6 +145,7 @@
};
DisplayState();
+ void merge(const DisplayState& other);
uint32_t what;
sp<IBinder> token;
@@ -150,6 +159,20 @@
status_t read(const Parcel& input);
};
+static inline
+int compare_type(const ComposerState& lhs, const ComposerState& rhs) {
+ if (lhs.client < rhs.client) return -1;
+ if (lhs.client > rhs.client) return 1;
+ if (lhs.state.surface < rhs.state.surface) return -1;
+ if (lhs.state.surface > rhs.state.surface) return 1;
+ return 0;
+}
+
+static inline
+int compare_type(const DisplayState& lhs, const DisplayState& rhs) {
+ return compare_type(lhs.token, rhs.token);
+}
+
}; // namespace android
#endif // ANDROID_SF_LAYER_STATE_H
diff --git a/libs/gui/include/gui/Surface.h b/libs/gui/include/gui/Surface.h
index 55dd6bf..3fe29d9 100644
--- a/libs/gui/include/gui/Surface.h
+++ b/libs/gui/include/gui/Surface.h
@@ -281,6 +281,8 @@
// detachNextBuffer, or attachBuffer call.
status_t getAndFlushRemovedBuffers(std::vector<sp<GraphicBuffer>>* out);
+ android_dataspace_t getBuffersDataSpace();
+
protected:
enum { NUM_BUFFER_SLOTS = BufferQueueDefs::NUM_BUFFER_SLOTS };
enum { DEFAULT_FORMAT = PIXEL_FORMAT_RGBA_8888 };
diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h
index 145c059..87fdfae 100644
--- a/libs/gui/include/gui/SurfaceComposerClient.h
+++ b/libs/gui/include/gui/SurfaceComposerClient.h
@@ -32,13 +32,14 @@
#include <gui/CpuConsumer.h>
#include <gui/SurfaceControl.h>
+#include <math/vec3.h>
+#include <gui/LayerState.h>
namespace android {
// ---------------------------------------------------------------------------
struct DisplayInfo;
-class Composer;
class HdrCapabilities;
class ISurfaceComposerClient;
class IGraphicBufferProducer;
@@ -121,91 +122,158 @@
//! Possible values for id are eDisplayIdMain and eDisplayIdHdmi.
static sp<IBinder> getBuiltInDisplay(int32_t id);
- // ------------------------------------------------------------------------
- // Composer parameters
- // All composer parameters must be changed within a transaction
- // several surfaces can be updated in one transaction, all changes are
- // committed at once when the transaction is closed.
- // closeGlobalTransaction() requires an IPC with the server.
-
- //! Open a composer transaction on all active SurfaceComposerClients.
- static void openGlobalTransaction();
-
- //! Close a composer transaction on all active SurfaceComposerClients.
- static void closeGlobalTransaction(bool synchronous = false);
-
static status_t enableVSyncInjections(bool enable);
static status_t injectVSync(nsecs_t when);
- //! Flag the currently open transaction as an animation transaction.
- static void setAnimationTransaction();
+ class Transaction {
+ SortedVector<ComposerState> mComposerStates;
+ SortedVector<DisplayState > mDisplayStates;
+ uint32_t mForceSynchronous = 0;
+ uint32_t mTransactionNestCount = 0;
+ bool mAnimation = false;
- status_t hide(const sp<IBinder>& id);
- status_t show(const sp<IBinder>& id);
- status_t setFlags(const sp<IBinder>& id, uint32_t flags, uint32_t mask);
- status_t setTransparentRegionHint(const sp<IBinder>& id, const Region& transparent);
- status_t setLayer(const sp<IBinder>& id, int32_t layer);
- status_t setRelativeLayer(const sp<IBinder>& id,
- const sp<IBinder>& relativeTo, int32_t layer);
- status_t setAlpha(const sp<IBinder>& id, float alpha=1.0f);
- status_t setMatrix(const sp<IBinder>& id, float dsdx, float dtdx, float dtdy, float dsdy);
- status_t setPosition(const sp<IBinder>& id, float x, float y);
- status_t setSize(const sp<IBinder>& id, uint32_t w, uint32_t h);
- status_t setCrop(const sp<IBinder>& id, const Rect& crop);
- status_t setFinalCrop(const sp<IBinder>& id, const Rect& crop);
- status_t setLayerStack(const sp<IBinder>& id, uint32_t layerStack);
- status_t deferTransactionUntil(const sp<IBinder>& id,
- const sp<IBinder>& handle, uint64_t frameNumber);
- status_t deferTransactionUntil(const sp<IBinder>& id,
- const sp<Surface>& handle, uint64_t frameNumber);
- status_t reparentChildren(const sp<IBinder>& id,
- const sp<IBinder>& newParentHandle);
- status_t detachChildren(const sp<IBinder>& id);
- status_t setOverrideScalingMode(const sp<IBinder>& id,
- int32_t overrideScalingMode);
- status_t setGeometryAppliesWithResize(const sp<IBinder>& id);
+ int mStatus = NO_ERROR;
+
+ layer_state_t* getLayerStateLocked(const sp<SurfaceControl>& sc);
+ DisplayState& getDisplayStateLocked(const sp<IBinder>& token);
+
+ public:
+ Transaction() = default;
+ virtual ~Transaction() = default;
+ Transaction(Transaction const& other);
+
+ status_t apply(bool synchronous = false);
+ // Merge another transaction in to this one, clearing other
+ // as if it had been applied.
+ Transaction& merge(Transaction&& other);
+ Transaction& show(const sp<SurfaceControl>& sc);
+ Transaction& hide(const sp<SurfaceControl>& sc);
+ Transaction& setPosition(const sp<SurfaceControl>& sc,
+ float x, float y);
+ Transaction& setSize(const sp<SurfaceControl>& sc,
+ uint32_t w, uint32_t h);
+ Transaction& setLayer(const sp<SurfaceControl>& sc,
+ int32_t z);
+
+ // Sets a Z order relative to the Surface specified by "relativeTo" but
+ // without becoming a full child of the relative. Z-ordering works exactly
+ // as if it were a child however.
+ //
+ // As a nod to sanity, only non-child surfaces may have a relative Z-order.
+ //
+ // This overrides any previous call and is overriden by any future calls
+ // to setLayer.
+ //
+ // If the relative is removed, the Surface will have no layer and be
+ // invisible, until the next time set(Relative)Layer is called.
+ Transaction& setRelativeLayer(const sp<SurfaceControl>& sc,
+ const sp<IBinder>& relativeTo, int32_t z);
+ Transaction& setFlags(const sp<SurfaceControl>& sc,
+ uint32_t flags, uint32_t mask);
+ Transaction& setTransparentRegionHint(const sp<SurfaceControl>& sc,
+ const Region& transparentRegion);
+ Transaction& setAlpha(const sp<SurfaceControl>& sc,
+ float alpha);
+ Transaction& setMatrix(const sp<SurfaceControl>& sc,
+ float dsdx, float dtdx, float dtdy, float dsdy);
+ Transaction& setCrop(const sp<SurfaceControl>& sc, const Rect& crop);
+ Transaction& setFinalCrop(const sp<SurfaceControl>& sc, const Rect& crop);
+ Transaction& setLayerStack(const sp<SurfaceControl>& sc, uint32_t layerStack);
+ // Defers applying any changes made in this transaction until the Layer
+ // identified by handle reaches the given frameNumber. If the Layer identified
+ // by handle is removed, then we will apply this transaction regardless of
+ // what frame number has been reached.
+ Transaction& deferTransactionUntil(const sp<SurfaceControl>& sc,
+ const sp<IBinder>& handle,
+ uint64_t frameNumber);
+ // A variant of deferTransactionUntil which identifies the Layer we wait for by
+ // Surface instead of Handle. Useful for clients which may not have the
+ // SurfaceControl for some of their Surfaces. Otherwise behaves identically.
+ Transaction& deferTransactionUntil(const sp<SurfaceControl>& sc,
+ const sp<Surface>& barrierSurface,
+ uint64_t frameNumber);
+ // Reparents all children of this layer to the new parent handle.
+ Transaction& reparentChildren(const sp<SurfaceControl>& sc,
+ const sp<IBinder>& newParentHandle);
+
+ /// Reparents the current layer to the new parent handle. The new parent must not be null.
+ // This can be used instead of reparentChildren if the caller wants to
+ // only re-parent a specific child.
+ Transaction& reparent(const sp<SurfaceControl>& sc,
+ const sp<IBinder>& newParentHandle);
+
+ Transaction& setColor(const sp<SurfaceControl>& sc, const half3& color);
+
+ // Detaches all child surfaces (and their children recursively)
+ // from their SurfaceControl.
+ // The child SurfaceControls will not throw exceptions or return errors,
+ // but transactions will have no effect.
+ // The child surfaces will continue to follow their parent surfaces,
+ // and remain eligible for rendering, but their relative state will be
+ // frozen. We use this in the WindowManager, in app shutdown/relaunch
+ // scenarios, where the app would otherwise clean up its child Surfaces.
+ // Sometimes the WindowManager needs to extend their lifetime slightly
+ // in order to perform an exit animation or prevent flicker.
+ Transaction& detachChildren(const sp<SurfaceControl>& sc);
+ // Set an override scaling mode as documented in <system/window.h>
+ // the override scaling mode will take precedence over any client
+ // specified scaling mode. -1 will clear the override scaling mode.
+ Transaction& setOverrideScalingMode(const sp<SurfaceControl>& sc,
+ int32_t overrideScalingMode);
+
+ // If the size changes in this transaction, all geometry updates specified
+ // in this transaction will not complete until a buffer of the new size
+ // arrives. As some elements normally apply immediately, this enables
+ // freezing the total geometry of a surface until a resize is completed.
+ Transaction& setGeometryAppliesWithResize(const sp<SurfaceControl>& sc);
+
+ status_t setDisplaySurface(const sp<IBinder>& token,
+ const sp<IGraphicBufferProducer>& bufferProducer);
+
+ void setDisplayLayerStack(const sp<IBinder>& token, uint32_t layerStack);
+
+ /* setDisplayProjection() defines the projection of layer stacks
+ * to a given display.
+ *
+ * - orientation defines the display's orientation.
+ * - layerStackRect defines which area of the window manager coordinate
+ * space will be used.
+ * - displayRect defines where on the display will layerStackRect be
+ * mapped to. displayRect is specified post-orientation, that is
+ * it uses the orientation seen by the end-user.
+ */
+ void setDisplayProjection(const sp<IBinder>& token,
+ uint32_t orientation,
+ const Rect& layerStackRect,
+ const Rect& displayRect);
+ void setDisplaySize(const sp<IBinder>& token, uint32_t width, uint32_t height);
+ void setAnimationTransaction();
+ };
status_t destroySurface(const sp<IBinder>& id);
status_t clearLayerFrameStats(const sp<IBinder>& token) const;
status_t getLayerFrameStats(const sp<IBinder>& token, FrameStats* outStats) const;
-
static status_t clearAnimationFrameStats();
static status_t getAnimationFrameStats(FrameStats* outStats);
static status_t getHdrCapabilities(const sp<IBinder>& display,
HdrCapabilities* outCapabilities);
- static status_t setDisplaySurface(const sp<IBinder>& token,
- sp<IGraphicBufferProducer> bufferProducer);
- static void setDisplayLayerStack(const sp<IBinder>& token,
- uint32_t layerStack);
- static void setDisplaySize(const sp<IBinder>& token, uint32_t width, uint32_t height);
-
- /* setDisplayProjection() defines the projection of layer stacks
- * to a given display.
- *
- * - orientation defines the display's orientation.
- * - layerStackRect defines which area of the window manager coordinate
- * space will be used.
- * - displayRect defines where on the display will layerStackRect be
- * mapped to. displayRect is specified post-orientation, that is
- * it uses the orientation seen by the end-user.
- */
static void setDisplayProjection(const sp<IBinder>& token,
uint32_t orientation,
const Rect& layerStackRect,
const Rect& displayRect);
+ inline sp<ISurfaceComposerClient> getClient() { return mClient; }
+
private:
virtual void onFirstRef();
- Composer& getComposer();
mutable Mutex mLock;
status_t mStatus;
sp<ISurfaceComposerClient> mClient;
- Composer& mComposer;
wp<IGraphicBufferProducer> mParent;
};
@@ -229,6 +297,9 @@
bool useIdentityTransform,
uint32_t rotation,
sp<GraphicBuffer>* outbuffer);
+ static status_t captureLayers(const sp<IBinder>& layerHandle,
+ const sp<IGraphicBufferProducer>& producer, uint32_t rotation);
+
private:
mutable sp<CpuConsumer> mCpuConsumer;
mutable sp<IGraphicBufferProducer> mProducer;
diff --git a/libs/gui/include/gui/SurfaceControl.h b/libs/gui/include/gui/SurfaceControl.h
index c15209d..384815d 100644
--- a/libs/gui/include/gui/SurfaceControl.h
+++ b/libs/gui/include/gui/SurfaceControl.h
@@ -29,6 +29,7 @@
#include <ui/Region.h>
#include <gui/ISurfaceComposerClient.h>
+#include <math/vec3.h>
namespace android {
@@ -60,87 +61,6 @@
// disconnect any api that's connected
void disconnect();
- status_t setLayerStack(uint32_t layerStack);
- status_t setLayer(int32_t layer);
-
- // Sets a Z order relative to the Surface specified by "relativeTo" but
- // without becoming a full child of the relative. Z-ordering works exactly
- // as if it were a child however.
- //
- // As a nod to sanity, only non-child surfaces may have a relative Z-order.
- //
- // This overrides any previous and is overriden by any future calls
- // to setLayer.
- //
- // If the relative dissapears, the Surface will have no layer and be
- // invisible, until the next time set(Relative)Layer is called.
- //
- // TODO: This is probably a hack. Currently it exists only to work around
- // some framework usage of the hidden APPLICATION_MEDIA_OVERLAY window type
- // which allows inserting a window between a SurfaceView and it's main application
- // window. However, since we are using child windows for the SurfaceView, but not using
- // child windows elsewhere in O, the WindowManager can't set the layer appropriately.
- // This is only used by the "TvInputService" and following the port of ViewRootImpl
- // to child surfaces, we can then port this and remove this method.
- status_t setRelativeLayer(const sp<IBinder>& relativeTo, int32_t layer);
- status_t setPosition(float x, float y);
- status_t setSize(uint32_t w, uint32_t h);
- status_t hide();
- status_t show();
- status_t setFlags(uint32_t flags, uint32_t mask);
- status_t setTransparentRegionHint(const Region& transparent);
- status_t setAlpha(float alpha=1.0f);
-
- // Experimentarily it appears that the matrix transforms the
- // on-screen rectangle and it's contents before the position is
- // applied.
- //
- // TODO: Test with other combinations to find approximate transformation rules.
- //
- // For example:
- // Layer sized (W,H) set to position (x,y) with matrix M=[-1, 0, 0, 1] (Horizontal flip) gives
- // [((0, 0), (W, H)) x M] + (x,y) = ((-W, 0), (0, H)) + (x,y) = ((-W + x, y), (x, H+y))
- status_t setMatrix(float dsdx, float dtdx, float dtdy, float dsdy);
- status_t setCrop(const Rect& crop);
- status_t setFinalCrop(const Rect& crop);
-
- // If the size changes in this transaction, all geometry updates specified
- // in this transaction will not complete until a buffer of the new size
- // arrives. As some elements normally apply immediately, this enables
- // freezing the total geometry of a surface until a resize is completed.
- status_t setGeometryAppliesWithResize();
-
- // Defers applying any changes made in this transaction until the Layer
- // identified by handle reaches the given frameNumber. If the Layer identified
- // by handle is removed, then we will apply this transaction regardless of
- // what frame number has been reached.
- status_t deferTransactionUntil(const sp<IBinder>& handle, uint64_t frameNumber);
-
- // A variant of deferTransactionUntil which identifies the Layer we wait for by
- // Surface instead of Handle. Useful for clients which may not have the
- // SurfaceControl for some of their Surfaces. Otherwise behaves identically.
- status_t deferTransactionUntil(const sp<Surface>& barrier, uint64_t frameNumber);
-
- // Reparents all children of this layer to the new parent handle.
- status_t reparentChildren(const sp<IBinder>& newParentHandle);
-
- // Detaches all child surfaces (and their children recursively)
- // from their SurfaceControl.
- // The child SurfaceControl's will not throw exceptions or return errors,
- // but transactions will have no effect.
- // The child surfaces will continue to follow their parent surfaces,
- // and remain eligible for rendering, but their relative state will be
- // frozen. We use this in the WindowManager, in app shutdown/relaunch
- // scenarios, where the app would otherwise clean up its child Surfaces.
- // Sometimes the WindowManager needs to extend their lifetime slightly
- // in order to perform an exit animation or prevent flicker.
- status_t detachChildren();
-
- // Set an override scaling mode as documented in <system/window.h>
- // the override scaling mode will take precedence over any client
- // specified scaling mode. -1 will clear the override scaling mode.
- status_t setOverrideScalingMode(int32_t overrideScalingMode);
-
static status_t writeSurfaceToParcel(
const sp<SurfaceControl>& control, Parcel* parcel);
@@ -151,6 +71,8 @@
status_t clearLayerFrameStats() const;
status_t getLayerFrameStats(FrameStats* outStats) const;
+ sp<SurfaceComposerClient> getClient() const;
+
private:
// can't be copied
SurfaceControl& operator = (SurfaceControl& rhs);
diff --git a/libs/gui/tests/GLTest.cpp b/libs/gui/tests/GLTest.cpp
index 1739d9c..a91552f 100644
--- a/libs/gui/tests/GLTest.cpp
+++ b/libs/gui/tests/GLTest.cpp
@@ -22,6 +22,8 @@
namespace android {
+using Transaction = SurfaceComposerClient::Transaction;
+
static int abs(int value) {
return value > 0 ? value : -value;
}
@@ -68,10 +70,10 @@
ASSERT_TRUE(mSurfaceControl != NULL);
ASSERT_TRUE(mSurfaceControl->isValid());
- SurfaceComposerClient::openGlobalTransaction();
- ASSERT_EQ(NO_ERROR, mSurfaceControl->setLayer(0x7FFFFFFF));
- ASSERT_EQ(NO_ERROR, mSurfaceControl->show());
- SurfaceComposerClient::closeGlobalTransaction();
+ Transaction t;
+ ASSERT_EQ(NO_ERROR, t.setLayer(mSurfaceControl, 0x7FFFFFFF)
+ .show(mSurfaceControl)
+ .apply());
sp<ANativeWindow> window = mSurfaceControl->getSurface();
mEglSurface = createWindowSurface(mEglDisplay, mGlConfig, window);
diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp
index ca43c68..660680b 100644
--- a/libs/gui/tests/Surface_test.cpp
+++ b/libs/gui/tests/Surface_test.cpp
@@ -42,6 +42,8 @@
using namespace android::hardware::configstore;
using namespace android::hardware::configstore::V1_0;
+using Transaction = SurfaceComposerClient::Transaction;
+
static bool hasWideColorDisplay =
getBool<ISurfaceFlingerConfigs, &ISurfaceFlingerConfigs::hasWideColorDisplay>(false);
@@ -69,10 +71,10 @@
ASSERT_TRUE(mSurfaceControl != NULL);
ASSERT_TRUE(mSurfaceControl->isValid());
- SurfaceComposerClient::openGlobalTransaction();
- ASSERT_EQ(NO_ERROR, mSurfaceControl->setLayer(0x7fffffff));
- ASSERT_EQ(NO_ERROR, mSurfaceControl->show());
- SurfaceComposerClient::closeGlobalTransaction();
+ Transaction t;
+ ASSERT_EQ(NO_ERROR, t.setLayer(mSurfaceControl, 0x7fffffff)
+ .show(mSurfaceControl)
+ .apply());
mSurface = mSurfaceControl->getSurface();
ASSERT_TRUE(mSurface != NULL);
@@ -527,6 +529,11 @@
int32_t /*minLayerZ*/, int32_t /*maxLayerZ*/,
bool /*useIdentityTransform*/,
Rotation /*rotation*/) override { return NO_ERROR; }
+ virtual status_t captureLayers(const sp<IBinder>& /*parentHandle*/,
+ const sp<IGraphicBufferProducer>& /*producer*/,
+ ISurfaceComposer::Rotation /*rotation*/) override {
+ return NO_ERROR;
+ }
status_t clearAnimationFrameStats() override { return NO_ERROR; }
status_t getAnimationFrameStats(FrameStats* /*outStats*/) const override {
return NO_ERROR;
diff --git a/libs/input/InputTransport.cpp b/libs/input/InputTransport.cpp
index 9abd04c..b8901bd 100644
--- a/libs/input/InputTransport.cpp
+++ b/libs/input/InputTransport.cpp
@@ -254,7 +254,7 @@
#if DEBUG_TRANSPORT_ACTIONS
ALOGD("channel '%s' publisher ~ publishKeyEvent: seq=%u, deviceId=%d, source=0x%x, "
"action=0x%x, flags=0x%x, keyCode=%d, scanCode=%d, metaState=0x%x, repeatCount=%d,"
- "downTime=%lld, eventTime=%lld",
+ "downTime=%" PRId64 ", eventTime=%" PRId64,
mChannel->getName().string(), seq,
deviceId, source, action, flags, keyCode, scanCode, metaState, repeatCount,
downTime, eventTime);
@@ -305,7 +305,7 @@
ALOGD("channel '%s' publisher ~ publishMotionEvent: seq=%u, deviceId=%d, source=0x%x, "
"action=0x%x, actionButton=0x%08x, flags=0x%x, edgeFlags=0x%x, "
"metaState=0x%x, buttonState=0x%x, xOffset=%f, yOffset=%f, "
- "xPrecision=%f, yPrecision=%f, downTime=%lld, eventTime=%lld, "
+ "xPrecision=%f, yPrecision=%f, downTime=%" PRId64 ", eventTime=%" PRId64 ", "
"pointerCount=%" PRIu32,
mChannel->getName().string(), seq,
deviceId, source, action, actionButton, flags, edgeFlags, metaState, buttonState,
@@ -401,7 +401,7 @@
bool consumeBatches, nsecs_t frameTime, uint32_t* outSeq, InputEvent** outEvent,
int32_t* displayId) {
#if DEBUG_TRANSPORT_ACTIONS
- ALOGD("channel '%s' consumer ~ consume: consumeBatches=%s, frameTime=%lld",
+ ALOGD("channel '%s' consumer ~ consume: consumeBatches=%s, frameTime=%" PRId64,
mChannel->getName().string(), consumeBatches ? "true" : "false", frameTime);
#endif
diff --git a/libs/input/VelocityTracker.cpp b/libs/input/VelocityTracker.cpp
index 62acea3..e54f147 100644
--- a/libs/input/VelocityTracker.cpp
+++ b/libs/input/VelocityTracker.cpp
@@ -75,7 +75,9 @@
str += " ]";
return str;
}
+#endif
+#if DEBUG_STRATEGY
static std::string matrixToString(const float* a, uint32_t m, uint32_t n, bool rowMajor) {
std::string str;
str = "[";
@@ -141,6 +143,11 @@
}
VelocityTrackerStrategy* VelocityTracker::createStrategy(const char* strategy) {
+ if (!strcmp("impulse", strategy)) {
+ // Physical model of pushing an object. Quality: VERY GOOD.
+ // Works with duplicate coordinates, unclean finger liftoff.
+ return new ImpulseVelocityTrackerStrategy();
+ }
if (!strcmp("lsq1", strategy)) {
// 1st order least squares. Quality: POOR.
// Frequently underfits the touch data especially when the finger accelerates
@@ -352,9 +359,6 @@
// --- LeastSquaresVelocityTrackerStrategy ---
-const nsecs_t LeastSquaresVelocityTrackerStrategy::HORIZON;
-const uint32_t LeastSquaresVelocityTrackerStrategy::HISTORY_SIZE;
-
LeastSquaresVelocityTrackerStrategy::LeastSquaresVelocityTrackerStrategy(
uint32_t degree, Weighting weighting) :
mDegree(degree), mWeighting(weighting) {
@@ -863,10 +867,6 @@
// --- LegacyVelocityTrackerStrategy ---
-const nsecs_t LegacyVelocityTrackerStrategy::HORIZON;
-const uint32_t LegacyVelocityTrackerStrategy::HISTORY_SIZE;
-const nsecs_t LegacyVelocityTrackerStrategy::MIN_DURATION;
-
LegacyVelocityTrackerStrategy::LegacyVelocityTrackerStrategy() {
clear();
}
@@ -979,4 +979,194 @@
return true;
}
+// --- ImpulseVelocityTrackerStrategy ---
+
+ImpulseVelocityTrackerStrategy::ImpulseVelocityTrackerStrategy() {
+ clear();
+}
+
+ImpulseVelocityTrackerStrategy::~ImpulseVelocityTrackerStrategy() {
+}
+
+void ImpulseVelocityTrackerStrategy::clear() {
+ mIndex = 0;
+ mMovements[0].idBits.clear();
+}
+
+void ImpulseVelocityTrackerStrategy::clearPointers(BitSet32 idBits) {
+ BitSet32 remainingIdBits(mMovements[mIndex].idBits.value & ~idBits.value);
+ mMovements[mIndex].idBits = remainingIdBits;
+}
+
+void ImpulseVelocityTrackerStrategy::addMovement(nsecs_t eventTime, BitSet32 idBits,
+ const VelocityTracker::Position* positions) {
+ if (++mIndex == HISTORY_SIZE) {
+ mIndex = 0;
+ }
+
+ Movement& movement = mMovements[mIndex];
+ movement.eventTime = eventTime;
+ movement.idBits = idBits;
+ uint32_t count = idBits.count();
+ for (uint32_t i = 0; i < count; i++) {
+ movement.positions[i] = positions[i];
+ }
+}
+
+/**
+ * Calculate the total impulse provided to the screen and the resulting velocity.
+ *
+ * The touchscreen is modeled as a physical object.
+ * Initial condition is discussed below, but for now suppose that v(t=0) = 0
+ *
+ * The kinetic energy of the object at the release is E=0.5*m*v^2
+ * Then vfinal = sqrt(2E/m). The goal is to calculate E.
+ *
+ * The kinetic energy at the release is equal to the total work done on the object by the finger.
+ * The total work W is the sum of all dW along the path.
+ *
+ * dW = F*dx, where dx is the piece of path traveled.
+ * Force is change of momentum over time, F = dp/dt = m dv/dt.
+ * Then substituting:
+ * dW = m (dv/dt) * dx = m * v * dv
+ *
+ * Summing along the path, we get:
+ * W = sum(dW) = sum(m * v * dv) = m * sum(v * dv)
+ * Since the mass stays constant, the equation for final velocity is:
+ * vfinal = sqrt(2*sum(v * dv))
+ *
+ * Here,
+ * dv : change of velocity = (v[i+1]-v[i])
+ * dx : change of distance = (x[i+1]-x[i])
+ * dt : change of time = (t[i+1]-t[i])
+ * v : instantaneous velocity = dx/dt
+ *
+ * The final formula is:
+ * vfinal = sqrt(2) * sqrt(sum((v[i]-v[i-1])*|v[i]|)) for all i
+ * The absolute value is needed to properly account for the sign. If the velocity over a
+ * particular segment descreases, then this indicates braking, which means that negative
+ * work was done. So for two positive, but decreasing, velocities, this contribution would be
+ * negative and will cause a smaller final velocity.
+ *
+ * Initial condition
+ * There are two ways to deal with initial condition:
+ * 1) Assume that v(0) = 0, which would mean that the screen is initially at rest.
+ * This is not entirely accurate. We are only taking the past X ms of touch data, where X is
+ * currently equal to 100. However, a touch event that created a fling probably lasted for longer
+ * than that, which would mean that the user has already been interacting with the touchscreen
+ * and it has probably already been moving.
+ * 2) Assume that the touchscreen has already been moving at a certain velocity, calculate this
+ * initial velocity and the equivalent energy, and start with this initial energy.
+ * Consider an example where we have the following data, consisting of 3 points:
+ * time: t0, t1, t2
+ * x : x0, x1, x2
+ * v : 0 , v1, v2
+ * Here is what will happen in each of these scenarios:
+ * 1) By directly applying the formula above with the v(0) = 0 boundary condition, we will get
+ * vfinal = sqrt(2*(|v1|*(v1-v0) + |v2|*(v2-v1))). This can be simplified since v0=0
+ * vfinal = sqrt(2*(|v1|*v1 + |v2|*(v2-v1))) = sqrt(2*(v1^2 + |v2|*(v2 - v1)))
+ * since velocity is a real number
+ * 2) If we treat the screen as already moving, then it must already have an energy (per mass)
+ * equal to 1/2*v1^2. Then the initial energy should be 1/2*v1*2, and only the second segment
+ * will contribute to the total kinetic energy (since we can effectively consider that v0=v1).
+ * This will give the following expression for the final velocity:
+ * vfinal = sqrt(2*(1/2*v1^2 + |v2|*(v2-v1)))
+ * This analysis can be generalized to an arbitrary number of samples.
+ *
+ *
+ * Comparing the two equations above, we see that the only mathematical difference
+ * is the factor of 1/2 in front of the first velocity term.
+ * This boundary condition would allow for the "proper" calculation of the case when all of the
+ * samples are equally spaced in time and distance, which should suggest a constant velocity.
+ *
+ * Note that approach 2) is sensitive to the proper ordering of the data in time, since
+ * the boundary condition must be applied to the oldest sample to be accurate.
+ */
+static float kineticEnergyToVelocity(float work) {
+ static constexpr float sqrt2 = 1.41421356237;
+ return (work < 0 ? -1.0 : 1.0) * sqrtf(fabsf(work)) * sqrt2;
+}
+
+static float calculateImpulseVelocity(const nsecs_t* t, const float* x, size_t count) {
+ // The input should be in reversed time order (most recent sample at index i=0)
+ // t[i] is in nanoseconds, but due to FP arithmetic, convert to seconds inside this function
+ static constexpr float NANOS_PER_SECOND = 1E-9;
+
+ if (count < 2) {
+ return 0; // if 0 or 1 points, velocity is zero
+ }
+ if (t[1] > t[0]) { // Algorithm will still work, but not perfectly
+ ALOGE("Samples provided to calculateImpulseVelocity in the wrong order");
+ }
+ if (count == 2) { // if 2 points, basic linear calculation
+ if (t[1] == t[0]) {
+ ALOGE("Events have identical time stamps t=%" PRId64 ", setting velocity = 0", t[0]);
+ return 0;
+ }
+ return (x[1] - x[0]) / (NANOS_PER_SECOND * (t[1] - t[0]));
+ }
+ // Guaranteed to have at least 3 points here
+ float work = 0;
+ for (size_t i = count - 1; i > 0 ; i--) { // start with the oldest sample and go forward in time
+ if (t[i] == t[i-1]) {
+ ALOGE("Events have identical time stamps t=%" PRId64 ", skipping sample", t[i]);
+ continue;
+ }
+ float vprev = kineticEnergyToVelocity(work); // v[i-1]
+ float vcurr = (x[i] - x[i-1]) / (NANOS_PER_SECOND * (t[i] - t[i-1])); // v[i]
+ work += (vcurr - vprev) * fabsf(vcurr);
+ if (i == count - 1) {
+ work *= 0.5; // initial condition, case 2) above
+ }
+ }
+ return kineticEnergyToVelocity(work);
+}
+
+bool ImpulseVelocityTrackerStrategy::getEstimator(uint32_t id,
+ VelocityTracker::Estimator* outEstimator) const {
+ outEstimator->clear();
+
+ // Iterate over movement samples in reverse time order and collect samples.
+ float x[HISTORY_SIZE];
+ float y[HISTORY_SIZE];
+ nsecs_t time[HISTORY_SIZE];
+ size_t m = 0; // number of points that will be used for fitting
+ size_t index = mIndex;
+ const Movement& newestMovement = mMovements[mIndex];
+ do {
+ const Movement& movement = mMovements[index];
+ if (!movement.idBits.hasBit(id)) {
+ break;
+ }
+
+ nsecs_t age = newestMovement.eventTime - movement.eventTime;
+ if (age > HORIZON) {
+ break;
+ }
+
+ const VelocityTracker::Position& position = movement.getPosition(id);
+ x[m] = position.x;
+ y[m] = position.y;
+ time[m] = movement.eventTime;
+ index = (index == 0 ? HISTORY_SIZE : index) - 1;
+ } while (++m < HISTORY_SIZE);
+
+ if (m == 0) {
+ return false; // no data
+ }
+ outEstimator->xCoeff[0] = 0;
+ outEstimator->yCoeff[0] = 0;
+ outEstimator->xCoeff[1] = calculateImpulseVelocity(time, x, m);
+ outEstimator->yCoeff[1] = calculateImpulseVelocity(time, y, m);
+ outEstimator->xCoeff[2] = 0;
+ outEstimator->yCoeff[2] = 0;
+ outEstimator->time = newestMovement.eventTime;
+ outEstimator->degree = 2; // similar results to 2nd degree fit
+ outEstimator->confidence = 1;
+#if DEBUG_STRATEGY
+ ALOGD("velocity: (%f, %f)", outEstimator->xCoeff[1], outEstimator->yCoeff[1]);
+#endif
+ return true;
+}
+
} // namespace android
diff --git a/libs/input/tests/Android.bp b/libs/input/tests/Android.bp
index 0028655..aca9521 100644
--- a/libs/input/tests/Android.bp
+++ b/libs/input/tests/Android.bp
@@ -6,11 +6,12 @@
"InputChannel_test.cpp",
"InputEvent_test.cpp",
"InputPublisherAndConsumer_test.cpp",
+ "VelocityTracker_test.cpp",
],
cflags: [
"-Wall",
+ "-Wextra",
"-Werror",
- "-Wno-error=sign-compare", // to fix later
"-Wno-unused-variable",
],
shared_libs: [
@@ -19,6 +20,7 @@
"libutils",
"libbinder",
"libui",
+ "libbase",
]
}
diff --git a/libs/input/tests/InputEvent_test.cpp b/libs/input/tests/InputEvent_test.cpp
index 3fb1c6d..fd3b7c8 100644
--- a/libs/input/tests/InputEvent_test.cpp
+++ b/libs/input/tests/InputEvent_test.cpp
@@ -184,7 +184,7 @@
ASSERT_EQ(AINPUT_EVENT_TYPE_KEY, event.getType());
ASSERT_EQ(2, event.getDeviceId());
- ASSERT_EQ(AINPUT_SOURCE_GAMEPAD, event.getSource());
+ ASSERT_EQ(static_cast<int>(AINPUT_SOURCE_GAMEPAD), event.getSource());
ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, event.getAction());
ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM, event.getFlags());
ASSERT_EQ(AKEYCODE_BUTTON_X, event.getKeyCode());
@@ -196,7 +196,7 @@
// Set source.
event.setSource(AINPUT_SOURCE_JOYSTICK);
- ASSERT_EQ(AINPUT_SOURCE_JOYSTICK, event.getSource());
+ ASSERT_EQ(static_cast<int>(AINPUT_SOURCE_JOYSTICK), event.getSource());
}
@@ -300,7 +300,7 @@
// Check properties.
ASSERT_EQ(AINPUT_EVENT_TYPE_MOTION, event->getType());
ASSERT_EQ(2, event->getDeviceId());
- ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, event->getSource());
+ ASSERT_EQ(static_cast<int>(AINPUT_SOURCE_TOUCHSCREEN), event->getSource());
ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, event->getAction());
ASSERT_EQ(AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED, event->getFlags());
ASSERT_EQ(AMOTION_EVENT_EDGE_FLAG_TOP, event->getEdgeFlags());
@@ -432,7 +432,7 @@
// Set source.
event.setSource(AINPUT_SOURCE_JOYSTICK);
- ASSERT_EQ(AINPUT_SOURCE_JOYSTICK, event.getSource());
+ ASSERT_EQ(static_cast<int>(AINPUT_SOURCE_JOYSTICK), event.getSource());
// Set action.
event.setAction(AMOTION_EVENT_ACTION_CANCEL);
diff --git a/libs/input/tests/InputPublisherAndConsumer_test.cpp b/libs/input/tests/InputPublisherAndConsumer_test.cpp
index a136738..34c52d0 100644
--- a/libs/input/tests/InputPublisherAndConsumer_test.cpp
+++ b/libs/input/tests/InputPublisherAndConsumer_test.cpp
@@ -89,8 +89,9 @@
uint32_t consumeSeq;
InputEvent* event;
+ int32_t displayId;
status = mConsumer->consume(&mEventFactory, true /*consumeBatches*/, -1, &consumeSeq, &event,
- 0);
+ &displayId);
ASSERT_EQ(OK, status)
<< "consumer consume should return OK";
@@ -133,7 +134,7 @@
const uint32_t seq = 15;
const int32_t deviceId = 1;
const int32_t source = AINPUT_SOURCE_TOUCHSCREEN;
- const int32_t displayId = 0;
+ int32_t displayId = 0;
const int32_t action = AMOTION_EVENT_ACTION_MOVE;
const int32_t actionButton = 0;
const int32_t flags = AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED;
@@ -176,7 +177,7 @@
uint32_t consumeSeq;
InputEvent* event;
status = mConsumer->consume(&mEventFactory, true /*consumeBatches*/, -1, &consumeSeq, &event,
- 0);
+ &displayId);
ASSERT_EQ(OK, status)
<< "consumer consume should return OK";
diff --git a/libs/input/tests/VelocityTracker_test.cpp b/libs/input/tests/VelocityTracker_test.cpp
new file mode 100644
index 0000000..43b6012
--- /dev/null
+++ b/libs/input/tests/VelocityTracker_test.cpp
@@ -0,0 +1,664 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "VelocityTracker_test"
+
+#include <math.h>
+
+#include <android-base/stringprintf.h>
+#include <gtest/gtest.h>
+#include <input/VelocityTracker.h>
+
+using android::base::StringPrintf;
+
+namespace android {
+
+constexpr int32_t DEFAULT_POINTER_ID = 0; // pointer ID used for manually defined tests
+
+// velocity must be in the range (1-tol)*EV <= velocity <= (1+tol)*EV
+// here EV = expected value, tol = VELOCITY_TOLERANCE
+constexpr float VELOCITY_TOLERANCE = 0.2;
+
+// --- VelocityTrackerTest ---
+class VelocityTrackerTest : public testing::Test { };
+
+static void checkVelocity(float Vactual, float Vtarget) {
+ // Compare directions
+ if ((Vactual > 0 && Vtarget <= 0) || (Vactual < 0 && Vtarget >= 0)) {
+ FAIL() << StringPrintf("Velocity %f does not have the same direction"
+ " as the target velocity %f", Vactual, Vtarget);
+ }
+
+ // Compare magnitudes
+ const float Vlower = fabsf(Vtarget * (1 - VELOCITY_TOLERANCE));
+ const float Vupper = fabsf(Vtarget * (1 + VELOCITY_TOLERANCE));
+ if (fabsf(Vactual) < Vlower) {
+ FAIL() << StringPrintf("Velocity %f is more than %.0f%% below target velocity %f",
+ Vactual, VELOCITY_TOLERANCE * 100, Vtarget);
+ }
+ if (fabsf(Vactual) > Vupper) {
+ FAIL() << StringPrintf("Velocity %f is more than %.0f%% above target velocity %f",
+ Vactual, VELOCITY_TOLERANCE * 100, Vtarget);
+ }
+ SUCCEED() << StringPrintf("Velocity %f within %.0f%% of target %f)",
+ Vactual, VELOCITY_TOLERANCE * 100, Vtarget);
+}
+
+void failWithMessage(std::string message) {
+ FAIL() << message; // cannot do this directly from a non-void function
+}
+
+struct Position {
+ nsecs_t time;
+ float x;
+ float y;
+};
+
+
+MotionEvent* createSimpleMotionEvent(const Position* positions, size_t numSamples) {
+ /**
+ * Only populate the basic fields of a MotionEvent, such as time and a single axis
+ * Designed for use with manually-defined tests.
+ * Create a new MotionEvent on the heap, caller responsible for destroying the object.
+ */
+ if (numSamples < 1) {
+ failWithMessage(StringPrintf("Need at least 1 sample to create a MotionEvent."
+ " Received numSamples=%zu", numSamples));
+ }
+
+ MotionEvent* event = new MotionEvent();
+ PointerCoords coords;
+ PointerProperties properties[1];
+
+ properties[0].id = DEFAULT_POINTER_ID;
+ properties[0].toolType = AMOTION_EVENT_TOOL_TYPE_FINGER;
+
+ // First sample added separately with initialize
+ coords.setAxisValue(AMOTION_EVENT_AXIS_X, positions[0].x);
+ coords.setAxisValue(AMOTION_EVENT_AXIS_Y, positions[0].y);
+ event->initialize(0, AINPUT_SOURCE_TOUCHSCREEN, AMOTION_EVENT_ACTION_MOVE,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, positions[0].time, 1, properties, &coords);
+
+ for (size_t i = 1; i < numSamples; i++) {
+ coords.setAxisValue(AMOTION_EVENT_AXIS_X, positions[i].x);
+ coords.setAxisValue(AMOTION_EVENT_AXIS_Y, positions[i].y);
+ event->addSample(positions[i].time, &coords);
+ }
+ return event;
+}
+
+static void computeAndCheckVelocity(const Position* positions, size_t numSamples,
+ int32_t axis, float targetVelocity) {
+ VelocityTracker vt(nullptr);
+ float Vx, Vy;
+
+ MotionEvent* event = createSimpleMotionEvent(positions, numSamples);
+ vt.addMovement(event);
+
+ vt.getVelocity(DEFAULT_POINTER_ID, &Vx, &Vy);
+
+ switch (axis) {
+ case AMOTION_EVENT_AXIS_X:
+ checkVelocity(Vx, targetVelocity);
+ break;
+ case AMOTION_EVENT_AXIS_Y:
+ checkVelocity(Vy, targetVelocity);
+ break;
+ default:
+ FAIL() << "Axis must be either AMOTION_EVENT_AXIS_X or AMOTION_EVENT_AXIS_Y";
+ }
+ delete event;
+}
+
+/*
+ * ================== VelocityTracker tests generated manually =====================================
+ */
+ // @todo Currently disabled, enable when switching away from lsq2 VelocityTrackerStrategy
+TEST_F(VelocityTrackerTest, DISABLED_ThreePointsPositiveVelocityTest) {
+ // Same coordinate is reported 2 times in a row
+ // It is difficult to determine the correct answer here, but at least the direction
+ // of the reported velocity should be positive.
+ Position values[] = {
+ { 0, 273, NAN },
+ { 12585000, 293, NAN },
+ { 14730000, 293, NAN },
+ };
+ size_t count = sizeof(values) / sizeof(Position);
+ computeAndCheckVelocity(values, count, AMOTION_EVENT_AXIS_X, 1600);
+}
+
+TEST_F(VelocityTrackerTest, ThreePointsZeroVelocityTest) {
+ // Same coordinate is reported 3 times in a row
+ Position values[] = {
+ { 0, 293, NAN },
+ { 6132000, 293, NAN },
+ { 11283000, 293, NAN },
+ };
+ size_t count = sizeof(values) / sizeof(Position);
+ computeAndCheckVelocity(values, count, AMOTION_EVENT_AXIS_X, 0);
+}
+
+TEST_F(VelocityTrackerTest, ThreePointsLinearVelocityTest) {
+ // Fixed velocity at 5 points per 10 milliseconds
+ Position values[] = {
+ { 0, 0, NAN },
+ { 10000000, 5, NAN },
+ { 20000000, 10, NAN },
+ };
+ size_t count = sizeof(values) / sizeof(Position);
+ computeAndCheckVelocity(values, count, AMOTION_EVENT_AXIS_X, 500);
+}
+
+
+/**
+ * ================== VelocityTracker tests generated by recording real events =====================
+ *
+ * To add a test, record the input coordinates and event times to all calls
+ * to void VelocityTracker::addMovement(const MotionEvent* event).
+ * Also record all calls to VelocityTracker::clear().
+ * Finally, record the output of VelocityTracker::getVelocity(...)
+ * This will give you the necessary data to create a new test.
+ */
+
+// --------------- Recorded by hand on swordfish ---------------------------------------------------
+// @todo Currently disabled, enable when switching away from lsq2 VelocityTrackerStrategy
+TEST_F(VelocityTrackerTest, DISABLED_SwordfishFlingDown) {
+ // Recording of a fling on Swordfish that could cause a fling in the wrong direction
+ Position values[] = {
+ { 0, 271, 96 },
+ { 16071042, 269.786346, 106.922775 },
+ { 35648403, 267.983063, 156.660034 },
+ { 52313925, 262.638397, 220.339081 },
+ { 68976522, 266.138824, 331.581116 },
+ { 85639375, 274.79245, 428.113159 },
+ { 96948871, 274.79245, 428.113159 },
+ };
+ size_t count = sizeof(values) / sizeof(Position);
+ computeAndCheckVelocity(values, count, AMOTION_EVENT_AXIS_X, 623.577637);
+ computeAndCheckVelocity(values, count, AMOTION_EVENT_AXIS_Y, 8523.348633);
+}
+
+// --------------- Recorded by hand on sailfish, generated by a script -----------------------------
+// For some of these tests, the X-direction velocity checking has been removed, because the lsq2
+// and the impulse VelocityTrackerStrategies did not agree within 20%.
+// Since the flings were recorded in the Y-direction, the intentional user action should only
+// be relevant for the Y axis.
+// There have been also cases where lsq2 and impulse disagreed more than 20% in the Y-direction.
+// Those recordings have been discarded because we didn't feel one strategy's interpretation was
+// more correct than another's but didn't want to increase the tolerance for the entire test suite.
+//
+// There are 18 tests total below: 9 in the positive Y direction and 9 in the opposite.
+// The recordings were loosely binned into 3 categories - slow, faster, and fast, which roughly
+// characterizes the velocity of the finger motion.
+// These can be treated approximately as:
+// slow - less than 1 page gets scrolled
+// faster - more than 1 page gets scrolled, but less than 3
+// fast - entire list is scrolled (fling is done as hard as possible)
+
+TEST_F(VelocityTrackerTest, SailfishFlingUpSlow1) {
+ // Sailfish - fling up - slow - 1
+ Position values[] = {
+ { 235089067457000, 528.00, 983.00 },
+ { 235089084684000, 527.00, 981.00 },
+ { 235089093349000, 527.00, 977.00 },
+ { 235089095677625, 527.00, 975.93 },
+ { 235089101859000, 527.00, 970.00 },
+ { 235089110378000, 528.00, 960.00 },
+ { 235089112497111, 528.25, 957.51 },
+ { 235089118760000, 531.00, 946.00 },
+ { 235089126686000, 535.00, 931.00 },
+ { 235089129316820, 536.33, 926.02 },
+ { 235089135199000, 540.00, 914.00 },
+ { 235089144297000, 546.00, 896.00 },
+ { 235089146136443, 547.21, 892.36 },
+ { 235089152923000, 553.00, 877.00 },
+ { 235089160784000, 559.00, 851.00 },
+ { 235089162955851, 560.66, 843.82 },
+ };
+ size_t count = sizeof(values) / sizeof(Position);
+ computeAndCheckVelocity(values, count, AMOTION_EVENT_AXIS_X, 872.794617); // impulse
+ computeAndCheckVelocity(values, count, AMOTION_EVENT_AXIS_X, 951.698181); // lsq2
+ computeAndCheckVelocity(values, count, AMOTION_EVENT_AXIS_Y, -3604.819336); // impulse
+ computeAndCheckVelocity(values, count, AMOTION_EVENT_AXIS_Y, -3044.966064); // lsq2
+}
+
+
+TEST_F(VelocityTrackerTest, SailfishFlingUpSlow2) {
+ // Sailfish - fling up - slow - 2
+ Position values[] = {
+ { 235110560704000, 522.00, 1107.00 },
+ { 235110575764000, 522.00, 1107.00 },
+ { 235110584385000, 522.00, 1107.00 },
+ { 235110588421179, 521.52, 1106.52 },
+ { 235110592830000, 521.00, 1106.00 },
+ { 235110601385000, 520.00, 1104.00 },
+ { 235110605088160, 519.14, 1102.27 },
+ { 235110609952000, 518.00, 1100.00 },
+ { 235110618353000, 517.00, 1093.00 },
+ { 235110621755146, 516.60, 1090.17 },
+ { 235110627010000, 517.00, 1081.00 },
+ { 235110634785000, 518.00, 1063.00 },
+ { 235110638422450, 518.87, 1052.58 },
+ { 235110643161000, 520.00, 1039.00 },
+ { 235110651767000, 524.00, 1011.00 },
+ { 235110655089581, 525.54, 1000.19 },
+ { 235110660368000, 530.00, 980.00 },
+ };
+ size_t count = sizeof(values) / sizeof(Position);
+ computeAndCheckVelocity(values, count, AMOTION_EVENT_AXIS_Y, -4096.583008); // impulse
+ computeAndCheckVelocity(values, count, AMOTION_EVENT_AXIS_Y, -3455.094238); // lsq2
+}
+
+
+TEST_F(VelocityTrackerTest, SailfishFlingUpSlow3) {
+ // Sailfish - fling up - slow - 3
+ Position values[] = {
+ { 792536237000, 580.00, 1317.00 },
+ { 792541538987, 580.63, 1311.94 },
+ { 792544613000, 581.00, 1309.00 },
+ { 792552301000, 583.00, 1295.00 },
+ { 792558362309, 585.13, 1282.92 },
+ { 792560828000, 586.00, 1278.00 },
+ { 792569446000, 589.00, 1256.00 },
+ { 792575185095, 591.54, 1241.41 },
+ { 792578491000, 593.00, 1233.00 },
+ { 792587044000, 597.00, 1211.00 },
+ { 792592008172, 600.28, 1195.92 },
+ { 792594616000, 602.00, 1188.00 },
+ { 792603129000, 607.00, 1167.00 },
+ { 792608831290, 609.48, 1155.83 },
+ { 792612321000, 611.00, 1149.00 },
+ { 792620768000, 615.00, 1131.00 },
+ { 792625653873, 617.32, 1121.73 },
+ { 792629200000, 619.00, 1115.00 },
+ };
+ size_t count = sizeof(values) / sizeof(Position);
+ computeAndCheckVelocity(values, count, AMOTION_EVENT_AXIS_X, 574.33429); // impulse
+ computeAndCheckVelocity(values, count, AMOTION_EVENT_AXIS_X, 617.40564); // lsq2
+ computeAndCheckVelocity(values, count, AMOTION_EVENT_AXIS_Y, -2361.982666); // impulse
+ computeAndCheckVelocity(values, count, AMOTION_EVENT_AXIS_Y, -2500.055664); // lsq2
+}
+
+
+TEST_F(VelocityTrackerTest, SailfishFlingUpFaster1) {
+ // Sailfish - fling up - faster - 1
+ Position values[] = {
+ { 235160420675000, 610.00, 1042.00 },
+ { 235160428220000, 609.00, 1026.00 },
+ { 235160436544000, 609.00, 1024.00 },
+ { 235160441852394, 609.64, 1020.82 },
+ { 235160444878000, 610.00, 1019.00 },
+ { 235160452673000, 613.00, 1006.00 },
+ { 235160458519743, 617.18, 992.06 },
+ { 235160461061000, 619.00, 986.00 },
+ { 235160469798000, 627.00, 960.00 },
+ { 235160475186713, 632.22, 943.02 },
+ { 235160478051000, 635.00, 934.00 },
+ { 235160486489000, 644.00, 906.00 },
+ { 235160491853697, 649.56, 890.56 },
+ { 235160495177000, 653.00, 881.00 },
+ { 235160504148000, 662.00, 858.00 },
+ { 235160509231495, 666.81, 845.37 },
+ { 235160512603000, 670.00, 837.00 },
+ { 235160520366000, 679.00, 814.00 },
+ };
+ size_t count = sizeof(values) / sizeof(Position);
+ computeAndCheckVelocity(values, count, AMOTION_EVENT_AXIS_X, 1274.141724); // impulse
+ computeAndCheckVelocity(values, count, AMOTION_EVENT_AXIS_X, 1438.53186); // lsq2
+ computeAndCheckVelocity(values, count, AMOTION_EVENT_AXIS_Y, -3877.35498); // impulse
+ computeAndCheckVelocity(values, count, AMOTION_EVENT_AXIS_Y, -3695.859619); // lsq2
+}
+
+
+TEST_F(VelocityTrackerTest, SailfishFlingUpFaster2) {
+ // Sailfish - fling up - faster - 2
+ Position values[] = {
+ { 847153808000, 576.00, 1264.00 },
+ { 847171174000, 576.00, 1262.00 },
+ { 847179640000, 576.00, 1257.00 },
+ { 847185187540, 577.41, 1249.22 },
+ { 847187487000, 578.00, 1246.00 },
+ { 847195710000, 581.00, 1227.00 },
+ { 847202027059, 583.93, 1209.40 },
+ { 847204324000, 585.00, 1203.00 },
+ { 847212672000, 590.00, 1176.00 },
+ { 847218861395, 594.36, 1157.11 },
+ { 847221190000, 596.00, 1150.00 },
+ { 847230484000, 602.00, 1124.00 },
+ { 847235701400, 607.56, 1103.83 },
+ { 847237986000, 610.00, 1095.00 },
+ };
+ size_t count = sizeof(values) / sizeof(Position);
+ computeAndCheckVelocity(values, count, AMOTION_EVENT_AXIS_Y, -4280.07959); // impulse
+ computeAndCheckVelocity(values, count, AMOTION_EVENT_AXIS_Y, -4241.004395); // lsq2
+}
+
+
+TEST_F(VelocityTrackerTest, SailfishFlingUpFaster3) {
+ // Sailfish - fling up - faster - 3
+ Position values[] = {
+ { 235200532789000, 507.00, 1084.00 },
+ { 235200549221000, 507.00, 1083.00 },
+ { 235200557841000, 507.00, 1081.00 },
+ { 235200558051189, 507.00, 1080.95 },
+ { 235200566314000, 507.00, 1078.00 },
+ { 235200574876586, 508.97, 1070.12 },
+ { 235200575006000, 509.00, 1070.00 },
+ { 235200582900000, 514.00, 1054.00 },
+ { 235200591276000, 525.00, 1023.00 },
+ { 235200591701829, 525.56, 1021.42 },
+ { 235200600064000, 542.00, 976.00 },
+ { 235200608519000, 563.00, 911.00 },
+ { 235200608527086, 563.02, 910.94 },
+ { 235200616933000, 590.00, 844.00 },
+ };
+ size_t count = sizeof(values) / sizeof(Position);
+ computeAndCheckVelocity(values, count, AMOTION_EVENT_AXIS_Y, -8715.686523); // impulse
+ computeAndCheckVelocity(values, count, AMOTION_EVENT_AXIS_Y, -7639.026367); // lsq2
+}
+
+
+TEST_F(VelocityTrackerTest, SailfishFlingUpFast1) {
+ // Sailfish - fling up - fast - 1
+ Position values[] = {
+ { 920922149000, 561.00, 1412.00 },
+ { 920930185000, 559.00, 1377.00 },
+ { 920930262463, 558.98, 1376.66 },
+ { 920938547000, 559.00, 1371.00 },
+ { 920947096857, 562.91, 1342.68 },
+ { 920947302000, 563.00, 1342.00 },
+ { 920955502000, 577.00, 1272.00 },
+ { 920963931021, 596.87, 1190.54 },
+ { 920963987000, 597.00, 1190.00 },
+ { 920972530000, 631.00, 1093.00 },
+ { 920980765511, 671.31, 994.68 },
+ { 920980906000, 672.00, 993.00 },
+ { 920989261000, 715.00, 903.00 },
+ };
+ size_t count = sizeof(values) / sizeof(Position);
+ computeAndCheckVelocity(values, count, AMOTION_EVENT_AXIS_X, 5670.329102); // impulse
+ computeAndCheckVelocity(values, count, AMOTION_EVENT_AXIS_X, 5991.866699); // lsq2
+ computeAndCheckVelocity(values, count, AMOTION_EVENT_AXIS_Y, -13021.101562); // impulse
+ computeAndCheckVelocity(values, count, AMOTION_EVENT_AXIS_Y, -15093.995117); // lsq2
+}
+
+
+TEST_F(VelocityTrackerTest, SailfishFlingUpFast2) {
+ // Sailfish - fling up - fast - 2
+ Position values[] = {
+ { 235247153233000, 518.00, 1168.00 },
+ { 235247170452000, 517.00, 1167.00 },
+ { 235247178908000, 515.00, 1159.00 },
+ { 235247179556213, 514.85, 1158.39 },
+ { 235247186821000, 515.00, 1125.00 },
+ { 235247195265000, 521.00, 1051.00 },
+ { 235247196389476, 521.80, 1041.15 },
+ { 235247203649000, 538.00, 932.00 },
+ { 235247212253000, 571.00, 794.00 },
+ { 235247213222491, 574.72, 778.45 },
+ { 235247220736000, 620.00, 641.00 },
+ };
+ size_t count = sizeof(values) / sizeof(Position);
+ computeAndCheckVelocity(values, count, AMOTION_EVENT_AXIS_Y, -20286.958984); // impulse
+ computeAndCheckVelocity(values, count, AMOTION_EVENT_AXIS_Y, -20494.587891); // lsq2
+}
+
+
+TEST_F(VelocityTrackerTest, SailfishFlingUpFast3) {
+ // Sailfish - fling up - fast - 3
+ Position values[] = {
+ { 235302568736000, 529.00, 1167.00 },
+ { 235302576644000, 523.00, 1140.00 },
+ { 235302579395063, 520.91, 1130.61 },
+ { 235302585140000, 522.00, 1130.00 },
+ { 235302593615000, 527.00, 1065.00 },
+ { 235302596207444, 528.53, 1045.12 },
+ { 235302602102000, 559.00, 872.00 },
+ { 235302610545000, 652.00, 605.00 },
+ { 235302613019881, 679.26, 526.73 },
+ };
+ size_t count = sizeof(values) / sizeof(Position);
+ computeAndCheckVelocity(values, count, AMOTION_EVENT_AXIS_Y, -39295.941406); // impulse
+ computeAndCheckVelocity(values, count, AMOTION_EVENT_AXIS_Y, -36461.421875); // lsq2
+}
+
+
+TEST_F(VelocityTrackerTest, SailfishFlingDownSlow1) {
+ // Sailfish - fling down - slow - 1
+ Position values[] = {
+ { 235655749552755, 582.00, 432.49 },
+ { 235655750638000, 582.00, 433.00 },
+ { 235655758865000, 582.00, 440.00 },
+ { 235655766221523, 581.16, 448.43 },
+ { 235655767594000, 581.00, 450.00 },
+ { 235655776044000, 580.00, 462.00 },
+ { 235655782890696, 579.18, 474.35 },
+ { 235655784360000, 579.00, 477.00 },
+ { 235655792795000, 578.00, 496.00 },
+ { 235655799559531, 576.27, 515.04 },
+ { 235655800612000, 576.00, 518.00 },
+ { 235655809535000, 574.00, 542.00 },
+ { 235655816988015, 572.17, 564.86 },
+ { 235655817685000, 572.00, 567.00 },
+ { 235655825981000, 569.00, 595.00 },
+ { 235655833808653, 566.26, 620.60 },
+ { 235655834541000, 566.00, 623.00 },
+ { 235655842893000, 563.00, 649.00 },
+ };
+ size_t count = sizeof(values) / sizeof(Position);
+ computeAndCheckVelocity(values, count, AMOTION_EVENT_AXIS_X, -419.749695); // impulse
+ computeAndCheckVelocity(values, count, AMOTION_EVENT_AXIS_X, -398.303894); // lsq2
+ computeAndCheckVelocity(values, count, AMOTION_EVENT_AXIS_Y, 3309.016357); // impulse
+ computeAndCheckVelocity(values, count, AMOTION_EVENT_AXIS_Y, 3969.099854); // lsq2
+}
+
+
+TEST_F(VelocityTrackerTest, SailfishFlingDownSlow2) {
+ // Sailfish - fling down - slow - 2
+ Position values[] = {
+ { 235671152083370, 485.24, 558.28 },
+ { 235671154126000, 485.00, 559.00 },
+ { 235671162497000, 484.00, 566.00 },
+ { 235671168750511, 483.27, 573.29 },
+ { 235671171071000, 483.00, 576.00 },
+ { 235671179390000, 482.00, 588.00 },
+ { 235671185417210, 481.31, 598.98 },
+ { 235671188173000, 481.00, 604.00 },
+ { 235671196371000, 480.00, 624.00 },
+ { 235671202084196, 479.27, 639.98 },
+ { 235671204235000, 479.00, 646.00 },
+ { 235671212554000, 478.00, 673.00 },
+ { 235671219471011, 476.39, 697.12 },
+ { 235671221159000, 476.00, 703.00 },
+ { 235671229592000, 474.00, 734.00 },
+ { 235671236281462, 472.43, 758.38 },
+ { 235671238098000, 472.00, 765.00 },
+ { 235671246532000, 470.00, 799.00 },
+ };
+ size_t count = sizeof(values) / sizeof(Position);
+ computeAndCheckVelocity(values, count, AMOTION_EVENT_AXIS_X, -262.80426); // impulse
+ computeAndCheckVelocity(values, count, AMOTION_EVENT_AXIS_X, -243.665344); // lsq2
+ computeAndCheckVelocity(values, count, AMOTION_EVENT_AXIS_Y, 4215.682129); // impulse
+ computeAndCheckVelocity(values, count, AMOTION_EVENT_AXIS_Y, 4587.986816); // lsq2
+}
+
+
+TEST_F(VelocityTrackerTest, SailfishFlingDownSlow3) {
+ // Sailfish - fling down - slow - 3
+ Position values[] = {
+ { 170983201000, 557.00, 533.00 },
+ { 171000668000, 556.00, 534.00 },
+ { 171007359750, 554.73, 535.27 },
+ { 171011197000, 554.00, 536.00 },
+ { 171017660000, 552.00, 540.00 },
+ { 171024201831, 549.97, 544.73 },
+ { 171027333000, 549.00, 547.00 },
+ { 171034603000, 545.00, 557.00 },
+ { 171041043371, 541.98, 567.55 },
+ { 171043147000, 541.00, 571.00 },
+ { 171051052000, 536.00, 586.00 },
+ };
+ size_t count = sizeof(values) / sizeof(Position);
+ computeAndCheckVelocity(values, count, AMOTION_EVENT_AXIS_X, -723.413513); // impulse
+ computeAndCheckVelocity(values, count, AMOTION_EVENT_AXIS_X, -651.038452); // lsq2
+ computeAndCheckVelocity(values, count, AMOTION_EVENT_AXIS_Y, 2091.502441); // impulse
+ computeAndCheckVelocity(values, count, AMOTION_EVENT_AXIS_Y, 1934.517456); // lsq2
+}
+
+
+TEST_F(VelocityTrackerTest, SailfishFlingDownFaster1) {
+ // Sailfish - fling down - faster - 1
+ Position values[] = {
+ { 235695280333000, 558.00, 451.00 },
+ { 235695283971237, 558.43, 454.45 },
+ { 235695289038000, 559.00, 462.00 },
+ { 235695297388000, 561.00, 478.00 },
+ { 235695300638465, 561.83, 486.25 },
+ { 235695305265000, 563.00, 498.00 },
+ { 235695313591000, 564.00, 521.00 },
+ { 235695317305492, 564.43, 532.68 },
+ { 235695322181000, 565.00, 548.00 },
+ { 235695330709000, 565.00, 577.00 },
+ { 235695333972227, 565.00, 588.10 },
+ { 235695339250000, 565.00, 609.00 },
+ { 235695347839000, 565.00, 642.00 },
+ { 235695351313257, 565.00, 656.18 },
+ { 235695356412000, 565.00, 677.00 },
+ { 235695364899000, 563.00, 710.00 },
+ { 235695368118682, 562.24, 722.52 },
+ { 235695373403000, 564.00, 744.00 },
+ };
+ size_t count = sizeof(values) / sizeof(Position);
+ computeAndCheckVelocity(values, count, AMOTION_EVENT_AXIS_Y, 4254.639648); // impulse
+ computeAndCheckVelocity(values, count, AMOTION_EVENT_AXIS_Y, 4698.415039); // lsq2
+}
+
+
+TEST_F(VelocityTrackerTest, SailfishFlingDownFaster2) {
+ // Sailfish - fling down - faster - 2
+ Position values[] = {
+ { 235709624766000, 535.00, 579.00 },
+ { 235709642256000, 534.00, 580.00 },
+ { 235709643350278, 533.94, 580.06 },
+ { 235709650760000, 532.00, 584.00 },
+ { 235709658615000, 530.00, 593.00 },
+ { 235709660170495, 529.60, 594.78 },
+ { 235709667095000, 527.00, 606.00 },
+ { 235709675616000, 524.00, 628.00 },
+ { 235709676983261, 523.52, 631.53 },
+ { 235709684289000, 521.00, 652.00 },
+ { 235709692763000, 518.00, 682.00 },
+ { 235709693804993, 517.63, 685.69 },
+ { 235709701438000, 515.00, 709.00 },
+ { 235709709830000, 512.00, 739.00 },
+ { 235709710626776, 511.72, 741.85 },
+ };
+ size_t count = sizeof(values) / sizeof(Position);
+ computeAndCheckVelocity(values, count, AMOTION_EVENT_AXIS_X, -430.440247); // impulse
+ computeAndCheckVelocity(values, count, AMOTION_EVENT_AXIS_X, -447.600311); // lsq2
+ computeAndCheckVelocity(values, count, AMOTION_EVENT_AXIS_Y, 3953.859375); // impulse
+ computeAndCheckVelocity(values, count, AMOTION_EVENT_AXIS_Y, 4316.155273); // lsq2
+}
+
+
+TEST_F(VelocityTrackerTest, SailfishFlingDownFaster3) {
+ // Sailfish - fling down - faster - 3
+ Position values[] = {
+ { 235727628927000, 540.00, 440.00 },
+ { 235727636810000, 537.00, 454.00 },
+ { 235727646176000, 536.00, 454.00 },
+ { 235727653586628, 535.12, 456.65 },
+ { 235727654557000, 535.00, 457.00 },
+ { 235727663024000, 534.00, 465.00 },
+ { 235727670410103, 533.04, 479.45 },
+ { 235727670691000, 533.00, 480.00 },
+ { 235727679255000, 531.00, 501.00 },
+ { 235727687233704, 529.09, 526.73 },
+ { 235727687628000, 529.00, 528.00 },
+ { 235727696113000, 526.00, 558.00 },
+ { 235727704057546, 523.18, 588.98 },
+ { 235727704576000, 523.00, 591.00 },
+ { 235727713099000, 520.00, 626.00 },
+ { 235727720880776, 516.33, 655.36 },
+ { 235727721580000, 516.00, 658.00 },
+ };
+ size_t count = sizeof(values) / sizeof(Position);
+ computeAndCheckVelocity(values, count, AMOTION_EVENT_AXIS_Y, 4484.617676); // impulse
+ computeAndCheckVelocity(values, count, AMOTION_EVENT_AXIS_Y, 4927.92627); // lsq2
+}
+
+
+TEST_F(VelocityTrackerTest, SailfishFlingDownFast1) {
+ // Sailfish - fling down - fast - 1
+ Position values[] = {
+ { 235762352849000, 467.00, 286.00 },
+ { 235762360250000, 443.00, 344.00 },
+ { 235762362787412, 434.77, 363.89 },
+ { 235762368807000, 438.00, 359.00 },
+ { 235762377220000, 425.00, 423.00 },
+ { 235762379608561, 421.31, 441.17 },
+ { 235762385698000, 412.00, 528.00 },
+ { 235762394133000, 406.00, 648.00 },
+ { 235762396429369, 404.37, 680.67 },
+ };
+ size_t count = sizeof(values) / sizeof(Position);
+ computeAndCheckVelocity(values, count, AMOTION_EVENT_AXIS_Y, 19084.931641); // impulse
+ computeAndCheckVelocity(values, count, AMOTION_EVENT_AXIS_Y, 16064.685547); // lsq2
+}
+
+
+TEST_F(VelocityTrackerTest, SailfishFlingDownFast2) {
+ // Sailfish - fling down - fast - 2
+ Position values[] = {
+ { 235772487188000, 576.00, 204.00 },
+ { 235772495159000, 553.00, 236.00 },
+ { 235772503568000, 551.00, 240.00 },
+ { 235772508192247, 545.55, 254.17 },
+ { 235772512051000, 541.00, 266.00 },
+ { 235772520794000, 520.00, 337.00 },
+ { 235772525015263, 508.92, 394.43 },
+ { 235772529174000, 498.00, 451.00 },
+ { 235772537635000, 484.00, 589.00 },
+ };
+ size_t count = sizeof(values) / sizeof(Position);
+ computeAndCheckVelocity(values, count, AMOTION_EVENT_AXIS_Y, 18660.048828); // impulse
+ computeAndCheckVelocity(values, count, AMOTION_EVENT_AXIS_Y, 16918.439453); // lsq2
+}
+
+
+TEST_F(VelocityTrackerTest, SailfishFlingDownFast3) {
+ // Sailfish - fling down - fast - 3
+ Position values[] = {
+ { 507650295000, 628.00, 233.00 },
+ { 507658234000, 605.00, 269.00 },
+ { 507666784000, 601.00, 274.00 },
+ { 507669660483, 599.65, 275.68 },
+ { 507675427000, 582.00, 308.00 },
+ { 507683740000, 541.00, 404.00 },
+ { 507686506238, 527.36, 435.95 },
+ { 507692220000, 487.00, 581.00 },
+ { 507700707000, 454.00, 792.00 },
+ { 507703352649, 443.71, 857.77 },
+ };
+ size_t count = sizeof(values) / sizeof(Position);
+ computeAndCheckVelocity(values, count, AMOTION_EVENT_AXIS_X, -6772.508301); // impulse
+ computeAndCheckVelocity(values, count, AMOTION_EVENT_AXIS_X, -6388.48877); // lsq2
+ computeAndCheckVelocity(values, count, AMOTION_EVENT_AXIS_Y, 29765.908203); // impulse
+ computeAndCheckVelocity(values, count, AMOTION_EVENT_AXIS_Y, 28354.796875); // lsq2
+}
+
+
+} // namespace android
diff --git a/libs/sensor/ISensorServer.cpp b/libs/sensor/ISensorServer.cpp
index f20668d..efbbf7d 100644
--- a/libs/sensor/ISensorServer.cpp
+++ b/libs/sensor/ISensorServer.cpp
@@ -63,7 +63,8 @@
Vector<Sensor> v;
uint32_t n = reply.readUint32();
v.setCapacity(n);
- while (n--) {
+ while (n) {
+ n--;
reply.read(s);
v.add(s);
}
@@ -80,7 +81,8 @@
Vector<Sensor> v;
uint32_t n = reply.readUint32();
v.setCapacity(n);
- while (n--) {
+ while (n) {
+ n--;
reply.read(s);
v.add(s);
}
diff --git a/libs/sensor/OWNERS b/libs/sensor/OWNERS
new file mode 100644
index 0000000..6a38a1f
--- /dev/null
+++ b/libs/sensor/OWNERS
@@ -0,0 +1,2 @@
+ashutoshj@google.com
+pengxu@google.com
diff --git a/libs/ui/Android.bp b/libs/ui/Android.bp
index 07aba32..102964f 100644
--- a/libs/ui/Android.bp
+++ b/libs/ui/Android.bp
@@ -47,7 +47,7 @@
],
sanitize: {
- //misc_undefined: ["integer"],
+ integer_overflow: true,
},
srcs: [
@@ -74,6 +74,7 @@
shared_libs: [
"android.hardware.graphics.allocator@2.0",
"android.hardware.graphics.mapper@2.0",
+ "android.hardware.graphics.mapper@2.1",
"android.hardware.configstore@1.0",
"android.hardware.configstore-utils",
"libbase",
diff --git a/libs/ui/Gralloc2.cpp b/libs/ui/Gralloc2.cpp
index 0eb08e5..1f746a2 100644
--- a/libs/ui/Gralloc2.cpp
+++ b/libs/ui/Gralloc2.cpp
@@ -39,9 +39,15 @@
Mapper::Mapper()
{
mMapper = IMapper::getService();
- if (mMapper == nullptr || mMapper->isRemote()) {
+ if (mMapper == nullptr) {
+ LOG_ALWAYS_FATAL("gralloc-mapper is missing");
+ }
+ if (mMapper->isRemote()) {
LOG_ALWAYS_FATAL("gralloc-mapper must be in passthrough mode");
}
+
+ // IMapper 2.1 is optional
+ mMapperV2_1 = hardware::graphics::mapper::V2_1::IMapper::castFrom(mMapper);
}
Error Mapper::createDescriptor(
@@ -91,6 +97,50 @@
buffer, error);
}
+Error Mapper::validateBufferSize(buffer_handle_t bufferHandle,
+ const IMapper::BufferDescriptorInfo& descriptorInfo,
+ uint32_t stride) const
+{
+ if (mMapperV2_1 == nullptr) {
+ return Error::NONE;
+ }
+
+ auto buffer = const_cast<native_handle_t*>(bufferHandle);
+ auto ret = mMapperV2_1->validateBufferSize(buffer, descriptorInfo, stride);
+
+ return (ret.isOk()) ? static_cast<Error>(ret) : kTransactionError;
+}
+
+void Mapper::getTransportSize(buffer_handle_t bufferHandle,
+ uint32_t* outNumFds, uint32_t* outNumInts) const
+{
+ *outNumFds = uint32_t(bufferHandle->numFds);
+ *outNumInts = uint32_t(bufferHandle->numInts);
+
+ if (mMapperV2_1 == nullptr) {
+ return;
+ }
+
+ Error error;
+ auto buffer = const_cast<native_handle_t*>(bufferHandle);
+ auto ret = mMapperV2_1->getTransportSize(buffer,
+ [&](const auto& tmpError, const auto& tmpNumFds, const auto& tmpNumInts) {
+ error = tmpError;
+ if (error != Error::NONE) {
+ return;
+ }
+
+ *outNumFds = tmpNumFds;
+ *outNumInts = tmpNumInts;
+ });
+
+ if (!ret.isOk()) {
+ error = kTransactionError;
+ }
+ ALOGE_IF(error != Error::NONE, "getTransportSize(%p) failed with %d",
+ buffer, error);
+}
+
Error Mapper::lock(buffer_handle_t bufferHandle, uint64_t usage,
const IMapper::Rect& accessRegion,
int acquireFence, void** outData) const
diff --git a/libs/ui/GraphicBuffer.cpp b/libs/ui/GraphicBuffer.cpp
index c880500..4ed2aa4 100644
--- a/libs/ui/GraphicBuffer.cpp
+++ b/libs/ui/GraphicBuffer.cpp
@@ -170,6 +170,8 @@
inUsage, &handle, &outStride, mId,
std::move(requestorName));
if (err == NO_ERROR) {
+ mBufferMapper.getTransportSize(handle, &mTransportNumFds, &mTransportNumInts);
+
width = static_cast<int>(inWidth);
height = static_cast<int>(inHeight);
format = inFormat;
@@ -199,7 +201,8 @@
if (method == TAKE_UNREGISTERED_HANDLE || method == CLONE_HANDLE) {
buffer_handle_t importedHandle;
- status_t err = mBufferMapper.importBuffer(handle, &importedHandle);
+ status_t err = mBufferMapper.importBuffer(handle, width, height,
+ layerCount, format, usage, stride, &importedHandle);
if (err != NO_ERROR) {
initWithHandle(nullptr, WRAP_HANDLE, 0, 0, 0, 0, 0, 0);
@@ -212,6 +215,7 @@
}
handle = importedHandle;
+ mBufferMapper.getTransportSize(handle, &mTransportNumFds, &mTransportNumInts);
}
ANativeWindowBuffer::handle = handle;
@@ -323,11 +327,11 @@
}
size_t GraphicBuffer::getFlattenedSize() const {
- return static_cast<size_t>(13 + (handle ? handle->numInts : 0)) * sizeof(int);
+ return static_cast<size_t>(13 + (handle ? mTransportNumInts : 0)) * sizeof(int);
}
size_t GraphicBuffer::getFdCount() const {
- return static_cast<size_t>(handle ? handle->numFds : 0);
+ return static_cast<size_t>(handle ? mTransportNumFds : 0);
}
status_t GraphicBuffer::flatten(void*& buffer, size_t& size, int*& fds, size_t& count) const {
@@ -353,18 +357,18 @@
buf[12] = int(usage >> 32); // high 32-bits
if (handle) {
- buf[10] = handle->numFds;
- buf[11] = handle->numInts;
- memcpy(fds, handle->data, static_cast<size_t>(handle->numFds) * sizeof(int));
+ buf[10] = int32_t(mTransportNumFds);
+ buf[11] = int32_t(mTransportNumInts);
+ memcpy(fds, handle->data, static_cast<size_t>(mTransportNumFds) * sizeof(int));
memcpy(buf + 13, handle->data + handle->numFds,
- static_cast<size_t>(handle->numInts) * sizeof(int));
+ static_cast<size_t>(mTransportNumInts) * sizeof(int));
}
buffer = static_cast<void*>(static_cast<uint8_t*>(buffer) + sizeNeeded);
size -= sizeNeeded;
if (handle) {
- fds += handle->numFds;
- count -= static_cast<size_t>(handle->numFds);
+ fds += mTransportNumFds;
+ count -= static_cast<size_t>(mTransportNumFds);
}
return NO_ERROR;
@@ -457,7 +461,8 @@
if (handle != 0) {
buffer_handle_t importedHandle;
- status_t err = mBufferMapper.importBuffer(handle, &importedHandle);
+ status_t err = mBufferMapper.importBuffer(handle, uint32_t(width), uint32_t(height),
+ uint32_t(layerCount), format, usage, uint32_t(stride), &importedHandle);
if (err != NO_ERROR) {
width = height = stride = format = usage_deprecated = 0;
layerCount = 0;
@@ -470,6 +475,7 @@
native_handle_close(handle);
native_handle_delete(const_cast<native_handle_t*>(handle));
handle = importedHandle;
+ mBufferMapper.getTransportSize(handle, &mTransportNumFds, &mTransportNumInts);
}
buffer = static_cast<void const*>(static_cast<uint8_t const*>(buffer) + sizeNeeded);
diff --git a/libs/ui/GraphicBufferMapper.cpp b/libs/ui/GraphicBufferMapper.cpp
index d854489..2cac287 100644
--- a/libs/ui/GraphicBufferMapper.cpp
+++ b/libs/ui/GraphicBufferMapper.cpp
@@ -52,17 +52,42 @@
}
status_t GraphicBufferMapper::importBuffer(buffer_handle_t rawHandle,
+ uint32_t width, uint32_t height, uint32_t layerCount,
+ PixelFormat format, uint64_t usage, uint32_t stride,
buffer_handle_t* outHandle)
{
ATRACE_CALL();
+ buffer_handle_t bufferHandle;
Gralloc2::Error error = mMapper->importBuffer(
- hardware::hidl_handle(rawHandle), outHandle);
+ hardware::hidl_handle(rawHandle), &bufferHandle);
+ if (error != Gralloc2::Error::NONE) {
+ ALOGW("importBuffer(%p) failed: %d", rawHandle, error);
+ return static_cast<status_t>(error);
+ }
- ALOGW_IF(error != Gralloc2::Error::NONE, "importBuffer(%p) failed: %d",
- rawHandle, error);
+ Gralloc2::IMapper::BufferDescriptorInfo info = {};
+ info.width = width;
+ info.height = height;
+ info.layerCount = layerCount;
+ info.format = static_cast<Gralloc2::PixelFormat>(format);
+ info.usage = usage;
+ error = mMapper->validateBufferSize(bufferHandle, info, stride);
+ if (error != Gralloc2::Error::NONE) {
+ ALOGE("validateBufferSize(%p) failed: %d", rawHandle, error);
+ freeBuffer(bufferHandle);
+ return static_cast<status_t>(error);
+ }
- return static_cast<status_t>(error);
+ *outHandle = bufferHandle;
+
+ return NO_ERROR;
+}
+
+void GraphicBufferMapper::getTransportSize(buffer_handle_t handle,
+ uint32_t* outTransportNumFds, uint32_t* outTransportNumInts)
+{
+ mMapper->getTransportSize(handle, outTransportNumFds, outTransportNumInts);
}
status_t GraphicBufferMapper::freeBuffer(buffer_handle_t handle)
diff --git a/libs/ui/include/ui/Gralloc2.h b/libs/ui/include/ui/Gralloc2.h
index 8aee160..69c35f7 100644
--- a/libs/ui/include/ui/Gralloc2.h
+++ b/libs/ui/include/ui/Gralloc2.h
@@ -21,6 +21,7 @@
#include <android/hardware/graphics/allocator/2.0/IAllocator.h>
#include <android/hardware/graphics/mapper/2.0/IMapper.h>
+#include <android/hardware/graphics/mapper/2.1/IMapper.h>
#include <utils/StrongPointer.h>
namespace android {
@@ -55,6 +56,13 @@
void freeBuffer(buffer_handle_t bufferHandle) const;
+ Error validateBufferSize(buffer_handle_t bufferHandle,
+ const IMapper::BufferDescriptorInfo& descriptorInfo,
+ uint32_t stride) const;
+
+ void getTransportSize(buffer_handle_t bufferHandle,
+ uint32_t* outNumFds, uint32_t* outNumInts) const;
+
// The ownership of acquireFence is always transferred to the callee, even
// on errors.
Error lock(buffer_handle_t bufferHandle, uint64_t usage,
@@ -73,6 +81,7 @@
private:
sp<IMapper> mMapper;
+ sp<hardware::graphics::mapper::V2_1::IMapper> mMapperV2_1;
};
// A wrapper to IAllocator
diff --git a/libs/ui/include/ui/GraphicBuffer.h b/libs/ui/include/ui/GraphicBuffer.h
index 95c2d22..e794462 100644
--- a/libs/ui/include/ui/GraphicBuffer.h
+++ b/libs/ui/include/ui/GraphicBuffer.h
@@ -230,6 +230,10 @@
GraphicBufferMapper& mBufferMapper;
ssize_t mInitCheck;
+ // numbers of fds/ints in native_handle_t to flatten
+ uint32_t mTransportNumFds;
+ uint32_t mTransportNumInts;
+
uint64_t mId;
// Stores the generation number of this buffer. If this number does not
diff --git a/libs/ui/include/ui/GraphicBufferMapper.h b/libs/ui/include/ui/GraphicBufferMapper.h
index 06961b1..7cf003d 100644
--- a/libs/ui/include/ui/GraphicBufferMapper.h
+++ b/libs/ui/include/ui/GraphicBufferMapper.h
@@ -22,6 +22,7 @@
#include <memory>
+#include <ui/PixelFormat.h>
#include <utils/Singleton.h>
@@ -49,10 +50,15 @@
// The imported outHandle must be freed with freeBuffer when no longer
// needed. rawHandle is owned by the caller.
status_t importBuffer(buffer_handle_t rawHandle,
+ uint32_t width, uint32_t height, uint32_t layerCount,
+ PixelFormat format, uint64_t usage, uint32_t stride,
buffer_handle_t* outHandle);
status_t freeBuffer(buffer_handle_t handle);
+ void getTransportSize(buffer_handle_t handle,
+ uint32_t* outTransportNumFds, uint32_t* outTransportNumInts);
+
status_t lock(buffer_handle_t handle,
uint32_t usage, const Rect& bounds, void** vaddr);
diff --git a/libs/vr/libbufferhub/Android.bp b/libs/vr/libbufferhub/Android.bp
index f327200..a550ba5 100644
--- a/libs/vr/libbufferhub/Android.bp
+++ b/libs/vr/libbufferhub/Android.bp
@@ -29,6 +29,7 @@
sharedLibraries = [
"libbase",
+ "libbinder",
"libcutils",
"libhardware",
"liblog",
@@ -61,10 +62,10 @@
cc_test {
tags: ["optional"],
- srcs: ["bufferhub_tests.cpp"],
+ srcs: ["buffer_hub-test.cpp"],
static_libs: ["libbufferhub"] + staticLibraries,
shared_libs: sharedLibraries,
header_libs: headerLibraries,
- name: "bufferhub_tests",
+ name: "buffer_hub-test",
}
diff --git a/libs/vr/libbufferhub/bufferhub_tests.cpp b/libs/vr/libbufferhub/buffer_hub-test.cpp
similarity index 60%
rename from libs/vr/libbufferhub/bufferhub_tests.cpp
rename to libs/vr/libbufferhub/buffer_hub-test.cpp
index c4b9a8c..a5cf9ae 100644
--- a/libs/vr/libbufferhub/bufferhub_tests.cpp
+++ b/libs/vr/libbufferhub/buffer_hub-test.cpp
@@ -20,6 +20,10 @@
using android::dvr::BufferConsumer;
using android::dvr::BufferHubDefs::kConsumerStateMask;
using android::dvr::BufferHubDefs::kProducerStateBit;
+using android::dvr::BufferHubDefs::IsBufferGained;
+using android::dvr::BufferHubDefs::IsBufferPosted;
+using android::dvr::BufferHubDefs::IsBufferAcquired;
+using android::dvr::BufferHubDefs::IsBufferReleased;
using android::dvr::BufferProducer;
using android::pdx::LocalHandle;
@@ -28,6 +32,8 @@
const int kFormat = HAL_PIXEL_FORMAT_RGBA_8888;
const int kUsage = 0;
const uint64_t kContext = 42;
+const size_t kMaxConsumerCount = 63;
+const int kPollTimeoutMs = 100;
using LibBufferHubTest = ::testing::Test;
@@ -46,51 +52,51 @@
// Producer state mask is unique, i.e. 1.
EXPECT_EQ(p->buffer_state_bit(), kProducerStateBit);
// Consumer state mask cannot have producer bit on.
- EXPECT_EQ(c->buffer_state_bit() & kProducerStateBit, 0);
+ EXPECT_EQ(c->buffer_state_bit() & kProducerStateBit, 0U);
// Consumer state mask must be a single, i.e. power of 2.
- EXPECT_NE(c->buffer_state_bit(), 0);
- EXPECT_EQ(c->buffer_state_bit() & (c->buffer_state_bit() - 1), 0);
+ EXPECT_NE(c->buffer_state_bit(), 0U);
+ EXPECT_EQ(c->buffer_state_bit() & (c->buffer_state_bit() - 1), 0U);
// Consumer state mask cannot have producer bit on.
- EXPECT_EQ(c2->buffer_state_bit() & kProducerStateBit, 0);
+ EXPECT_EQ(c2->buffer_state_bit() & kProducerStateBit, 0U);
// Consumer state mask must be a single, i.e. power of 2.
- EXPECT_NE(c2->buffer_state_bit(), 0);
- EXPECT_EQ(c2->buffer_state_bit() & (c2->buffer_state_bit() - 1), 0);
+ EXPECT_NE(c2->buffer_state_bit(), 0U);
+ EXPECT_EQ(c2->buffer_state_bit() & (c2->buffer_state_bit() - 1), 0U);
// Each consumer should have unique bit.
- EXPECT_EQ(c->buffer_state_bit() & c2->buffer_state_bit(), 0);
+ EXPECT_EQ(c->buffer_state_bit() & c2->buffer_state_bit(), 0U);
// Initial state: producer not available, consumers not available.
- EXPECT_EQ(0, RETRY_EINTR(p->Poll(100)));
- EXPECT_EQ(0, RETRY_EINTR(c->Poll(100)));
- EXPECT_EQ(0, RETRY_EINTR(c2->Poll(100)));
+ EXPECT_EQ(0, RETRY_EINTR(p->Poll(kPollTimeoutMs)));
+ EXPECT_EQ(0, RETRY_EINTR(c->Poll(kPollTimeoutMs)));
+ EXPECT_EQ(0, RETRY_EINTR(c2->Poll(kPollTimeoutMs)));
EXPECT_EQ(0, p->Post(LocalHandle(), kContext));
// New state: producer not available, consumers available.
- EXPECT_EQ(0, RETRY_EINTR(p->Poll(100)));
- EXPECT_EQ(1, RETRY_EINTR(c->Poll(100)));
- EXPECT_EQ(1, RETRY_EINTR(c2->Poll(100)));
+ EXPECT_EQ(0, RETRY_EINTR(p->Poll(kPollTimeoutMs)));
+ EXPECT_EQ(1, RETRY_EINTR(c->Poll(kPollTimeoutMs)));
+ EXPECT_EQ(1, RETRY_EINTR(c2->Poll(kPollTimeoutMs)));
uint64_t context;
LocalHandle fence;
EXPECT_EQ(0, c->Acquire(&fence, &context));
EXPECT_EQ(kContext, context);
- EXPECT_EQ(0, RETRY_EINTR(c->Poll(100)));
- EXPECT_EQ(1, RETRY_EINTR(c2->Poll(100)));
+ EXPECT_EQ(0, RETRY_EINTR(c->Poll(kPollTimeoutMs)));
+ EXPECT_EQ(1, RETRY_EINTR(c2->Poll(kPollTimeoutMs)));
EXPECT_EQ(0, c2->Acquire(&fence, &context));
EXPECT_EQ(kContext, context);
- EXPECT_EQ(0, RETRY_EINTR(c2->Poll(100)));
- EXPECT_EQ(0, RETRY_EINTR(c->Poll(100)));
+ EXPECT_EQ(0, RETRY_EINTR(c2->Poll(kPollTimeoutMs)));
+ EXPECT_EQ(0, RETRY_EINTR(c->Poll(kPollTimeoutMs)));
EXPECT_EQ(0, c->Release(LocalHandle()));
- EXPECT_EQ(0, RETRY_EINTR(p->Poll(100)));
+ EXPECT_EQ(0, RETRY_EINTR(p->Poll(kPollTimeoutMs)));
EXPECT_EQ(0, c2->Discard());
- EXPECT_EQ(1, RETRY_EINTR(p->Poll(100)));
+ EXPECT_EQ(1, RETRY_EINTR(p->Poll(kPollTimeoutMs)));
EXPECT_EQ(0, p->Gain(&fence));
- EXPECT_EQ(0, RETRY_EINTR(p->Poll(100)));
- EXPECT_EQ(0, RETRY_EINTR(c->Poll(100)));
- EXPECT_EQ(0, RETRY_EINTR(c2->Poll(100)));
+ EXPECT_EQ(0, RETRY_EINTR(p->Poll(kPollTimeoutMs)));
+ EXPECT_EQ(0, RETRY_EINTR(c->Poll(kPollTimeoutMs)));
+ EXPECT_EQ(0, RETRY_EINTR(c2->Poll(kPollTimeoutMs)));
}
TEST_F(LibBufferHubTest, TestEpoll) {
@@ -132,7 +138,8 @@
// Post the producer and check for consumer signal.
EXPECT_EQ(0, p->Post({}, kContext));
- ASSERT_EQ(1, epoll_wait(epoll_fd.Get(), events.data(), events.size(), 100));
+ ASSERT_EQ(1, epoll_wait(epoll_fd.Get(), events.data(), events.size(),
+ kPollTimeoutMs));
ASSERT_TRUE(events[0].events & EPOLLIN);
ASSERT_EQ(c->event_fd(), events[0].data.fd);
@@ -140,10 +147,14 @@
event = events[0];
// Check for events again. Edge-triggered mode should prevent any.
- EXPECT_EQ(0, epoll_wait(epoll_fd.Get(), events.data(), events.size(), 100));
- EXPECT_EQ(0, epoll_wait(epoll_fd.Get(), events.data(), events.size(), 100));
- EXPECT_EQ(0, epoll_wait(epoll_fd.Get(), events.data(), events.size(), 100));
- EXPECT_EQ(0, epoll_wait(epoll_fd.Get(), events.data(), events.size(), 100));
+ EXPECT_EQ(0, epoll_wait(epoll_fd.Get(), events.data(), events.size(),
+ kPollTimeoutMs));
+ EXPECT_EQ(0, epoll_wait(epoll_fd.Get(), events.data(), events.size(),
+ kPollTimeoutMs));
+ EXPECT_EQ(0, epoll_wait(epoll_fd.Get(), events.data(), events.size(),
+ kPollTimeoutMs));
+ EXPECT_EQ(0, epoll_wait(epoll_fd.Get(), events.data(), events.size(),
+ kPollTimeoutMs));
// Translate the events.
auto event_status = c->GetEventMask(event.events);
@@ -151,7 +162,8 @@
ASSERT_TRUE(event_status.get() & EPOLLIN);
// Check for events again. Edge-triggered mode should prevent any.
- EXPECT_EQ(0, epoll_wait(epoll_fd.Get(), events.data(), events.size(), 100));
+ EXPECT_EQ(0, epoll_wait(epoll_fd.Get(), events.data(), events.size(),
+ kPollTimeoutMs));
}
TEST_F(LibBufferHubTest, TestStateMask) {
@@ -159,14 +171,14 @@
kWidth, kHeight, kFormat, kUsage, sizeof(uint64_t));
ASSERT_TRUE(p.get() != nullptr);
- // It's ok to create up to 63 consumer buffers.
+ // It's ok to create up to kMaxConsumerCount consumer buffers.
uint64_t buffer_state_bits = p->buffer_state_bit();
- std::array<std::unique_ptr<BufferConsumer>, 63> cs;
- for (size_t i = 0; i < 63; i++) {
+ std::array<std::unique_ptr<BufferConsumer>, kMaxConsumerCount> cs;
+ for (size_t i = 0; i < kMaxConsumerCount; i++) {
cs[i] = BufferConsumer::Import(p->CreateConsumer());
ASSERT_TRUE(cs[i].get() != nullptr);
// Expect all buffers have unique state mask.
- EXPECT_EQ(buffer_state_bits & cs[i]->buffer_state_bit(), 0);
+ EXPECT_EQ(buffer_state_bits & cs[i]->buffer_state_bit(), 0U);
buffer_state_bits |= cs[i]->buffer_state_bit();
}
EXPECT_EQ(buffer_state_bits, kProducerStateBit | kConsumerStateMask);
@@ -176,13 +188,13 @@
EXPECT_EQ(state.error(), E2BIG);
// Release any consumer should allow us to re-create.
- for (size_t i = 0; i < 63; i++) {
+ for (size_t i = 0; i < kMaxConsumerCount; i++) {
buffer_state_bits &= ~cs[i]->buffer_state_bit();
cs[i] = nullptr;
cs[i] = BufferConsumer::Import(p->CreateConsumer());
ASSERT_TRUE(cs[i].get() != nullptr);
// The released state mask will be reused.
- EXPECT_EQ(buffer_state_bits & cs[i]->buffer_state_bit(), 0);
+ EXPECT_EQ(buffer_state_bits & cs[i]->buffer_state_bit(), 0U);
buffer_state_bits |= cs[i]->buffer_state_bit();
EXPECT_EQ(buffer_state_bits, kProducerStateBit | kConsumerStateMask);
}
@@ -224,7 +236,7 @@
// Release in acquired state should succeed.
EXPECT_EQ(0, c->Release(LocalHandle()));
- EXPECT_LT(0, RETRY_EINTR(p->Poll(10)));
+ EXPECT_LT(0, RETRY_EINTR(p->Poll(kPollTimeoutMs)));
// Release, acquire, and post in released state should fail.
EXPECT_EQ(-EBUSY, c->Release(LocalHandle()));
@@ -240,6 +252,217 @@
EXPECT_EQ(-EALREADY, p->Gain(&fence));
}
+TEST_F(LibBufferHubTest, TestAsyncStateTransitions) {
+ std::unique_ptr<BufferProducer> p = BufferProducer::Create(
+ kWidth, kHeight, kFormat, kUsage, sizeof(uint64_t));
+ ASSERT_TRUE(p.get() != nullptr);
+ std::unique_ptr<BufferConsumer> c =
+ BufferConsumer::Import(p->CreateConsumer());
+ ASSERT_TRUE(c.get() != nullptr);
+
+ DvrNativeBufferMetadata metadata;
+ LocalHandle invalid_fence;
+
+ // The producer buffer starts in gained state.
+
+ // Acquire, release, and gain in gained state should fail.
+ EXPECT_EQ(-EBUSY, c->AcquireAsync(&metadata, &invalid_fence));
+ EXPECT_FALSE(invalid_fence.IsValid());
+ EXPECT_EQ(-EBUSY, c->ReleaseAsync(&metadata, invalid_fence));
+ EXPECT_EQ(-EALREADY, p->GainAsync(&metadata, &invalid_fence));
+ EXPECT_FALSE(invalid_fence.IsValid());
+
+ // Post in gained state should succeed.
+ EXPECT_EQ(0, p->PostAsync(&metadata, invalid_fence));
+ EXPECT_EQ(p->buffer_state(), c->buffer_state());
+ EXPECT_TRUE(IsBufferPosted(p->buffer_state()));
+
+ // Post, release, and gain in posted state should fail.
+ EXPECT_EQ(-EBUSY, p->PostAsync(&metadata, invalid_fence));
+ EXPECT_EQ(-EBUSY, c->ReleaseAsync(&metadata, invalid_fence));
+ EXPECT_EQ(-EBUSY, p->GainAsync(&metadata, &invalid_fence));
+ EXPECT_FALSE(invalid_fence.IsValid());
+
+ // Acquire in posted state should succeed.
+ EXPECT_LT(0, RETRY_EINTR(c->Poll(kPollTimeoutMs)));
+ EXPECT_EQ(0, c->AcquireAsync(&metadata, &invalid_fence));
+ EXPECT_FALSE(invalid_fence.IsValid());
+ EXPECT_EQ(p->buffer_state(), c->buffer_state());
+ EXPECT_TRUE(IsBufferAcquired(p->buffer_state()));
+
+ // Acquire, post, and gain in acquired state should fail.
+ EXPECT_EQ(-EBUSY, c->AcquireAsync(&metadata, &invalid_fence));
+ EXPECT_FALSE(invalid_fence.IsValid());
+ EXPECT_EQ(-EBUSY, p->PostAsync(&metadata, invalid_fence));
+ EXPECT_EQ(-EBUSY, p->GainAsync(&metadata, &invalid_fence));
+ EXPECT_FALSE(invalid_fence.IsValid());
+
+ // Release in acquired state should succeed.
+ EXPECT_EQ(0, c->ReleaseAsync(&metadata, invalid_fence));
+ EXPECT_LT(0, RETRY_EINTR(p->Poll(kPollTimeoutMs)));
+ EXPECT_EQ(p->buffer_state(), c->buffer_state());
+ EXPECT_TRUE(IsBufferReleased(p->buffer_state()));
+
+ // Release, acquire, and post in released state should fail.
+ EXPECT_EQ(-EBUSY, c->ReleaseAsync(&metadata, invalid_fence));
+ EXPECT_EQ(-EBUSY, c->AcquireAsync(&metadata, &invalid_fence));
+ EXPECT_FALSE(invalid_fence.IsValid());
+ EXPECT_EQ(-EBUSY, p->PostAsync(&metadata, invalid_fence));
+
+ // Gain in released state should succeed.
+ EXPECT_EQ(0, p->GainAsync(&metadata, &invalid_fence));
+ EXPECT_FALSE(invalid_fence.IsValid());
+ EXPECT_EQ(p->buffer_state(), c->buffer_state());
+ EXPECT_TRUE(IsBufferGained(p->buffer_state()));
+
+ // Acquire, release, and gain in gained state should fail.
+ EXPECT_EQ(-EBUSY, c->AcquireAsync(&metadata, &invalid_fence));
+ EXPECT_FALSE(invalid_fence.IsValid());
+ EXPECT_EQ(-EBUSY, c->ReleaseAsync(&metadata, invalid_fence));
+ EXPECT_EQ(-EALREADY, p->GainAsync(&metadata, &invalid_fence));
+ EXPECT_FALSE(invalid_fence.IsValid());
+}
+
+TEST_F(LibBufferHubTest, TestZeroConsumer) {
+ std::unique_ptr<BufferProducer> p = BufferProducer::Create(
+ kWidth, kHeight, kFormat, kUsage, sizeof(uint64_t));
+ ASSERT_TRUE(p.get() != nullptr);
+
+ DvrNativeBufferMetadata metadata;
+ LocalHandle invalid_fence;
+
+ // Newly created.
+ EXPECT_TRUE(IsBufferGained(p->buffer_state()));
+ EXPECT_EQ(0, p->PostAsync(&metadata, invalid_fence));
+ EXPECT_TRUE(IsBufferPosted(p->buffer_state()));
+
+ // The buffer should stay in posted stay until a consumer picks it up.
+ EXPECT_GE(0, RETRY_EINTR(p->Poll(kPollTimeoutMs)));
+
+ // A new consumer should still be able to acquire the buffer immediately.
+ std::unique_ptr<BufferConsumer> c =
+ BufferConsumer::Import(p->CreateConsumer());
+ ASSERT_TRUE(c.get() != nullptr);
+ EXPECT_EQ(0, c->AcquireAsync(&metadata, &invalid_fence));
+ EXPECT_TRUE(IsBufferAcquired(c->buffer_state()));
+}
+
+TEST_F(LibBufferHubTest, TestMaxConsumers) {
+ std::unique_ptr<BufferProducer> p = BufferProducer::Create(
+ kWidth, kHeight, kFormat, kUsage, sizeof(uint64_t));
+ ASSERT_TRUE(p.get() != nullptr);
+
+ std::array<std::unique_ptr<BufferConsumer>, kMaxConsumerCount> cs;
+ for (size_t i = 0; i < kMaxConsumerCount; i++) {
+ cs[i] = BufferConsumer::Import(p->CreateConsumer());
+ ASSERT_TRUE(cs[i].get() != nullptr);
+ EXPECT_TRUE(IsBufferGained(cs[i]->buffer_state()));
+ }
+
+ DvrNativeBufferMetadata metadata;
+ LocalHandle invalid_fence;
+
+ // Post the producer should trigger all consumers to be available.
+ EXPECT_EQ(0, p->PostAsync(&metadata, invalid_fence));
+ EXPECT_TRUE(IsBufferPosted(p->buffer_state()));
+ for (size_t i = 0; i < kMaxConsumerCount; i++) {
+ EXPECT_TRUE(IsBufferPosted(cs[i]->buffer_state(),
+ cs[i]->buffer_state_bit()));
+ EXPECT_LT(0, RETRY_EINTR(cs[i]->Poll(kPollTimeoutMs)));
+ EXPECT_EQ(0, cs[i]->AcquireAsync(&metadata, &invalid_fence));
+ EXPECT_TRUE(IsBufferAcquired(p->buffer_state()));
+ }
+
+ // All consumers have to release before the buffer is considered to be
+ // released.
+ for (size_t i = 0; i < kMaxConsumerCount; i++) {
+ EXPECT_FALSE(IsBufferReleased(p->buffer_state()));
+ EXPECT_EQ(0, cs[i]->ReleaseAsync(&metadata, invalid_fence));
+ }
+
+ EXPECT_LT(0, RETRY_EINTR(p->Poll(kPollTimeoutMs)));
+ EXPECT_TRUE(IsBufferReleased(p->buffer_state()));
+
+ // Buffer state cross all clients must be consistent.
+ for (size_t i = 0; i < kMaxConsumerCount; i++) {
+ EXPECT_EQ(p->buffer_state(), cs[i]->buffer_state());
+ }
+}
+
+TEST_F(LibBufferHubTest, TestCreateConsumerWhenBufferGained) {
+ std::unique_ptr<BufferProducer> p = BufferProducer::Create(
+ kWidth, kHeight, kFormat, kUsage, sizeof(uint64_t));
+ ASSERT_TRUE(p.get() != nullptr);
+ EXPECT_TRUE(IsBufferGained(p->buffer_state()));
+
+ std::unique_ptr<BufferConsumer> c =
+ BufferConsumer::Import(p->CreateConsumer());
+ ASSERT_TRUE(c.get() != nullptr);
+ EXPECT_TRUE(IsBufferGained(c->buffer_state()));
+
+ DvrNativeBufferMetadata metadata;
+ LocalHandle invalid_fence;
+
+ // Post the gained buffer should signal already created consumer.
+ EXPECT_EQ(0, p->PostAsync(&metadata, invalid_fence));
+ EXPECT_TRUE(IsBufferPosted(p->buffer_state()));
+ EXPECT_LT(0, RETRY_EINTR(c->Poll(kPollTimeoutMs)));
+ EXPECT_EQ(0, c->AcquireAsync(&metadata, &invalid_fence));
+ EXPECT_TRUE(IsBufferAcquired(c->buffer_state()));
+}
+
+TEST_F(LibBufferHubTest, TestCreateConsumerWhenBufferPosted) {
+ std::unique_ptr<BufferProducer> p = BufferProducer::Create(
+ kWidth, kHeight, kFormat, kUsage, sizeof(uint64_t));
+ ASSERT_TRUE(p.get() != nullptr);
+ EXPECT_TRUE(IsBufferGained(p->buffer_state()));
+
+ DvrNativeBufferMetadata metadata;
+ LocalHandle invalid_fence;
+
+ // Post the gained buffer before any consumer gets created.
+ EXPECT_EQ(0, p->PostAsync(&metadata, invalid_fence));
+ EXPECT_TRUE(IsBufferPosted(p->buffer_state()));
+
+ // Newly created consumer should be automatically sigalled.
+ std::unique_ptr<BufferConsumer> c =
+ BufferConsumer::Import(p->CreateConsumer());
+ ASSERT_TRUE(c.get() != nullptr);
+ EXPECT_TRUE(IsBufferPosted(c->buffer_state()));
+ EXPECT_EQ(0, c->AcquireAsync(&metadata, &invalid_fence));
+ EXPECT_TRUE(IsBufferAcquired(c->buffer_state()));
+}
+
+TEST_F(LibBufferHubTest, TestCreateConsumerWhenBufferReleased) {
+ std::unique_ptr<BufferProducer> p = BufferProducer::Create(
+ kWidth, kHeight, kFormat, kUsage, sizeof(uint64_t));
+ ASSERT_TRUE(p.get() != nullptr);
+
+ std::unique_ptr<BufferConsumer> c1 =
+ BufferConsumer::Import(p->CreateConsumer());
+ ASSERT_TRUE(c1.get() != nullptr);
+
+ DvrNativeBufferMetadata metadata;
+ LocalHandle invalid_fence;
+
+ // Post, acquire, and release the buffer..
+ EXPECT_EQ(0, p->PostAsync(&metadata, invalid_fence));
+ EXPECT_LT(0, RETRY_EINTR(c1->Poll(kPollTimeoutMs)));
+ EXPECT_EQ(0, c1->AcquireAsync(&metadata, &invalid_fence));
+ EXPECT_EQ(0, c1->ReleaseAsync(&metadata, invalid_fence));
+
+ // Create another consumer immediately after the release, should not make the
+ // buffer un-released. This is guaranteed by IPC execution order in bufferhubd.
+ std::unique_ptr<BufferConsumer> c2 =
+ BufferConsumer::Import(p->CreateConsumer());
+ ASSERT_TRUE(c2.get() != nullptr);
+
+ EXPECT_LT(0, RETRY_EINTR(p->Poll(kPollTimeoutMs)));
+ EXPECT_TRUE(IsBufferReleased(p->buffer_state()));
+ EXPECT_EQ(0, p->GainAsync(&metadata, &invalid_fence));
+ EXPECT_TRUE(IsBufferGained(p->buffer_state()));
+}
+
TEST_F(LibBufferHubTest, TestWithCustomMetadata) {
struct Metadata {
int64_t field1;
@@ -254,7 +477,7 @@
Metadata m = {1, 3};
EXPECT_EQ(0, p->Post(LocalHandle(), m));
- EXPECT_LE(0, RETRY_EINTR(c->Poll(10)));
+ EXPECT_LE(0, RETRY_EINTR(c->Poll(kPollTimeoutMs)));
LocalHandle fence;
Metadata m2 = {};
@@ -287,7 +510,7 @@
// buffer allocation.
OverSizedMetadata evil_meta = {};
EXPECT_NE(0, p->Post(LocalHandle(), evil_meta));
- EXPECT_GE(0, RETRY_EINTR(c->Poll(10)));
+ EXPECT_GE(0, RETRY_EINTR(c->Poll(kPollTimeoutMs)));
// It is ok to post metadata smaller than originally requested during
// buffer allocation.
@@ -422,7 +645,7 @@
EXPECT_EQ(0, p->Post<void>(LocalHandle()));
EXPECT_EQ(0, c->Acquire(&fence));
EXPECT_EQ(0, c->Release(LocalHandle()));
- EXPECT_LT(0, RETRY_EINTR(p->Poll(10)));
+ EXPECT_LT(0, RETRY_EINTR(p->Poll(kPollTimeoutMs)));
// Test that removing persistence and closing the producer orphans the
// consumer.
@@ -463,7 +686,7 @@
// Should acquire a valid fence.
LocalHandle f2;
- EXPECT_LT(0, RETRY_EINTR(c->Poll(10)));
+ EXPECT_LT(0, RETRY_EINTR(c->Poll(kPollTimeoutMs)));
EXPECT_EQ(0, c->AcquireAsync(&meta, &f2));
EXPECT_TRUE(f2.IsValid());
// The original fence and acquired fence should have different fd number.
@@ -473,14 +696,14 @@
// Signal the original fence will trigger the new fence.
eventfd_write(f1.Get(), 1);
// Now the original FD has been signaled.
- EXPECT_LT(0, PollFd(f2.Get(), 10));
+ EXPECT_LT(0, PollFd(f2.Get(), kPollTimeoutMs));
// Release the consumer with an invalid fence.
EXPECT_EQ(0, c->ReleaseAsync(&meta, LocalHandle()));
// Should gain an invalid fence.
LocalHandle f3;
- EXPECT_LT(0, RETRY_EINTR(p->Poll(10)));
+ EXPECT_LT(0, RETRY_EINTR(p->Poll(kPollTimeoutMs)));
EXPECT_EQ(0, p->GainAsync(&meta, &f3));
EXPECT_FALSE(f3.IsValid());
@@ -489,10 +712,10 @@
// Should acquire a valid fence and it's already signalled.
LocalHandle f4;
- EXPECT_LT(0, RETRY_EINTR(c->Poll(10)));
+ EXPECT_LT(0, RETRY_EINTR(c->Poll(kPollTimeoutMs)));
EXPECT_EQ(0, c->AcquireAsync(&meta, &f4));
EXPECT_TRUE(f4.IsValid());
- EXPECT_LT(0, PollFd(f4.Get(), 10));
+ EXPECT_LT(0, PollFd(f4.Get(), kPollTimeoutMs));
// Release with an unsignalled fence and signal it immediately after release
// without producer gainning.
@@ -502,10 +725,10 @@
// Should gain a valid fence, which is already signaled.
LocalHandle f6;
- EXPECT_LT(0, RETRY_EINTR(p->Poll(10)));
+ EXPECT_LT(0, RETRY_EINTR(p->Poll(kPollTimeoutMs)));
EXPECT_EQ(0, p->GainAsync(&meta, &f6));
EXPECT_TRUE(f6.IsValid());
- EXPECT_LT(0, PollFd(f6.Get(), 10));
+ EXPECT_LT(0, PollFd(f6.Get(), kPollTimeoutMs));
}
TEST_F(LibBufferHubTest, TestOrphanedAcquire) {
@@ -521,12 +744,12 @@
EXPECT_EQ(0, p->PostAsync(&meta, LocalHandle()));
LocalHandle fence;
- EXPECT_LT(0, RETRY_EINTR(c1->Poll(10)));
+ EXPECT_LT(0, RETRY_EINTR(c1->Poll(kPollTimeoutMs)));
EXPECT_LE(0, c1->AcquireAsync(&meta, &fence));
// Destroy the consumer now will make it orphaned and the buffer is still
// acquired.
c1 = nullptr;
- EXPECT_GE(0, RETRY_EINTR(p->Poll(10)));
+ EXPECT_GE(0, RETRY_EINTR(p->Poll(kPollTimeoutMs)));
std::unique_ptr<BufferConsumer> c2 =
BufferConsumer::Import(p->CreateConsumer());
@@ -535,13 +758,13 @@
EXPECT_NE(consumer_state_bit1, consumer_state_bit2);
// The new consumer is available for acquire.
- EXPECT_LT(0, RETRY_EINTR(c2->Poll(10)));
+ EXPECT_LT(0, RETRY_EINTR(c2->Poll(kPollTimeoutMs)));
EXPECT_LE(0, c2->AcquireAsync(&meta, &fence));
// Releasing the consumer makes the buffer gainable.
EXPECT_EQ(0, c2->ReleaseAsync(&meta, LocalHandle()));
// The buffer is now available for the producer to gain.
- EXPECT_LT(0, RETRY_EINTR(p->Poll(10)));
+ EXPECT_LT(0, RETRY_EINTR(p->Poll(kPollTimeoutMs)));
// But if another consumer is created in released state.
std::unique_ptr<BufferConsumer> c3 =
@@ -550,7 +773,7 @@
const uint64_t consumer_state_bit3 = c3->buffer_state_bit();
EXPECT_NE(consumer_state_bit2, consumer_state_bit3);
// The consumer buffer is not acquirable.
- EXPECT_GE(0, RETRY_EINTR(c3->Poll(10)));
+ EXPECT_GE(0, RETRY_EINTR(c3->Poll(kPollTimeoutMs)));
EXPECT_EQ(-EBUSY, c3->AcquireAsync(&meta, &fence));
// Producer should be able to gain no matter what.
diff --git a/libs/vr/libbufferhub/include/private/dvr/buffer_hub_client.h b/libs/vr/libbufferhub/include/private/dvr/buffer_hub_client.h
index 1186f93..a356959 100644
--- a/libs/vr/libbufferhub/include/private/dvr/buffer_hub_client.h
+++ b/libs/vr/libbufferhub/include/private/dvr/buffer_hub_client.h
@@ -94,6 +94,9 @@
int id() const { return id_; }
+ // Returns the buffer buffer state.
+ uint64_t buffer_state() { return buffer_state_->load(); };
+
// A state mask which is unique to a buffer hub client among all its siblings
// sharing the same concrete graphic buffer.
uint64_t buffer_state_bit() const { return buffer_state_bit_; }
diff --git a/libs/vr/libbufferhubqueue/Android.bp b/libs/vr/libbufferhubqueue/Android.bp
index 93ccd0f..feefe74 100644
--- a/libs/vr/libbufferhubqueue/Android.bp
+++ b/libs/vr/libbufferhubqueue/Android.bp
@@ -14,6 +14,7 @@
sourceFiles = [
"buffer_hub_queue_client.cpp",
+ "buffer_hub_queue_parcelable.cpp",
"buffer_hub_queue_producer.cpp",
]
diff --git a/libs/vr/libbufferhubqueue/buffer_hub_queue_client.cpp b/libs/vr/libbufferhubqueue/buffer_hub_queue_client.cpp
index 8bea0cd..a5cefd9 100644
--- a/libs/vr/libbufferhubqueue/buffer_hub_queue_client.cpp
+++ b/libs/vr/libbufferhubqueue/buffer_hub_queue_client.cpp
@@ -137,6 +137,28 @@
return status;
}
+pdx::Status<ConsumerQueueParcelable>
+BufferHubQueue::CreateConsumerQueueParcelable(bool silent) {
+ auto status = CreateConsumerQueueHandle(silent);
+ if (!status)
+ return status.error_status();
+
+ // A temporary consumer queue client to pull its channel parcelable.
+ auto consumer_queue =
+ std::unique_ptr<ConsumerQueue>(new ConsumerQueue(status.take()));
+ ConsumerQueueParcelable queue_parcelable(
+ consumer_queue->GetChannel()->TakeChannelParcelable());
+
+ if (!queue_parcelable.IsValid()) {
+ ALOGE(
+ "BufferHubQueue::CreateConsumerQueueParcelable: Failed to create "
+ "consumer queue parcelable.");
+ return ErrorStatus(EINVAL);
+ }
+
+ return {std::move(queue_parcelable)};
+}
+
bool BufferHubQueue::WaitForBuffers(int timeout) {
ATRACE_NAME("BufferHubQueue::WaitForBuffers");
std::array<epoll_event, kMaxEvents> events;
@@ -555,6 +577,25 @@
return {std::move(buffer)};
}
+pdx::Status<ProducerQueueParcelable> ProducerQueue::TakeAsParcelable() {
+ if (capacity() != 0) {
+ ALOGE(
+ "ProducerQueue::TakeAsParcelable: producer queue can only be taken out"
+ " as a parcelable when empty. Current queue capacity: %zu",
+ capacity());
+ return ErrorStatus(EINVAL);
+ }
+
+ std::unique_ptr<pdx::ClientChannel> channel = TakeChannel();
+ ProducerQueueParcelable queue_parcelable(channel->TakeChannelParcelable());
+
+ // Here the queue parcelable is returned and holds the underlying system
+ // resources backing the queue; while the original client channel of this
+ // producer queue is destroyed in place so that this client can no longer
+ // provide producer operations.
+ return {std::move(queue_parcelable)};
+}
+
ConsumerQueue::ConsumerQueue(LocalChannelHandle handle)
: BufferHubQueue(std::move(handle)) {
auto status = ImportQueue();
diff --git a/libs/vr/libbufferhubqueue/buffer_hub_queue_parcelable.cpp b/libs/vr/libbufferhubqueue/buffer_hub_queue_parcelable.cpp
new file mode 100644
index 0000000..2cd7c45
--- /dev/null
+++ b/libs/vr/libbufferhubqueue/buffer_hub_queue_parcelable.cpp
@@ -0,0 +1,82 @@
+#include "include/private/dvr/buffer_hub_queue_parcelable.h"
+
+#include <binder/Parcel.h>
+#include <pdx/default_transport/channel_parcelable.h>
+
+namespace android {
+namespace dvr {
+
+template <BufferHubQueueParcelableMagic Magic>
+bool BufferHubQueueParcelable<Magic>::IsValid() const {
+ return !!channel_parcelable_ && channel_parcelable_->IsValid();
+}
+
+template <BufferHubQueueParcelableMagic Magic>
+pdx::LocalChannelHandle BufferHubQueueParcelable<Magic>::TakeChannelHandle() {
+ if (!IsValid()) {
+ ALOGE(
+ "BufferHubQueueParcelable::TakeChannelHandle: Invalid channel parcel.");
+ return {}; // Returns an empty channel handle.
+ }
+
+ // Take channel handle out of the parcelable and reset the parcelable.
+ pdx::LocalChannelHandle handle = channel_parcelable_->TakeChannelHandle();
+ // Now channel_parcelable_ should already be invalid, but reset it to release
+ // the invalid parcelable object from unique_ptr.
+ channel_parcelable_ = nullptr;
+ return handle;
+}
+
+template <BufferHubQueueParcelableMagic Magic>
+status_t BufferHubQueueParcelable<Magic>::writeToParcel(Parcel* parcel) const {
+ if (!IsValid()) {
+ ALOGE("BufferHubQueueParcelable::writeToParcel: Invalid channel.");
+ return -EINVAL;
+ }
+
+ status_t res = parcel->writeUint32(Magic);
+ if (res != NO_ERROR) {
+ ALOGE("BufferHubQueueParcelable::writeToParcel: Cannot write magic.");
+ return res;
+ }
+
+ return channel_parcelable_->writeToParcel(parcel);
+}
+
+template <BufferHubQueueParcelableMagic Magic>
+status_t BufferHubQueueParcelable<Magic>::readFromParcel(const Parcel* parcel) {
+ if (IsValid()) {
+ ALOGE(
+ "BufferHubQueueParcelable::readFromParcel: This parcelable object has "
+ "been initialized already.");
+ return -EINVAL;
+ }
+
+ uint32_t out_magic = 0;
+ status_t res = NO_ERROR;
+
+ res = parcel->readUint32(&out_magic);
+ if (res != NO_ERROR)
+ return res;
+
+ if (out_magic != Magic) {
+ ALOGE(
+ "BufferHubQueueParcelable::readFromParcel: Unexpected magic: 0x%x, "
+ "epxected: 0x%x",
+ out_magic, Magic);
+ return -EINVAL;
+ }
+
+ // (Re)Alocate channel parcelable object.
+ channel_parcelable_ =
+ std::make_unique<pdx::default_transport::ChannelParcelable>();
+ return channel_parcelable_->readFromParcel(parcel);
+}
+
+template class BufferHubQueueParcelable<
+ BufferHubQueueParcelableMagic::Producer>;
+template class BufferHubQueueParcelable<
+ BufferHubQueueParcelableMagic::Consumer>;
+
+} // namespace dvr
+} // namespace android
diff --git a/libs/vr/libbufferhubqueue/include/private/dvr/buffer_hub_queue_client.h b/libs/vr/libbufferhubqueue/include/private/dvr/buffer_hub_queue_client.h
index 6962d6c..c8e31c7 100644
--- a/libs/vr/libbufferhubqueue/include/private/dvr/buffer_hub_queue_client.h
+++ b/libs/vr/libbufferhubqueue/include/private/dvr/buffer_hub_queue_client.h
@@ -6,6 +6,7 @@
#include <pdx/client.h>
#include <pdx/status.h>
#include <private/dvr/buffer_hub_client.h>
+#include <private/dvr/buffer_hub_queue_parcelable.h>
#include <private/dvr/bufferhub_rpc.h>
#include <private/dvr/epoll_file_descriptor.h>
#include <private/dvr/ring_buffer.h>
@@ -54,6 +55,11 @@
pdx::Status<pdx::LocalChannelHandle> CreateConsumerQueueHandle(
bool silent = false);
+ // Creates a new consumer in parcelable form for immediate transport over
+ // Binder.
+ pdx::Status<ConsumerQueueParcelable> CreateConsumerQueueParcelable(
+ bool silent = false);
+
// Returns the number of buffers avaiable for dequeue.
size_t count() const { return available_buffers_.size(); }
@@ -337,6 +343,11 @@
return BufferHubQueue::Enqueue({buffer, slot, index});
}
+ // Takes out the current producer queue as a binder parcelable object. Note
+ // that the queue must be empty to be exportable. After successful export, the
+ // producer queue client should no longer be used.
+ pdx::Status<ProducerQueueParcelable> TakeAsParcelable();
+
private:
friend BASE;
diff --git a/libs/vr/libbufferhubqueue/include/private/dvr/buffer_hub_queue_parcelable.h b/libs/vr/libbufferhubqueue/include/private/dvr/buffer_hub_queue_parcelable.h
new file mode 100644
index 0000000..89baf92
--- /dev/null
+++ b/libs/vr/libbufferhubqueue/include/private/dvr/buffer_hub_queue_parcelable.h
@@ -0,0 +1,60 @@
+#ifndef ANDROID_DVR_BUFFER_HUB_QUEUE_PARCELABLE_H_
+#define ANDROID_DVR_BUFFER_HUB_QUEUE_PARCELABLE_H_
+
+#include <pdx/channel_parcelable.h>
+
+namespace android {
+namespace dvr {
+
+enum BufferHubQueueParcelableMagic : uint32_t {
+ Producer = 0x62687170, // 'bhqp'
+ Consumer = 0x62687163, // 'bhqc'
+};
+
+template <BufferHubQueueParcelableMagic Magic>
+class BufferHubQueueParcelable : public Parcelable {
+ public:
+ BufferHubQueueParcelable() = default;
+
+ BufferHubQueueParcelable(BufferHubQueueParcelable&& other) = default;
+ BufferHubQueueParcelable& operator=(BufferHubQueueParcelable&& other) =
+ default;
+
+ // Constructs an parcelable contains the channel parcelable.
+ BufferHubQueueParcelable(
+ std::unique_ptr<pdx::ChannelParcelable> channel_parcelable)
+ : channel_parcelable_(std::move(channel_parcelable)) {}
+
+ BufferHubQueueParcelable(const BufferHubQueueParcelable&) = delete;
+ void operator=(const BufferHubQueueParcelable&) = delete;
+
+ bool IsValid() const;
+
+ // Returns a channel handle constructed from this parcelable object and takes
+ // the ownership of all resources from the parcelable object.
+ pdx::LocalChannelHandle TakeChannelHandle();
+
+ // Serializes the queue parcelable into the given parcel. Note that no system
+ // resources are getting duplicated, nor did the parcel takes ownership of the
+ // queue parcelable. Thus, the parcelable object must remain valid for the
+ // lifetime of the parcel.
+ status_t writeToParcel(Parcel* parcel) const override;
+
+ // Deserialize the queue parcelable from the given parcel. Note that system
+ // resources are duplicated from the parcel into the queue parcelable. Returns
+ // error if the targeting parcelable object is already valid.
+ status_t readFromParcel(const Parcel* parcel) override;
+
+ private:
+ std::unique_ptr<pdx::ChannelParcelable> channel_parcelable_;
+};
+
+using ProducerQueueParcelable =
+ BufferHubQueueParcelable<BufferHubQueueParcelableMagic::Producer>;
+using ConsumerQueueParcelable =
+ BufferHubQueueParcelable<BufferHubQueueParcelableMagic::Consumer>;
+
+} // namespace dvr
+} // namespace android
+
+#endif // ANDROID_DVR_BUFFER_HUB_QUEUE_PARCELABLE_H_
diff --git a/libs/vr/libbufferhubqueue/tests/Android.bp b/libs/vr/libbufferhubqueue/tests/Android.bp
index 8bd1ef1..5e4df84 100644
--- a/libs/vr/libbufferhubqueue/tests/Android.bp
+++ b/libs/vr/libbufferhubqueue/tests/Android.bp
@@ -12,6 +12,7 @@
"libhardware",
"libui",
"libutils",
+ "libnativewindow",
]
static_libraries = [
@@ -20,6 +21,7 @@
"libchrome",
"libdvrcommon",
"libpdx_default_transport",
+ "libperformance",
]
cc_test {
@@ -51,3 +53,17 @@
name: "buffer_hub_queue_producer-test",
tags: ["optional"],
}
+
+cc_benchmark {
+ srcs: ["buffer_transport_benchmark.cpp"],
+ static_libs: static_libraries,
+ shared_libs: shared_libraries,
+ header_libs: header_libraries,
+ cflags: [
+ "-DLOG_TAG=\"buffer_transport_benchmark\"",
+ "-DTRACE=0",
+ "-O2",
+ ],
+ name: "buffer_transport_benchmark",
+ tags: ["optional"],
+}
diff --git a/libs/vr/libbufferhubqueue/tests/buffer_hub_queue-test.cpp b/libs/vr/libbufferhubqueue/tests/buffer_hub_queue-test.cpp
index 8a72531..f67ef37 100644
--- a/libs/vr/libbufferhubqueue/tests/buffer_hub_queue-test.cpp
+++ b/libs/vr/libbufferhubqueue/tests/buffer_hub_queue-test.cpp
@@ -1,4 +1,5 @@
#include <base/logging.h>
+#include <binder/Parcel.h>
#include <private/dvr/buffer_hub_client.h>
#include <private/dvr/buffer_hub_queue_client.h>
@@ -14,6 +15,7 @@
namespace android {
namespace dvr {
+using pdx::LocalChannelHandle;
using pdx::LocalHandle;
namespace {
@@ -680,6 +682,156 @@
#undef CHECK_NO_BUFFER_THEN_ALLOCATE
}
+TEST_F(BufferHubQueueTest, TestProducerToParcelableNotEmpty) {
+ ASSERT_TRUE(CreateQueues(config_builder_.SetMetadata<uint64_t>().Build(),
+ UsagePolicy{}));
+
+ // Allocate only one buffer.
+ AllocateBuffer();
+
+ // Export should fail as the queue is not empty.
+ auto status = producer_queue_->TakeAsParcelable();
+ EXPECT_FALSE(status.ok());
+}
+
+TEST_F(BufferHubQueueTest, TestProducerExportToParcelable) {
+ ASSERT_TRUE(CreateQueues(config_builder_.Build(), UsagePolicy{}));
+
+ auto s1 = producer_queue_->TakeAsParcelable();
+ EXPECT_TRUE(s1.ok());
+
+ ProducerQueueParcelable output_parcelable = s1.take();
+ EXPECT_TRUE(output_parcelable.IsValid());
+
+ Parcel parcel;
+ status_t res;
+ res = output_parcelable.writeToParcel(&parcel);
+ EXPECT_EQ(res, NO_ERROR);
+
+ // After written into parcelable, the output_parcelable is still valid has
+ // keeps the producer channel alive.
+ EXPECT_TRUE(output_parcelable.IsValid());
+
+ // Creating producer buffer should fail.
+ auto s2 = producer_queue_->AllocateBuffer(kBufferWidth, kBufferHeight,
+ kBufferLayerCount, kBufferFormat,
+ kBufferUsage);
+ ASSERT_FALSE(s2.ok());
+
+ // Reset the data position so that we can read back from the same parcel
+ // without doing actually Binder IPC.
+ parcel.setDataPosition(0);
+ producer_queue_ = nullptr;
+
+ // Recreate the producer queue from the parcel.
+ ProducerQueueParcelable input_parcelable;
+ EXPECT_FALSE(input_parcelable.IsValid());
+
+ res = input_parcelable.readFromParcel(&parcel);
+ EXPECT_EQ(res, NO_ERROR);
+ EXPECT_TRUE(input_parcelable.IsValid());
+
+ EXPECT_EQ(producer_queue_, nullptr);
+ producer_queue_ = ProducerQueue::Import(input_parcelable.TakeChannelHandle());
+ EXPECT_FALSE(input_parcelable.IsValid());
+ ASSERT_NE(producer_queue_, nullptr);
+
+ // Newly created queue from the parcel can allocate buffer, post buffer to
+ // consumer.
+ EXPECT_NO_FATAL_FAILURE(AllocateBuffer());
+ EXPECT_EQ(producer_queue_->count(), 1U);
+ EXPECT_EQ(producer_queue_->capacity(), 1U);
+
+ size_t slot;
+ DvrNativeBufferMetadata producer_meta;
+ DvrNativeBufferMetadata consumer_meta;
+ LocalHandle fence;
+ auto s3 = producer_queue_->Dequeue(0, &slot, &producer_meta, &fence);
+ EXPECT_TRUE(s3.ok());
+
+ std::shared_ptr<BufferProducer> p1 = s3.take();
+ EXPECT_NE(p1, nullptr);
+
+ producer_meta.timestamp = 42;
+ EXPECT_EQ(p1->PostAsync(&producer_meta, LocalHandle()), 0);
+
+ // Make sure the buffer can be dequeued from consumer side.
+ auto s4 = consumer_queue_->Dequeue(100, &slot, &consumer_meta, &fence);
+ EXPECT_TRUE(s4.ok());
+ EXPECT_EQ(consumer_queue_->capacity(), 1U);
+
+ auto consumer = s4.take();
+ EXPECT_NE(consumer, nullptr);
+ EXPECT_EQ(producer_meta.timestamp, consumer_meta.timestamp);
+}
+
+TEST_F(BufferHubQueueTest, TestCreateConsumerParcelable) {
+ ASSERT_TRUE(CreateProducerQueue(config_builder_.Build(), UsagePolicy{}));
+
+ auto s1 = producer_queue_->CreateConsumerQueueParcelable();
+ EXPECT_TRUE(s1.ok());
+ ConsumerQueueParcelable output_parcelable = s1.take();
+ EXPECT_TRUE(output_parcelable.IsValid());
+
+ // Write to a Parcel new object.
+ Parcel parcel;
+ status_t res;
+ res = output_parcelable.writeToParcel(&parcel);
+
+ // Reset the data position so that we can read back from the same parcel
+ // without doing actually Binder IPC.
+ parcel.setDataPosition(0);
+
+ // No consumer queue created yet.
+ EXPECT_EQ(consumer_queue_, nullptr);
+
+ // If the parcel contains a consumer queue, read into a
+ // ProducerQueueParcelable should fail.
+ ProducerQueueParcelable wrongly_typed_parcelable;
+ EXPECT_FALSE(wrongly_typed_parcelable.IsValid());
+ res = wrongly_typed_parcelable.readFromParcel(&parcel);
+ EXPECT_EQ(res, -EINVAL);
+ parcel.setDataPosition(0);
+
+ // Create the consumer queue from the parcel.
+ ConsumerQueueParcelable input_parcelable;
+ EXPECT_FALSE(input_parcelable.IsValid());
+
+ res = input_parcelable.readFromParcel(&parcel);
+ EXPECT_EQ(res, NO_ERROR);
+ EXPECT_TRUE(input_parcelable.IsValid());
+
+ consumer_queue_ = ConsumerQueue::Import(input_parcelable.TakeChannelHandle());
+ EXPECT_FALSE(input_parcelable.IsValid());
+ ASSERT_NE(consumer_queue_, nullptr);
+
+ EXPECT_NO_FATAL_FAILURE(AllocateBuffer());
+ EXPECT_EQ(producer_queue_->count(), 1U);
+ EXPECT_EQ(producer_queue_->capacity(), 1U);
+
+ size_t slot;
+ DvrNativeBufferMetadata producer_meta;
+ DvrNativeBufferMetadata consumer_meta;
+ LocalHandle fence;
+ auto s2 = producer_queue_->Dequeue(0, &slot, &producer_meta, &fence);
+ EXPECT_TRUE(s2.ok());
+
+ std::shared_ptr<BufferProducer> p1 = s2.take();
+ EXPECT_NE(p1, nullptr);
+
+ producer_meta.timestamp = 42;
+ EXPECT_EQ(p1->PostAsync(&producer_meta, LocalHandle()), 0);
+
+ // Make sure the buffer can be dequeued from consumer side.
+ auto s3 = consumer_queue_->Dequeue(100, &slot, &consumer_meta, &fence);
+ EXPECT_TRUE(s3.ok());
+ EXPECT_EQ(consumer_queue_->capacity(), 1U);
+
+ auto consumer = s3.take();
+ EXPECT_NE(consumer, nullptr);
+ EXPECT_EQ(producer_meta.timestamp, consumer_meta.timestamp);
+}
+
} // namespace
} // namespace dvr
diff --git a/libs/vr/libbufferhubqueue/tests/buffer_transport_benchmark.cpp b/libs/vr/libbufferhubqueue/tests/buffer_transport_benchmark.cpp
new file mode 100644
index 0000000..658b496
--- /dev/null
+++ b/libs/vr/libbufferhubqueue/tests/buffer_transport_benchmark.cpp
@@ -0,0 +1,539 @@
+#include <android/native_window.h>
+#include <android-base/logging.h>
+#include <benchmark/benchmark.h>
+#include <binder/IPCThreadState.h>
+#include <binder/IServiceManager.h>
+#include <dvr/dvr_api.h>
+#include <dvr/performance_client_api.h>
+#include <gui/BufferItem.h>
+#include <gui/BufferItemConsumer.h>
+#include <gui/Surface.h>
+#include <private/dvr/buffer_hub_queue_producer.h>
+#include <utils/Trace.h>
+
+#include <chrono>
+#include <functional>
+#include <iostream>
+#include <thread>
+#include <vector>
+
+#include <poll.h>
+#include <sys/wait.h>
+
+// Use ALWAYS at the tag level. Control is performed manually during command
+// line processing.
+#ifdef ATRACE_TAG
+#undef ATRACE_TAG
+#endif
+#define ATRACE_TAG ATRACE_TAG_ALWAYS
+
+using namespace android;
+using namespace android::dvr;
+using ::benchmark::State;
+
+static const String16 kBinderService = String16("bufferTransport");
+static const uint32_t kBufferWidth = 100;
+static const uint32_t kBufferHeight = 1;
+static const uint32_t kBufferLayerCount = 1;
+static const uint32_t kBufferFormat = HAL_PIXEL_FORMAT_BLOB;
+static const uint64_t kBufferUsage =
+ GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN;
+static const int kMaxAcquiredImages = 1;
+static const int kQueueDepth = 2; // We are double buffering for this test.
+static const size_t kMaxQueueCounts = 128;
+
+enum BufferTransportServiceCode {
+ CREATE_BUFFER_QUEUE = IBinder::FIRST_CALL_TRANSACTION,
+};
+
+// A binder services that minics a compositor that consumes buffers. It provides
+// one Binder interface to create a new Surface for buffer producer to write
+// into; while itself will carry out no-op buffer consuming by acquiring then
+// releasing the buffer immediately.
+class BufferTransportService : public BBinder {
+ public:
+ BufferTransportService() = default;
+ ~BufferTransportService() = default;
+
+ virtual status_t onTransact(uint32_t code, const Parcel& data, Parcel* reply,
+ uint32_t flags = 0) {
+ (void)flags;
+ (void)data;
+ switch (code) {
+ case CREATE_BUFFER_QUEUE: {
+ auto new_queue = std::make_shared<BufferQueueHolder>(this);
+ reply->writeStrongBinder(
+ IGraphicBufferProducer::asBinder(new_queue->producer_));
+ buffer_queues_.push_back(new_queue);
+ return NO_ERROR;
+ }
+ default:
+ return UNKNOWN_TRANSACTION;
+ };
+ }
+
+ private:
+ struct FrameListener : public ConsumerBase::FrameAvailableListener {
+ public:
+ FrameListener(BufferTransportService* service,
+ sp<BufferItemConsumer> buffer_item_consumer)
+ : service_(service),
+ buffer_item_consumer_(buffer_item_consumer) {}
+
+ void onFrameAvailable(const BufferItem& /*item*/) override {
+ BufferItem buffer;
+ status_t ret = 0;
+ {
+ ATRACE_NAME("AcquireBuffer");
+ ret = buffer_item_consumer_->acquireBuffer(&buffer, /*presentWhen=*/0,
+ /*waitForFence=*/false);
+ }
+
+ if (ret != NO_ERROR) {
+ LOG(ERROR) << "Failed to acquire next buffer.";
+ return;
+ }
+
+ {
+ ATRACE_NAME("ReleaseBuffer");
+ ret = buffer_item_consumer_->releaseBuffer(buffer);
+ }
+
+ if (ret != NO_ERROR) {
+ LOG(ERROR) << "Failed to release buffer.";
+ return;
+ }
+ }
+
+ private:
+ BufferTransportService* service_ = nullptr;
+ sp<BufferItemConsumer> buffer_item_consumer_;
+ };
+
+ struct BufferQueueHolder {
+ explicit BufferQueueHolder(BufferTransportService* service) {
+ BufferQueue::createBufferQueue(&producer_, &consumer_);
+
+ sp<BufferItemConsumer> buffer_item_consumer =
+ new BufferItemConsumer(consumer_, kBufferUsage, kMaxAcquiredImages,
+ /*controlledByApp=*/true);
+ buffer_item_consumer->setName(String8("BinderBufferTransport"));
+ frame_listener_ = new FrameListener(service, buffer_item_consumer);
+ buffer_item_consumer->setFrameAvailableListener(frame_listener_);
+ }
+
+ sp<IGraphicBufferProducer> producer_;
+ sp<IGraphicBufferConsumer> consumer_;
+ sp<FrameListener> frame_listener_;
+ };
+
+ std::vector<std::shared_ptr<BufferQueueHolder>> buffer_queues_;
+};
+
+// A virtual interfaces that abstracts the common BufferQueue operations, so
+// that the test suite can use the same test case to drive different types of
+// transport backends.
+class BufferTransport {
+ public:
+ virtual ~BufferTransport() {}
+
+ virtual int Start() = 0;
+ virtual sp<Surface> CreateSurface() = 0;
+};
+
+// Binder-based buffer transport backend.
+//
+// On Start() a new process will be swapned to run a Binder server that
+// actually consumes the buffer.
+// On CreateSurface() a new Binder BufferQueue will be created, which the
+// service holds the concrete binder node of the IGraphicBufferProducer while
+// sending the binder proxy to the client. In another word, the producer side
+// operations are carried out process while the consumer side operations are
+// carried out within the BufferTransportService's own process.
+class BinderBufferTransport : public BufferTransport {
+ public:
+ BinderBufferTransport() {}
+
+ int Start() override {
+ sp<IServiceManager> sm = defaultServiceManager();
+ service_ = sm->getService(kBinderService);
+ if (service_ == nullptr) {
+ LOG(ERROR) << "Failed to get the benchmark service.";
+ return -EIO;
+ }
+
+ LOG(INFO) << "Binder server is ready for client.";
+ return 0;
+ }
+
+ sp<Surface> CreateSurface() override {
+ Parcel data;
+ Parcel reply;
+ int error = service_->transact(CREATE_BUFFER_QUEUE, data, &reply);
+ if (error != NO_ERROR) {
+ LOG(ERROR) << "Failed to get buffer queue over binder.";
+ return nullptr;
+ }
+
+ sp<IBinder> binder;
+ error = reply.readNullableStrongBinder(&binder);
+ if (error != NO_ERROR) {
+ LOG(ERROR) << "Failed to get IGraphicBufferProducer over binder.";
+ return nullptr;
+ }
+
+ auto producer = interface_cast<IGraphicBufferProducer>(binder);
+ if (producer == nullptr) {
+ LOG(ERROR) << "Failed to get IGraphicBufferProducer over binder.";
+ return nullptr;
+ }
+
+ sp<Surface> surface = new Surface(producer, /*controlledByApp=*/true);
+
+ // Set buffer dimension.
+ ANativeWindow* window = static_cast<ANativeWindow*>(surface.get());
+ ANativeWindow_setBuffersGeometry(window, kBufferWidth, kBufferHeight,
+ kBufferFormat);
+
+ return surface;
+ }
+
+ private:
+ sp<IBinder> service_;
+};
+
+// BufferHub/PDX-based buffer transport.
+//
+// On Start() a new thread will be swapned to run an epoll polling thread which
+// minics the behavior of a compositor. Similar to Binder-based backend, the
+// buffer available handler is also a no-op: Buffer gets acquired and released
+// immediately.
+// On CreateSurface() a pair of dvr::ProducerQueue and dvr::ConsumerQueue will
+// be created. The epoll thread holds on the consumer queue and dequeues buffer
+// from it; while the producer queue will be wrapped in a Surface and returned
+// to test suite.
+class BufferHubTransport : public BufferTransport {
+ public:
+ virtual ~BufferHubTransport() {
+ stopped_.store(true);
+ if (reader_thread_.joinable()) {
+ reader_thread_.join();
+ }
+ }
+
+ int Start() override {
+ int ret = epoll_fd_.Create();
+ if (ret < 0) {
+ LOG(ERROR) << "Failed to create epoll fd: %s", strerror(-ret);
+ return -1;
+ }
+
+ // Create the reader thread.
+ reader_thread_ = std::thread([this]() {
+ int ret = dvrSetSchedulerClass(0, "graphics");
+ if (ret < 0) {
+ LOG(ERROR) << "Failed to set thread priority";
+ return;
+ }
+
+
+ ret = dvrSetCpuPartition(0, "/system/performance");
+ if (ret < 0) {
+ LOG(ERROR) << "Failed to set thread cpu partition";
+ return;
+ }
+
+ stopped_.store(false);
+ LOG(INFO) << "Reader Thread Running...";
+
+ while (!stopped_.load()) {
+ std::array<epoll_event, kMaxQueueCounts> events;
+
+ // Don't sleep forever so that we will have a chance to wake up.
+ const int ret = epoll_fd_.Wait(events.data(), events.size(),
+ /*timeout=*/100);
+ if (ret < 0) {
+ LOG(ERROR) << "Error polling consumer queues.";
+ continue;
+ }
+ if (ret == 0) {
+ continue;
+ }
+
+ const int num_events = ret;
+ for (int i = 0; i < num_events; i++) {
+ uint32_t surface_index = events[i].data.u32;
+ buffer_queues_[surface_index]->consumer_queue_->HandleQueueEvents();
+ }
+ }
+
+ LOG(INFO) << "Reader Thread Exiting...";
+ });
+
+ return 0;
+ }
+
+ sp<Surface> CreateSurface() override {
+ auto new_queue = std::make_shared<BufferQueueHolder>();
+ if (new_queue->producer_ == nullptr) {
+ LOG(ERROR) << "Failed to create buffer producer.";
+ return nullptr;
+ }
+
+ sp<Surface> surface =
+ new Surface(new_queue->producer_, /*controlledByApp=*/true);
+
+ // Set buffer dimension.
+ ANativeWindow* window = static_cast<ANativeWindow*>(surface.get());
+ ANativeWindow_setBuffersGeometry(window, kBufferWidth, kBufferHeight,
+ kBufferFormat);
+
+ // Use the next position as buffer_queue index.
+ uint32_t index = buffer_queues_.size();
+ epoll_event event = {.events = EPOLLIN | EPOLLET, .data = {.u32 = index}};
+ const int ret = epoll_fd_.Control(
+ EPOLL_CTL_ADD, new_queue->consumer_queue_->queue_fd(), &event);
+ if (ret < 0) {
+ LOG(ERROR) << "Failed to track consumer queue: " << strerror(-ret)
+ << ", consumer queue fd: "
+ << new_queue->consumer_queue_->queue_fd();
+ return nullptr;
+ }
+
+ new_queue->queue_index_ = index;
+ buffer_queues_.push_back(new_queue);
+ return surface;
+ }
+
+ private:
+ struct BufferQueueHolder {
+ BufferQueueHolder() {
+ ProducerQueueConfigBuilder config_builder;
+ producer_queue_ =
+ ProducerQueue::Create(config_builder.SetDefaultWidth(kBufferWidth)
+ .SetDefaultHeight(kBufferHeight)
+ .SetDefaultFormat(kBufferFormat)
+ .SetMetadata<DvrNativeBufferMetadata>()
+ .Build(),
+ UsagePolicy{});
+ consumer_queue_ = producer_queue_->CreateConsumerQueue();
+ consumer_queue_->SetBufferAvailableCallback([this]() {
+ size_t index = 0;
+ pdx::LocalHandle fence;
+ DvrNativeBufferMetadata meta;
+ pdx::Status<std::shared_ptr<BufferConsumer>> status;
+
+ {
+ ATRACE_NAME("AcquireBuffer");
+ status = consumer_queue_->Dequeue(0, &index, &meta, &fence);
+ }
+ if (!status.ok()) {
+ LOG(ERROR) << "Failed to dequeue consumer buffer, error: "
+ << status.GetErrorMessage().c_str();
+ return;
+ }
+
+ auto buffer = status.take();
+
+ if (buffer) {
+ ATRACE_NAME("ReleaseBuffer");
+ buffer->ReleaseAsync();
+ }
+ });
+
+ producer_ = BufferHubQueueProducer::Create(producer_queue_);
+ }
+
+ int count_ = 0;
+ int queue_index_;
+ std::shared_ptr<ProducerQueue> producer_queue_;
+ std::shared_ptr<ConsumerQueue> consumer_queue_;
+ sp<IGraphicBufferProducer> producer_;
+ };
+
+ std::atomic<bool> stopped_;
+ std::thread reader_thread_;
+
+ EpollFileDescriptor epoll_fd_;
+ std::vector<std::shared_ptr<BufferQueueHolder>> buffer_queues_;
+};
+
+enum TransportType {
+ kBinderBufferTransport,
+ kBufferHubTransport,
+};
+
+// Main test suite, which supports two transport backend: 1) BinderBufferQueue,
+// 2) BufferHubQueue. The test case drives the producer end of both transport
+// backend by queuing buffers into the buffer queue by using ANativeWindow API.
+class BufferTransportBenchmark : public ::benchmark::Fixture {
+ public:
+ void SetUp(State& state) override {
+ if (state.thread_index == 0) {
+ const int transport = state.range(0);
+ switch (transport) {
+ case kBinderBufferTransport:
+ transport_.reset(new BinderBufferTransport);
+ break;
+ case kBufferHubTransport:
+ transport_.reset(new BufferHubTransport);
+ break;
+ default:
+ CHECK(false) << "Unknown test case.";
+ break;
+ }
+
+ CHECK(transport_);
+ const int ret = transport_->Start();
+ CHECK_EQ(ret, 0);
+
+ LOG(INFO) << "Transport backend running, transport=" << transport << ".";
+
+ // Create surfaces for each thread.
+ surfaces_.resize(state.threads);
+ for (int i = 0; i < state.threads; i++) {
+ // Common setup every thread needs.
+ surfaces_[i] = transport_->CreateSurface();
+ CHECK(surfaces_[i]);
+
+ LOG(INFO) << "Surface initialized on thread " << i << ".";
+ }
+ }
+ }
+
+ void TearDown(State& state) override {
+ if (state.thread_index == 0) {
+ surfaces_.clear();
+ transport_.reset();
+ LOG(INFO) << "Tear down benchmark.";
+ }
+ }
+
+ protected:
+ std::unique_ptr<BufferTransport> transport_;
+ std::vector<sp<Surface>> surfaces_;
+};
+
+BENCHMARK_DEFINE_F(BufferTransportBenchmark, Producers)(State& state) {
+ ANativeWindow* window = nullptr;
+ ANativeWindow_Buffer buffer;
+ int32_t error = 0;
+ double total_gain_buffer_us = 0;
+ double total_post_buffer_us = 0;
+ int iterations = 0;
+
+ while (state.KeepRunning()) {
+ if (window == nullptr) {
+ CHECK(surfaces_[state.thread_index]);
+ window = static_cast<ANativeWindow*>(surfaces_[state.thread_index].get());
+
+ // Lock buffers a couple time from the queue, so that we have the buffer
+ // allocated.
+ for (int i = 0; i < kQueueDepth; i++) {
+ error = ANativeWindow_lock(window, &buffer,
+ /*inOutDirtyBounds=*/nullptr);
+ CHECK_EQ(error, 0);
+ error = ANativeWindow_unlockAndPost(window);
+ CHECK_EQ(error, 0);
+ }
+ }
+
+ {
+ ATRACE_NAME("GainBuffer");
+ auto t1 = std::chrono::high_resolution_clock::now();
+ error = ANativeWindow_lock(window, &buffer,
+ /*inOutDirtyBounds=*/nullptr);
+ auto t2 = std::chrono::high_resolution_clock::now();
+ std::chrono::duration<double, std::micro> delta_us = t2 - t1;
+ total_gain_buffer_us += delta_us.count();
+ }
+ CHECK_EQ(error, 0);
+
+ {
+ ATRACE_NAME("PostBuffer");
+ auto t1 = std::chrono::high_resolution_clock::now();
+ error = ANativeWindow_unlockAndPost(window);
+ auto t2 = std::chrono::high_resolution_clock::now();
+ std::chrono::duration<double, std::micro> delta_us = t2 - t1;
+ total_post_buffer_us += delta_us.count();
+ }
+ CHECK_EQ(error, 0);
+
+ iterations++;
+ }
+
+ state.counters["gain_buffer_us"] = ::benchmark::Counter(
+ total_gain_buffer_us / iterations, ::benchmark::Counter::kAvgThreads);
+ state.counters["post_buffer_us"] = ::benchmark::Counter(
+ total_post_buffer_us / iterations, ::benchmark::Counter::kAvgThreads);
+ state.counters["producer_us"] = ::benchmark::Counter(
+ (total_gain_buffer_us + total_post_buffer_us) / iterations,
+ ::benchmark::Counter::kAvgThreads);
+}
+
+BENCHMARK_REGISTER_F(BufferTransportBenchmark, Producers)
+ ->Unit(::benchmark::kMicrosecond)
+ ->Ranges({{kBinderBufferTransport, kBufferHubTransport}})
+ ->ThreadRange(1, 32);
+
+static void runBinderServer() {
+ ProcessState::self()->setThreadPoolMaxThreadCount(0);
+ ProcessState::self()->startThreadPool();
+
+ sp<IServiceManager> sm = defaultServiceManager();
+ sp<BufferTransportService> service = new BufferTransportService;
+ sm->addService(kBinderService, service, false);
+
+ LOG(INFO) << "Binder server running...";
+
+ while (true) {
+ int stat, retval;
+ retval = wait(&stat);
+ if (retval == -1 && errno == ECHILD) {
+ break;
+ }
+ }
+
+ LOG(INFO) << "Service Exiting...";
+}
+
+// To run binder-based benchmark, use:
+// adb shell buffer_transport_benchmark \
+// --benchmark_filter="BufferTransportBenchmark/ContinuousLoad/0/"
+//
+// To run bufferhub-based benchmark, use:
+// adb shell buffer_transport_benchmark \
+// --benchmark_filter="BufferTransportBenchmark/ContinuousLoad/1/"
+int main(int argc, char** argv) {
+ bool tracing_enabled = false;
+
+ // Parse arguments in addition to "--benchmark_filter" paramters.
+ for (int i = 1; i < argc; i++) {
+ if (std::string(argv[i]) == "--help") {
+ std::cout << "Usage: binderThroughputTest [OPTIONS]" << std::endl;
+ std::cout << "\t--trace: Enable systrace logging."
+ << std::endl;
+ return 0;
+ }
+ if (std::string(argv[i]) == "--trace") {
+ tracing_enabled = true;
+ continue;
+ }
+ }
+
+ // Setup ATRACE/systrace based on command line.
+ atrace_setup();
+ atrace_set_tracing_enabled(tracing_enabled);
+
+ pid_t pid = fork();
+ if (pid == 0) {
+ // parent, i.e. the client side.
+ ProcessState::self()->startThreadPool();
+
+ ::benchmark::Initialize(&argc, argv);
+ ::benchmark::RunSpecifiedBenchmarks();
+ } else {
+ LOG(INFO) << "Benchmark process pid: " << pid;
+ runBinderServer();
+ }
+}
diff --git a/libs/vr/libdisplay/Android.bp b/libs/vr/libdisplay/Android.bp
index e3ab7fa..684dff1 100644
--- a/libs/vr/libdisplay/Android.bp
+++ b/libs/vr/libdisplay/Android.bp
@@ -26,6 +26,7 @@
sharedLibraries = [
"libbase",
+ "libbinder",
"libcutils",
"liblog",
"libutils",
diff --git a/libs/vr/libpdx/private/pdx/channel_parcelable.h b/libs/vr/libpdx/private/pdx/channel_parcelable.h
new file mode 100644
index 0000000..59ef9d3
--- /dev/null
+++ b/libs/vr/libpdx/private/pdx/channel_parcelable.h
@@ -0,0 +1,31 @@
+#ifndef ANDROID_PDX_CHANNEL_PARCELABLE_H_
+#define ANDROID_PDX_CHANNEL_PARCELABLE_H_
+
+#include <binder/Parcelable.h>
+#include <pdx/channel_handle.h>
+
+namespace android {
+namespace pdx {
+
+/**
+ * A parcelable object holds all necessary objects to recreate a ClientChannel.
+ * In addition to the android::Parcelable interface, this interface exposees
+ * more PDX-related interface.
+ */
+class ChannelParcelable : public Parcelable {
+ public:
+ virtual ~ChannelParcelable() = default;
+
+ // Returns whether the parcelable object holds a valid client channel.
+ virtual bool IsValid() const = 0;
+
+ // Returns a channel handle constructed from this parcelable object and takes
+ // the ownership of all resources from the parcelable object. In another word,
+ // the parcelable object will become invalid after TakeChannelHandle returns.
+ virtual LocalChannelHandle TakeChannelHandle() = 0;
+};
+
+} // namespace pdx
+} // namespace android
+
+#endif // ANDROID_PDX_CHANNEL_PARCELABLE_H_
diff --git a/libs/vr/libpdx/private/pdx/client_channel.h b/libs/vr/libpdx/private/pdx/client_channel.h
index 10a49bb..8f5fdfe 100644
--- a/libs/vr/libpdx/private/pdx/client_channel.h
+++ b/libs/vr/libpdx/private/pdx/client_channel.h
@@ -4,6 +4,7 @@
#include <vector>
#include <pdx/channel_handle.h>
+#include <pdx/channel_parcelable.h>
#include <pdx/file_handle.h>
#include <pdx/status.h>
@@ -61,6 +62,11 @@
LocalHandle* handle) const = 0;
virtual bool GetChannelHandle(void* transaction_state, ChannelReference ref,
LocalChannelHandle* handle) const = 0;
+
+ // Returns the internal state of the channel as a parcelable object. The
+ // ClientChannel is invalidated however, the channel is kept alive by the
+ // parcelable object and may be transferred to another process.
+ virtual std::unique_ptr<ChannelParcelable> TakeChannelParcelable() = 0;
};
} // namespace pdx
diff --git a/libs/vr/libpdx/private/pdx/mock_client_channel.h b/libs/vr/libpdx/private/pdx/mock_client_channel.h
index 49e0682..ecc20b3 100644
--- a/libs/vr/libpdx/private/pdx/mock_client_channel.h
+++ b/libs/vr/libpdx/private/pdx/mock_client_channel.h
@@ -49,6 +49,7 @@
MOCK_CONST_METHOD3(GetChannelHandle,
bool(void* transaction_state, ChannelReference ref,
LocalChannelHandle* handle));
+ MOCK_METHOD0(TakeChannelParcelable, std::unique_ptr<ChannelParcelable>());
};
} // namespace pdx
diff --git a/libs/vr/libpdx_default_transport/Android.bp b/libs/vr/libpdx_default_transport/Android.bp
index f891c59..cda3c95 100644
--- a/libs/vr/libpdx_default_transport/Android.bp
+++ b/libs/vr/libpdx_default_transport/Android.bp
@@ -42,6 +42,7 @@
"pdx_tool.cpp",
],
shared_libs: [
+ "libbinder",
"libcutils",
"liblog",
],
@@ -59,6 +60,7 @@
],
shared_libs: [
"libbase",
+ "libbinder",
"libchrome",
"libcutils",
"liblog",
diff --git a/libs/vr/libpdx_default_transport/private/servicefs/pdx/default_transport/channel_parcelable.h b/libs/vr/libpdx_default_transport/private/servicefs/pdx/default_transport/channel_parcelable.h
new file mode 100644
index 0000000..a8623b2
--- /dev/null
+++ b/libs/vr/libpdx_default_transport/private/servicefs/pdx/default_transport/channel_parcelable.h
@@ -0,0 +1,17 @@
+#ifndef ANDROID_PDX_DEFAULT_TRANSPORT_SERVICEFS_CHANNEL_PARCELABLE_H_
+#define ANDROID_PDX_DEFAULT_TRANSPORT_SERVICEFS_CHANNEL_PARCELABLE_H_
+
+#include <servicefs/channel_parcelable.h>
+
+namespace android {
+namespace pdx {
+namespace default_transport {
+
+using ChannelParcelable = ::android::pdx::servicefs::ChannelParcelable;
+
+} // namespace default_transport
+} // namespace pdx
+} // namespace android
+
+
+#endif // ANDROID_PDX_DEFAULT_TRANSPORT_SERVICEFS_CHANNEL_PARCELABLE_H_
diff --git a/libs/vr/libpdx_default_transport/private/uds/pdx/default_transport/channel_parcelable.h b/libs/vr/libpdx_default_transport/private/uds/pdx/default_transport/channel_parcelable.h
new file mode 100644
index 0000000..bcd74e6
--- /dev/null
+++ b/libs/vr/libpdx_default_transport/private/uds/pdx/default_transport/channel_parcelable.h
@@ -0,0 +1,17 @@
+#ifndef ANDROID_PDX_DEFAULT_TRANSPORT_UDS_CHANNEL_PARCELABLE_H_
+#define ANDROID_PDX_DEFAULT_TRANSPORT_UDS_CHANNEL_PARCELABLE_H_
+
+#include <uds/channel_parcelable.h>
+
+namespace android {
+namespace pdx {
+namespace default_transport {
+
+using ChannelParcelable = ::android::pdx::uds::ChannelParcelable;
+
+} // namespace default_transport
+} // namespace pdx
+} // namespace android
+
+
+#endif // ANDROID_PDX_DEFAULT_TRANSPORT_UDS_CHANNEL_PARCELABLE_H_
diff --git a/libs/vr/libpdx_uds/Android.bp b/libs/vr/libpdx_uds/Android.bp
index d0b7cab..d640950 100644
--- a/libs/vr/libpdx_uds/Android.bp
+++ b/libs/vr/libpdx_uds/Android.bp
@@ -13,6 +13,7 @@
srcs: [
"channel_event_set.cpp",
"channel_manager.cpp",
+ "channel_parcelable.cpp",
"client_channel_factory.cpp",
"client_channel.cpp",
"ipc_helper.cpp",
@@ -23,6 +24,9 @@
"libbase",
"libpdx",
],
+ shared_libs: [
+ "libbinder",
+ ],
whole_static_libs: [
"libselinux",
],
@@ -52,5 +56,6 @@
"libcutils",
"liblog",
"libutils",
+ "libbinder",
],
}
diff --git a/libs/vr/libpdx_uds/channel_parcelable.cpp b/libs/vr/libpdx_uds/channel_parcelable.cpp
new file mode 100644
index 0000000..e7bce27
--- /dev/null
+++ b/libs/vr/libpdx_uds/channel_parcelable.cpp
@@ -0,0 +1,125 @@
+#include "uds/channel_parcelable.h"
+
+#include <binder/Parcel.h>
+#include <uds/channel_manager.h>
+
+namespace android {
+namespace pdx {
+namespace uds {
+
+namespace {
+
+static constexpr uint32_t kUdsMagicParcelHeader = 0x7564736d; // 'udsm'.
+
+} // namespace
+
+ChannelParcelable::ChannelParcelable(LocalHandle data_fd,
+ LocalHandle pollin_event_fd,
+ LocalHandle pollhup_event_fd)
+ : data_fd_{std::move(data_fd)},
+ pollin_event_fd_{std::move(pollin_event_fd)},
+ pollhup_event_fd_{std::move(pollhup_event_fd)} {}
+
+bool ChannelParcelable::IsValid() const {
+ return !!data_fd_ && !!pollin_event_fd_ && !!pollhup_event_fd_;
+}
+
+LocalChannelHandle ChannelParcelable::TakeChannelHandle() {
+ if (!IsValid()) {
+ ALOGE("ChannelParcelable::TakeChannelHandle: Invalid channel parcel.");
+ return {}; // Returns an empty channel handle.
+ }
+
+ return ChannelManager::Get().CreateHandle(std::move(data_fd_),
+ std::move(pollin_event_fd_),
+ std::move(pollhup_event_fd_));
+}
+
+status_t ChannelParcelable::writeToParcel(Parcel* parcel) const {
+ status_t res = NO_ERROR;
+
+ if (!IsValid()) {
+ ALOGE("ChannelParcelable::writeToParcel: Invalid channel parcel.");
+ return BAD_VALUE;
+ }
+
+ res = parcel->writeUint32(kUdsMagicParcelHeader);
+ if (res != NO_ERROR) {
+ ALOGE("ChannelParcelable::writeToParcel: Cannot write magic: res=%d.", res);
+ return res;
+ }
+
+ res = parcel->writeFileDescriptor(data_fd_.Get());
+ if (res != NO_ERROR) {
+ ALOGE("ChannelParcelable::writeToParcel: Cannot write data fd: res=%d.",
+ res);
+ return res;
+ }
+
+ res = parcel->writeFileDescriptor(pollin_event_fd_.Get());
+ if (res != NO_ERROR) {
+ ALOGE(
+ "ChannelParcelable::writeToParcel: Cannot write pollin event fd: "
+ "res=%d.",
+ res);
+ return res;
+ }
+
+ res = parcel->writeFileDescriptor(pollhup_event_fd_.Get());
+ if (res != NO_ERROR) {
+ ALOGE(
+ "ChannelParcelable::writeToParcel: Cannot write pollhup event fd: "
+ "res=%d.",
+ res);
+ return res;
+ }
+
+ return res;
+}
+
+status_t ChannelParcelable::readFromParcel(const Parcel* parcel) {
+ uint32_t magic = 0;
+ status_t res = NO_ERROR;
+
+ if (IsValid()) {
+ ALOGE(
+ "ChannelParcelable::readFromParcel: This channel parcel is already "
+ "initailzied.");
+ return ALREADY_EXISTS;
+ }
+
+ res = parcel->readUint32(&magic);
+ if (res != NO_ERROR) {
+ ALOGE("ChannelParcelable::readFromParcel: Failed to read magic: res=%d.",
+ res);
+ return res;
+ }
+
+ if (magic != kUdsMagicParcelHeader) {
+ ALOGE(
+ "ChannelParcelable::readFromParcel: Unknown magic: 0x%x, epxected: "
+ "0x%x",
+ magic, kUdsMagicParcelHeader);
+ return BAD_VALUE;
+ }
+
+ // TODO(b/69010509): We have to dup() the FD from android::Parcel as it
+ // doesn't support taking out the FD's ownership. We can remove the dup() here
+ // once android::Parcel support such operation.
+ data_fd_.Reset(dup(parcel->readFileDescriptor()));
+ pollin_event_fd_.Reset(dup(parcel->readFileDescriptor()));
+ pollhup_event_fd_.Reset(dup(parcel->readFileDescriptor()));
+ if (!IsValid()) {
+ ALOGE(
+ "ChannelParcelable::readFromParcel: Cannot read fd from parcel: "
+ "data_fd=%d, pollin_event_fd=%d, pollhup_event_fd=%d.",
+ data_fd_.Get(), pollin_event_fd_.Get(), pollhup_event_fd_.Get());
+ return DEAD_OBJECT;
+ }
+
+ return res;
+}
+
+} // namespace uds
+} // namespace pdx
+} // namespace android
diff --git a/libs/vr/libpdx_uds/client_channel.cpp b/libs/vr/libpdx_uds/client_channel.cpp
index 2e9c1de..6073c3c 100644
--- a/libs/vr/libpdx_uds/client_channel.cpp
+++ b/libs/vr/libpdx_uds/client_channel.cpp
@@ -1,3 +1,4 @@
+#include "uds/channel_parcelable.h"
#include "uds/client_channel.h"
#include <errno.h>
@@ -292,6 +293,29 @@
return state->GetLocalChannelHandle(ref, handle);
}
+std::unique_ptr<pdx::ChannelParcelable> ClientChannel::TakeChannelParcelable()
+ {
+ if (!channel_handle_)
+ return nullptr;
+
+ if (auto* channel_data =
+ ChannelManager::Get().GetChannelData(channel_handle_.value())) {
+ auto fds = channel_data->TakeFds();
+ auto parcelable = std::make_unique<ChannelParcelable>(
+ std::move(std::get<0>(fds)), std::move(std::get<1>(fds)),
+ std::move(std::get<2>(fds)));
+
+ // Here we need to explicitly close the channel handle so that the channel
+ // won't get shutdown in the destructor, while the FDs in ChannelParcelable
+ // can keep the channel alive so that new client can be created from it
+ // later.
+ channel_handle_.Close();
+ return parcelable;
+ } else {
+ return nullptr;
+ }
+}
+
} // namespace uds
} // namespace pdx
} // namespace android
diff --git a/libs/vr/libpdx_uds/private/uds/channel_event_set.h b/libs/vr/libpdx_uds/private/uds/channel_event_set.h
index 99e7502..e960740 100644
--- a/libs/vr/libpdx_uds/private/uds/channel_event_set.h
+++ b/libs/vr/libpdx_uds/private/uds/channel_event_set.h
@@ -54,6 +54,14 @@
BorrowedHandle pollhup_event_fd() const { return pollhup_event_fd_.Borrow(); }
BorrowedHandle data_fd() const { return data_fd_.Borrow(); }
+ // Moves file descriptors out of ChannelEventReceiver. Note these operations
+ // immediately invalidates the receiver.
+ std::tuple<LocalHandle, LocalHandle, LocalHandle> TakeFds() {
+ epoll_fd_.Close();
+ return {std::move(data_fd_), std::move(pollin_event_fd_),
+ std::move(pollhup_event_fd_)};
+ }
+
Status<int> GetPendingEvents() const;
Status<int> PollPendingEvents(int timeout_ms) const;
diff --git a/libs/vr/libpdx_uds/private/uds/channel_parcelable.h b/libs/vr/libpdx_uds/private/uds/channel_parcelable.h
new file mode 100644
index 0000000..1c3fae9
--- /dev/null
+++ b/libs/vr/libpdx_uds/private/uds/channel_parcelable.h
@@ -0,0 +1,35 @@
+#ifndef ANDROID_PDX_UDS_CHANNEL_PARCELABLE_H_
+#define ANDROID_PDX_UDS_CHANNEL_PARCELABLE_H_
+
+#include <pdx/channel_parcelable.h>
+#include <pdx/file_handle.h>
+
+namespace android {
+namespace pdx {
+namespace uds {
+
+class ChannelParcelable : public pdx::ChannelParcelable {
+ public:
+ ChannelParcelable() = default;
+ ChannelParcelable(LocalHandle data_fd, LocalHandle pollin_event_fd,
+ LocalHandle pollhup_event_fd);
+
+ // Implements pdx::ChannelParcelable interface.
+ bool IsValid() const override;
+ LocalChannelHandle TakeChannelHandle() override;
+
+ // Implements android::Parcelable interface.
+ status_t writeToParcel(Parcel* parcel) const override;
+ status_t readFromParcel(const Parcel* parcel) override;
+
+ private:
+ LocalHandle data_fd_;
+ LocalHandle pollin_event_fd_;
+ LocalHandle pollhup_event_fd_;
+};
+
+} // namespace uds
+} // namespace pdx
+} // namespace android
+
+#endif // ANDROID_PDX_UDS_CHANNEL_PARCELABLE_H_
diff --git a/libs/vr/libpdx_uds/private/uds/client_channel.h b/libs/vr/libpdx_uds/private/uds/client_channel.h
index 7a5ddf4..b5524d8 100644
--- a/libs/vr/libpdx_uds/private/uds/client_channel.h
+++ b/libs/vr/libpdx_uds/private/uds/client_channel.h
@@ -74,6 +74,8 @@
bool GetChannelHandle(void* transaction_state, ChannelReference ref,
LocalChannelHandle* handle) const override;
+ std::unique_ptr<pdx::ChannelParcelable> TakeChannelParcelable() override;
+
private:
explicit ClientChannel(LocalChannelHandle channel_handle);
diff --git a/libs/vr/libperformance/Android.bp b/libs/vr/libperformance/Android.bp
index 364873d..278a425 100644
--- a/libs/vr/libperformance/Android.bp
+++ b/libs/vr/libperformance/Android.bp
@@ -23,6 +23,7 @@
sharedLibraries = [
"libbase",
+ "libbinder",
"libcutils",
"liblog",
"libutils",
diff --git a/libs/vr/libvrflinger/hardware_composer.cpp b/libs/vr/libvrflinger/hardware_composer.cpp
index fb69d5c..44be0ab 100644
--- a/libs/vr/libvrflinger/hardware_composer.cpp
+++ b/libs/vr/libvrflinger/hardware_composer.cpp
@@ -570,6 +570,9 @@
// Copy from latest record in shared_config_ring_ to local copy.
DvrConfig record;
if (shared_config_ring_.GetNewest(&shared_config_ring_sequence_, &record)) {
+ ALOGI("DvrConfig updated: sequence %u, post offset %d",
+ shared_config_ring_sequence_, record.frame_post_offset_ns);
+ ++shared_config_ring_sequence_;
post_thread_config_ = record;
}
}
diff --git a/libs/vr/libvrsensor/Android.bp b/libs/vr/libvrsensor/Android.bp
index d022adf..cc1803b 100644
--- a/libs/vr/libvrsensor/Android.bp
+++ b/libs/vr/libvrsensor/Android.bp
@@ -33,6 +33,7 @@
sharedLibraries = [
"libbase",
+ "libbinder",
"libcutils",
"libhardware",
"liblog",
diff --git a/opengl/libs/Android.bp b/opengl/libs/Android.bp
index 32c2d7e..d43c164 100644
--- a/opengl/libs/Android.bp
+++ b/opengl/libs/Android.bp
@@ -122,6 +122,16 @@
},
}
+cc_library_static {
+ name: "libEGL_blobCache",
+ defaults: ["egl_libs_defaults"],
+ srcs: [
+ "EGL/BlobCache.cpp",
+ "EGL/FileBlobCache.cpp",
+ ],
+ export_include_dirs: ["EGL"],
+}
+
cc_library_shared {
name: "libEGL",
defaults: ["egl_libs_defaults"],
@@ -133,7 +143,6 @@
"EGL/egl.cpp",
"EGL/eglApi.cpp",
"EGL/Loader.cpp",
- "EGL/BlobCache.cpp",
],
shared_libs: [
"libvndksupport",
@@ -143,7 +152,10 @@
"libhidltransport",
"libutils",
],
- static_libs: ["libEGL_getProcAddress"],
+ static_libs: [
+ "libEGL_getProcAddress",
+ "libEGL_blobCache",
+ ],
ldflags: ["-Wl,--exclude-libs=ALL"],
export_include_dirs: ["EGL/include"],
}
diff --git a/opengl/libs/EGL/BlobCache.cpp b/opengl/libs/EGL/BlobCache.cpp
index 0624b60..b3752f5 100644
--- a/opengl/libs/EGL/BlobCache.cpp
+++ b/opengl/libs/EGL/BlobCache.cpp
@@ -37,9 +37,9 @@
static const uint32_t blobCacheDeviceVersion = 1;
BlobCache::BlobCache(size_t maxKeySize, size_t maxValueSize, size_t maxTotalSize):
+ mMaxTotalSize(maxTotalSize),
mMaxKeySize(maxKeySize),
mMaxValueSize(maxValueSize),
- mMaxTotalSize(maxTotalSize),
mTotalSize(0) {
int64_t now = std::chrono::steady_clock::now().time_since_epoch().count();
#ifdef _WIN32
diff --git a/opengl/libs/EGL/BlobCache.h b/opengl/libs/EGL/BlobCache.h
index a0a270a..1f5d535 100644
--- a/opengl/libs/EGL/BlobCache.h
+++ b/opengl/libs/EGL/BlobCache.h
@@ -97,6 +97,14 @@
//
int unflatten(void const* buffer, size_t size);
+protected:
+ // mMaxTotalSize is the maximum size that all cache entries can occupy. This
+ // includes space for both keys and values. When a call to BlobCache::set
+ // would otherwise cause this limit to be exceeded, either the key/value
+ // pair passed to BlobCache::set will not be cached or other cache entries
+ // will be evicted from the cache to make room for the new entry.
+ const size_t mMaxTotalSize;
+
private:
// Copying is disallowed.
BlobCache(const BlobCache&);
@@ -220,13 +228,6 @@
// simply not add the key/value pair to the cache.
const size_t mMaxValueSize;
- // mMaxTotalSize is the maximum size that all cache entries can occupy. This
- // includes space for both keys and values. When a call to BlobCache::set
- // would otherwise cause this limit to be exceeded, either the key/value
- // pair passed to BlobCache::set will not be cached or other cache entries
- // will be evicted from the cache to make room for the new entry.
- const size_t mMaxTotalSize;
-
// mTotalSize is the total combined size of all keys and values currently in
// the cache.
size_t mTotalSize;
diff --git a/opengl/libs/EGL/FileBlobCache.cpp b/opengl/libs/EGL/FileBlobCache.cpp
new file mode 100644
index 0000000..ff608a3
--- /dev/null
+++ b/opengl/libs/EGL/FileBlobCache.cpp
@@ -0,0 +1,185 @@
+/*
+ ** Copyright 2017, The Android Open Source Project
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ ** http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ** See the License for the specific language governing permissions and
+ ** limitations under the License.
+ */
+
+#include "FileBlobCache.h"
+
+#include <inttypes.h>
+#include <log/log.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+
+
+// Cache file header
+static const char* cacheFileMagic = "EGL$";
+static const size_t cacheFileHeaderSize = 8;
+
+namespace android {
+
+static uint32_t crc32c(const uint8_t* buf, size_t len) {
+ const uint32_t polyBits = 0x82F63B78;
+ uint32_t r = 0;
+ for (size_t i = 0; i < len; i++) {
+ r ^= buf[i];
+ for (int j = 0; j < 8; j++) {
+ if (r & 1) {
+ r = (r >> 1) ^ polyBits;
+ } else {
+ r >>= 1;
+ }
+ }
+ }
+ return r;
+}
+
+FileBlobCache::FileBlobCache(size_t maxKeySize, size_t maxValueSize, size_t maxTotalSize,
+ const std::string& filename)
+ : BlobCache(maxKeySize, maxValueSize, maxTotalSize)
+ , mFilename(filename) {
+ if (mFilename.length() > 0) {
+ size_t headerSize = cacheFileHeaderSize;
+
+ int fd = open(mFilename.c_str(), O_RDONLY, 0);
+ if (fd == -1) {
+ if (errno != ENOENT) {
+ ALOGE("error opening cache file %s: %s (%d)", mFilename.c_str(),
+ strerror(errno), errno);
+ }
+ return;
+ }
+
+ struct stat statBuf;
+ if (fstat(fd, &statBuf) == -1) {
+ ALOGE("error stat'ing cache file: %s (%d)", strerror(errno), errno);
+ close(fd);
+ return;
+ }
+
+ // Sanity check the size before trying to mmap it.
+ size_t fileSize = statBuf.st_size;
+ if (fileSize > mMaxTotalSize * 2) {
+ ALOGE("cache file is too large: %#" PRIx64,
+ static_cast<off64_t>(statBuf.st_size));
+ close(fd);
+ return;
+ }
+
+ uint8_t* buf = reinterpret_cast<uint8_t*>(mmap(NULL, fileSize,
+ PROT_READ, MAP_PRIVATE, fd, 0));
+ if (buf == MAP_FAILED) {
+ ALOGE("error mmaping cache file: %s (%d)", strerror(errno),
+ errno);
+ close(fd);
+ return;
+ }
+
+ // Check the file magic and CRC
+ size_t cacheSize = fileSize - headerSize;
+ if (memcmp(buf, cacheFileMagic, 4) != 0) {
+ ALOGE("cache file has bad mojo");
+ close(fd);
+ return;
+ }
+ uint32_t* crc = reinterpret_cast<uint32_t*>(buf + 4);
+ if (crc32c(buf + headerSize, cacheSize) != *crc) {
+ ALOGE("cache file failed CRC check");
+ close(fd);
+ return;
+ }
+
+ int err = unflatten(buf + headerSize, cacheSize);
+ if (err < 0) {
+ ALOGE("error reading cache contents: %s (%d)", strerror(-err),
+ -err);
+ munmap(buf, fileSize);
+ close(fd);
+ return;
+ }
+
+ munmap(buf, fileSize);
+ close(fd);
+ }
+}
+
+void FileBlobCache::writeToFile() {
+ if (mFilename.length() > 0) {
+ size_t cacheSize = getFlattenedSize();
+ size_t headerSize = cacheFileHeaderSize;
+ const char* fname = mFilename.c_str();
+
+ // Try to create the file with no permissions so we can write it
+ // without anyone trying to read it.
+ int fd = open(fname, O_CREAT | O_EXCL | O_RDWR, 0);
+ if (fd == -1) {
+ if (errno == EEXIST) {
+ // The file exists, delete it and try again.
+ if (unlink(fname) == -1) {
+ // No point in retrying if the unlink failed.
+ ALOGE("error unlinking cache file %s: %s (%d)", fname,
+ strerror(errno), errno);
+ return;
+ }
+ // Retry now that we've unlinked the file.
+ fd = open(fname, O_CREAT | O_EXCL | O_RDWR, 0);
+ }
+ if (fd == -1) {
+ ALOGE("error creating cache file %s: %s (%d)", fname,
+ strerror(errno), errno);
+ return;
+ }
+ }
+
+ size_t fileSize = headerSize + cacheSize;
+
+ uint8_t* buf = new uint8_t [fileSize];
+ if (!buf) {
+ ALOGE("error allocating buffer for cache contents: %s (%d)",
+ strerror(errno), errno);
+ close(fd);
+ unlink(fname);
+ return;
+ }
+
+ int err = flatten(buf + headerSize, cacheSize);
+ if (err < 0) {
+ ALOGE("error writing cache contents: %s (%d)", strerror(-err),
+ -err);
+ delete [] buf;
+ close(fd);
+ unlink(fname);
+ return;
+ }
+
+ // Write the file magic and CRC
+ memcpy(buf, cacheFileMagic, 4);
+ uint32_t* crc = reinterpret_cast<uint32_t*>(buf + 4);
+ *crc = crc32c(buf + headerSize, cacheSize);
+
+ if (write(fd, buf, fileSize) == -1) {
+ ALOGE("error writing cache file: %s (%d)", strerror(errno),
+ errno);
+ delete [] buf;
+ close(fd);
+ unlink(fname);
+ return;
+ }
+
+ delete [] buf;
+ fchmod(fd, S_IRUSR);
+ close(fd);
+ }
+}
+
+}
\ No newline at end of file
diff --git a/opengl/libs/EGL/FileBlobCache.h b/opengl/libs/EGL/FileBlobCache.h
new file mode 100644
index 0000000..393703f
--- /dev/null
+++ b/opengl/libs/EGL/FileBlobCache.h
@@ -0,0 +1,43 @@
+/*
+ ** Copyright 2017, The Android Open Source Project
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ ** http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ** See the License for the specific language governing permissions and
+ ** limitations under the License.
+ */
+
+#ifndef ANDROID_FILE_BLOB_CACHE_H
+#define ANDROID_FILE_BLOB_CACHE_H
+
+#include "BlobCache.h"
+#include <string>
+
+namespace android {
+
+class FileBlobCache : public BlobCache {
+public:
+ // FileBlobCache attempts to load the saved cache contents from disk into
+ // BlobCache.
+ FileBlobCache(size_t maxKeySize, size_t maxValueSize, size_t maxTotalSize,
+ const std::string& filename);
+
+ // writeToFile attempts to save the current contents of BlobCache to
+ // disk.
+ void writeToFile();
+
+private:
+ // mFilename is the name of the file for storing cache contents.
+ std::string mFilename;
+};
+
+} // namespace android
+
+#endif // ANDROID_BLOB_CACHE_H
diff --git a/opengl/libs/EGL/egl_cache.cpp b/opengl/libs/EGL/egl_cache.cpp
index 579e422..ec548f3 100644
--- a/opengl/libs/EGL/egl_cache.cpp
+++ b/opengl/libs/EGL/egl_cache.cpp
@@ -20,12 +20,8 @@
#include "egl_display.h"
-
#include <private/EGL/cache.h>
-#include <inttypes.h>
-#include <sys/mman.h>
-#include <sys/stat.h>
#include <unistd.h>
#include <thread>
@@ -37,10 +33,6 @@
static const size_t maxValueSize = 64 * 1024;
static const size_t maxTotalSize = 2 * 1024 * 1024;
-// Cache file header
-static const char* cacheFileMagic = "EGL$";
-static const size_t cacheFileHeaderSize = 8;
-
// The time in seconds to wait before saving newly inserted cache entries.
static const unsigned int deferredSaveDelay = 4;
@@ -124,7 +116,9 @@
void egl_cache_t::terminate() {
std::lock_guard<std::mutex> lock(mMutex);
- saveBlobCacheLocked();
+ if (mBlobCache) {
+ mBlobCache->writeToFile();
+ }
mBlobCache = NULL;
}
@@ -146,8 +140,8 @@
std::thread deferredSaveThread([this]() {
sleep(deferredSaveDelay);
std::lock_guard<std::mutex> lock(mMutex);
- if (mInitialized) {
- saveBlobCacheLocked();
+ if (mInitialized && mBlobCache) {
+ mBlobCache->writeToFile();
}
mSavePending = false;
});
@@ -179,163 +173,11 @@
BlobCache* egl_cache_t::getBlobCacheLocked() {
if (mBlobCache == nullptr) {
- mBlobCache.reset(new BlobCache(maxKeySize, maxValueSize, maxTotalSize));
- loadBlobCacheLocked();
+ mBlobCache.reset(new FileBlobCache(maxKeySize, maxValueSize, maxTotalSize, mFilename));
}
return mBlobCache.get();
}
-static uint32_t crc32c(const uint8_t* buf, size_t len) {
- const uint32_t polyBits = 0x82F63B78;
- uint32_t r = 0;
- for (size_t i = 0; i < len; i++) {
- r ^= buf[i];
- for (int j = 0; j < 8; j++) {
- if (r & 1) {
- r = (r >> 1) ^ polyBits;
- } else {
- r >>= 1;
- }
- }
- }
- return r;
-}
-
-void egl_cache_t::saveBlobCacheLocked() {
- if (mFilename.length() > 0 && mBlobCache != NULL) {
- size_t cacheSize = mBlobCache->getFlattenedSize();
- size_t headerSize = cacheFileHeaderSize;
- const char* fname = mFilename.c_str();
-
- // Try to create the file with no permissions so we can write it
- // without anyone trying to read it.
- int fd = open(fname, O_CREAT | O_EXCL | O_RDWR, 0);
- if (fd == -1) {
- if (errno == EEXIST) {
- // The file exists, delete it and try again.
- if (unlink(fname) == -1) {
- // No point in retrying if the unlink failed.
- ALOGE("error unlinking cache file %s: %s (%d)", fname,
- strerror(errno), errno);
- return;
- }
- // Retry now that we've unlinked the file.
- fd = open(fname, O_CREAT | O_EXCL | O_RDWR, 0);
- }
- if (fd == -1) {
- ALOGE("error creating cache file %s: %s (%d)", fname,
- strerror(errno), errno);
- return;
- }
- }
-
- size_t fileSize = headerSize + cacheSize;
-
- uint8_t* buf = new uint8_t [fileSize];
- if (!buf) {
- ALOGE("error allocating buffer for cache contents: %s (%d)",
- strerror(errno), errno);
- close(fd);
- unlink(fname);
- return;
- }
-
- int err = mBlobCache->flatten(buf + headerSize, cacheSize);
- if (err < 0) {
- ALOGE("error writing cache contents: %s (%d)", strerror(-err),
- -err);
- delete [] buf;
- close(fd);
- unlink(fname);
- return;
- }
-
- // Write the file magic and CRC
- memcpy(buf, cacheFileMagic, 4);
- uint32_t* crc = reinterpret_cast<uint32_t*>(buf + 4);
- *crc = crc32c(buf + headerSize, cacheSize);
-
- if (write(fd, buf, fileSize) == -1) {
- ALOGE("error writing cache file: %s (%d)", strerror(errno),
- errno);
- delete [] buf;
- close(fd);
- unlink(fname);
- return;
- }
-
- delete [] buf;
- fchmod(fd, S_IRUSR);
- close(fd);
- }
-}
-
-void egl_cache_t::loadBlobCacheLocked() {
- if (mFilename.length() > 0) {
- size_t headerSize = cacheFileHeaderSize;
-
- int fd = open(mFilename.c_str(), O_RDONLY, 0);
- if (fd == -1) {
- if (errno != ENOENT) {
- ALOGE("error opening cache file %s: %s (%d)", mFilename.c_str(),
- strerror(errno), errno);
- }
- return;
- }
-
- struct stat statBuf;
- if (fstat(fd, &statBuf) == -1) {
- ALOGE("error stat'ing cache file: %s (%d)", strerror(errno), errno);
- close(fd);
- return;
- }
-
- // Sanity check the size before trying to mmap it.
- size_t fileSize = statBuf.st_size;
- if (fileSize > maxTotalSize * 2) {
- ALOGE("cache file is too large: %#" PRIx64,
- static_cast<off64_t>(statBuf.st_size));
- close(fd);
- return;
- }
-
- uint8_t* buf = reinterpret_cast<uint8_t*>(mmap(NULL, fileSize,
- PROT_READ, MAP_PRIVATE, fd, 0));
- if (buf == MAP_FAILED) {
- ALOGE("error mmaping cache file: %s (%d)", strerror(errno),
- errno);
- close(fd);
- return;
- }
-
- // Check the file magic and CRC
- size_t cacheSize = fileSize - headerSize;
- if (memcmp(buf, cacheFileMagic, 4) != 0) {
- ALOGE("cache file has bad mojo");
- close(fd);
- return;
- }
- uint32_t* crc = reinterpret_cast<uint32_t*>(buf + 4);
- if (crc32c(buf + headerSize, cacheSize) != *crc) {
- ALOGE("cache file failed CRC check");
- close(fd);
- return;
- }
-
- int err = mBlobCache->unflatten(buf + headerSize, cacheSize);
- if (err < 0) {
- ALOGE("error reading cache contents: %s (%d)", strerror(-err),
- -err);
- munmap(buf, fileSize);
- close(fd);
- return;
- }
-
- munmap(buf, fileSize);
- close(fd);
- }
-}
-
// ----------------------------------------------------------------------------
}; // namespace android
// ----------------------------------------------------------------------------
diff --git a/opengl/libs/EGL/egl_cache.h b/opengl/libs/EGL/egl_cache.h
index 56360f0..7382b91 100644
--- a/opengl/libs/EGL/egl_cache.h
+++ b/opengl/libs/EGL/egl_cache.h
@@ -20,7 +20,7 @@
#include <EGL/egl.h>
#include <EGL/eglext.h>
-#include "BlobCache.h"
+#include "FileBlobCache.h"
#include <memory>
#include <mutex>
@@ -82,14 +82,6 @@
// possible.
BlobCache* getBlobCacheLocked();
- // saveBlobCache attempts to save the current contents of mBlobCache to
- // disk.
- void saveBlobCacheLocked();
-
- // loadBlobCache attempts to load the saved cache contents from disk into
- // mBlobCache.
- void loadBlobCacheLocked();
-
// mInitialized indicates whether the egl_cache_t is in the initialized
// state. It is initialized to false at construction time, and gets set to
// true when initialize is called. It is set back to false when terminate
@@ -101,7 +93,7 @@
// mBlobCache is the cache in which the key/value blob pairs are stored. It
// is initially NULL, and will be initialized by getBlobCacheLocked the
// first time it's needed.
- std::unique_ptr<BlobCache> mBlobCache;
+ std::unique_ptr<FileBlobCache> mBlobCache;
// mFilename is the name of the file for storing cache contents in between
// program invocations. It is initialized to an empty string at
diff --git a/opengl/tests/lib/WindowSurface.cpp b/opengl/tests/lib/WindowSurface.cpp
index 1428945..2b76279 100644
--- a/opengl/tests/lib/WindowSurface.cpp
+++ b/opengl/tests/lib/WindowSurface.cpp
@@ -62,19 +62,10 @@
return;
}
- SurfaceComposerClient::openGlobalTransaction();
- err = sc->setLayer(0x7FFFFFFF); // always on top
- if (err != NO_ERROR) {
- fprintf(stderr, "SurfaceComposer::setLayer error: %#x\n", err);
- return;
- }
-
- err = sc->show();
- if (err != NO_ERROR) {
- fprintf(stderr, "SurfaceComposer::show error: %#x\n", err);
- return;
- }
- SurfaceComposerClient::closeGlobalTransaction();
+ SurfaceComposerClient::Transaction{}
+ .setLayer(sc, 0x7FFFFFFF)
+ .show(sc)
+ .apply();
mSurfaceControl = sc;
}
diff --git a/opengl/tools/glgen/stubs/egl/EGL14cHeader.cpp b/opengl/tools/glgen/stubs/egl/EGL14cHeader.cpp
index bdbd855..f90e3ec 100644
--- a/opengl/tools/glgen/stubs/egl/EGL14cHeader.cpp
+++ b/opengl/tools/glgen/stubs/egl/EGL14cHeader.cpp
@@ -20,7 +20,7 @@
#pragma GCC diagnostic ignored "-Wunused-function"
#include "jni.h"
-#include "JNIHelp.h"
+#include <nativehelper/JNIHelp.h>
#include <android_runtime/AndroidRuntime.h>
#include <android_runtime/android_view_Surface.h>
#include <android_runtime/android_graphics_SurfaceTexture.h>
diff --git a/opengl/tools/glgen/stubs/egl/EGLExtcHeader.cpp b/opengl/tools/glgen/stubs/egl/EGLExtcHeader.cpp
index 3258ac4..12b96f4 100644
--- a/opengl/tools/glgen/stubs/egl/EGLExtcHeader.cpp
+++ b/opengl/tools/glgen/stubs/egl/EGLExtcHeader.cpp
@@ -20,7 +20,7 @@
#pragma GCC diagnostic ignored "-Wunused-function"
#include "jni.h"
-#include "JNIHelp.h"
+#include <nativehelper/JNIHelp.h>
#include <android_runtime/AndroidRuntime.h>
#include <android_runtime/android_view_Surface.h>
#include <android_runtime/android_graphics_SurfaceTexture.h>
diff --git a/opengl/tools/glgen/stubs/gles11/common.cpp b/opengl/tools/glgen/stubs/gles11/common.cpp
index 7062c57..2163d76 100644
--- a/opengl/tools/glgen/stubs/gles11/common.cpp
+++ b/opengl/tools/glgen/stubs/gles11/common.cpp
@@ -1,5 +1,5 @@
#include <jni.h>
-#include <JNIHelp.h>
+#include <nativehelper/JNIHelp.h>
#include <android_runtime/AndroidRuntime.h>
#include <utils/misc.h>
#include <assert.h>
diff --git a/opengl/tools/glgen/stubs/jsr239/GLCHeader.cpp b/opengl/tools/glgen/stubs/jsr239/GLCHeader.cpp
index 0da80fb..29296ff 100644
--- a/opengl/tools/glgen/stubs/jsr239/GLCHeader.cpp
+++ b/opengl/tools/glgen/stubs/jsr239/GLCHeader.cpp
@@ -20,7 +20,7 @@
#pragma GCC diagnostic ignored "-Wunused-function"
#include "jni.h"
-#include "JNIHelp.h"
+#include <nativehelper/JNIHelp.h>
#include <android_runtime/AndroidRuntime.h>
#include <utils/misc.h>
diff --git a/services/audiomanager/Android.bp b/services/audiomanager/Android.bp
index 22b084a..12ad47e 100644
--- a/services/audiomanager/Android.bp
+++ b/services/audiomanager/Android.bp
@@ -3,7 +3,6 @@
srcs: [
"IAudioManager.cpp",
- "IPlayer.cpp",
],
shared_libs: [
diff --git a/services/audiomanager/IPlayer.cpp b/services/audiomanager/IPlayer.cpp
deleted file mode 100644
index e8a9c34..0000000
--- a/services/audiomanager/IPlayer.cpp
+++ /dev/null
@@ -1,189 +0,0 @@
-/*
-**
-** Copyright 2017, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
-
-#define LOG_TAG "IPlayer"
-//#define LOG_NDEBUG 0
-#include <utils/Log.h>
-
-#include <stdint.h>
-#include <sys/types.h>
-
-#include <binder/Parcel.h>
-
-#include <audiomanager/IPlayer.h>
-
-namespace android {
-
-enum {
- START = IBinder::FIRST_CALL_TRANSACTION,
- PAUSE = IBinder::FIRST_CALL_TRANSACTION + 1,
- STOP = IBinder::FIRST_CALL_TRANSACTION + 2,
- SET_VOLUME = IBinder::FIRST_CALL_TRANSACTION + 3,
- SET_PAN = IBinder::FIRST_CALL_TRANSACTION + 4,
- SET_START_DELAY_MS = IBinder::FIRST_CALL_TRANSACTION + 5,
- APPLY_VOLUME_SHAPER = IBinder::FIRST_CALL_TRANSACTION + 6,
-};
-
-class BpPlayer : public BpInterface<IPlayer>
-{
-public:
- explicit BpPlayer(const sp<IBinder>& impl)
- : BpInterface<IPlayer>(impl)
- {
- }
-
- virtual void start()
- {
- Parcel data, reply;
- data.writeInterfaceToken(IPlayer::getInterfaceDescriptor());
- remote()->transact(START, data, &reply);
- }
-
- virtual void pause()
- {
- Parcel data, reply;
- data.writeInterfaceToken(IPlayer::getInterfaceDescriptor());
- remote()->transact(PAUSE, data, &reply);
- }
-
- virtual void stop()
- {
- Parcel data, reply;
- data.writeInterfaceToken(IPlayer::getInterfaceDescriptor());
- remote()->transact(STOP, data, &reply);
- }
-
- virtual void setVolume(float vol)
- {
- Parcel data, reply;
- data.writeInterfaceToken(IPlayer::getInterfaceDescriptor());
- data.writeFloat(vol);
- remote()->transact(SET_VOLUME, data, &reply);
- }
-
- virtual void setPan(float pan)
- {
- Parcel data, reply;
- data.writeInterfaceToken(IPlayer::getInterfaceDescriptor());
- data.writeFloat(pan);
- remote()->transact(SET_PAN, data, &reply);
- }
-
- virtual void setStartDelayMs(int32_t delayMs) {
- Parcel data, reply;
- data.writeInterfaceToken(IPlayer::getInterfaceDescriptor());
- data.writeInt32(delayMs);
- remote()->transact(SET_START_DELAY_MS, data, &reply);
- }
-
- virtual void applyVolumeShaper(
- const sp<VolumeShaper::Configuration>& configuration,
- const sp<VolumeShaper::Operation>& operation) {
- Parcel data, reply;
- data.writeInterfaceToken(IPlayer::getInterfaceDescriptor());
-
- status_t status = configuration.get() == nullptr
- ? data.writeInt32(0)
- : data.writeInt32(1)
- ?: configuration->writeToParcel(&data);
- if (status != NO_ERROR) {
- ALOGW("applyVolumeShaper failed configuration parceling: %d", status);
- return; // ignore error
- }
-
- status = operation.get() == nullptr
- ? status = data.writeInt32(0)
- : data.writeInt32(1)
- ?: operation->writeToParcel(&data);
- if (status != NO_ERROR) {
- ALOGW("applyVolumeShaper failed operation parceling: %d", status);
- return; // ignore error
- }
-
- status = remote()->transact(APPLY_VOLUME_SHAPER, data, &reply);
-
- ALOGW_IF(status != NO_ERROR, "applyVolumeShaper failed transact: %d", status);
- return; // one way transaction, ignore error
- }
-};
-
-IMPLEMENT_META_INTERFACE(Player, "android.media.IPlayer");
-
-// ----------------------------------------------------------------------
-
-status_t BnPlayer::onTransact(
- uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
-{
- switch (code) {
- case START: {
- CHECK_INTERFACE(IPlayer, data, reply);
- start();
- return NO_ERROR;
- } break;
- case PAUSE: {
- CHECK_INTERFACE(IPlayer, data, reply);
- pause();
- return NO_ERROR;
- }
- case STOP: {
- CHECK_INTERFACE(IPlayer, data, reply);
- stop();
- return NO_ERROR;
- } break;
- case SET_VOLUME: {
- CHECK_INTERFACE(IPlayer, data, reply);
- setVolume(data.readFloat());
- return NO_ERROR;
- } break;
- case SET_PAN: {
- CHECK_INTERFACE(IPlayer, data, reply);
- setPan(data.readFloat());
- return NO_ERROR;
- } break;
- case SET_START_DELAY_MS: {
- CHECK_INTERFACE(IPlayer, data, reply);
- setStartDelayMs(data.readInt32());
- return NO_ERROR;
- } break;
- case APPLY_VOLUME_SHAPER: {
- CHECK_INTERFACE(IPlayer, data, reply);
- sp<VolumeShaper::Configuration> configuration;
- sp<VolumeShaper::Operation> operation;
-
- int32_t present;
- status_t status = data.readInt32(&present);
- if (status == NO_ERROR && present != 0) {
- configuration = new VolumeShaper::Configuration();
- status = configuration->readFromParcel(data);
- }
- status = status ?: data.readInt32(&present);
- if (status == NO_ERROR && present != 0) {
- operation = new VolumeShaper::Operation();
- status = operation->readFromParcel(data);
- }
- if (status == NO_ERROR) {
- // one way transaction, no error returned
- applyVolumeShaper(configuration, operation);
- }
- return NO_ERROR;
- } break;
- default:
- return BBinder::onTransact(code, data, reply, flags);
- }
-}
-
-} // namespace android
diff --git a/services/batteryservice/Android.bp b/services/batteryservice/Android.bp
index 4c7265b..186f399 100644
--- a/services/batteryservice/Android.bp
+++ b/services/batteryservice/Android.bp
@@ -5,29 +5,3 @@
header_libs: ["libbinder_headers"],
export_header_lib_headers: ["libbinder_headers"],
}
-
-cc_library {
- name: "libbatteryservice",
-
- srcs: [
- "BatteryProperties.cpp",
- "BatteryProperty.cpp",
- "IBatteryPropertiesListener.cpp",
- "IBatteryPropertiesRegistrar.cpp",
- ],
-
- header_libs: ["libbatteryservice_headers"],
- export_header_lib_headers: ["libbatteryservice_headers"],
-
- shared_libs: [
- "libutils",
- "libbinder",
- ],
-
- cflags: [
- "-Wall",
- "-Werror",
- "-Wunused",
- "-Wunreachable-code",
- ],
-}
diff --git a/services/batteryservice/BatteryProperties.cpp b/services/batteryservice/BatteryProperties.cpp
deleted file mode 100644
index 8fa111d..0000000
--- a/services/batteryservice/BatteryProperties.cpp
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright (C) 2013 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 <stdint.h>
-#include <sys/types.h>
-#include <batteryservice/BatteryService.h>
-#include <binder/Parcel.h>
-#include <utils/Errors.h>
-#include <utils/String8.h>
-#include <utils/String16.h>
-
-namespace android {
-
-/*
- * Parcel read/write code must be kept in sync with
- * frameworks/base/core/java/android/os/BatteryProperties.java
- */
-
-status_t BatteryProperties::readFromParcel(Parcel* p) {
- chargerAcOnline = p->readInt32() == 1 ? true : false;
- chargerUsbOnline = p->readInt32() == 1 ? true : false;
- chargerWirelessOnline = p->readInt32() == 1 ? true : false;
- maxChargingCurrent = p->readInt32();
- maxChargingVoltage = p->readInt32();
- batteryStatus = p->readInt32();
- batteryHealth = p->readInt32();
- batteryPresent = p->readInt32() == 1 ? true : false;
- batteryLevel = p->readInt32();
- batteryVoltage = p->readInt32();
- batteryTemperature = p->readInt32();
- batteryFullCharge = p->readInt32();
- batteryChargeCounter = p->readInt32();
- batteryTechnology = String8((p->readString16()).string());
- return OK;
-}
-
-status_t BatteryProperties::writeToParcel(Parcel* p) const {
- p->writeInt32(chargerAcOnline ? 1 : 0);
- p->writeInt32(chargerUsbOnline ? 1 : 0);
- p->writeInt32(chargerWirelessOnline ? 1 : 0);
- p->writeInt32(maxChargingCurrent);
- p->writeInt32(maxChargingVoltage);
- p->writeInt32(batteryStatus);
- p->writeInt32(batteryHealth);
- p->writeInt32(batteryPresent ? 1 : 0);
- p->writeInt32(batteryLevel);
- p->writeInt32(batteryVoltage);
- p->writeInt32(batteryTemperature);
- p->writeInt32(batteryFullCharge);
- p->writeInt32(batteryChargeCounter);
- p->writeString16(String16(batteryTechnology));
- return OK;
-}
-
-}; // namespace android
diff --git a/services/batteryservice/BatteryProperty.cpp b/services/batteryservice/BatteryProperty.cpp
deleted file mode 100644
index 483d925..0000000
--- a/services/batteryservice/BatteryProperty.cpp
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright (C) 2013 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 <stdint.h>
-#include <sys/types.h>
-#include <batteryservice/BatteryService.h>
-#include <binder/Parcel.h>
-#include <utils/Errors.h>
-
-namespace android {
-
-/*
- * Parcel read/write code must be kept in sync with
- * frameworks/base/core/java/android/os/BatteryProperty.java
- */
-
-status_t BatteryProperty::readFromParcel(Parcel* p) {
- valueInt64 = p->readInt64();
- return OK;
-}
-
-status_t BatteryProperty::writeToParcel(Parcel* p) const {
- p->writeInt64(valueInt64);
- return OK;
-}
-
-}; // namespace android
diff --git a/services/batteryservice/IBatteryPropertiesListener.cpp b/services/batteryservice/IBatteryPropertiesListener.cpp
deleted file mode 100644
index 6e5bcfe..0000000
--- a/services/batteryservice/IBatteryPropertiesListener.cpp
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright (C) 2013 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 <stdint.h>
-#include <sys/types.h>
-#include <batteryservice/IBatteryPropertiesListener.h>
-#include <binder/Parcel.h>
-
-namespace android {
-
-class BpBatteryPropertiesListener : public BpInterface<IBatteryPropertiesListener>
-{
-public:
- explicit BpBatteryPropertiesListener(const sp<IBinder>& impl)
- : BpInterface<IBatteryPropertiesListener>(impl)
- {
- }
-
- void batteryPropertiesChanged(struct BatteryProperties props)
- {
- Parcel data, reply;
- data.writeInterfaceToken(IBatteryPropertiesListener::getInterfaceDescriptor());
- data.writeInt32(1);
- props.writeToParcel(&data);
- remote()->transact(TRANSACT_BATTERYPROPERTIESCHANGED, data, &reply, IBinder::FLAG_ONEWAY);
- }
-};
-
-IMPLEMENT_META_INTERFACE(BatteryPropertiesListener, "android.os.IBatteryPropertiesListener");
-
-// ----------------------------------------------------------------------------
-
-status_t BnBatteryPropertiesListener::onTransact(uint32_t code, const Parcel& data,
- Parcel* reply, uint32_t flags)
-{
- switch(code) {
- case TRANSACT_BATTERYPROPERTIESCHANGED: {
- CHECK_INTERFACE(IBatteryPropertiesListener, data, reply);
- struct BatteryProperties props = {};
- if (data.readInt32() != 0) {
- props.readFromParcel((Parcel*)&data);
- }
- batteryPropertiesChanged(props);
- return NO_ERROR;
- }
- default:
- return BBinder::onTransact(code, data, reply, flags);
- }
-};
-
-}; // namespace android
diff --git a/services/batteryservice/IBatteryPropertiesRegistrar.cpp b/services/batteryservice/IBatteryPropertiesRegistrar.cpp
deleted file mode 100644
index 01a65ae..0000000
--- a/services/batteryservice/IBatteryPropertiesRegistrar.cpp
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define LOG_TAG "IBatteryPropertiesRegistrar"
-//#define LOG_NDEBUG 0
-#include <utils/Log.h>
-
-#include <batteryservice/IBatteryPropertiesListener.h>
-#include <batteryservice/IBatteryPropertiesRegistrar.h>
-#include <stdint.h>
-#include <sys/types.h>
-#include <binder/Parcel.h>
-
-namespace android {
-
-class BpBatteryPropertiesRegistrar : public BpInterface<IBatteryPropertiesRegistrar> {
-public:
- explicit BpBatteryPropertiesRegistrar(const sp<IBinder>& impl)
- : BpInterface<IBatteryPropertiesRegistrar>(impl) {}
-
- void registerListener(const sp<IBatteryPropertiesListener>& listener) {
- Parcel data;
- data.writeInterfaceToken(IBatteryPropertiesRegistrar::getInterfaceDescriptor());
- data.writeStrongBinder(IInterface::asBinder(listener));
- remote()->transact(REGISTER_LISTENER, data, NULL);
- }
-
- void unregisterListener(const sp<IBatteryPropertiesListener>& listener) {
- Parcel data;
- data.writeInterfaceToken(IBatteryPropertiesRegistrar::getInterfaceDescriptor());
- data.writeStrongBinder(IInterface::asBinder(listener));
- remote()->transact(UNREGISTER_LISTENER, data, NULL);
- }
-
- status_t getProperty(int id, struct BatteryProperty *val) {
- Parcel data, reply;
- data.writeInterfaceToken(IBatteryPropertiesRegistrar::getInterfaceDescriptor());
- data.writeInt32(id);
- remote()->transact(GET_PROPERTY, data, &reply);
- int32_t ret = reply.readExceptionCode();
- if (ret != 0) {
- return ret;
- }
- ret = reply.readInt32();
- int parcelpresent = reply.readInt32();
- if (parcelpresent)
- val->readFromParcel(&reply);
- return ret;
- }
-
- void scheduleUpdate() {
- Parcel data;
- data.writeInterfaceToken(IBatteryPropertiesRegistrar::getInterfaceDescriptor());
- remote()->transact(SCHEDULE_UPDATE, data, NULL);
- }
-};
-
-IMPLEMENT_META_INTERFACE(BatteryPropertiesRegistrar, "android.os.IBatteryPropertiesRegistrar");
-
-status_t BnBatteryPropertiesRegistrar::onTransact(uint32_t code,
- const Parcel& data,
- Parcel* reply,
- uint32_t flags)
-{
- switch(code) {
- case REGISTER_LISTENER: {
- CHECK_INTERFACE(IBatteryPropertiesRegistrar, data, reply);
- sp<IBatteryPropertiesListener> listener =
- interface_cast<IBatteryPropertiesListener>(data.readStrongBinder());
- registerListener(listener);
- return OK;
- }
-
- case UNREGISTER_LISTENER: {
- CHECK_INTERFACE(IBatteryPropertiesRegistrar, data, reply);
- sp<IBatteryPropertiesListener> listener =
- interface_cast<IBatteryPropertiesListener>(data.readStrongBinder());
- unregisterListener(listener);
- return OK;
- }
-
- case GET_PROPERTY: {
- CHECK_INTERFACE(IBatteryPropertiesRegistrar, data, reply);
- int id = data.readInt32();
- struct BatteryProperty val;
- status_t result = getProperty(id, &val);
- reply->writeNoException();
- reply->writeInt32(result);
- reply->writeInt32(1);
- val.writeToParcel(reply);
- return OK;
- }
-
- case SCHEDULE_UPDATE: {
- CHECK_INTERFACE(IBatteryPropertiesRegistrar, data, reply);
- scheduleUpdate();
- return OK;
- }
- }
- return BBinder::onTransact(code, data, reply, flags);
-};
-
-// ----------------------------------------------------------------------------
-
-}; // namespace android
diff --git a/services/inputflinger/InputDispatcher.cpp b/services/inputflinger/InputDispatcher.cpp
index 42f9ba9..8ab30e8 100644
--- a/services/inputflinger/InputDispatcher.cpp
+++ b/services/inputflinger/InputDispatcher.cpp
@@ -685,7 +685,7 @@
bool InputDispatcher::dispatchConfigurationChangedLocked(
nsecs_t currentTime, ConfigurationChangedEntry* entry) {
#if DEBUG_OUTBOUND_EVENT_DETAILS
- ALOGD("dispatchConfigurationChanged - eventTime=%lld", entry->eventTime);
+ ALOGD("dispatchConfigurationChanged - eventTime=%" PRId64, entry->eventTime);
#endif
// Reset key repeating in case a keyboard device was added or removed or something.
@@ -701,7 +701,8 @@
bool InputDispatcher::dispatchDeviceResetLocked(
nsecs_t currentTime, DeviceResetEntry* entry) {
#if DEBUG_OUTBOUND_EVENT_DETAILS
- ALOGD("dispatchDeviceReset - eventTime=%lld, deviceId=%d", entry->eventTime, entry->deviceId);
+ ALOGD("dispatchDeviceReset - eventTime=%" PRId64 ", deviceId=%d", entry->eventTime,
+ entry->deviceId);
#endif
CancelationOptions options(CancelationOptions::CANCEL_ALL_EVENTS,
@@ -811,9 +812,9 @@
void InputDispatcher::logOutboundKeyDetailsLocked(const char* prefix, const KeyEntry* entry) {
#if DEBUG_OUTBOUND_EVENT_DETAILS
- ALOGD("%seventTime=%lld, deviceId=%d, source=0x%x, policyFlags=0x%x, "
+ ALOGD("%seventTime=%" PRId64 ", deviceId=%d, source=0x%x, policyFlags=0x%x, "
"action=0x%x, flags=0x%x, keyCode=0x%x, scanCode=0x%x, metaState=0x%x, "
- "repeatCount=%d, downTime=%lld",
+ "repeatCount=%d, downTime=%" PRId64,
prefix,
entry->eventTime, entry->deviceId, entry->source, entry->policyFlags,
entry->action, entry->flags, entry->keyCode, entry->scanCode, entry->metaState,
@@ -884,10 +885,10 @@
void InputDispatcher::logOutboundMotionDetailsLocked(const char* prefix, const MotionEntry* entry) {
#if DEBUG_OUTBOUND_EVENT_DETAILS
- ALOGD("%seventTime=%lld, deviceId=%d, source=0x%x, policyFlags=0x%x, "
+ ALOGD("%seventTime=%" PRId64 ", deviceId=%d, source=0x%x, policyFlags=0x%x, "
"action=0x%x, actionButton=0x%x, flags=0x%x, "
"metaState=0x%x, buttonState=0x%x,"
- "edgeFlags=0x%x, xPrecision=%f, yPrecision=%f, downTime=%lld",
+ "edgeFlags=0x%x, xPrecision=%f, yPrecision=%f, downTime=%" PRId64,
prefix,
entry->eventTime, entry->deviceId, entry->source, entry->policyFlags,
entry->action, entry->actionButton, entry->flags,
@@ -1992,10 +1993,10 @@
const PointerCoords* usingCoords = motionEntry->pointerCoords;
// Set the X and Y offset depending on the input source.
- float xOffset, yOffset, scaleFactor;
+ float xOffset, yOffset;
if ((motionEntry->source & AINPUT_SOURCE_CLASS_POINTER)
&& !(dispatchEntry->targetFlags & InputTarget::FLAG_ZERO_COORDS)) {
- scaleFactor = dispatchEntry->scaleFactor;
+ float scaleFactor = dispatchEntry->scaleFactor;
xOffset = dispatchEntry->xOffset * scaleFactor;
yOffset = dispatchEntry->yOffset * scaleFactor;
if (scaleFactor != 1.0f) {
@@ -2008,7 +2009,6 @@
} else {
xOffset = 0.0f;
yOffset = 0.0f;
- scaleFactor = 1.0f;
// We don't want the dispatch target to know.
if (dispatchEntry->targetFlags & InputTarget::FLAG_ZERO_COORDS) {
@@ -2231,7 +2231,7 @@
if (!cancelationEvents.isEmpty()) {
#if DEBUG_OUTBOUND_EVENT_DETAILS
- ALOGD("channel '%s' ~ Synthesized %d cancelation events to bring channel back in sync "
+ ALOGD("channel '%s' ~ Synthesized %zu cancelation events to bring channel back in sync "
"with reality: %s, mode=%d.",
connection->getInputChannelName(), cancelationEvents.size(),
options.reason, options.mode);
@@ -2367,7 +2367,7 @@
void InputDispatcher::notifyConfigurationChanged(const NotifyConfigurationChangedArgs* args) {
#if DEBUG_INBOUND_EVENT_DETAILS
- ALOGD("notifyConfigurationChanged - eventTime=%lld", args->eventTime);
+ ALOGD("notifyConfigurationChanged - eventTime=%" PRId64, args->eventTime);
#endif
bool needWake;
@@ -2385,8 +2385,9 @@
void InputDispatcher::notifyKey(const NotifyKeyArgs* args) {
#if DEBUG_INBOUND_EVENT_DETAILS
- ALOGD("notifyKey - eventTime=%lld, deviceId=%d, source=0x%x, policyFlags=0x%x, action=0x%x, "
- "flags=0x%x, keyCode=0x%x, scanCode=0x%x, metaState=0x%x, downTime=%lld",
+ ALOGD("notifyKey - eventTime=%" PRId64
+ ", deviceId=%d, source=0x%x, policyFlags=0x%x, action=0x%x, "
+ "flags=0x%x, keyCode=0x%x, scanCode=0x%x, metaState=0x%x, downTime=%" PRId64,
args->eventTime, args->deviceId, args->source, args->policyFlags,
args->action, args->flags, args->keyCode, args->scanCode,
args->metaState, args->downTime);
@@ -2480,9 +2481,9 @@
void InputDispatcher::notifyMotion(const NotifyMotionArgs* args) {
#if DEBUG_INBOUND_EVENT_DETAILS
- ALOGD("notifyMotion - eventTime=%lld, deviceId=%d, source=0x%x, policyFlags=0x%x, "
+ ALOGD("notifyMotion - eventTime=%" PRId64 ", deviceId=%d, source=0x%x, policyFlags=0x%x, "
"action=0x%x, actionButton=0x%x, flags=0x%x, metaState=0x%x, buttonState=0x%x,"
- "edgeFlags=0x%x, xPrecision=%f, yPrecision=%f, downTime=%lld",
+ "edgeFlags=0x%x, xPrecision=%f, yPrecision=%f, downTime=%" PRId64,
args->eventTime, args->deviceId, args->source, args->policyFlags,
args->action, args->actionButton, args->flags, args->metaState, args->buttonState,
args->edgeFlags, args->xPrecision, args->yPrecision, args->downTime);
@@ -2560,9 +2561,9 @@
void InputDispatcher::notifySwitch(const NotifySwitchArgs* args) {
#if DEBUG_INBOUND_EVENT_DETAILS
- ALOGD("notifySwitch - eventTime=%lld, policyFlags=0x%x, switchValues=0x%08x, switchMask=0x%08x",
- args->eventTime, args->policyFlags,
- args->switchValues, args->switchMask);
+ ALOGD("notifySwitch - eventTime=%" PRId64 ", policyFlags=0x%x, switchValues=0x%08x, "
+ "switchMask=0x%08x",
+ args->eventTime, args->policyFlags, args->switchValues, args->switchMask);
#endif
uint32_t policyFlags = args->policyFlags;
@@ -2573,7 +2574,7 @@
void InputDispatcher::notifyDeviceReset(const NotifyDeviceResetArgs* args) {
#if DEBUG_INBOUND_EVENT_DETAILS
- ALOGD("notifyDeviceReset - eventTime=%lld, deviceId=%d",
+ ALOGD("notifyDeviceReset - eventTime=%" PRId64 ", deviceId=%d",
args->eventTime, args->deviceId);
#endif
@@ -2902,7 +2903,7 @@
for (size_t d = 0; d < mTouchStatesByDisplay.size(); d++) {
TouchState& state = mTouchStatesByDisplay.editValueAt(d);
- for (size_t i = 0; i < state.windows.size(); i++) {
+ for (size_t i = 0; i < state.windows.size(); ) {
TouchedWindow& touchedWindow = state.windows.editItemAt(i);
if (!hasWindowHandleLocked(touchedWindow.windowHandle)) {
#if DEBUG_FOCUS
@@ -2917,7 +2918,9 @@
synthesizeCancelationEventsForInputChannelLocked(
touchedInputChannel, options);
}
- state.windows.removeAt(i--);
+ state.windows.removeAt(i);
+ } else {
+ ++i;
}
}
}
@@ -3741,7 +3744,7 @@
msg.appendFormat(", %d->%d", fallbackKeys.keyAt(i),
fallbackKeys.valueAt(i));
}
- ALOGD("Unhandled key event: %d currently tracked fallback keys%s.",
+ ALOGD("Unhandled key event: %zu currently tracked fallback keys%s.",
fallbackKeys.size(), msg.string());
}
#endif
diff --git a/services/inputflinger/InputReader.cpp b/services/inputflinger/InputReader.cpp
index d4266f6..591f8d7 100644
--- a/services/inputflinger/InputReader.cpp
+++ b/services/inputflinger/InputReader.cpp
@@ -429,7 +429,7 @@
batchSize += 1;
}
#if DEBUG_RAW_EVENTS
- ALOGD("BatchSize: %d Count: %d", batchSize, count);
+ ALOGD("BatchSize: %zu Count: %zu", batchSize, count);
#endif
processEventsForDeviceLocked(deviceId, rawEvent, batchSize);
} else {
@@ -1174,9 +1174,9 @@
// gamepad button presses are handled by different mappers but they should be dispatched
// in the order received.
size_t numMappers = mMappers.size();
- for (const RawEvent* rawEvent = rawEvents; count--; rawEvent++) {
+ for (const RawEvent* rawEvent = rawEvents; count != 0; rawEvent++) {
#if DEBUG_RAW_EVENTS
- ALOGD("Input event: device=%d type=0x%04x code=0x%04x value=0x%08x when=%lld",
+ ALOGD("Input event: device=%d type=0x%04x code=0x%04x value=0x%08x when=%" PRId64,
rawEvent->deviceId, rawEvent->type, rawEvent->code, rawEvent->value,
rawEvent->when);
#endif
@@ -1202,6 +1202,7 @@
mapper->process(rawEvent);
}
}
+ --count;
}
}
@@ -1851,7 +1852,7 @@
#if DEBUG_POINTERS
if (newSlot) {
ALOGW("MultiTouch device emitted invalid slot index %d but it "
- "should be between 0 and %d; ignoring this slot.",
+ "should be between 0 and %zd; ignoring this slot.",
mCurrentSlot, mSlotCount - 1);
}
#endif
@@ -2147,9 +2148,9 @@
if (i != 0) {
patternStr.append(", ");
}
- patternStr.appendFormat("%lld", pattern[i]);
+ patternStr.appendFormat("%" PRId64, pattern[i]);
}
- ALOGD("vibrate: deviceId=%d, pattern=[%s], repeat=%ld, token=%d",
+ ALOGD("vibrate: deviceId=%d, pattern=[%s], repeat=%zd, token=%d",
getDeviceId(), patternStr.string(), repeat, token);
#endif
@@ -2198,8 +2199,7 @@
nsecs_t duration = mPattern[mIndex];
if (vibratorOn) {
#if DEBUG_VIBRATOR
- ALOGD("nextStep: sending vibrate deviceId=%d, duration=%lld",
- getDeviceId(), duration);
+ ALOGD("nextStep: sending vibrate deviceId=%d, duration=%" PRId64, getDeviceId(), duration);
#endif
getEventHub()->vibrate(getDeviceId(), duration);
} else {
@@ -2259,7 +2259,7 @@
dump.appendFormat(INDENT3 "Orientation: %d\n", mOrientation);
dump.appendFormat(INDENT3 "KeyDowns: %zu keys currently down\n", mKeyDowns.size());
dump.appendFormat(INDENT3 "MetaState: 0x%0x\n", mMetaState);
- dump.appendFormat(INDENT3 "DownTime: %lld\n", (long long)mDownTime);
+ dump.appendFormat(INDENT3 "DownTime: %" PRId64 "\n", mDownTime);
}
@@ -2620,7 +2620,7 @@
dump.appendFormat(INDENT3 "Orientation: %d\n", mOrientation);
dump.appendFormat(INDENT3 "ButtonState: 0x%08x\n", mButtonState);
dump.appendFormat(INDENT3 "Down: %s\n", toString(isPointerDown(mButtonState)));
- dump.appendFormat(INDENT3 "DownTime: %lld\n", (long long)mDownTime);
+ dump.appendFormat(INDENT3 "DownTime: %" PRId64 "\n", mDownTime);
}
void CursorInputMapper::configure(nsecs_t when,
@@ -5509,18 +5509,15 @@
// Otherwise choose an arbitrary remaining pointer.
// This guarantees we always have an active touch id when there is at least one pointer.
// We keep the same active touch id for as long as possible.
- bool activeTouchChanged = false;
int32_t lastActiveTouchId = mPointerGesture.activeTouchId;
int32_t activeTouchId = lastActiveTouchId;
if (activeTouchId < 0) {
if (!mCurrentCookedState.fingerIdBits.isEmpty()) {
- activeTouchChanged = true;
activeTouchId = mPointerGesture.activeTouchId =
mCurrentCookedState.fingerIdBits.firstMarkedBit();
mPointerGesture.firstTouchTime = when;
}
} else if (!mCurrentCookedState.fingerIdBits.hasBit(activeTouchId)) {
- activeTouchChanged = true;
if (!mCurrentCookedState.fingerIdBits.isEmpty()) {
activeTouchId = mPointerGesture.activeTouchId =
mCurrentCookedState.fingerIdBits.firstMarkedBit();
@@ -5616,7 +5613,6 @@
}
if (bestId >= 0 && bestId != activeTouchId) {
mPointerGesture.activeTouchId = activeTouchId = bestId;
- activeTouchChanged = true;
#if DEBUG_GESTURES
ALOGD("Gestures: BUTTON_CLICK_OR_DRAG switched pointers, "
"bestId=%d, bestSpeed=%0.3f", bestId, bestSpeed);
@@ -6631,7 +6627,7 @@
#if DEBUG_POINTER_ASSIGNMENT
ALOGD("assignPointerIds - initial distance min-heap: size=%d", heapSize);
for (size_t i = 0; i < heapSize; i++) {
- ALOGD(" heap[%d]: cur=%d, last=%d, distance=%lld",
+ ALOGD(" heap[%zu]: cur=%" PRIu32 ", last=%" PRIu32 ", distance=%" PRIu64,
i, heap[i].currentPointerIndex, heap[i].lastPointerIndex,
heap[i].distance);
}
@@ -6677,7 +6673,7 @@
#if DEBUG_POINTER_ASSIGNMENT
ALOGD("assignPointerIds - reduced distance min-heap: size=%d", heapSize);
for (size_t i = 0; i < heapSize; i++) {
- ALOGD(" heap[%d]: cur=%d, last=%d, distance=%lld",
+ ALOGD(" heap[%zu]: cur=%" PRIu32 ", last=%" PRIu32 ", distance=%" PRIu64,
i, heap[i].currentPointerIndex, heap[i].lastPointerIndex,
heap[i].distance);
}
@@ -6703,7 +6699,8 @@
usedIdBits.markBit(id);
#if DEBUG_POINTER_ASSIGNMENT
- ALOGD("assignPointerIds - matched: cur=%d, last=%d, id=%d, distance=%lld",
+ ALOGD("assignPointerIds - matched: cur=%" PRIu32 ", last=%" PRIu32
+ ", id=%" PRIu32 ", distance=%" PRIu64,
lastPointerIndex, currentPointerIndex, id, heap[0].distance);
#endif
break;
@@ -6721,8 +6718,7 @@
current->rawPointerData.isHovering(currentPointerIndex));
#if DEBUG_POINTER_ASSIGNMENT
- ALOGD("assignPointerIds - assigned: cur=%d, id=%d",
- currentPointerIndex, id);
+ ALOGD("assignPointerIds - assigned: cur=%" PRIu32 ", id=%" PRIu32, currentPointerIndex, id);
#endif
}
}
diff --git a/services/inputflinger/tests/Android.bp b/services/inputflinger/tests/Android.bp
index a49c8c8..8a35509 100644
--- a/services/inputflinger/tests/Android.bp
+++ b/services/inputflinger/tests/Android.bp
@@ -19,7 +19,6 @@
"libhardware",
"libhardware_legacy",
"libui",
- "libskia",
"libinput",
"libinputflinger",
"libinputservice",
diff --git a/services/sensorservice/BatteryService.cpp b/services/sensorservice/BatteryService.cpp
index 452c8c6..330861d 100644
--- a/services/sensorservice/BatteryService.cpp
+++ b/services/sensorservice/BatteryService.cpp
@@ -78,12 +78,13 @@
if (checkService()) {
Mutex::Autolock _l(mActivationsLock);
int64_t identity = IPCThreadState::self()->clearCallingIdentity();
- for (size_t i=0 ; i<mActivations.size() ; i++) {
+ for (size_t i=0 ; i<mActivations.size() ; ) {
const Info& info(mActivations[i]);
if (info.uid == uid) {
mBatteryStatService->noteStopSensor(info.uid, info.handle);
mActivations.removeAt(i);
- i--;
+ } else {
+ i++;
}
}
IPCThreadState::self()->restoreCallingIdentity(identity);
@@ -105,4 +106,3 @@
// ---------------------------------------------------------------------------
}; // namespace android
-
diff --git a/services/sensorservice/OWNERS b/services/sensorservice/OWNERS
new file mode 100644
index 0000000..6a38a1f
--- /dev/null
+++ b/services/sensorservice/OWNERS
@@ -0,0 +1,2 @@
+ashutoshj@google.com
+pengxu@google.com
diff --git a/services/sensorservice/SensorDevice.cpp b/services/sensorservice/SensorDevice.cpp
index 535d0db..fdb69d3 100644
--- a/services/sensorservice/SensorDevice.cpp
+++ b/services/sensorservice/SensorDevice.cpp
@@ -217,8 +217,13 @@
}
void SensorDevice::autoDisable(void *ident, int handle) {
- Info& info( mActivationCount.editValueFor(handle) );
Mutex::Autolock _l(mLock);
+ ssize_t activationIndex = mActivationCount.indexOfKey(handle);
+ if (activationIndex < 0) {
+ ALOGW("Handle %d cannot be found in activation record", handle);
+ return;
+ }
+ Info& info(mActivationCount.editValueAt(activationIndex));
info.removeBatchParamsForIdent(ident);
}
@@ -229,7 +234,12 @@
bool actuateHardware = false;
Mutex::Autolock _l(mLock);
- Info& info( mActivationCount.editValueFor(handle) );
+ ssize_t activationIndex = mActivationCount.indexOfKey(handle);
+ if (activationIndex < 0) {
+ ALOGW("Handle %d cannot be found in activation record", handle);
+ return BAD_VALUE;
+ }
+ Info& info(mActivationCount.editValueAt(activationIndex));
ALOGD_IF(DEBUG_CONNECTIONS,
"SensorDevice::activate: ident=%p, handle=0x%08x, enabled=%d, count=%zu",
@@ -323,7 +333,12 @@
ident, handle, flags, samplingPeriodNs, maxBatchReportLatencyNs);
Mutex::Autolock _l(mLock);
- Info& info(mActivationCount.editValueFor(handle));
+ ssize_t activationIndex = mActivationCount.indexOfKey(handle);
+ if (activationIndex < 0) {
+ ALOGW("Handle %d cannot be found in activation record", handle);
+ return BAD_VALUE;
+ }
+ Info& info(mActivationCount.editValueAt(activationIndex));
if (info.batchParams.indexOfKey(ident) < 0) {
BatchParams params(samplingPeriodNs, maxBatchReportLatencyNs);
diff --git a/services/sensorservice/SensorDeviceUtils.cpp b/services/sensorservice/SensorDeviceUtils.cpp
index b1344be..dbafffe 100644
--- a/services/sensorservice/SensorDeviceUtils.cpp
+++ b/services/sensorservice/SensorDeviceUtils.cpp
@@ -28,8 +28,13 @@
namespace android {
namespace SensorDeviceUtils {
-HidlServiceRegistrationWaiter::HidlServiceRegistrationWaiter()
- : mRegistered(ISensors::registerForNotifications("default", this)) {
+HidlServiceRegistrationWaiter::HidlServiceRegistrationWaiter() {
+}
+
+void HidlServiceRegistrationWaiter::onFirstRef() {
+ // Creating sp<...>(this) in the constructor should be avoided, hence
+ // registerForNotifications is called in onFirstRef callback.
+ mRegistered = ISensors::registerForNotifications("default", this);
}
Return<void> HidlServiceRegistrationWaiter::onRegistration(
diff --git a/services/sensorservice/SensorDeviceUtils.h b/services/sensorservice/SensorDeviceUtils.h
index da36928..e2eb606 100644
--- a/services/sensorservice/SensorDeviceUtils.h
+++ b/services/sensorservice/SensorDeviceUtils.h
@@ -46,8 +46,10 @@
* @return true if service is restart since last reset(); false otherwise.
*/
bool wait();
+protected:
+ void onFirstRef() override;
private:
- const bool mRegistered;
+ bool mRegistered;
std::mutex mLock;
std::condition_variable mCondition;
diff --git a/services/surfaceflinger/Android.bp b/services/surfaceflinger/Android.bp
index 4775e4e..bd7f0ea 100644
--- a/services/surfaceflinger/Android.bp
+++ b/services/surfaceflinger/Android.bp
@@ -1,6 +1,8 @@
cc_library_static {
name: "libsurfaceflingerincludes",
export_include_dirs: ["."],
+ static_libs = ["libserviceutils"],
+ export_static_lib_headers = ["libserviceutils"],
}
-subdirs = ["tests/fakehwc"]
\ No newline at end of file
+subdirs = ["tests/fakehwc", "layerproto"]
\ No newline at end of file
diff --git a/services/surfaceflinger/Android.mk b/services/surfaceflinger/Android.mk
index 38529b6..7115ad6 100644
--- a/services/surfaceflinger/Android.mk
+++ b/services/surfaceflinger/Android.mk
@@ -14,13 +14,15 @@
FrameTracker.cpp \
GpuService.cpp \
Layer.cpp \
- LayerDim.cpp \
+ BufferLayer.cpp \
+ ColorLayer.cpp \
LayerRejecter.cpp \
LayerVector.cpp \
MessageQueue.cpp \
MonitoredProducer.cpp \
SurfaceFlingerConsumer.cpp \
SurfaceInterceptor.cpp \
+ SurfaceTracing.cpp \
Transform.cpp \
DisplayHardware/ComposerHal.cpp \
DisplayHardware/FramebufferSurface.cpp \
@@ -39,6 +41,8 @@
RenderEngine/RenderEngine.cpp \
RenderEngine/Texture.cpp \
RenderEngine/GLES20RenderEngine.cpp \
+ LayerProtoHelper.cpp \
+ RenderArea.cpp \
LOCAL_MODULE := libsurfaceflinger
LOCAL_C_INCLUDES := \
@@ -67,7 +71,10 @@
libtrace_proto \
libvkjson \
libvr_manager \
- libvrflinger
+ libvrflinger \
+ libserviceutils
+
+LOCAL_EXPORT_STATIC_LIBRARY_HEADERS := libserviceutils
LOCAL_SHARED_LIBRARIES := \
android.frameworks.vr.composer@1.0 \
@@ -95,7 +102,8 @@
libsync \
libprotobuf-cpp-lite \
libbase \
- android.hardware.power@1.0
+ android.hardware.power@1.0 \
+ liblayers_proto
LOCAL_EXPORT_SHARED_LIBRARY_HEADERS := \
android.hardware.graphics.allocator@2.0 \
@@ -142,10 +150,12 @@
libutils \
libui \
libgui \
- libdl
+ libdl \
+ liblayers_proto
LOCAL_WHOLE_STATIC_LIBRARIES := libsigchain
-LOCAL_STATIC_LIBRARIES := libtrace_proto
+LOCAL_STATIC_LIBRARIES := libtrace_proto \
+ libserviceutils
LOCAL_MODULE := surfaceflinger
diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp
new file mode 100644
index 0000000..fc0949d
--- /dev/null
+++ b/services/surfaceflinger/BufferLayer.cpp
@@ -0,0 +1,1002 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#undef LOG_TAG
+#define LOG_TAG "BufferLayer"
+#define ATRACE_TAG ATRACE_TAG_GRAPHICS
+
+#include "BufferLayer.h"
+#include "Colorizer.h"
+#include "DisplayDevice.h"
+#include "LayerRejecter.h"
+#include "clz.h"
+
+#include "RenderEngine/RenderEngine.h"
+
+#include <gui/BufferItem.h>
+#include <gui/BufferQueue.h>
+#include <gui/LayerDebugInfo.h>
+#include <gui/Surface.h>
+
+#include <ui/DebugUtils.h>
+
+#include <utils/Errors.h>
+#include <utils/Log.h>
+#include <utils/NativeHandle.h>
+#include <utils/StopWatch.h>
+#include <utils/Trace.h>
+
+#include <cutils/compiler.h>
+#include <cutils/native_handle.h>
+#include <cutils/properties.h>
+
+#include <math.h>
+#include <stdlib.h>
+#include <mutex>
+
+namespace android {
+
+BufferLayer::BufferLayer(SurfaceFlinger* flinger, const sp<Client>& client, const String8& name,
+ uint32_t w, uint32_t h, uint32_t flags)
+ : Layer(flinger, client, name, w, h, flags),
+ mSurfaceFlingerConsumer(nullptr),
+ mTextureName(UINT32_MAX),
+ mFormat(PIXEL_FORMAT_NONE),
+ mCurrentScalingMode(NATIVE_WINDOW_SCALING_MODE_FREEZE),
+ mBufferLatched(false),
+ mPreviousFrameNumber(0),
+ mUpdateTexImageFailed(false),
+ mRefreshPending(false) {
+#ifdef USE_HWC2
+ ALOGV("Creating Layer %s", name.string());
+#endif
+
+ mFlinger->getRenderEngine().genTextures(1, &mTextureName);
+ mTexture.init(Texture::TEXTURE_EXTERNAL, mTextureName);
+
+ if (flags & ISurfaceComposerClient::eNonPremultiplied) mPremultipliedAlpha = false;
+
+ mCurrentState.requested = mCurrentState.active;
+
+ // drawing state & current state are identical
+ mDrawingState = mCurrentState;
+}
+
+BufferLayer::~BufferLayer() {
+ sp<Client> c(mClientRef.promote());
+ if (c != 0) {
+ c->detachLayer(this);
+ }
+
+ for (auto& point : mRemoteSyncPoints) {
+ point->setTransactionApplied();
+ }
+ for (auto& point : mLocalSyncPoints) {
+ point->setFrameAvailable();
+ }
+ mFlinger->deleteTextureAsync(mTextureName);
+
+#ifdef USE_HWC2
+ if (!mHwcLayers.empty()) {
+ ALOGE("Found stale hardware composer layers when destroying "
+ "surface flinger layer %s",
+ mName.string());
+ destroyAllHwcLayers();
+ }
+#endif
+}
+
+void BufferLayer::useSurfaceDamage() {
+ if (mFlinger->mForceFullDamage) {
+ surfaceDamageRegion = Region::INVALID_REGION;
+ } else {
+ surfaceDamageRegion = mSurfaceFlingerConsumer->getSurfaceDamage();
+ }
+}
+
+void BufferLayer::useEmptyDamage() {
+ surfaceDamageRegion.clear();
+}
+
+bool BufferLayer::isProtected() const {
+ const sp<GraphicBuffer>& activeBuffer(mActiveBuffer);
+ return (activeBuffer != 0) && (activeBuffer->getUsage() & GRALLOC_USAGE_PROTECTED);
+}
+
+bool BufferLayer::isVisible() const {
+ return !(isHiddenByPolicy()) && getAlpha() > 0.0f &&
+ (mActiveBuffer != NULL || mSidebandStream != NULL);
+}
+
+bool BufferLayer::isFixedSize() const {
+ return getEffectiveScalingMode() != NATIVE_WINDOW_SCALING_MODE_FREEZE;
+}
+
+status_t BufferLayer::setBuffers(uint32_t w, uint32_t h, PixelFormat format, uint32_t flags) {
+ uint32_t const maxSurfaceDims =
+ min(mFlinger->getMaxTextureSize(), mFlinger->getMaxViewportDims());
+
+ // never allow a surface larger than what our underlying GL implementation
+ // can handle.
+ if ((uint32_t(w) > maxSurfaceDims) || (uint32_t(h) > maxSurfaceDims)) {
+ ALOGE("dimensions too large %u x %u", uint32_t(w), uint32_t(h));
+ return BAD_VALUE;
+ }
+
+ mFormat = format;
+
+ mPotentialCursor = (flags & ISurfaceComposerClient::eCursorWindow) ? true : false;
+ mProtectedByApp = (flags & ISurfaceComposerClient::eProtectedByApp) ? true : false;
+ mCurrentOpacity = getOpacityForFormat(format);
+
+ mSurfaceFlingerConsumer->setDefaultBufferSize(w, h);
+ mSurfaceFlingerConsumer->setDefaultBufferFormat(format);
+ mSurfaceFlingerConsumer->setConsumerUsageBits(getEffectiveUsage(0));
+
+ return NO_ERROR;
+}
+
+static constexpr mat4 inverseOrientation(uint32_t transform) {
+ const mat4 flipH(-1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1);
+ const mat4 flipV(1, 0, 0, 0, 0, -1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1);
+ const mat4 rot90(0, 1, 0, 0, -1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1);
+ mat4 tr;
+
+ if (transform & NATIVE_WINDOW_TRANSFORM_ROT_90) {
+ tr = tr * rot90;
+ }
+ if (transform & NATIVE_WINDOW_TRANSFORM_FLIP_H) {
+ tr = tr * flipH;
+ }
+ if (transform & NATIVE_WINDOW_TRANSFORM_FLIP_V) {
+ tr = tr * flipV;
+ }
+ return inverse(tr);
+}
+
+/*
+ * onDraw will draw the current layer onto the presentable buffer
+ */
+void BufferLayer::onDraw(const RenderArea& renderArea, const Region& clip,
+ bool useIdentityTransform) const {
+ ATRACE_CALL();
+
+ if (CC_UNLIKELY(mActiveBuffer == 0)) {
+ // the texture has not been created yet, this Layer has
+ // in fact never been drawn into. This happens frequently with
+ // SurfaceView because the WindowManager can't know when the client
+ // has drawn the first time.
+
+ // If there is nothing under us, we paint the screen in black, otherwise
+ // we just skip this update.
+
+ // figure out if there is something below us
+ Region under;
+ bool finished = false;
+ mFlinger->mDrawingState.traverseInZOrder([&](Layer* layer) {
+ if (finished || layer == static_cast<BufferLayer const*>(this)) {
+ finished = true;
+ return;
+ }
+ under.orSelf(renderArea.getTransform().transform(layer->visibleRegion));
+ });
+ // if not everything below us is covered, we plug the holes!
+ Region holes(clip.subtract(under));
+ if (!holes.isEmpty()) {
+ clearWithOpenGL(renderArea, 0, 0, 0, 1);
+ }
+ return;
+ }
+
+ // Bind the current buffer to the GL texture, and wait for it to be
+ // ready for us to draw into.
+ status_t err = mSurfaceFlingerConsumer->bindTextureImage();
+ if (err != NO_ERROR) {
+ ALOGW("onDraw: bindTextureImage failed (err=%d)", err);
+ // Go ahead and draw the buffer anyway; no matter what we do the screen
+ // is probably going to have something visibly wrong.
+ }
+
+ bool blackOutLayer = isProtected() || (isSecure() && !renderArea.isSecure());
+
+ RenderEngine& engine(mFlinger->getRenderEngine());
+
+ if (!blackOutLayer) {
+ // TODO: we could be more subtle with isFixedSize()
+ const bool useFiltering = getFiltering() || needsFiltering(renderArea) || isFixedSize();
+
+ // Query the texture matrix given our current filtering mode.
+ float textureMatrix[16];
+ mSurfaceFlingerConsumer->setFilteringEnabled(useFiltering);
+ mSurfaceFlingerConsumer->getTransformMatrix(textureMatrix);
+
+ if (getTransformToDisplayInverse()) {
+ /*
+ * the code below applies the primary display's inverse transform to
+ * the texture transform
+ */
+ uint32_t transform = DisplayDevice::getPrimaryDisplayOrientationTransform();
+ mat4 tr = inverseOrientation(transform);
+
+ /**
+ * TODO(b/36727915): This is basically a hack.
+ *
+ * Ensure that regardless of the parent transformation,
+ * this buffer is always transformed from native display
+ * orientation to display orientation. For example, in the case
+ * of a camera where the buffer remains in native orientation,
+ * we want the pixels to always be upright.
+ */
+ sp<Layer> p = mDrawingParent.promote();
+ if (p != nullptr) {
+ const auto parentTransform = p->getTransform();
+ tr = tr * inverseOrientation(parentTransform.getOrientation());
+ }
+
+ // and finally apply it to the original texture matrix
+ const mat4 texTransform(mat4(static_cast<const float*>(textureMatrix)) * tr);
+ memcpy(textureMatrix, texTransform.asArray(), sizeof(textureMatrix));
+ }
+
+ // Set things up for texturing.
+ mTexture.setDimensions(mActiveBuffer->getWidth(), mActiveBuffer->getHeight());
+ mTexture.setFiltering(useFiltering);
+ mTexture.setMatrix(textureMatrix);
+
+ engine.setupLayerTexturing(mTexture);
+ } else {
+ engine.setupLayerBlackedOut();
+ }
+ drawWithOpenGL(renderArea, useIdentityTransform);
+ engine.disableTexturing();
+}
+
+#ifdef USE_HWC2
+void BufferLayer::onLayerDisplayed(const sp<Fence>& releaseFence) {
+ if (mHwcLayers.empty()) {
+ return;
+ }
+ mSurfaceFlingerConsumer->setReleaseFence(releaseFence);
+}
+#else
+void BufferLayer::onLayerDisplayed(const sp<const DisplayDevice>& /*hw*/,
+ HWComposer::HWCLayerInterface* layer) {
+ if (layer) {
+ layer->onDisplayed();
+ mSurfaceFlingerConsumer->setReleaseFence(layer->getAndResetReleaseFence());
+ }
+}
+#endif
+
+void BufferLayer::abandon() {
+ mSurfaceFlingerConsumer->abandon();
+}
+
+bool BufferLayer::shouldPresentNow(const DispSync& dispSync) const {
+ if (mSidebandStreamChanged || mAutoRefresh) {
+ return true;
+ }
+
+ Mutex::Autolock lock(mQueueItemLock);
+ if (mQueueItems.empty()) {
+ return false;
+ }
+ auto timestamp = mQueueItems[0].mTimestamp;
+ nsecs_t expectedPresent = mSurfaceFlingerConsumer->computeExpectedPresent(dispSync);
+
+ // Ignore timestamps more than a second in the future
+ bool isPlausible = timestamp < (expectedPresent + s2ns(1));
+ ALOGW_IF(!isPlausible,
+ "[%s] Timestamp %" PRId64 " seems implausible "
+ "relative to expectedPresent %" PRId64,
+ mName.string(), timestamp, expectedPresent);
+
+ bool isDue = timestamp < expectedPresent;
+ return isDue || !isPlausible;
+}
+
+void BufferLayer::setTransformHint(uint32_t orientation) const {
+ mSurfaceFlingerConsumer->setTransformHint(orientation);
+}
+
+bool BufferLayer::onPreComposition(nsecs_t refreshStartTime) {
+ if (mBufferLatched) {
+ Mutex::Autolock lock(mFrameEventHistoryMutex);
+ mFrameEventHistory.addPreComposition(mCurrentFrameNumber, refreshStartTime);
+ }
+ mRefreshPending = false;
+ return mQueuedFrames > 0 || mSidebandStreamChanged || mAutoRefresh;
+}
+bool BufferLayer::onPostComposition(const std::shared_ptr<FenceTime>& glDoneFence,
+ const std::shared_ptr<FenceTime>& presentFence,
+ const CompositorTiming& compositorTiming) {
+ // mFrameLatencyNeeded is true when a new frame was latched for the
+ // composition.
+ if (!mFrameLatencyNeeded) return false;
+
+ // Update mFrameEventHistory.
+ {
+ Mutex::Autolock lock(mFrameEventHistoryMutex);
+ mFrameEventHistory.addPostComposition(mCurrentFrameNumber, glDoneFence, presentFence,
+ compositorTiming);
+ }
+
+ // Update mFrameTracker.
+ nsecs_t desiredPresentTime = mSurfaceFlingerConsumer->getTimestamp();
+ mFrameTracker.setDesiredPresentTime(desiredPresentTime);
+
+ std::shared_ptr<FenceTime> frameReadyFence = mSurfaceFlingerConsumer->getCurrentFenceTime();
+ if (frameReadyFence->isValid()) {
+ mFrameTracker.setFrameReadyFence(std::move(frameReadyFence));
+ } else {
+ // There was no fence for this frame, so assume that it was ready
+ // to be presented at the desired present time.
+ mFrameTracker.setFrameReadyTime(desiredPresentTime);
+ }
+
+ if (presentFence->isValid()) {
+ mFrameTracker.setActualPresentFence(std::shared_ptr<FenceTime>(presentFence));
+ } else {
+ // The HWC doesn't support present fences, so use the refresh
+ // timestamp instead.
+ mFrameTracker.setActualPresentTime(
+ mFlinger->getHwComposer().getRefreshTimestamp(HWC_DISPLAY_PRIMARY));
+ }
+
+ mFrameTracker.advanceFrame();
+ mFrameLatencyNeeded = false;
+ return true;
+}
+
+std::vector<OccupancyTracker::Segment> BufferLayer::getOccupancyHistory(bool forceFlush) {
+ std::vector<OccupancyTracker::Segment> history;
+ status_t result = mSurfaceFlingerConsumer->getOccupancyHistory(forceFlush, &history);
+ if (result != NO_ERROR) {
+ ALOGW("[%s] Failed to obtain occupancy history (%d)", mName.string(), result);
+ return {};
+ }
+ return history;
+}
+
+bool BufferLayer::getTransformToDisplayInverse() const {
+ return mSurfaceFlingerConsumer->getTransformToDisplayInverse();
+}
+
+#ifdef USE_HWC2
+void BufferLayer::releasePendingBuffer(nsecs_t dequeueReadyTime) {
+ if (!mSurfaceFlingerConsumer->releasePendingBuffer()) {
+ return;
+ }
+
+ auto releaseFenceTime =
+ std::make_shared<FenceTime>(mSurfaceFlingerConsumer->getPrevFinalReleaseFence());
+ mReleaseTimeline.updateSignalTimes();
+ mReleaseTimeline.push(releaseFenceTime);
+
+ Mutex::Autolock lock(mFrameEventHistoryMutex);
+ if (mPreviousFrameNumber != 0) {
+ mFrameEventHistory.addRelease(mPreviousFrameNumber, dequeueReadyTime,
+ std::move(releaseFenceTime));
+ }
+}
+#endif
+
+Region BufferLayer::latchBuffer(bool& recomputeVisibleRegions, nsecs_t latchTime) {
+ ATRACE_CALL();
+
+ if (android_atomic_acquire_cas(true, false, &mSidebandStreamChanged) == 0) {
+ // mSidebandStreamChanged was true
+ mSidebandStream = mSurfaceFlingerConsumer->getSidebandStream();
+ if (mSidebandStream != NULL) {
+ setTransactionFlags(eTransactionNeeded);
+ mFlinger->setTransactionFlags(eTraversalNeeded);
+ }
+ recomputeVisibleRegions = true;
+
+ const State& s(getDrawingState());
+ return getTransform().transform(Region(Rect(s.active.w, s.active.h)));
+ }
+
+ Region outDirtyRegion;
+ if (mQueuedFrames <= 0 && !mAutoRefresh) {
+ return outDirtyRegion;
+ }
+
+ // if we've already called updateTexImage() without going through
+ // a composition step, we have to skip this layer at this point
+ // because we cannot call updateTeximage() without a corresponding
+ // compositionComplete() call.
+ // we'll trigger an update in onPreComposition().
+ if (mRefreshPending) {
+ return outDirtyRegion;
+ }
+
+ // If the head buffer's acquire fence hasn't signaled yet, return and
+ // try again later
+ if (!headFenceHasSignaled()) {
+ mFlinger->signalLayerUpdate();
+ return outDirtyRegion;
+ }
+
+ // Capture the old state of the layer for comparisons later
+ const State& s(getDrawingState());
+ const bool oldOpacity = isOpaque(s);
+ sp<GraphicBuffer> oldActiveBuffer = mActiveBuffer;
+
+ if (!allTransactionsSignaled()) {
+ mFlinger->signalLayerUpdate();
+ return outDirtyRegion;
+ }
+
+ // This boolean is used to make sure that SurfaceFlinger's shadow copy
+ // of the buffer queue isn't modified when the buffer queue is returning
+ // BufferItem's that weren't actually queued. This can happen in shared
+ // buffer mode.
+ bool queuedBuffer = false;
+ LayerRejecter r(mDrawingState, getCurrentState(), recomputeVisibleRegions,
+ getProducerStickyTransform() != 0, mName.string(), mOverrideScalingMode,
+ mFreezeGeometryUpdates);
+ status_t updateResult =
+ mSurfaceFlingerConsumer->updateTexImage(&r, mFlinger->mPrimaryDispSync, &mAutoRefresh,
+ &queuedBuffer, mLastFrameNumberReceived);
+ if (updateResult == BufferQueue::PRESENT_LATER) {
+ // Producer doesn't want buffer to be displayed yet. Signal a
+ // layer update so we check again at the next opportunity.
+ mFlinger->signalLayerUpdate();
+ return outDirtyRegion;
+ } else if (updateResult == SurfaceFlingerConsumer::BUFFER_REJECTED) {
+ // If the buffer has been rejected, remove it from the shadow queue
+ // and return early
+ if (queuedBuffer) {
+ Mutex::Autolock lock(mQueueItemLock);
+ mQueueItems.removeAt(0);
+ android_atomic_dec(&mQueuedFrames);
+ }
+ return outDirtyRegion;
+ } else if (updateResult != NO_ERROR || mUpdateTexImageFailed) {
+ // This can occur if something goes wrong when trying to create the
+ // EGLImage for this buffer. If this happens, the buffer has already
+ // been released, so we need to clean up the queue and bug out
+ // early.
+ if (queuedBuffer) {
+ Mutex::Autolock lock(mQueueItemLock);
+ mQueueItems.clear();
+ android_atomic_and(0, &mQueuedFrames);
+ }
+
+ // Once we have hit this state, the shadow queue may no longer
+ // correctly reflect the incoming BufferQueue's contents, so even if
+ // updateTexImage starts working, the only safe course of action is
+ // to continue to ignore updates.
+ mUpdateTexImageFailed = true;
+
+ return outDirtyRegion;
+ }
+
+ if (queuedBuffer) {
+ // Autolock scope
+ auto currentFrameNumber = mSurfaceFlingerConsumer->getFrameNumber();
+
+ Mutex::Autolock lock(mQueueItemLock);
+
+ // Remove any stale buffers that have been dropped during
+ // updateTexImage
+ while (mQueueItems[0].mFrameNumber != currentFrameNumber) {
+ mQueueItems.removeAt(0);
+ android_atomic_dec(&mQueuedFrames);
+ }
+
+ mQueueItems.removeAt(0);
+ }
+
+ // Decrement the queued-frames count. Signal another event if we
+ // have more frames pending.
+ if ((queuedBuffer && android_atomic_dec(&mQueuedFrames) > 1) || mAutoRefresh) {
+ mFlinger->signalLayerUpdate();
+ }
+
+ // update the active buffer
+ mActiveBuffer = mSurfaceFlingerConsumer->getCurrentBuffer(&mActiveBufferSlot);
+ if (mActiveBuffer == NULL) {
+ // this can only happen if the very first buffer was rejected.
+ return outDirtyRegion;
+ }
+
+ mBufferLatched = true;
+ mPreviousFrameNumber = mCurrentFrameNumber;
+ mCurrentFrameNumber = mSurfaceFlingerConsumer->getFrameNumber();
+
+ {
+ Mutex::Autolock lock(mFrameEventHistoryMutex);
+ mFrameEventHistory.addLatch(mCurrentFrameNumber, latchTime);
+#ifndef USE_HWC2
+ auto releaseFenceTime =
+ std::make_shared<FenceTime>(mSurfaceFlingerConsumer->getPrevFinalReleaseFence());
+ mReleaseTimeline.updateSignalTimes();
+ mReleaseTimeline.push(releaseFenceTime);
+ if (mPreviousFrameNumber != 0) {
+ mFrameEventHistory.addRelease(mPreviousFrameNumber, latchTime,
+ std::move(releaseFenceTime));
+ }
+#endif
+ }
+
+ mRefreshPending = true;
+ mFrameLatencyNeeded = true;
+ if (oldActiveBuffer == NULL) {
+ // the first time we receive a buffer, we need to trigger a
+ // geometry invalidation.
+ recomputeVisibleRegions = true;
+ }
+
+ setDataSpace(mSurfaceFlingerConsumer->getCurrentDataSpace());
+
+ Rect crop(mSurfaceFlingerConsumer->getCurrentCrop());
+ const uint32_t transform(mSurfaceFlingerConsumer->getCurrentTransform());
+ const uint32_t scalingMode(mSurfaceFlingerConsumer->getCurrentScalingMode());
+ if ((crop != mCurrentCrop) || (transform != mCurrentTransform) ||
+ (scalingMode != mCurrentScalingMode)) {
+ mCurrentCrop = crop;
+ mCurrentTransform = transform;
+ mCurrentScalingMode = scalingMode;
+ recomputeVisibleRegions = true;
+ }
+
+ if (oldActiveBuffer != NULL) {
+ uint32_t bufWidth = mActiveBuffer->getWidth();
+ uint32_t bufHeight = mActiveBuffer->getHeight();
+ if (bufWidth != uint32_t(oldActiveBuffer->width) ||
+ bufHeight != uint32_t(oldActiveBuffer->height)) {
+ recomputeVisibleRegions = true;
+ }
+ }
+
+ mCurrentOpacity = getOpacityForFormat(mActiveBuffer->format);
+ if (oldOpacity != isOpaque(s)) {
+ recomputeVisibleRegions = true;
+ }
+
+ // Remove any sync points corresponding to the buffer which was just
+ // latched
+ {
+ Mutex::Autolock lock(mLocalSyncPointMutex);
+ auto point = mLocalSyncPoints.begin();
+ while (point != mLocalSyncPoints.end()) {
+ if (!(*point)->frameIsAvailable() || !(*point)->transactionIsApplied()) {
+ // This sync point must have been added since we started
+ // latching. Don't drop it yet.
+ ++point;
+ continue;
+ }
+
+ if ((*point)->getFrameNumber() <= mCurrentFrameNumber) {
+ point = mLocalSyncPoints.erase(point);
+ } else {
+ ++point;
+ }
+ }
+ }
+
+ // FIXME: postedRegion should be dirty & bounds
+ Region dirtyRegion(Rect(s.active.w, s.active.h));
+
+ // transform the dirty region to window-manager space
+ outDirtyRegion = (getTransform().transform(dirtyRegion));
+
+ return outDirtyRegion;
+}
+
+void BufferLayer::setDefaultBufferSize(uint32_t w, uint32_t h) {
+ mSurfaceFlingerConsumer->setDefaultBufferSize(w, h);
+}
+
+#ifdef USE_HWC2
+void BufferLayer::setPerFrameData(const sp<const DisplayDevice>& displayDevice) {
+ // Apply this display's projection's viewport to the visible region
+ // before giving it to the HWC HAL.
+ const Transform& tr = displayDevice->getTransform();
+ const auto& viewport = displayDevice->getViewport();
+ Region visible = tr.transform(visibleRegion.intersect(viewport));
+ auto hwcId = displayDevice->getHwcDisplayId();
+ auto& hwcInfo = mHwcLayers[hwcId];
+ auto& hwcLayer = hwcInfo.layer;
+ auto error = hwcLayer->setVisibleRegion(visible);
+ if (error != HWC2::Error::None) {
+ ALOGE("[%s] Failed to set visible region: %s (%d)", mName.string(),
+ to_string(error).c_str(), static_cast<int32_t>(error));
+ visible.dump(LOG_TAG);
+ }
+
+ error = hwcLayer->setSurfaceDamage(surfaceDamageRegion);
+ if (error != HWC2::Error::None) {
+ ALOGE("[%s] Failed to set surface damage: %s (%d)", mName.string(),
+ to_string(error).c_str(), static_cast<int32_t>(error));
+ surfaceDamageRegion.dump(LOG_TAG);
+ }
+
+ // Sideband layers
+ if (mSidebandStream.get()) {
+ setCompositionType(hwcId, HWC2::Composition::Sideband);
+ ALOGV("[%s] Requesting Sideband composition", mName.string());
+ error = hwcLayer->setSidebandStream(mSidebandStream->handle());
+ if (error != HWC2::Error::None) {
+ ALOGE("[%s] Failed to set sideband stream %p: %s (%d)", mName.string(),
+ mSidebandStream->handle(), to_string(error).c_str(), static_cast<int32_t>(error));
+ }
+ return;
+ }
+
+ // Client layers
+ if (hwcInfo.forceClientComposition ||
+ (mActiveBuffer != nullptr && mActiveBuffer->handle == nullptr)) {
+ ALOGV("[%s] Requesting Client composition", mName.string());
+ setCompositionType(hwcId, HWC2::Composition::Client);
+ return;
+ }
+
+ // Device or Cursor layers
+ if (mPotentialCursor) {
+ ALOGV("[%s] Requesting Cursor composition", mName.string());
+ setCompositionType(hwcId, HWC2::Composition::Cursor);
+ } else {
+ ALOGV("[%s] Requesting Device composition", mName.string());
+ setCompositionType(hwcId, HWC2::Composition::Device);
+ }
+
+ ALOGV("setPerFrameData: dataspace = %d", mCurrentState.dataSpace);
+ error = hwcLayer->setDataspace(mCurrentState.dataSpace);
+ if (error != HWC2::Error::None) {
+ ALOGE("[%s] Failed to set dataspace %d: %s (%d)", mName.string(), mCurrentState.dataSpace,
+ to_string(error).c_str(), static_cast<int32_t>(error));
+ }
+
+ uint32_t hwcSlot = 0;
+ sp<GraphicBuffer> hwcBuffer;
+ hwcInfo.bufferCache.getHwcBuffer(mActiveBufferSlot, mActiveBuffer, &hwcSlot, &hwcBuffer);
+
+ auto acquireFence = mSurfaceFlingerConsumer->getCurrentFence();
+ error = hwcLayer->setBuffer(hwcSlot, hwcBuffer, acquireFence);
+ if (error != HWC2::Error::None) {
+ ALOGE("[%s] Failed to set buffer %p: %s (%d)", mName.string(), mActiveBuffer->handle,
+ to_string(error).c_str(), static_cast<int32_t>(error));
+ }
+}
+
+#else
+void BufferLayer::setAcquireFence(const sp<const DisplayDevice>& /* hw */,
+ HWComposer::HWCLayerInterface& layer) {
+ int fenceFd = -1;
+
+ // TODO: there is a possible optimization here: we only need to set the
+ // acquire fence the first time a new buffer is acquired on EACH display.
+
+ if (layer.getCompositionType() == HWC_OVERLAY ||
+ layer.getCompositionType() == HWC_CURSOR_OVERLAY) {
+ sp<Fence> fence = mSurfaceFlingerConsumer->getCurrentFence();
+ if (fence->isValid()) {
+ fenceFd = fence->dup();
+ if (fenceFd == -1) {
+ ALOGW("failed to dup layer fence, skipping sync: %d", errno);
+ }
+ }
+ }
+ layer.setAcquireFenceFd(fenceFd);
+}
+#endif
+
+bool BufferLayer::isOpaque(const Layer::State& s) const {
+ // if we don't have a buffer or sidebandStream yet, we're translucent regardless of the
+ // layer's opaque flag.
+ if ((mSidebandStream == nullptr) && (mActiveBuffer == nullptr)) {
+ return false;
+ }
+
+ // if the layer has the opaque flag, then we're always opaque,
+ // otherwise we use the current buffer's format.
+ return ((s.flags & layer_state_t::eLayerOpaque) != 0) || mCurrentOpacity;
+}
+
+void BufferLayer::onFirstRef() {
+ // Creates a custom BufferQueue for SurfaceFlingerConsumer to use
+ sp<IGraphicBufferProducer> producer;
+ sp<IGraphicBufferConsumer> consumer;
+ BufferQueue::createBufferQueue(&producer, &consumer, true);
+ mProducer = new MonitoredProducer(producer, mFlinger, this);
+ mSurfaceFlingerConsumer = new SurfaceFlingerConsumer(consumer, mTextureName, this);
+ mSurfaceFlingerConsumer->setConsumerUsageBits(getEffectiveUsage(0));
+ mSurfaceFlingerConsumer->setContentsChangedListener(this);
+ mSurfaceFlingerConsumer->setName(mName);
+
+ if (mFlinger->isLayerTripleBufferingDisabled()) {
+ mProducer->setMaxDequeuedBufferCount(2);
+ }
+
+ const sp<const DisplayDevice> hw(mFlinger->getDefaultDisplayDevice());
+ updateTransformHint(hw);
+}
+
+// ---------------------------------------------------------------------------
+// Interface implementation for SurfaceFlingerConsumer::ContentsChangedListener
+// ---------------------------------------------------------------------------
+
+void BufferLayer::onFrameAvailable(const BufferItem& item) {
+ // Add this buffer from our internal queue tracker
+ { // Autolock scope
+ Mutex::Autolock lock(mQueueItemLock);
+ mFlinger->mInterceptor.saveBufferUpdate(this, item.mGraphicBuffer->getWidth(),
+ item.mGraphicBuffer->getHeight(),
+ item.mFrameNumber);
+ // Reset the frame number tracker when we receive the first buffer after
+ // a frame number reset
+ if (item.mFrameNumber == 1) {
+ mLastFrameNumberReceived = 0;
+ }
+
+ // Ensure that callbacks are handled in order
+ while (item.mFrameNumber != mLastFrameNumberReceived + 1) {
+ status_t result = mQueueItemCondition.waitRelative(mQueueItemLock, ms2ns(500));
+ if (result != NO_ERROR) {
+ ALOGE("[%s] Timed out waiting on callback", mName.string());
+ }
+ }
+
+ mQueueItems.push_back(item);
+ android_atomic_inc(&mQueuedFrames);
+
+ // Wake up any pending callbacks
+ mLastFrameNumberReceived = item.mFrameNumber;
+ mQueueItemCondition.broadcast();
+ }
+
+ mFlinger->signalLayerUpdate();
+}
+
+void BufferLayer::onFrameReplaced(const BufferItem& item) {
+ { // Autolock scope
+ Mutex::Autolock lock(mQueueItemLock);
+
+ // Ensure that callbacks are handled in order
+ while (item.mFrameNumber != mLastFrameNumberReceived + 1) {
+ status_t result = mQueueItemCondition.waitRelative(mQueueItemLock, ms2ns(500));
+ if (result != NO_ERROR) {
+ ALOGE("[%s] Timed out waiting on callback", mName.string());
+ }
+ }
+
+ if (mQueueItems.empty()) {
+ ALOGE("Can't replace a frame on an empty queue");
+ return;
+ }
+ mQueueItems.editItemAt(mQueueItems.size() - 1) = item;
+
+ // Wake up any pending callbacks
+ mLastFrameNumberReceived = item.mFrameNumber;
+ mQueueItemCondition.broadcast();
+ }
+}
+
+void BufferLayer::onSidebandStreamChanged() {
+ if (android_atomic_release_cas(false, true, &mSidebandStreamChanged) == 0) {
+ // mSidebandStreamChanged was false
+ mFlinger->signalLayerUpdate();
+ }
+}
+
+bool BufferLayer::needsFiltering(const RenderArea& renderArea) const {
+ return mNeedsFiltering || renderArea.needsFiltering();
+}
+
+// As documented in libhardware header, formats in the range
+// 0x100 - 0x1FF are specific to the HAL implementation, and
+// are known to have no alpha channel
+// TODO: move definition for device-specific range into
+// hardware.h, instead of using hard-coded values here.
+#define HARDWARE_IS_DEVICE_FORMAT(f) ((f) >= 0x100 && (f) <= 0x1FF)
+
+bool BufferLayer::getOpacityForFormat(uint32_t format) {
+ if (HARDWARE_IS_DEVICE_FORMAT(format)) {
+ return true;
+ }
+ switch (format) {
+ case HAL_PIXEL_FORMAT_RGBA_8888:
+ case HAL_PIXEL_FORMAT_BGRA_8888:
+ case HAL_PIXEL_FORMAT_RGBA_FP16:
+ case HAL_PIXEL_FORMAT_RGBA_1010102:
+ return false;
+ }
+ // in all other case, we have no blending (also for unknown formats)
+ return true;
+}
+
+void BufferLayer::drawWithOpenGL(const RenderArea& renderArea, bool useIdentityTransform) const {
+ const State& s(getDrawingState());
+
+ computeGeometry(renderArea, mMesh, useIdentityTransform);
+
+ /*
+ * NOTE: the way we compute the texture coordinates here produces
+ * different results than when we take the HWC path -- in the later case
+ * the "source crop" is rounded to texel boundaries.
+ * This can produce significantly different results when the texture
+ * is scaled by a large amount.
+ *
+ * The GL code below is more logical (imho), and the difference with
+ * HWC is due to a limitation of the HWC API to integers -- a question
+ * is suspend is whether we should ignore this problem or revert to
+ * GL composition when a buffer scaling is applied (maybe with some
+ * minimal value)? Or, we could make GL behave like HWC -- but this feel
+ * like more of a hack.
+ */
+ Rect win(computeBounds());
+
+ Transform t = getTransform();
+ if (!s.finalCrop.isEmpty()) {
+ win = t.transform(win);
+ if (!win.intersect(s.finalCrop, &win)) {
+ win.clear();
+ }
+ win = t.inverse().transform(win);
+ if (!win.intersect(computeBounds(), &win)) {
+ win.clear();
+ }
+ }
+
+ float left = float(win.left) / float(s.active.w);
+ float top = float(win.top) / float(s.active.h);
+ float right = float(win.right) / float(s.active.w);
+ float bottom = float(win.bottom) / float(s.active.h);
+
+ // TODO: we probably want to generate the texture coords with the mesh
+ // here we assume that we only have 4 vertices
+ Mesh::VertexArray<vec2> texCoords(mMesh.getTexCoordArray<vec2>());
+ texCoords[0] = vec2(left, 1.0f - top);
+ texCoords[1] = vec2(left, 1.0f - bottom);
+ texCoords[2] = vec2(right, 1.0f - bottom);
+ texCoords[3] = vec2(right, 1.0f - top);
+
+ RenderEngine& engine(mFlinger->getRenderEngine());
+ engine.setupLayerBlending(mPremultipliedAlpha, isOpaque(s), false /* disableTexture */,
+ getColor());
+#ifdef USE_HWC2
+ engine.setSourceDataSpace(mCurrentState.dataSpace);
+#endif
+ engine.drawMesh(mMesh);
+ engine.disableBlending();
+}
+
+uint32_t BufferLayer::getProducerStickyTransform() const {
+ int producerStickyTransform = 0;
+ int ret = mProducer->query(NATIVE_WINDOW_STICKY_TRANSFORM, &producerStickyTransform);
+ if (ret != OK) {
+ ALOGW("%s: Error %s (%d) while querying window sticky transform.", __FUNCTION__,
+ strerror(-ret), ret);
+ return 0;
+ }
+ return static_cast<uint32_t>(producerStickyTransform);
+}
+
+bool BufferLayer::latchUnsignaledBuffers() {
+ static bool propertyLoaded = false;
+ static bool latch = false;
+ static std::mutex mutex;
+ std::lock_guard<std::mutex> lock(mutex);
+ if (!propertyLoaded) {
+ char value[PROPERTY_VALUE_MAX] = {};
+ property_get("debug.sf.latch_unsignaled", value, "0");
+ latch = atoi(value);
+ propertyLoaded = true;
+ }
+ return latch;
+}
+
+uint64_t BufferLayer::getHeadFrameNumber() const {
+ Mutex::Autolock lock(mQueueItemLock);
+ if (!mQueueItems.empty()) {
+ return mQueueItems[0].mFrameNumber;
+ } else {
+ return mCurrentFrameNumber;
+ }
+}
+
+bool BufferLayer::headFenceHasSignaled() const {
+#ifdef USE_HWC2
+ if (latchUnsignaledBuffers()) {
+ return true;
+ }
+
+ Mutex::Autolock lock(mQueueItemLock);
+ if (mQueueItems.empty()) {
+ return true;
+ }
+ if (mQueueItems[0].mIsDroppable) {
+ // Even though this buffer's fence may not have signaled yet, it could
+ // be replaced by another buffer before it has a chance to, which means
+ // that it's possible to get into a situation where a buffer is never
+ // able to be latched. To avoid this, grab this buffer anyway.
+ return true;
+ }
+ return mQueueItems[0].mFenceTime->getSignalTime() != Fence::SIGNAL_TIME_PENDING;
+#else
+ return true;
+#endif
+}
+
+uint32_t BufferLayer::getEffectiveScalingMode() const {
+ if (mOverrideScalingMode >= 0) {
+ return mOverrideScalingMode;
+ }
+ return mCurrentScalingMode;
+}
+
+// ----------------------------------------------------------------------------
+// transaction
+// ----------------------------------------------------------------------------
+
+void BufferLayer::notifyAvailableFrames() {
+ auto headFrameNumber = getHeadFrameNumber();
+ bool headFenceSignaled = headFenceHasSignaled();
+ Mutex::Autolock lock(mLocalSyncPointMutex);
+ for (auto& point : mLocalSyncPoints) {
+ if (headFrameNumber >= point->getFrameNumber() && headFenceSignaled) {
+ point->setFrameAvailable();
+ }
+ }
+}
+
+sp<IGraphicBufferProducer> BufferLayer::getProducer() const {
+ return mProducer;
+}
+
+// ---------------------------------------------------------------------------
+// h/w composer set-up
+// ---------------------------------------------------------------------------
+
+bool BufferLayer::allTransactionsSignaled() {
+ auto headFrameNumber = getHeadFrameNumber();
+ bool matchingFramesFound = false;
+ bool allTransactionsApplied = true;
+ Mutex::Autolock lock(mLocalSyncPointMutex);
+
+ for (auto& point : mLocalSyncPoints) {
+ if (point->getFrameNumber() > headFrameNumber) {
+ break;
+ }
+ matchingFramesFound = true;
+
+ if (!point->frameIsAvailable()) {
+ // We haven't notified the remote layer that the frame for
+ // this point is available yet. Notify it now, and then
+ // abort this attempt to latch.
+ point->setFrameAvailable();
+ allTransactionsApplied = false;
+ break;
+ }
+
+ allTransactionsApplied = allTransactionsApplied && point->transactionIsApplied();
+ }
+ return !matchingFramesFound || allTransactionsApplied;
+}
+
+} // namespace android
+
+#if defined(__gl_h_)
+#error "don't include gl/gl.h in this file"
+#endif
+
+#if defined(__gl2_h_)
+#error "don't include gl2/gl2.h in this file"
+#endif
diff --git a/services/surfaceflinger/BufferLayer.h b/services/surfaceflinger/BufferLayer.h
new file mode 100644
index 0000000..418f032
--- /dev/null
+++ b/services/surfaceflinger/BufferLayer.h
@@ -0,0 +1,211 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include "Client.h"
+#include "Layer.h"
+#include "DisplayHardware/HWComposer.h"
+#include "DisplayHardware/HWComposerBufferCache.h"
+#include "FrameTracker.h"
+#include "LayerVector.h"
+#include "MonitoredProducer.h"
+#include "RenderEngine/Mesh.h"
+#include "RenderEngine/Texture.h"
+#include "SurfaceFlinger.h"
+#include "SurfaceFlingerConsumer.h"
+#include "Transform.h"
+
+#include <gui/ISurfaceComposerClient.h>
+#include <gui/LayerState.h>
+
+#include <EGL/egl.h>
+#include <EGL/eglext.h>
+
+#include <ui/FrameStats.h>
+#include <ui/GraphicBuffer.h>
+#include <ui/PixelFormat.h>
+#include <ui/Region.h>
+
+#include <utils/RefBase.h>
+#include <utils/String8.h>
+#include <utils/Timers.h>
+
+#include <stdint.h>
+#include <sys/types.h>
+#include <list>
+
+namespace android {
+
+/*
+ * A new BufferQueue and a new SurfaceFlingerConsumer are created when the
+ * BufferLayer is first referenced.
+ *
+ * This also implements onFrameAvailable(), which notifies SurfaceFlinger
+ * that new data has arrived.
+ */
+class BufferLayer : public Layer, public SurfaceFlingerConsumer::ContentsChangedListener {
+public:
+ BufferLayer(SurfaceFlinger* flinger, const sp<Client>& client, const String8& name, uint32_t w,
+ uint32_t h, uint32_t flags);
+
+ ~BufferLayer() override;
+
+ // If we have received a new buffer this frame, we will pass its surface
+ // damage down to hardware composer. Otherwise, we must send a region with
+ // one empty rect.
+ void useSurfaceDamage();
+ void useEmptyDamage();
+
+ // -----------------------------------------------------------------------
+ // Overriden from Layer
+ // -----------------------------------------------------------------------
+
+ /*
+ * getTypeId - Provide unique string for each class type in the Layer
+ * hierarchy
+ */
+ const char* getTypeId() const override { return "BufferLayer"; }
+
+ /*
+ * isProtected - true if the layer may contain protected content in the
+ * GRALLOC_USAGE_PROTECTED sense.
+ */
+ bool isProtected() const;
+
+ /*
+ * isVisible - true if this layer is visible, false otherwise
+ */
+ bool isVisible() const override;
+
+ /*
+ * isFixedSize - true if content has a fixed size
+ */
+ bool isFixedSize() const override;
+
+ // the this layer's size and format
+ status_t setBuffers(uint32_t w, uint32_t h, PixelFormat format, uint32_t flags);
+
+ /*
+ * onDraw - draws the surface.
+ */
+ void onDraw(const RenderArea& renderArea, const Region& clip,
+ bool useIdentityTransform) const override;
+
+#ifdef USE_HWC2
+ void onLayerDisplayed(const sp<Fence>& releaseFence) override;
+#else
+ void onLayerDisplayed(const sp<const DisplayDevice>& hw,
+ HWComposer::HWCLayerInterface* layer) override;
+#endif
+
+ void abandon() override;
+ bool shouldPresentNow(const DispSync& dispSync) const override;
+ void setTransformHint(uint32_t orientation) const override;
+ bool onPostComposition(const std::shared_ptr<FenceTime>& glDoneFence,
+ const std::shared_ptr<FenceTime>& presentFence,
+ const CompositorTiming& compositorTiming) override;
+ std::vector<OccupancyTracker::Segment> getOccupancyHistory(bool forceFlush) override;
+ bool getTransformToDisplayInverse() const override;
+
+public:
+ bool onPreComposition(nsecs_t refreshStartTime) override;
+
+#ifdef USE_HWC2
+ // If a buffer was replaced this frame, release the former buffer
+ void releasePendingBuffer(nsecs_t dequeueReadyTime);
+#endif
+
+ /*
+ * latchBuffer - called each time the screen is redrawn and returns whether
+ * the visible regions need to be recomputed (this is a fairly heavy
+ * operation, so this should be set only if needed). Typically this is used
+ * to figure out if the content or size of a surface has changed.
+ */
+ Region latchBuffer(bool& recomputeVisibleRegions, nsecs_t latchTime) override;
+ bool isBufferLatched() const override { return mRefreshPending; }
+ void setDefaultBufferSize(uint32_t w, uint32_t h) override;
+
+#ifdef USE_HWC2
+ void setPerFrameData(const sp<const DisplayDevice>& displayDevice) override;
+#else
+ void setAcquireFence(const sp<const DisplayDevice>& hw,
+ HWComposer::HWCLayerInterface& layer) override;
+#endif
+
+ bool isOpaque(const Layer::State& s) const override;
+
+private:
+ void onFirstRef() override;
+
+ // Interface implementation for
+ // SurfaceFlingerConsumer::ContentsChangedListener
+ void onFrameAvailable(const BufferItem& item) override;
+ void onFrameReplaced(const BufferItem& item) override;
+ void onSidebandStreamChanged() override;
+
+ // needsLinearFiltering - true if this surface's state requires filtering
+ bool needsFiltering(const RenderArea& renderArea) const;
+
+ static bool getOpacityForFormat(uint32_t format);
+
+ // drawing
+ void drawWithOpenGL(const RenderArea& renderArea, bool useIdentityTransform) const;
+
+ // Temporary - Used only for LEGACY camera mode.
+ uint32_t getProducerStickyTransform() const;
+
+ // Loads the corresponding system property once per process
+ static bool latchUnsignaledBuffers();
+
+ uint64_t getHeadFrameNumber() const;
+ bool headFenceHasSignaled() const;
+
+ // Returns the current scaling mode, unless mOverrideScalingMode
+ // is set, in which case, it returns mOverrideScalingMode
+ uint32_t getEffectiveScalingMode() const override;
+
+public:
+ void notifyAvailableFrames() override;
+
+ PixelFormat getPixelFormat() const override { return mFormat; }
+ sp<IGraphicBufferProducer> getProducer() const;
+
+private:
+ sp<SurfaceFlingerConsumer> mSurfaceFlingerConsumer;
+
+ // Check all of the local sync points to ensure that all transactions
+ // which need to have been applied prior to the frame which is about to
+ // be latched have signaled
+ bool allTransactionsSignaled();
+ sp<IGraphicBufferProducer> mProducer;
+
+ // constants
+ uint32_t mTextureName; // from GLES
+ PixelFormat mFormat;
+
+ // main thread
+ uint32_t mCurrentScalingMode;
+ bool mBufferLatched = false; // TODO: Use mActiveBuffer?
+ uint64_t mPreviousFrameNumber; // Only accessed on the main thread.
+ // The texture used to draw the layer in GLES composition mode
+ mutable Texture mTexture;
+
+ bool mUpdateTexImageFailed; // This is only accessed on the main thread.
+ bool mRefreshPending;
+};
+
+} // namespace android
diff --git a/services/surfaceflinger/Client.cpp b/services/surfaceflinger/Client.cpp
index 8ba6cb9..ea6541a 100644
--- a/services/surfaceflinger/Client.cpp
+++ b/services/surfaceflinger/Client.cpp
@@ -140,7 +140,8 @@
{
sp<Layer> parent = nullptr;
if (parentHandle != nullptr) {
- parent = getLayerUser(parentHandle);
+ auto layerHandle = reinterpret_cast<Layer::Handle*>(parentHandle.get());
+ parent = layerHandle->owner.promote();
if (parent == nullptr) {
return NAME_NOT_FOUND;
}
diff --git a/services/surfaceflinger/ColorLayer.cpp b/services/surfaceflinger/ColorLayer.cpp
new file mode 100644
index 0000000..8a17f88
--- /dev/null
+++ b/services/surfaceflinger/ColorLayer.cpp
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// #define LOG_NDEBUG 0
+#undef LOG_TAG
+#define LOG_TAG "ColorLayer"
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <sys/types.h>
+
+#include <utils/Errors.h>
+#include <utils/Log.h>
+
+#include <ui/GraphicBuffer.h>
+
+#include "ColorLayer.h"
+#include "DisplayDevice.h"
+#include "RenderEngine/RenderEngine.h"
+#include "SurfaceFlinger.h"
+
+namespace android {
+// ---------------------------------------------------------------------------
+
+ColorLayer::ColorLayer(SurfaceFlinger* flinger, const sp<Client>& client, const String8& name,
+ uint32_t w, uint32_t h, uint32_t flags)
+ : Layer(flinger, client, name, w, h, flags) {
+ // drawing state & current state are identical
+ mDrawingState = mCurrentState;
+}
+
+void ColorLayer::onDraw(const RenderArea& renderArea, const Region& /* clip */,
+ bool useIdentityTransform) const {
+ const State& s(getDrawingState());
+ if (s.color.a > 0) {
+ Mesh mesh(Mesh::TRIANGLE_FAN, 4, 2);
+ computeGeometry(renderArea, mesh, useIdentityTransform);
+ RenderEngine& engine(mFlinger->getRenderEngine());
+ engine.setupLayerBlending(getPremultipledAlpha(), false /* opaque */,
+ true /* disableTexture */, s.color);
+ engine.drawMesh(mesh);
+ engine.disableBlending();
+ }
+}
+
+bool ColorLayer::isVisible() const {
+ const Layer::State& s(getDrawingState());
+ return !isHiddenByPolicy() && s.color.a;
+}
+
+#ifdef USE_HWC2
+void ColorLayer::setPerFrameData(const sp<const DisplayDevice>& displayDevice) {
+ const Transform& tr = displayDevice->getTransform();
+ const auto& viewport = displayDevice->getViewport();
+ Region visible = tr.transform(visibleRegion.intersect(viewport));
+ auto hwcId = displayDevice->getHwcDisplayId();
+ auto& hwcInfo = mHwcLayers[hwcId];
+ auto& hwcLayer = hwcInfo.layer;
+ auto error = hwcLayer->setVisibleRegion(visible);
+
+ setCompositionType(hwcId, HWC2::Composition::SolidColor);
+
+ half4 color = getColor();
+ error = hwcLayer->setColor({static_cast<uint8_t>(std::round(255.0f * color.r)),
+ static_cast<uint8_t>(std::round(255.0f * color.g)),
+ static_cast<uint8_t>(std::round(255.0f * color.b)), 255});
+ if (error != HWC2::Error::None) {
+ ALOGE("[%s] Failed to set color: %s (%d)", mName.string(), to_string(error).c_str(),
+ static_cast<int32_t>(error));
+ }
+
+ // Clear out the transform, because it doesn't make sense absent a source buffer
+ error = hwcLayer->setTransform(HWC2::Transform::None);
+ if (error != HWC2::Error::None) {
+ ALOGE("[%s] Failed to clear transform: %s (%d)", mName.string(), to_string(error).c_str(),
+ static_cast<int32_t>(error));
+ }
+}
+#endif
+
+// ---------------------------------------------------------------------------
+
+}; // namespace android
diff --git a/services/surfaceflinger/ColorLayer.h b/services/surfaceflinger/ColorLayer.h
new file mode 100644
index 0000000..debd3c3
--- /dev/null
+++ b/services/surfaceflinger/ColorLayer.h
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2007 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_COLOR_LAYER_H
+#define ANDROID_COLOR_LAYER_H
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include "Layer.h"
+
+// ---------------------------------------------------------------------------
+
+namespace android {
+
+class ColorLayer : public Layer {
+public:
+ ColorLayer(SurfaceFlinger* flinger, const sp<Client>& client, const String8& name, uint32_t w,
+ uint32_t h, uint32_t flags);
+ virtual ~ColorLayer() = default;
+
+ virtual const char* getTypeId() const { return "ColorLayer"; }
+ virtual void onDraw(const RenderArea& renderArea, const Region& clip,
+ bool useIdentityTransform) const;
+ bool isVisible() const override;
+ virtual bool isOpaque(const Layer::State&) const { return false; }
+ virtual bool isFixedSize() const { return true; }
+
+ void notifyAvailableFrames() override {}
+ PixelFormat getPixelFormat() const override { return PIXEL_FORMAT_NONE; }
+ uint32_t getEffectiveScalingMode() const override { return 0; }
+#ifdef USE_HWC2
+ void releasePendingBuffer(nsecs_t) override {}
+#endif
+ Region latchBuffer(bool&, nsecs_t) override { return Region(); }
+ void useSurfaceDamage() override {}
+ void useEmptyDamage() override {}
+ bool isBufferLatched() const override { return false; }
+ bool onPreComposition(nsecs_t) override { return true; }
+ void abandon() override {}
+#ifdef USE_HWC2
+ void setPerFrameData(const sp<const DisplayDevice>& displayDevice) override;
+#else
+ void setAcquireFence(const sp<const DisplayDevice>& /*hw*/,
+ HWComposer::HWCLayerInterface& /*layer*/) override {}
+#endif
+ void setDefaultBufferSize(uint32_t /*w*/, uint32_t /*h*/) override {}
+ bool shouldPresentNow(const DispSync& /*dispSync*/) const override { return false; }
+ bool onPostComposition(const std::shared_ptr<FenceTime>& /*glDoneFence*/,
+ const std::shared_ptr<FenceTime>& /*presentFence*/,
+ const CompositorTiming& /*compositorTiming*/) override {
+ return false;
+ }
+ void setTransformHint(uint32_t /*orientation*/) const override {}
+ std::vector<OccupancyTracker::Segment> getOccupancyHistory(bool /*forceFlush*/) override {
+ return {};
+ }
+ bool getTransformToDisplayInverse() const override { return false; }
+};
+
+// ---------------------------------------------------------------------------
+
+}; // namespace android
+
+#endif // ANDROID_COLOR_LAYER_H
diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp
index 248ef53..0244c1b 100644
--- a/services/surfaceflinger/DisplayDevice.cpp
+++ b/services/surfaceflinger/DisplayDevice.cpp
@@ -28,6 +28,7 @@
#include <utils/RefBase.h>
#include <utils/Log.h>
+#include <ui/DebugUtils.h>
#include <ui/DisplayInfo.h>
#include <ui/PixelFormat.h>
@@ -617,6 +618,7 @@
void DisplayDevice::dump(String8& result) const {
const Transform& tr(mGlobalTransform);
+ ANativeWindow* const window = mNativeWindow.get();
EGLint redSize, greenSize, blueSize, alphaSize;
eglGetConfigAttrib(mDisplay, mConfig, EGL_RED_SIZE, &redSize);
eglGetConfigAttrib(mDisplay, mConfig, EGL_GREEN_SIZE, &greenSize);
@@ -626,9 +628,9 @@
result.appendFormat(" type=%x, hwcId=%d, layerStack=%u, (%4dx%4d), ANativeWindow=%p "
"(%d:%d:%d:%d), orient=%2d (type=%08x), "
"flips=%u, isSecure=%d, powerMode=%d, activeConfig=%d, numLayers=%zu\n",
- mType, mHwcDisplayId, mLayerStack, mDisplayWidth, mDisplayHeight,
- mNativeWindow.get(), redSize, greenSize, blueSize, alphaSize, mOrientation,
- tr.getType(), getPageFlipCount(), mIsSecure, mPowerMode, mActiveConfig,
+ mType, mHwcDisplayId, mLayerStack, mDisplayWidth, mDisplayHeight, window,
+ redSize, greenSize, blueSize, alphaSize, mOrientation, tr.getType(),
+ getPageFlipCount(), mIsSecure, mPowerMode, mActiveConfig,
mVisibleLayersSortedByZ.size());
result.appendFormat(" v:[%d,%d,%d,%d], f:[%d,%d,%d,%d], s:[%d,%d,%d,%d],"
"transform:[[%0.3f,%0.3f,%0.3f][%0.3f,%0.3f,%0.3f][%0.3f,%0.3f,%0.3f]]\n",
@@ -636,6 +638,9 @@
mFrame.left, mFrame.top, mFrame.right, mFrame.bottom, mScissor.left,
mScissor.top, mScissor.right, mScissor.bottom, tr[0][0], tr[1][0], tr[2][0],
tr[0][1], tr[1][1], tr[2][1], tr[0][2], tr[1][2], tr[2][2]);
+ auto const surface = static_cast<Surface*>(window);
+ android_dataspace dataspace = surface->getBuffersDataSpace();
+ result.appendFormat(" dataspace: %s (%d)\n", dataspaceDetails(dataspace).c_str(), dataspace);
String8 surfaceDump;
mDisplaySurface->dumpAsString(surfaceDump);
diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h
index 8636e2a..49fef58 100644
--- a/services/surfaceflinger/DisplayDevice.h
+++ b/services/surfaceflinger/DisplayDevice.h
@@ -37,7 +37,9 @@
#include <utils/String8.h>
#include <utils/Timers.h>
+#include <gui/ISurfaceComposer.h>
#include <hardware/hwcomposer_defs.h>
+#include "RenderArea.h"
#ifdef USE_HWC2
#include <memory>
@@ -300,6 +302,35 @@
bool isSecure = false;
};
+class DisplayRenderArea : public RenderArea {
+public:
+ DisplayRenderArea(const sp<const DisplayDevice> device,
+ ISurfaceComposer::Rotation rotation = ISurfaceComposer::eRotateNone)
+ : DisplayRenderArea(device, device->getBounds(), device->getHeight(), device->getWidth(),
+ rotation) {}
+ DisplayRenderArea(const sp<const DisplayDevice> device, Rect sourceCrop, uint32_t reqHeight,
+ uint32_t reqWidth, ISurfaceComposer::Rotation rotation)
+ : RenderArea(reqHeight, reqWidth, rotation), mDevice(device), mSourceCrop(sourceCrop) {}
+
+ const Transform& getTransform() const override { return mDevice->getTransform(); }
+ Rect getBounds() const override { return mDevice->getBounds(); }
+ int getHeight() const override { return mDevice->getHeight(); }
+ int getWidth() const override { return mDevice->getWidth(); }
+ bool isSecure() const override { return mDevice->isSecure(); }
+ bool needsFiltering() const override { return mDevice->needsFiltering(); }
+ Rect getSourceCrop() const override { return mSourceCrop; }
+#ifdef USE_HWC2
+ bool getWideColorSupport() const override { return mDevice->getWideColorSupport(); }
+ android_color_mode_t getActiveColorMode() const override {
+ return mDevice->getActiveColorMode();
+ }
+#endif
+
+private:
+ const sp<const DisplayDevice> mDevice;
+ const Rect mSourceCrop;
+};
+
}; // namespace android
#endif // ANDROID_DISPLAY_DEVICE_H
diff --git a/services/surfaceflinger/DisplayHardware/ComposerHal.cpp b/services/surfaceflinger/DisplayHardware/ComposerHal.cpp
index 7d6d988..c707e3c 100644
--- a/services/surfaceflinger/DisplayHardware/ComposerHal.cpp
+++ b/services/surfaceflinger/DisplayHardware/ComposerHal.cpp
@@ -223,6 +223,10 @@
mWriter.reset();
}
+Error Composer::executeCommands() {
+ return execute();
+}
+
uint32_t Composer::getMaxVirtualDisplayCount()
{
auto ret = mClient->getMaxVirtualDisplayCount();
@@ -750,6 +754,11 @@
}
}
+ if (commandLength == 0) {
+ mWriter.reset();
+ return Error::NONE;
+ }
+
Error error = kDefaultError;
auto ret = mClient->executeCommands(commandLength, commandHandles,
[&](const auto& tmpError, const auto& tmpOutChanged,
diff --git a/services/surfaceflinger/DisplayHardware/ComposerHal.h b/services/surfaceflinger/DisplayHardware/ComposerHal.h
index 31a3c1d..104ca60 100644
--- a/services/surfaceflinger/DisplayHardware/ComposerHal.h
+++ b/services/surfaceflinger/DisplayHardware/ComposerHal.h
@@ -152,6 +152,9 @@
// skip a frame but have already queued some commands.
void resetCommands();
+ // Explicitly flush all pending commands in the command buffer.
+ Error executeCommands();
+
uint32_t getMaxVirtualDisplayCount();
bool isUsingVrComposer() const { return mIsUsingVrComposer; }
Error createVirtualDisplay(uint32_t width, uint32_t height,
diff --git a/services/surfaceflinger/DisplayHardware/HWC2.cpp b/services/surfaceflinger/DisplayHardware/HWC2.cpp
index 78c0c85..ab4a4b2 100644
--- a/services/surfaceflinger/DisplayHardware/HWC2.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWC2.cpp
@@ -221,6 +221,11 @@
}
}
+Error Device::flushCommands()
+{
+ return static_cast<Error>(mComposer->executeCommands());
+}
+
// Display methods
Display::Display(android::Hwc2::Composer& composer,
@@ -632,11 +637,6 @@
return error;
}
-void Display::discardCommands()
-{
- mComposer.resetCommands();
-}
-
// For use by Device
void Display::setConnected(bool connected) {
diff --git a/services/surfaceflinger/DisplayHardware/HWC2.h b/services/surfaceflinger/DisplayHardware/HWC2.h
index fbe4c7e..a15c6d9 100644
--- a/services/surfaceflinger/DisplayHardware/HWC2.h
+++ b/services/surfaceflinger/DisplayHardware/HWC2.h
@@ -106,6 +106,11 @@
android::Hwc2::Composer* getComposer() { return mComposer.get(); }
+ // We buffer most state changes and flush them implicitly with
+ // Display::validate, Display::present, and Display::presentOrValidate.
+ // This method provides an explicit way to flush state changes to HWC.
+ Error flushCommands();
+
private:
// Initialization methods
@@ -244,12 +249,6 @@
uint32_t* outNumRequests,
android::sp<android::Fence>* outPresentFence, uint32_t* state);
- // Most methods in this class write a command to a command buffer. The
- // command buffer is implicitly submitted in validate, present, and
- // presentOrValidate. This method provides a way to discard the commands,
- // which can be used to discard stale commands.
- void discardCommands();
-
// Other Display methods
hwc2_display_t getId() const { return mId; }
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
index b096a3a..5328a22 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
@@ -605,8 +605,11 @@
auto& hwcDisplay = displayData.hwcDisplay;
if (displayData.validateWasSkipped) {
- hwcDisplay->discardCommands();
- auto error = displayData.presentError;
+ // explicitly flush all pending commands
+ auto error = mHwcDevice->flushCommands();
+ if (displayData.presentError != HWC2::Error::None) {
+ error = displayData.presentError;
+ }
if (error != HWC2::Error::None) {
ALOGE("skipValidate: failed for display %d: %s (%d)",
displayId, to_string(error).c_str(), static_cast<int32_t>(error));
diff --git a/services/surfaceflinger/EventThread.cpp b/services/surfaceflinger/EventThread.cpp
index a9bb2ba..f647742 100644
--- a/services/surfaceflinger/EventThread.cpp
+++ b/services/surfaceflinger/EventThread.cpp
@@ -248,7 +248,7 @@
// find out connections waiting for events
size_t count = mDisplayEventConnections.size();
- for (size_t i=0 ; i<count ; i++) {
+ for (size_t i=0 ; i<count ; ) {
sp<Connection> connection(mDisplayEventConnections[i].promote());
if (connection != NULL) {
bool added = false;
@@ -279,11 +279,12 @@
// messages.
signalConnections.add(connection);
}
+ ++i;
} else {
// we couldn't promote this reference, the connection has
// died, so clean-up!
mDisplayEventConnections.removeAt(i);
- --i; --count;
+ --count;
}
}
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
old mode 100755
new mode 100644
index e92565f..80987a4
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -19,10 +19,10 @@
#define LOG_TAG "Layer"
#define ATRACE_TAG ATRACE_TAG_GRAPHICS
-#include <stdlib.h>
-#include <stdint.h>
-#include <sys/types.h>
#include <math.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <sys/types.h>
#include <cutils/compiler.h>
#include <cutils/native_handle.h>
@@ -43,37 +43,34 @@
#include <gui/LayerDebugInfo.h>
#include <gui/Surface.h>
-#include "clz.h"
#include "Colorizer.h"
#include "DisplayDevice.h"
#include "Layer.h"
#include "LayerRejecter.h"
#include "MonitoredProducer.h"
#include "SurfaceFlinger.h"
+#include "clz.h"
#include "DisplayHardware/HWComposer.h"
#include "RenderEngine/RenderEngine.h"
#include <mutex>
+#include "LayerProtoHelper.h"
-#define DEBUG_RESIZE 0
+#define DEBUG_RESIZE 0
namespace android {
-// ---------------------------------------------------------------------------
-
int32_t Layer::sSequence = 1;
-Layer::Layer(SurfaceFlinger* flinger, const sp<Client>& client,
- const String8& name, uint32_t w, uint32_t h, uint32_t flags)
- : contentDirty(false),
+Layer::Layer(SurfaceFlinger* flinger, const sp<Client>& client, const String8& name, uint32_t w,
+ uint32_t h, uint32_t flags)
+ : contentDirty(false),
sequence(uint32_t(android_atomic_inc(&sSequence))),
mFlinger(flinger),
- mTextureName(-1U),
mPremultipliedAlpha(true),
- mName("unnamed"),
- mFormat(PIXEL_FORMAT_NONE),
+ mName(name),
mTransactionFlags(0),
mPendingStateMutex(),
mPendingStates(),
@@ -81,13 +78,9 @@
mSidebandStreamChanged(false),
mActiveBufferSlot(BufferQueue::INVALID_BUFFER_SLOT),
mCurrentTransform(0),
- mCurrentScalingMode(NATIVE_WINDOW_SCALING_MODE_FREEZE),
mOverrideScalingMode(-1),
mCurrentOpacity(true),
- mBufferLatched(false),
mCurrentFrameNumber(0),
- mPreviousFrameNumber(0),
- mRefreshPending(false),
mFrameLatencyNeeded(false),
mFiltering(false),
mNeedsFiltering(false),
@@ -96,54 +89,36 @@
mIsGlesComposition(false),
#endif
mProtectedByApp(false),
- mHasSurface(false),
mClientRef(client),
mPotentialCursor(false),
mQueueItemLock(),
mQueueItemCondition(),
mQueueItems(),
mLastFrameNumberReceived(0),
- mUpdateTexImageFailed(false),
mAutoRefresh(false),
- mFreezeGeometryUpdates(false)
-{
-#ifdef USE_HWC2
- ALOGV("Creating Layer %s", name.string());
-#endif
+ mFreezeGeometryUpdates(false) {
mCurrentCrop.makeInvalid();
- mFlinger->getRenderEngine().genTextures(1, &mTextureName);
- mTexture.init(Texture::TEXTURE_EXTERNAL, mTextureName);
uint32_t layerFlags = 0;
- if (flags & ISurfaceComposerClient::eHidden)
- layerFlags |= layer_state_t::eLayerHidden;
- if (flags & ISurfaceComposerClient::eOpaque)
- layerFlags |= layer_state_t::eLayerOpaque;
- if (flags & ISurfaceComposerClient::eSecure)
- layerFlags |= layer_state_t::eLayerSecure;
-
- if (flags & ISurfaceComposerClient::eNonPremultiplied)
- mPremultipliedAlpha = false;
+ if (flags & ISurfaceComposerClient::eHidden) layerFlags |= layer_state_t::eLayerHidden;
+ if (flags & ISurfaceComposerClient::eOpaque) layerFlags |= layer_state_t::eLayerOpaque;
+ if (flags & ISurfaceComposerClient::eSecure) layerFlags |= layer_state_t::eLayerSecure;
mName = name;
mTransactionName = String8("TX - ") + mName;
mCurrentState.active.w = w;
mCurrentState.active.h = h;
+ mCurrentState.flags = layerFlags;
mCurrentState.active.transform.set(0, 0);
mCurrentState.crop.makeInvalid();
mCurrentState.finalCrop.makeInvalid();
mCurrentState.requestedFinalCrop = mCurrentState.finalCrop;
mCurrentState.requestedCrop = mCurrentState.crop;
mCurrentState.z = 0;
-#ifdef USE_HWC2
- mCurrentState.alpha = 1.0f;
-#else
- mCurrentState.alpha = 0xFF;
-#endif
+ mCurrentState.color.a = 1.0f;
mCurrentState.layerStack = 0;
- mCurrentState.flags = layerFlags;
mCurrentState.sequence = 0;
mCurrentState.requested = mCurrentState.active;
mCurrentState.dataSpace = HAL_DATASPACE_UNKNOWN;
@@ -158,8 +133,7 @@
const auto& activeConfig = hwc.getActiveConfig(HWC_DISPLAY_PRIMARY);
nsecs_t displayPeriod = activeConfig->getVsyncPeriod();
#else
- nsecs_t displayPeriod =
- flinger->getHwComposer().getRefreshPeriod(HWC_DISPLAY_PRIMARY);
+ nsecs_t displayPeriod = flinger->getHwComposer().getRefreshPeriod(HWC_DISPLAY_PRIMARY);
#endif
mFrameTracker.setDisplayRefreshPeriod(displayPeriod);
@@ -168,137 +142,33 @@
mFrameEventHistory.initializeCompositorTiming(compositorTiming);
}
-void Layer::onFirstRef() {
- // Creates a custom BufferQueue for SurfaceFlingerConsumer to use
- sp<IGraphicBufferProducer> producer;
- sp<IGraphicBufferConsumer> consumer;
- BufferQueue::createBufferQueue(&producer, &consumer, true);
- mProducer = new MonitoredProducer(producer, mFlinger, this);
- mSurfaceFlingerConsumer = new SurfaceFlingerConsumer(consumer, mTextureName, this);
- mSurfaceFlingerConsumer->setConsumerUsageBits(getEffectiveUsage(0));
- mSurfaceFlingerConsumer->setContentsChangedListener(this);
- mSurfaceFlingerConsumer->setName(mName);
-
- if (mFlinger->isLayerTripleBufferingDisabled()) {
- mProducer->setMaxDequeuedBufferCount(2);
- }
-
- const sp<const DisplayDevice> hw(mFlinger->getDefaultDisplayDevice());
- updateTransformHint(hw);
-}
+void Layer::onFirstRef() {}
Layer::~Layer() {
- sp<Client> c(mClientRef.promote());
- if (c != 0) {
- c->detachLayer(this);
- }
-
- for (auto& point : mRemoteSyncPoints) {
- point->setTransactionApplied();
- }
- for (auto& point : mLocalSyncPoints) {
- point->setFrameAvailable();
- }
- mFlinger->deleteTextureAsync(mTextureName);
mFrameTracker.logAndResetStats(mName);
-
-#ifdef USE_HWC2
- if (!mHwcLayers.empty()) {
- ALOGE("Found stale hardware composer layers when destroying "
- "surface flinger layer %s", mName.string());
- destroyAllHwcLayers();
- }
-#endif
}
// ---------------------------------------------------------------------------
// callbacks
// ---------------------------------------------------------------------------
+/*
+ * onLayerDisplayed is only meaningful for BufferLayer, but, is called through
+ * Layer. So, the implementation is done in BufferLayer. When called on a
+ * ColorLayer object, it's essentially a NOP.
+ */
#ifdef USE_HWC2
-void Layer::onLayerDisplayed(const sp<Fence>& releaseFence) {
- if (mHwcLayers.empty()) {
- return;
- }
- mSurfaceFlingerConsumer->setReleaseFence(releaseFence);
-}
+void Layer::onLayerDisplayed(const sp<Fence>& /*releaseFence*/) {}
#else
void Layer::onLayerDisplayed(const sp<const DisplayDevice>& /* hw */,
- HWComposer::HWCLayerInterface* layer) {
- if (layer) {
- layer->onDisplayed();
- mSurfaceFlingerConsumer->setReleaseFence(layer->getAndResetReleaseFence());
- }
-}
+ HWComposer::HWCLayerInterface* /*layer*/) {}
#endif
-void Layer::onFrameAvailable(const BufferItem& item) {
- // Add this buffer from our internal queue tracker
- { // Autolock scope
- Mutex::Autolock lock(mQueueItemLock);
- mFlinger->mInterceptor.saveBufferUpdate(this, item.mGraphicBuffer->getWidth(),
- item.mGraphicBuffer->getHeight(), item.mFrameNumber);
- // Reset the frame number tracker when we receive the first buffer after
- // a frame number reset
- if (item.mFrameNumber == 1) {
- mLastFrameNumberReceived = 0;
- }
-
- // Ensure that callbacks are handled in order
- while (item.mFrameNumber != mLastFrameNumberReceived + 1) {
- status_t result = mQueueItemCondition.waitRelative(mQueueItemLock,
- ms2ns(500));
- if (result != NO_ERROR) {
- ALOGE("[%s] Timed out waiting on callback", mName.string());
- }
- }
-
- mQueueItems.push_back(item);
- android_atomic_inc(&mQueuedFrames);
-
- // Wake up any pending callbacks
- mLastFrameNumberReceived = item.mFrameNumber;
- mQueueItemCondition.broadcast();
- }
-
- mFlinger->signalLayerUpdate();
-}
-
-void Layer::onFrameReplaced(const BufferItem& item) {
- { // Autolock scope
- Mutex::Autolock lock(mQueueItemLock);
-
- // Ensure that callbacks are handled in order
- while (item.mFrameNumber != mLastFrameNumberReceived + 1) {
- status_t result = mQueueItemCondition.waitRelative(mQueueItemLock,
- ms2ns(500));
- if (result != NO_ERROR) {
- ALOGE("[%s] Timed out waiting on callback", mName.string());
- }
- }
-
- if (mQueueItems.empty()) {
- ALOGE("Can't replace a frame on an empty queue");
- return;
- }
- mQueueItems.editItemAt(mQueueItems.size() - 1) = item;
-
- // Wake up any pending callbacks
- mLastFrameNumberReceived = item.mFrameNumber;
- mQueueItemCondition.broadcast();
- }
-}
-
-void Layer::onSidebandStreamChanged() {
- if (android_atomic_release_cas(false, true, &mSidebandStreamChanged) == 0) {
- // mSidebandStreamChanged was false
- mFlinger->signalLayerUpdate();
- }
-}
-
void Layer::onRemovedFromCurrentState() {
// the layer is removed from SF mCurrentState to mLayersPendingRemoval
+ mPendingRemoval = true;
+
if (mCurrentState.zOrderRelativeOf != nullptr) {
sp<Layer> strongRelative = mCurrentState.zOrderRelativeOf.promote();
if (strongRelative != nullptr) {
@@ -315,8 +185,8 @@
void Layer::onRemoved() {
// the layer is removed from SF mLayersPendingRemoval
+ abandon();
- mSurfaceFlingerConsumer->abandon();
#ifdef USE_HWC2
destroyAllHwcLayers();
#endif
@@ -334,55 +204,22 @@
return mName;
}
-status_t Layer::setBuffers( uint32_t w, uint32_t h,
- PixelFormat format, uint32_t flags)
-{
- uint32_t const maxSurfaceDims = min(
- mFlinger->getMaxTextureSize(), mFlinger->getMaxViewportDims());
-
- // never allow a surface larger than what our underlying GL implementation
- // can handle.
- if ((uint32_t(w)>maxSurfaceDims) || (uint32_t(h)>maxSurfaceDims)) {
- ALOGE("dimensions too large %u x %u", uint32_t(w), uint32_t(h));
- return BAD_VALUE;
- }
-
- mFormat = format;
-
- mPotentialCursor = (flags & ISurfaceComposerClient::eCursorWindow) ? true : false;
- mProtectedByApp = (flags & ISurfaceComposerClient::eProtectedByApp) ? true : false;
- mCurrentOpacity = getOpacityForFormat(format);
-
- mSurfaceFlingerConsumer->setDefaultBufferSize(w, h);
- mSurfaceFlingerConsumer->setDefaultBufferFormat(format);
- mSurfaceFlingerConsumer->setConsumerUsageBits(getEffectiveUsage(0));
-
- return NO_ERROR;
+bool Layer::getPremultipledAlpha() const {
+ return mPremultipliedAlpha;
}
sp<IBinder> Layer::getHandle() {
Mutex::Autolock _l(mLock);
-
- LOG_ALWAYS_FATAL_IF(mHasSurface,
- "Layer::getHandle() has already been called");
-
- mHasSurface = true;
-
return new Handle(mFlinger, this);
}
-sp<IGraphicBufferProducer> Layer::getProducer() const {
- return mProducer;
-}
-
// ---------------------------------------------------------------------------
// h/w composer set-up
// ---------------------------------------------------------------------------
#ifdef USE_HWC2
bool Layer::createHwcLayer(HWComposer* hwc, int32_t hwcId) {
- LOG_ALWAYS_FATAL_IF(mHwcLayers.count(hwcId) != 0,
- "Already have a layer for hwcId %d", hwcId);
+ LOG_ALWAYS_FATAL_IF(mHwcLayers.count(hwcId) != 0, "Already have a layer for hwcId %d", hwcId);
HWC2::Layer* layer = hwc->createLayer(hwcId);
if (!layer) {
return false;
@@ -391,7 +228,7 @@
hwcInfo.hwc = hwc;
hwcInfo.layer = layer;
layer->setLayerDestroyedListener(
- [this, hwcId] (HWC2::Layer* /*layer*/){mHwcLayers.erase(hwcId);});
+ [this, hwcId](HWC2::Layer* /*layer*/) { mHwcLayers.erase(hwcId); });
return true;
}
@@ -400,14 +237,12 @@
return;
}
auto& hwcInfo = mHwcLayers[hwcId];
- LOG_ALWAYS_FATAL_IF(hwcInfo.layer == nullptr,
- "Attempt to destroy null layer");
+ LOG_ALWAYS_FATAL_IF(hwcInfo.layer == nullptr, "Attempt to destroy null layer");
LOG_ALWAYS_FATAL_IF(hwcInfo.hwc == nullptr, "Missing HWComposer");
hwcInfo.hwc->destroyLayer(hwcId, hwcInfo.layer);
// The layer destroyed listener should have cleared the entry from
// mHwcLayers. Verify that.
- LOG_ALWAYS_FATAL_IF(mHwcLayers.count(hwcId) != 0,
- "Stale layer entry in mHwcLayers");
+ LOG_ALWAYS_FATAL_IF(mHwcLayers.count(hwcId) != 0, "Stale layer entry in mHwcLayers");
}
void Layer::destroyAllHwcLayers() {
@@ -417,7 +252,7 @@
destroyHwcLayer(mHwcLayers.begin()->first);
}
LOG_ALWAYS_FATAL_IF(!mHwcLayers.empty(),
- "All hardware composer layers should have been destroyed");
+ "All hardware composer layers should have been destroyed");
}
#endif
@@ -541,10 +376,17 @@
activeCrop.clear();
}
if (!s.finalCrop.isEmpty()) {
- if(!activeCrop.intersect(s.finalCrop, &activeCrop)) {
+ if (!activeCrop.intersect(s.finalCrop, &activeCrop)) {
activeCrop.clear();
}
}
+
+ const auto& p = mDrawingParent.promote();
+ if (p != nullptr) {
+ auto parentCrop = p->computeInitialCrop(hw);
+ activeCrop.intersect(parentCrop, &activeCrop);
+ }
+
return activeCrop;
}
@@ -558,11 +400,6 @@
// Screen space to make reduction to parent crop clearer.
Rect activeCrop = computeInitialCrop(hw);
- const auto& p = mDrawingParent.promote();
- if (p != nullptr) {
- auto parentCrop = p->computeInitialCrop(hw);
- activeCrop.intersect(parentCrop, &activeCrop);
- }
Transform t = getTransform();
// Back to layer space to work with the content crop.
activeCrop = t.inverse().transform(activeCrop);
@@ -589,16 +426,13 @@
* the code below applies the primary display's inverse transform to the
* buffer
*/
- uint32_t invTransformOrient =
- DisplayDevice::getPrimaryDisplayOrientationTransform();
+ uint32_t invTransformOrient = DisplayDevice::getPrimaryDisplayOrientationTransform();
// calculate the inverse transform
if (invTransformOrient & NATIVE_WINDOW_TRANSFORM_ROT_90) {
- invTransformOrient ^= NATIVE_WINDOW_TRANSFORM_FLIP_V |
- NATIVE_WINDOW_TRANSFORM_FLIP_H;
+ invTransformOrient ^= NATIVE_WINDOW_TRANSFORM_FLIP_V | NATIVE_WINDOW_TRANSFORM_FLIP_H;
}
// and apply to the current transform
- invTransform = (Transform(invTransformOrient) * Transform(invTransform))
- .getOrientation();
+ invTransform = (Transform(invTransformOrient) * Transform(invTransform)).getOrientation();
}
int winWidth = s.active.w;
@@ -612,27 +446,25 @@
bool is_h_flipped = (invTransform & NATIVE_WINDOW_TRANSFORM_FLIP_H) != 0;
bool is_v_flipped = (invTransform & NATIVE_WINDOW_TRANSFORM_FLIP_V) != 0;
if (is_h_flipped == is_v_flipped) {
- invTransform ^= NATIVE_WINDOW_TRANSFORM_FLIP_V |
- NATIVE_WINDOW_TRANSFORM_FLIP_H;
+ invTransform ^= NATIVE_WINDOW_TRANSFORM_FLIP_V | NATIVE_WINDOW_TRANSFORM_FLIP_H;
}
winWidth = s.active.h;
winHeight = s.active.w;
}
- const Rect winCrop = activeCrop.transform(
- invTransform, s.active.w, s.active.h);
+ const Rect winCrop = activeCrop.transform(invTransform, s.active.w, s.active.h);
// below, crop is intersected with winCrop expressed in crop's coordinate space
- float xScale = crop.getWidth() / float(winWidth);
+ float xScale = crop.getWidth() / float(winWidth);
float yScale = crop.getHeight() / float(winHeight);
- float insetL = winCrop.left * xScale;
- float insetT = winCrop.top * yScale;
- float insetR = (winWidth - winCrop.right ) * xScale;
+ float insetL = winCrop.left * xScale;
+ float insetT = winCrop.top * yScale;
+ float insetR = (winWidth - winCrop.right) * xScale;
float insetB = (winHeight - winCrop.bottom) * yScale;
- crop.left += insetL;
- crop.top += insetT;
- crop.right -= insetR;
+ crop.left += insetL;
+ crop.top += insetT;
+ crop.right -= insetR;
crop.bottom -= insetB;
return crop;
@@ -641,9 +473,7 @@
#ifdef USE_HWC2
void Layer::setGeometry(const sp<const DisplayDevice>& displayDevice, uint32_t z)
#else
-void Layer::setGeometry(
- const sp<const DisplayDevice>& hw,
- HWComposer::HWCLayerInterface& layer)
+void Layer::setGeometry(const sp<const DisplayDevice>& hw, HWComposer::HWCLayerInterface& layer)
#endif
{
#ifdef USE_HWC2
@@ -675,18 +505,18 @@
#ifdef USE_HWC2
auto blendMode = HWC2::BlendMode::None;
if (!isOpaque(s) || getAlpha() != 1.0f) {
- blendMode = mPremultipliedAlpha ?
- HWC2::BlendMode::Premultiplied : HWC2::BlendMode::Coverage;
+ blendMode =
+ mPremultipliedAlpha ? HWC2::BlendMode::Premultiplied : HWC2::BlendMode::Coverage;
}
auto error = hwcLayer->setBlendMode(blendMode);
- ALOGE_IF(error != HWC2::Error::None, "[%s] Failed to set blend mode %s:"
- " %s (%d)", mName.string(), to_string(blendMode).c_str(),
- to_string(error).c_str(), static_cast<int32_t>(error));
+ ALOGE_IF(error != HWC2::Error::None,
+ "[%s] Failed to set blend mode %s:"
+ " %s (%d)",
+ mName.string(), to_string(blendMode).c_str(), to_string(error).c_str(),
+ static_cast<int32_t>(error));
#else
- if (!isOpaque(s) || getAlpha() != 0xFF) {
- layer.setBlending(mPremultipliedAlpha ?
- HWC_BLENDING_PREMULT :
- HWC_BLENDING_COVERAGE);
+ if (!isOpaque(s) || getAlpha() != 1.0f) {
+ layer.setBlending(mPremultipliedAlpha ? HWC_BLENDING_PREMULT : HWC_BLENDING_COVERAGE);
}
#endif
@@ -698,9 +528,9 @@
Rect activeCrop(s.crop);
activeCrop = t.transform(activeCrop);
#ifdef USE_HWC2
- if(!activeCrop.intersect(displayDevice->getViewport(), &activeCrop)) {
+ if (!activeCrop.intersect(displayDevice->getViewport(), &activeCrop)) {
#else
- if(!activeCrop.intersect(hw->getViewport(), &activeCrop)) {
+ if (!activeCrop.intersect(hw->getViewport(), &activeCrop)) {
#endif
activeCrop.clear();
}
@@ -711,22 +541,20 @@
// transform.inverse().transform(transform.transform(Rect)) != Rect
// in which case we need to make sure the final rect is clipped to the
// display bounds.
- if(!activeCrop.intersect(Rect(s.active.w, s.active.h), &activeCrop)) {
+ if (!activeCrop.intersect(Rect(s.active.w, s.active.h), &activeCrop)) {
activeCrop.clear();
}
// mark regions outside the crop as transparent
activeTransparentRegion.orSelf(Rect(0, 0, s.active.w, activeCrop.top));
- activeTransparentRegion.orSelf(Rect(0, activeCrop.bottom,
- s.active.w, s.active.h));
- activeTransparentRegion.orSelf(Rect(0, activeCrop.top,
- activeCrop.left, activeCrop.bottom));
- activeTransparentRegion.orSelf(Rect(activeCrop.right, activeCrop.top,
- s.active.w, activeCrop.bottom));
+ activeTransparentRegion.orSelf(Rect(0, activeCrop.bottom, s.active.w, s.active.h));
+ activeTransparentRegion.orSelf(Rect(0, activeCrop.top, activeCrop.left, activeCrop.bottom));
+ activeTransparentRegion.orSelf(
+ Rect(activeCrop.right, activeCrop.top, s.active.w, activeCrop.bottom));
}
Rect frame(t.transform(computeBounds(activeTransparentRegion)));
if (!s.finalCrop.isEmpty()) {
- if(!frame.intersect(s.finalCrop, &frame)) {
+ if (!frame.intersect(s.finalCrop, &frame)) {
frame.clear();
}
}
@@ -738,10 +566,9 @@
Rect transformedFrame = tr.transform(frame);
error = hwcLayer->setDisplayFrame(transformedFrame);
if (error != HWC2::Error::None) {
- ALOGE("[%s] Failed to set display frame [%d, %d, %d, %d]: %s (%d)",
- mName.string(), transformedFrame.left, transformedFrame.top,
- transformedFrame.right, transformedFrame.bottom,
- to_string(error).c_str(), static_cast<int32_t>(error));
+ ALOGE("[%s] Failed to set display frame [%d, %d, %d, %d]: %s (%d)", mName.string(),
+ transformedFrame.left, transformedFrame.top, transformedFrame.right,
+ transformedFrame.bottom, to_string(error).c_str(), static_cast<int32_t>(error));
} else {
hwcInfo.displayFrame = transformedFrame;
}
@@ -750,23 +577,23 @@
error = hwcLayer->setSourceCrop(sourceCrop);
if (error != HWC2::Error::None) {
ALOGE("[%s] Failed to set source crop [%.3f, %.3f, %.3f, %.3f]: "
- "%s (%d)", mName.string(), sourceCrop.left, sourceCrop.top,
- sourceCrop.right, sourceCrop.bottom, to_string(error).c_str(),
- static_cast<int32_t>(error));
+ "%s (%d)",
+ mName.string(), sourceCrop.left, sourceCrop.top, sourceCrop.right, sourceCrop.bottom,
+ to_string(error).c_str(), static_cast<int32_t>(error));
} else {
hwcInfo.sourceCrop = sourceCrop;
}
- float alpha = getAlpha();
+ float alpha = static_cast<float>(getAlpha());
error = hwcLayer->setPlaneAlpha(alpha);
- ALOGE_IF(error != HWC2::Error::None, "[%s] Failed to set plane alpha %.3f: "
- "%s (%d)", mName.string(), alpha, to_string(error).c_str(),
- static_cast<int32_t>(error));
+ ALOGE_IF(error != HWC2::Error::None,
+ "[%s] Failed to set plane alpha %.3f: "
+ "%s (%d)",
+ mName.string(), alpha, to_string(error).c_str(), static_cast<int32_t>(error));
error = hwcLayer->setZOrder(z);
- ALOGE_IF(error != HWC2::Error::None, "[%s] Failed to set Z %u: %s (%d)",
- mName.string(), z, to_string(error).c_str(),
- static_cast<int32_t>(error));
+ ALOGE_IF(error != HWC2::Error::None, "[%s] Failed to set Z %u: %s (%d)", mName.string(), z,
+ to_string(error).c_str(), static_cast<int32_t>(error));
int type = s.type;
int appId = s.appId;
@@ -778,8 +605,8 @@
}
error = hwcLayer->setInfo(type, appId);
- ALOGE_IF(error != HWC2::Error::None, "[%s] Failed to set info (%d)",
- mName.string(), static_cast<int32_t>(error));
+ ALOGE_IF(error != HWC2::Error::None, "[%s] Failed to set info (%d)", mName.string(),
+ static_cast<int32_t>(error));
#else
if (!frame.intersect(hw->getViewport(), &frame)) {
frame.clear();
@@ -787,7 +614,7 @@
const Transform& tr(hw->getTransform());
layer.setFrame(tr.transform(frame));
layer.setCrop(computeCrop(hw));
- layer.setPlaneAlpha(getAlpha());
+ layer.setPlaneAlpha(static_cast<uint8_t>(std::round(255.0f * getAlpha())));
#endif
/*
@@ -806,12 +633,10 @@
* the code below applies the primary display's inverse transform to the
* buffer
*/
- uint32_t invTransform =
- DisplayDevice::getPrimaryDisplayOrientationTransform();
+ uint32_t invTransform = DisplayDevice::getPrimaryDisplayOrientationTransform();
// calculate the inverse transform
if (invTransform & NATIVE_WINDOW_TRANSFORM_ROT_90) {
- invTransform ^= NATIVE_WINDOW_TRANSFORM_FLIP_V |
- NATIVE_WINDOW_TRANSFORM_FLIP_H;
+ invTransform ^= NATIVE_WINDOW_TRANSFORM_FLIP_V | NATIVE_WINDOW_TRANSFORM_FLIP_H;
}
/*
@@ -832,9 +657,11 @@
} else {
auto transform = static_cast<HWC2::Transform>(orientation);
auto error = hwcLayer->setTransform(transform);
- ALOGE_IF(error != HWC2::Error::None, "[%s] Failed to set transform %s: "
- "%s (%d)", mName.string(), to_string(transform).c_str(),
- to_string(error).c_str(), static_cast<int32_t>(error));
+ ALOGE_IF(error != HWC2::Error::None,
+ "[%s] Failed to set transform %s: "
+ "%s (%d)",
+ mName.string(), to_string(transform).c_str(), to_string(error).c_str(),
+ static_cast<int32_t>(error));
}
#else
if (orientation & Transform::ROT_INVALID) {
@@ -855,107 +682,9 @@
mHwcLayers[hwcId].forceClientComposition = true;
}
-
-void Layer::setPerFrameData(const sp<const DisplayDevice>& displayDevice) {
- // Apply this display's projection's viewport to the visible region
- // before giving it to the HWC HAL.
- const Transform& tr = displayDevice->getTransform();
- const auto& viewport = displayDevice->getViewport();
- Region visible = tr.transform(visibleRegion.intersect(viewport));
- auto hwcId = displayDevice->getHwcDisplayId();
- auto& hwcInfo = mHwcLayers[hwcId];
- auto& hwcLayer = hwcInfo.layer;
- auto error = hwcLayer->setVisibleRegion(visible);
- if (error != HWC2::Error::None) {
- ALOGE("[%s] Failed to set visible region: %s (%d)", mName.string(),
- to_string(error).c_str(), static_cast<int32_t>(error));
- visible.dump(LOG_TAG);
- }
-
- error = hwcLayer->setSurfaceDamage(surfaceDamageRegion);
- if (error != HWC2::Error::None) {
- ALOGE("[%s] Failed to set surface damage: %s (%d)", mName.string(),
- to_string(error).c_str(), static_cast<int32_t>(error));
- surfaceDamageRegion.dump(LOG_TAG);
- }
-
- // Sideband layers
- if (mSidebandStream.get()) {
- setCompositionType(hwcId, HWC2::Composition::Sideband);
- ALOGV("[%s] Requesting Sideband composition", mName.string());
- error = hwcLayer->setSidebandStream(mSidebandStream->handle());
- if (error != HWC2::Error::None) {
- ALOGE("[%s] Failed to set sideband stream %p: %s (%d)",
- mName.string(), mSidebandStream->handle(),
- to_string(error).c_str(), static_cast<int32_t>(error));
- }
- return;
- }
-
- // Client layers
- if (hwcInfo.forceClientComposition ||
- (mActiveBuffer != nullptr && mActiveBuffer->handle == nullptr)) {
- ALOGV("[%s] Requesting Client composition", mName.string());
- setCompositionType(hwcId, HWC2::Composition::Client);
- return;
- }
-
- // SolidColor layers
- if (mActiveBuffer == nullptr) {
- setCompositionType(hwcId, HWC2::Composition::SolidColor);
-
- // For now, we only support black for DimLayer
- error = hwcLayer->setColor({0, 0, 0, 255});
- if (error != HWC2::Error::None) {
- ALOGE("[%s] Failed to set color: %s (%d)", mName.string(),
- to_string(error).c_str(), static_cast<int32_t>(error));
- }
-
- // Clear out the transform, because it doesn't make sense absent a
- // source buffer
- error = hwcLayer->setTransform(HWC2::Transform::None);
- if (error != HWC2::Error::None) {
- ALOGE("[%s] Failed to clear transform: %s (%d)", mName.string(),
- to_string(error).c_str(), static_cast<int32_t>(error));
- }
-
- return;
- }
-
- // Device or Cursor layers
- if (mPotentialCursor) {
- ALOGV("[%s] Requesting Cursor composition", mName.string());
- setCompositionType(hwcId, HWC2::Composition::Cursor);
- } else {
- ALOGV("[%s] Requesting Device composition", mName.string());
- setCompositionType(hwcId, HWC2::Composition::Device);
- }
-
- ALOGV("setPerFrameData: dataspace = %d", mCurrentState.dataSpace);
- error = hwcLayer->setDataspace(mCurrentState.dataSpace);
- if (error != HWC2::Error::None) {
- ALOGE("[%s] Failed to set dataspace %d: %s (%d)", mName.string(),
- mCurrentState.dataSpace, to_string(error).c_str(),
- static_cast<int32_t>(error));
- }
-
- uint32_t hwcSlot = 0;
- sp<GraphicBuffer> hwcBuffer;
- hwcInfo.bufferCache.getHwcBuffer(mActiveBufferSlot, mActiveBuffer,
- &hwcSlot, &hwcBuffer);
-
- auto acquireFence = mSurfaceFlingerConsumer->getCurrentFence();
- error = hwcLayer->setBuffer(hwcSlot, hwcBuffer, acquireFence);
- if (error != HWC2::Error::None) {
- ALOGE("[%s] Failed to set buffer %p: %s (%d)", mName.string(),
- mActiveBuffer->handle, to_string(error).c_str(),
- static_cast<int32_t>(error));
- }
-}
-
#else
void Layer::setPerFrameData(const sp<const DisplayDevice>& hw,
- HWComposer::HWCLayerInterface& layer) {
+ HWComposer::HWCLayerInterface& layer) {
// we have to set the visible region on every frame because
// we currently free it during onLayerDisplayed(), which is called
// after HWComposer::commit() -- every frame.
@@ -977,11 +706,11 @@
}
#endif
+
#ifdef USE_HWC2
void Layer::updateCursorPosition(const sp<const DisplayDevice>& displayDevice) {
auto hwcId = displayDevice->getHwcDisplayId();
- if (mHwcLayers.count(hwcId) == 0 ||
- getCompositionType(hwcId) != HWC2::Composition::Cursor) {
+ if (mHwcLayers.count(hwcId) == 0 || getCompositionType(hwcId) != HWC2::Composition::Cursor) {
return;
}
@@ -1004,36 +733,15 @@
auto& displayTransform(displayDevice->getTransform());
auto position = displayTransform.transform(frame);
- auto error = mHwcLayers[hwcId].layer->setCursorPosition(position.left,
- position.top);
- ALOGE_IF(error != HWC2::Error::None, "[%s] Failed to set cursor position "
- "to (%d, %d): %s (%d)", mName.string(), position.left,
- position.top, to_string(error).c_str(),
- static_cast<int32_t>(error));
+ auto error = mHwcLayers[hwcId].layer->setCursorPosition(position.left, position.top);
+ ALOGE_IF(error != HWC2::Error::None,
+ "[%s] Failed to set cursor position "
+ "to (%d, %d): %s (%d)",
+ mName.string(), position.left, position.top, to_string(error).c_str(),
+ static_cast<int32_t>(error));
}
#else
-void Layer::setAcquireFence(const sp<const DisplayDevice>& /* hw */,
- HWComposer::HWCLayerInterface& layer) {
- int fenceFd = -1;
-
- // TODO: there is a possible optimization here: we only need to set the
- // acquire fence the first time a new buffer is acquired on EACH display.
-
- if (layer.getCompositionType() == HWC_OVERLAY || layer.getCompositionType() == HWC_CURSOR_OVERLAY) {
- sp<Fence> fence = mSurfaceFlingerConsumer->getCurrentFence();
- if (fence->isValid()) {
- fenceFd = fence->dup();
- if (fenceFd == -1) {
- ALOGW("failed to dup layer fence, skipping sync: %d", errno);
- }
- }
- }
- layer.setAcquireFenceFd(fenceFd);
-}
-
-Rect Layer::getPosition(
- const sp<const DisplayDevice>& hw)
-{
+Rect Layer::getPosition(const sp<const DisplayDevice>& hw) {
// this gives us only the "orientation" component of the transform
const State& s(getCurrentState());
@@ -1059,229 +767,50 @@
// drawing...
// ---------------------------------------------------------------------------
-void Layer::draw(const sp<const DisplayDevice>& hw, const Region& clip) const {
- onDraw(hw, clip, false);
+void Layer::draw(const RenderArea& renderArea, const Region& clip) const {
+ onDraw(renderArea, clip, false);
}
-void Layer::draw(const sp<const DisplayDevice>& hw,
- bool useIdentityTransform) const {
- onDraw(hw, Region(hw->bounds()), useIdentityTransform);
+void Layer::draw(const RenderArea& renderArea, bool useIdentityTransform) const {
+ onDraw(renderArea, Region(renderArea.getBounds()), useIdentityTransform);
}
-void Layer::draw(const sp<const DisplayDevice>& hw) const {
- onDraw(hw, Region(hw->bounds()), false);
+void Layer::draw(const RenderArea& renderArea) const {
+ onDraw(renderArea, Region(renderArea.getBounds()), false);
}
-static constexpr mat4 inverseOrientation(uint32_t transform) {
- const mat4 flipH(-1,0,0,0, 0,1,0,0, 0,0,1,0, 1,0,0,1);
- const mat4 flipV( 1,0,0,0, 0,-1,0,0, 0,0,1,0, 0,1,0,1);
- const mat4 rot90( 0,1,0,0, -1,0,0,0, 0,0,1,0, 1,0,0,1);
- mat4 tr;
-
- if (transform & NATIVE_WINDOW_TRANSFORM_ROT_90) {
- tr = tr * rot90;
- }
- if (transform & NATIVE_WINDOW_TRANSFORM_FLIP_H) {
- tr = tr * flipH;
- }
- if (transform & NATIVE_WINDOW_TRANSFORM_FLIP_V) {
- tr = tr * flipV;
- }
- return inverse(tr);
-}
-
-/*
- * onDraw will draw the current layer onto the presentable buffer
- */
-void Layer::onDraw(const sp<const DisplayDevice>& hw, const Region& clip,
- bool useIdentityTransform) const
-{
- ATRACE_CALL();
-
- if (CC_UNLIKELY(mActiveBuffer == 0)) {
- // the texture has not been created yet, this Layer has
- // in fact never been drawn into. This happens frequently with
- // SurfaceView because the WindowManager can't know when the client
- // has drawn the first time.
-
- // If there is nothing under us, we paint the screen in black, otherwise
- // we just skip this update.
-
- // figure out if there is something below us
- Region under;
- bool finished = false;
- mFlinger->mDrawingState.traverseInZOrder([&](Layer* layer) {
- if (finished || layer == static_cast<Layer const*>(this)) {
- finished = true;
- return;
- }
- under.orSelf( hw->getTransform().transform(layer->visibleRegion) );
- });
- // if not everything below us is covered, we plug the holes!
- Region holes(clip.subtract(under));
- if (!holes.isEmpty()) {
- clearWithOpenGL(hw, 0, 0, 0, 1);
- }
- return;
- }
-
- // Bind the current buffer to the GL texture, and wait for it to be
- // ready for us to draw into.
- status_t err = mSurfaceFlingerConsumer->bindTextureImage();
- if (err != NO_ERROR) {
- ALOGW("onDraw: bindTextureImage failed (err=%d)", err);
- // Go ahead and draw the buffer anyway; no matter what we do the screen
- // is probably going to have something visibly wrong.
- }
-
- bool blackOutLayer = isProtected() || (isSecure() && !hw->isSecure());
-
+void Layer::clearWithOpenGL(const RenderArea& renderArea, float red, float green, float blue,
+ float alpha) const {
RenderEngine& engine(mFlinger->getRenderEngine());
-
- if (!blackOutLayer) {
- // TODO: we could be more subtle with isFixedSize()
- const bool useFiltering = getFiltering() || needsFiltering(hw) || isFixedSize();
-
- // Query the texture matrix given our current filtering mode.
- float textureMatrix[16];
- mSurfaceFlingerConsumer->setFilteringEnabled(useFiltering);
- mSurfaceFlingerConsumer->getTransformMatrix(textureMatrix);
-
- if (getTransformToDisplayInverse()) {
-
- /*
- * the code below applies the primary display's inverse transform to
- * the texture transform
- */
- uint32_t transform =
- DisplayDevice::getPrimaryDisplayOrientationTransform();
- mat4 tr = inverseOrientation(transform);
-
- /**
- * TODO(b/36727915): This is basically a hack.
- *
- * Ensure that regardless of the parent transformation,
- * this buffer is always transformed from native display
- * orientation to display orientation. For example, in the case
- * of a camera where the buffer remains in native orientation,
- * we want the pixels to always be upright.
- */
- sp<Layer> p = mDrawingParent.promote();
- if (p != nullptr) {
- const auto parentTransform = p->getTransform();
- tr = tr * inverseOrientation(parentTransform.getOrientation());
- }
-
- // and finally apply it to the original texture matrix
- const mat4 texTransform(mat4(static_cast<const float*>(textureMatrix)) * tr);
- memcpy(textureMatrix, texTransform.asArray(), sizeof(textureMatrix));
- }
-
- // Set things up for texturing.
- mTexture.setDimensions(mActiveBuffer->getWidth(), mActiveBuffer->getHeight());
- mTexture.setFiltering(useFiltering);
- mTexture.setMatrix(textureMatrix);
-
- engine.setupLayerTexturing(mTexture);
- } else {
- engine.setupLayerBlackedOut();
- }
- drawWithOpenGL(hw, useIdentityTransform);
- engine.disableTexturing();
-}
-
-
-void Layer::clearWithOpenGL(const sp<const DisplayDevice>& hw,
- float red, float green, float blue,
- float alpha) const
-{
- RenderEngine& engine(mFlinger->getRenderEngine());
- computeGeometry(hw, mMesh, false);
+ computeGeometry(renderArea, mMesh, false);
engine.setupFillWithColor(red, green, blue, alpha);
engine.drawMesh(mMesh);
}
-void Layer::clearWithOpenGL(
- const sp<const DisplayDevice>& hw) const {
- clearWithOpenGL(hw, 0,0,0,0);
-}
-
-void Layer::drawWithOpenGL(const sp<const DisplayDevice>& hw,
- bool useIdentityTransform) const {
- const State& s(getDrawingState());
-
- computeGeometry(hw, mMesh, useIdentityTransform);
-
- /*
- * NOTE: the way we compute the texture coordinates here produces
- * different results than when we take the HWC path -- in the later case
- * the "source crop" is rounded to texel boundaries.
- * This can produce significantly different results when the texture
- * is scaled by a large amount.
- *
- * The GL code below is more logical (imho), and the difference with
- * HWC is due to a limitation of the HWC API to integers -- a question
- * is suspend is whether we should ignore this problem or revert to
- * GL composition when a buffer scaling is applied (maybe with some
- * minimal value)? Or, we could make GL behave like HWC -- but this feel
- * like more of a hack.
- */
- Rect win(computeBounds());
-
- Transform t = getTransform();
- if (!s.finalCrop.isEmpty()) {
- win = t.transform(win);
- if (!win.intersect(s.finalCrop, &win)) {
- win.clear();
- }
- win = t.inverse().transform(win);
- if (!win.intersect(computeBounds(), &win)) {
- win.clear();
- }
- }
-
- float left = float(win.left) / float(s.active.w);
- float top = float(win.top) / float(s.active.h);
- float right = float(win.right) / float(s.active.w);
- float bottom = float(win.bottom) / float(s.active.h);
-
- // TODO: we probably want to generate the texture coords with the mesh
- // here we assume that we only have 4 vertices
- Mesh::VertexArray<vec2> texCoords(mMesh.getTexCoordArray<vec2>());
- texCoords[0] = vec2(left, 1.0f - top);
- texCoords[1] = vec2(left, 1.0f - bottom);
- texCoords[2] = vec2(right, 1.0f - bottom);
- texCoords[3] = vec2(right, 1.0f - top);
-
- RenderEngine& engine(mFlinger->getRenderEngine());
- engine.setupLayerBlending(mPremultipliedAlpha, isOpaque(s), getAlpha());
-#ifdef USE_HWC2
- engine.setSourceDataSpace(mCurrentState.dataSpace);
-#endif
- engine.drawMesh(mMesh);
- engine.disableBlending();
+void Layer::clearWithOpenGL(const RenderArea& renderArea) const {
+ clearWithOpenGL(renderArea, 0, 0, 0, 0);
}
#ifdef USE_HWC2
-void Layer::setCompositionType(int32_t hwcId, HWC2::Composition type,
- bool callIntoHwc) {
+void Layer::setCompositionType(int32_t hwcId, HWC2::Composition type, bool callIntoHwc) {
if (mHwcLayers.count(hwcId) == 0) {
ALOGE("setCompositionType called without a valid HWC layer");
return;
}
auto& hwcInfo = mHwcLayers[hwcId];
auto& hwcLayer = hwcInfo.layer;
- ALOGV("setCompositionType(%" PRIx64 ", %s, %d)", hwcLayer->getId(),
- to_string(type).c_str(), static_cast<int>(callIntoHwc));
+ ALOGV("setCompositionType(%" PRIx64 ", %s, %d)", hwcLayer->getId(), to_string(type).c_str(),
+ static_cast<int>(callIntoHwc));
if (hwcInfo.compositionType != type) {
ALOGV(" actually setting");
hwcInfo.compositionType = type;
if (callIntoHwc) {
auto error = hwcLayer->setCompositionType(type);
- ALOGE_IF(error != HWC2::Error::None, "[%s] Failed to set "
- "composition type %s: %s (%d)", mName.string(),
- to_string(type).c_str(), to_string(error).c_str(),
- static_cast<int32_t>(error));
+ ALOGE_IF(error != HWC2::Error::None,
+ "[%s] Failed to set "
+ "composition type %s: %s (%d)",
+ mName.string(), to_string(type).c_str(), to_string(error).c_str(),
+ static_cast<int32_t>(error));
}
}
}
@@ -1316,64 +845,6 @@
}
#endif
-uint32_t Layer::getProducerStickyTransform() const {
- int producerStickyTransform = 0;
- int ret = mProducer->query(NATIVE_WINDOW_STICKY_TRANSFORM, &producerStickyTransform);
- if (ret != OK) {
- ALOGW("%s: Error %s (%d) while querying window sticky transform.", __FUNCTION__,
- strerror(-ret), ret);
- return 0;
- }
- return static_cast<uint32_t>(producerStickyTransform);
-}
-
-bool Layer::latchUnsignaledBuffers() {
- static bool propertyLoaded = false;
- static bool latch = false;
- static std::mutex mutex;
- std::lock_guard<std::mutex> lock(mutex);
- if (!propertyLoaded) {
- char value[PROPERTY_VALUE_MAX] = {};
- property_get("debug.sf.latch_unsignaled", value, "0");
- latch = atoi(value);
- propertyLoaded = true;
- }
- return latch;
-}
-
-uint64_t Layer::getHeadFrameNumber() const {
- Mutex::Autolock lock(mQueueItemLock);
- if (!mQueueItems.empty()) {
- return mQueueItems[0].mFrameNumber;
- } else {
- return mCurrentFrameNumber;
- }
-}
-
-bool Layer::headFenceHasSignaled() const {
-#ifdef USE_HWC2
- if (latchUnsignaledBuffers()) {
- return true;
- }
-
- Mutex::Autolock lock(mQueueItemLock);
- if (mQueueItems.empty()) {
- return true;
- }
- if (mQueueItems[0].mIsDroppable) {
- // Even though this buffer's fence may not have signaled yet, it could
- // be replaced by another buffer before it has a chance to, which means
- // that it's possible to get into a situation where a buffer is never
- // able to be latched. To avoid this, grab this buffer anyway.
- return true;
- }
- return mQueueItems[0].mFenceTime->getSignalTime() !=
- Fence::SIGNAL_TIME_PENDING;
-#else
- return true;
-#endif
-}
-
bool Layer::addSyncPoint(const std::shared_ptr<SyncPoint>& point) {
if (point->getFrameNumber() <= mCurrentFrameNumber) {
// Don't bother with a SyncPoint, since we've already latched the
@@ -1394,28 +865,6 @@
return mFiltering;
}
-// As documented in libhardware header, formats in the range
-// 0x100 - 0x1FF are specific to the HAL implementation, and
-// are known to have no alpha channel
-// TODO: move definition for device-specific range into
-// hardware.h, instead of using hard-coded values here.
-#define HARDWARE_IS_DEVICE_FORMAT(f) ((f) >= 0x100 && (f) <= 0x1FF)
-
-bool Layer::getOpacityForFormat(uint32_t format) {
- if (HARDWARE_IS_DEVICE_FORMAT(format)) {
- return true;
- }
- switch (format) {
- case HAL_PIXEL_FORMAT_RGBA_8888:
- case HAL_PIXEL_FORMAT_BGRA_8888:
- case HAL_PIXEL_FORMAT_RGBA_FP16:
- case HAL_PIXEL_FORMAT_RGBA_1010102:
- return false;
- }
- // in all other case, we have no blending (also for unknown formats)
- return true;
-}
-
// ----------------------------------------------------------------------------
// local state
// ----------------------------------------------------------------------------
@@ -1435,12 +884,11 @@
}
}
-void Layer::computeGeometry(const sp<const DisplayDevice>& hw, Mesh& mesh,
- bool useIdentityTransform) const
-{
+void Layer::computeGeometry(const RenderArea& renderArea, Mesh& mesh,
+ bool useIdentityTransform) const {
const Layer::State& s(getDrawingState());
- const Transform hwTransform(hw->getTransform());
- const uint32_t hw_h = hw->getHeight();
+ const Transform renderAreaTransform(renderArea.getTransform());
+ const uint32_t height = renderArea.getHeight();
Rect win = computeBounds();
vec2 lt = vec2(win.left, win.top);
@@ -1464,53 +912,20 @@
}
Mesh::VertexArray<vec2> position(mesh.getPositionArray<vec2>());
- position[0] = hwTransform.transform(lt);
- position[1] = hwTransform.transform(lb);
- position[2] = hwTransform.transform(rb);
- position[3] = hwTransform.transform(rt);
- for (size_t i=0 ; i<4 ; i++) {
- position[i].y = hw_h - position[i].y;
+ position[0] = renderAreaTransform.transform(lt);
+ position[1] = renderAreaTransform.transform(lb);
+ position[2] = renderAreaTransform.transform(rb);
+ position[3] = renderAreaTransform.transform(rt);
+ for (size_t i = 0; i < 4; i++) {
+ position[i].y = height - position[i].y;
}
}
-bool Layer::isOpaque(const Layer::State& s) const
-{
- // if we don't have a buffer or sidebandStream yet, we're translucent regardless of the
- // layer's opaque flag.
- if ((mSidebandStream == nullptr) && (mActiveBuffer == nullptr)) {
- return false;
- }
-
- // if the layer has the opaque flag, then we're always opaque,
- // otherwise we use the current buffer's format.
- return ((s.flags & layer_state_t::eLayerOpaque) != 0) || mCurrentOpacity;
-}
-
-bool Layer::isSecure() const
-{
+bool Layer::isSecure() const {
const Layer::State& s(mDrawingState);
return (s.flags & layer_state_t::eLayerSecure);
}
-bool Layer::isProtected() const
-{
- const sp<GraphicBuffer>& activeBuffer(mActiveBuffer);
- return (activeBuffer != 0) &&
- (activeBuffer->getUsage() & GRALLOC_USAGE_PROTECTED);
-}
-
-bool Layer::isFixedSize() const {
- return getEffectiveScalingMode() != NATIVE_WINDOW_SCALING_MODE_FREEZE;
-}
-
-bool Layer::isCropped() const {
- return !mCurrentCrop.isEmpty();
-}
-
-bool Layer::needsFiltering(const sp<const DisplayDevice>& hw) const {
- return mNeedsFiltering || hw->needsFiltering();
-}
-
void Layer::setVisibleRegion(const Region& visibleRegion) {
// always called from main thread
this->visibleRegion = visibleRegion;
@@ -1521,8 +936,7 @@
this->coveredRegion = coveredRegion;
}
-void Layer::setVisibleNonTransparentRegion(const Region&
- setVisibleNonTransparentRegion) {
+void Layer::setVisibleNonTransparentRegion(const Region& setVisibleNonTransparentRegion) {
// always called from main thread
this->visibleNonTransparentRegion = setVisibleNonTransparentRegion;
}
@@ -1547,8 +961,7 @@
// to be applied as per normal (no synchronization).
mCurrentState.barrierLayer = nullptr;
} else {
- auto syncPoint = std::make_shared<SyncPoint>(
- mCurrentState.frameNumber);
+ auto syncPoint = std::make_shared<SyncPoint>(mCurrentState.frameNumber);
if (barrierLayer->addSyncPoint(syncPoint)) {
mRemoteSyncPoints.push_back(std::move(syncPoint));
} else {
@@ -1569,8 +982,8 @@
void Layer::popPendingState(State* stateToCommit) {
auto oldFlags = stateToCommit->flags;
*stateToCommit = mPendingStates[0];
- stateToCommit->flags = (oldFlags & ~stateToCommit->mask) |
- (stateToCommit->flags & stateToCommit->mask);
+ stateToCommit->flags =
+ (oldFlags & ~stateToCommit->mask) | (stateToCommit->flags & stateToCommit->mask);
mPendingStates.removeAt(0);
ATRACE_INT(mTransactionName.string(), mPendingStates.size());
@@ -1590,10 +1003,8 @@
continue;
}
- if (mRemoteSyncPoints.front()->getFrameNumber() !=
- mPendingStates[0].frameNumber) {
- ALOGE("[%s] Unexpected sync point frame number found",
- mName.string());
+ if (mRemoteSyncPoints.front()->getFrameNumber() != mPendingStates[0].frameNumber) {
+ ALOGE("[%s] Unexpected sync point frame number found", mName.string());
// Signal our end of the sync point and then dispose of it
mRemoteSyncPoints.front()->setTransactionApplied();
@@ -1629,17 +1040,6 @@
return stateUpdateAvailable;
}
-void Layer::notifyAvailableFrames() {
- auto headFrameNumber = getHeadFrameNumber();
- bool headFenceSignaled = headFenceHasSignaled();
- Mutex::Autolock lock(mLocalSyncPointMutex);
- for (auto& point : mLocalSyncPoints) {
- if (headFrameNumber >= point->getFrameNumber() && headFenceSignaled) {
- point->setFrameAvailable();
- }
- }
-}
-
uint32_t Layer::doTransaction(uint32_t flags) {
ATRACE_CALL();
@@ -1651,59 +1051,49 @@
const Layer::State& s(getDrawingState());
- const bool sizeChanged = (c.requested.w != s.requested.w) ||
- (c.requested.h != s.requested.h);
+ const bool sizeChanged = (c.requested.w != s.requested.w) || (c.requested.h != s.requested.h);
if (sizeChanged) {
// the size changed, we need to ask our client to request a new buffer
ALOGD_IF(DEBUG_RESIZE,
- "doTransaction: geometry (layer=%p '%s'), tr=%02x, scalingMode=%d\n"
- " current={ active ={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }\n"
- " requested={ wh={%4u,%4u} }}\n"
- " drawing={ active ={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }\n"
- " requested={ wh={%4u,%4u} }}\n",
- this, getName().string(), mCurrentTransform,
- getEffectiveScalingMode(),
- c.active.w, c.active.h,
- c.crop.left,
- c.crop.top,
- c.crop.right,
- c.crop.bottom,
- c.crop.getWidth(),
- c.crop.getHeight(),
- c.requested.w, c.requested.h,
- s.active.w, s.active.h,
- s.crop.left,
- s.crop.top,
- s.crop.right,
- s.crop.bottom,
- s.crop.getWidth(),
- s.crop.getHeight(),
- s.requested.w, s.requested.h);
+ "doTransaction: geometry (layer=%p '%s'), tr=%02x, scalingMode=%d\n"
+ " current={ active ={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }\n"
+ " requested={ wh={%4u,%4u} }}\n"
+ " drawing={ active ={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }\n"
+ " requested={ wh={%4u,%4u} }}\n",
+ this, getName().string(), mCurrentTransform, getEffectiveScalingMode(), c.active.w,
+ c.active.h, c.crop.left, c.crop.top, c.crop.right, c.crop.bottom,
+ c.crop.getWidth(), c.crop.getHeight(), c.requested.w, c.requested.h, s.active.w,
+ s.active.h, s.crop.left, s.crop.top, s.crop.right, s.crop.bottom,
+ s.crop.getWidth(), s.crop.getHeight(), s.requested.w, s.requested.h);
// record the new size, form this point on, when the client request
// a buffer, it'll get the new size.
- mSurfaceFlingerConsumer->setDefaultBufferSize(
- c.requested.w, c.requested.h);
+ setDefaultBufferSize(c.requested.w, c.requested.h);
}
- const bool resizePending = (c.requested.w != c.active.w) ||
- (c.requested.h != c.active.h);
+ // Don't let Layer::doTransaction update the drawing state
+ // if we have a pending resize, unless we are in fixed-size mode.
+ // the drawing state will be updated only once we receive a buffer
+ // with the correct size.
+ //
+ // In particular, we want to make sure the clip (which is part
+ // of the geometry state) is latched together with the size but is
+ // latched immediately when no resizing is involved.
+ //
+ // If a sideband stream is attached, however, we want to skip this
+ // optimization so that transactions aren't missed when a buffer
+ // never arrives
+ //
+ // In the case that we don't have a buffer we ignore other factors
+ // and avoid entering the resizePending state. At a high level the
+ // resizePending state is to avoid applying the state of the new buffer
+ // to the old buffer. However in the state where we don't have an old buffer
+ // there is no such concern but we may still be being used as a parent layer.
+ const bool resizePending = ((c.requested.w != c.active.w) || (c.requested.h != c.active.h)) &&
+ (mActiveBuffer != nullptr);
if (!isFixedSize()) {
if (resizePending && mSidebandStream == NULL) {
- // don't let Layer::doTransaction update the drawing state
- // if we have a pending resize, unless we are in fixed-size mode.
- // the drawing state will be updated only once we receive a buffer
- // with the correct size.
- //
- // in particular, we want to make sure the clip (which is part
- // of the geometry state) is latched together with the size but is
- // latched immediately when no resizing is involved.
- //
- // If a sideband stream is attached, however, we want to skip this
- // optimization so that transactions aren't missed when a buffer
- // never arrives
-
flags |= eDontUpdateGeometryState;
}
}
@@ -1750,8 +1140,7 @@
// we may use linear filtering, if the matrix scales us
const uint8_t type = c.active.transform.getType();
- mNeedsFiltering = (!c.active.transform.preserveRects() ||
- (type >= Transform::SCALE));
+ mNeedsFiltering = (!c.active.transform.preserveRects() || (type >= Transform::SCALE));
}
// If the layer is hidden, signal and clear out all local sync points so
@@ -1814,8 +1203,7 @@
}
bool Layer::setLayer(int32_t z) {
- if (mCurrentState.z == z)
- return false;
+ if (mCurrentState.z == z) return false;
mCurrentState.sequence++;
mCurrentState.z = z;
mCurrentState.modified = true;
@@ -1860,6 +1248,10 @@
mCurrentState.modified = true;
mCurrentState.z = z;
+ auto oldZOrderRelativeOf = mCurrentState.zOrderRelativeOf.promote();
+ if (oldZOrderRelativeOf != nullptr) {
+ oldZOrderRelativeOf->removeZOrderRelative(this);
+ }
mCurrentState.zOrderRelativeOf = relative;
relative->addZOrderRelative(this);
@@ -1869,31 +1261,39 @@
}
bool Layer::setSize(uint32_t w, uint32_t h) {
- if (mCurrentState.requested.w == w && mCurrentState.requested.h == h)
- return false;
+ if (mCurrentState.requested.w == w && mCurrentState.requested.h == h) return false;
mCurrentState.requested.w = w;
mCurrentState.requested.h = h;
mCurrentState.modified = true;
setTransactionFlags(eTransactionNeeded);
return true;
}
-#ifdef USE_HWC2
bool Layer::setAlpha(float alpha) {
-#else
-bool Layer::setAlpha(uint8_t alpha) {
-#endif
- if (mCurrentState.alpha == alpha)
- return false;
+ if (mCurrentState.color.a == alpha) return false;
mCurrentState.sequence++;
- mCurrentState.alpha = alpha;
+ mCurrentState.color.a = alpha;
mCurrentState.modified = true;
setTransactionFlags(eTransactionNeeded);
return true;
}
+
+bool Layer::setColor(const half3& color) {
+ if (color.r == mCurrentState.color.r && color.g == mCurrentState.color.g &&
+ color.b == mCurrentState.color.b)
+ return false;
+
+ mCurrentState.sequence++;
+ mCurrentState.color.r = color.r;
+ mCurrentState.color.g = color.g;
+ mCurrentState.color.b = color.b;
+ mCurrentState.modified = true;
+ setTransactionFlags(eTransactionNeeded);
+ return true;
+}
+
bool Layer::setMatrix(const layer_state_t::matrix22_t& matrix) {
mCurrentState.sequence++;
- mCurrentState.requested.transform.set(
- matrix.dsdx, matrix.dtdy, matrix.dtdx, matrix.dsdy);
+ mCurrentState.requested.transform.set(matrix.dsdx, matrix.dtdy, matrix.dtdx, matrix.dsdy);
mCurrentState.modified = true;
setTransactionFlags(eTransactionNeeded);
return true;
@@ -1906,8 +1306,7 @@
}
bool Layer::setFlags(uint8_t flags, uint8_t mask) {
const uint32_t newFlags = (mCurrentState.flags & ~mask) | (flags & mask);
- if (mCurrentState.flags == newFlags)
- return false;
+ if (mCurrentState.flags == newFlags) return false;
mCurrentState.sequence++;
mCurrentState.flags = newFlags;
mCurrentState.mask = mask;
@@ -1917,8 +1316,7 @@
}
bool Layer::setCrop(const Rect& crop, bool immediate) {
- if (mCurrentState.requestedCrop == crop)
- return false;
+ if (mCurrentState.requestedCrop == crop) return false;
mCurrentState.sequence++;
mCurrentState.requestedCrop = crop;
if (immediate && !mFreezeGeometryUpdates) {
@@ -1932,8 +1330,7 @@
}
bool Layer::setFinalCrop(const Rect& crop, bool immediate) {
- if (mCurrentState.requestedFinalCrop == crop)
- return false;
+ if (mCurrentState.requestedFinalCrop == crop) return false;
mCurrentState.sequence++;
mCurrentState.requestedFinalCrop = crop;
if (immediate && !mFreezeGeometryUpdates) {
@@ -1947,30 +1344,21 @@
}
bool Layer::setOverrideScalingMode(int32_t scalingMode) {
- if (scalingMode == mOverrideScalingMode)
- return false;
+ if (scalingMode == mOverrideScalingMode) return false;
mOverrideScalingMode = scalingMode;
setTransactionFlags(eTransactionNeeded);
return true;
}
void Layer::setInfo(uint32_t type, uint32_t appId) {
- mCurrentState.appId = appId;
- mCurrentState.type = type;
- mCurrentState.modified = true;
- setTransactionFlags(eTransactionNeeded);
-}
-
-uint32_t Layer::getEffectiveScalingMode() const {
- if (mOverrideScalingMode >= 0) {
- return mOverrideScalingMode;
- }
- return mCurrentScalingMode;
+ mCurrentState.appId = appId;
+ mCurrentState.type = type;
+ mCurrentState.modified = true;
+ setTransactionFlags(eTransactionNeeded);
}
bool Layer::setLayerStack(uint32_t layerStack) {
- if (mCurrentState.layerStack == layerStack)
- return false;
+ if (mCurrentState.layerStack == layerStack) return false;
mCurrentState.sequence++;
mCurrentState.layerStack = layerStack;
mCurrentState.modified = true;
@@ -1979,8 +1367,7 @@
}
bool Layer::setDataSpace(android_dataspace dataSpace) {
- if (mCurrentState.dataSpace == dataSpace)
- return false;
+ if (mCurrentState.dataSpace == dataSpace) return false;
mCurrentState.sequence++;
mCurrentState.dataSpace = dataSpace;
mCurrentState.modified = true;
@@ -2000,8 +1387,7 @@
return p->getLayerStack();
}
-void Layer::deferTransactionUntil(const sp<Layer>& barrierLayer,
- uint64_t frameNumber) {
+void Layer::deferTransactionUntil(const sp<Layer>& barrierLayer, uint64_t frameNumber) {
mCurrentState.barrierLayer = barrierLayer;
mCurrentState.frameNumber = frameNumber;
// We don't set eTransactionNeeded, because just receiving a deferral
@@ -2013,124 +1399,16 @@
mCurrentState.modified = false;
}
-void Layer::deferTransactionUntil(const sp<IBinder>& barrierHandle,
- uint64_t frameNumber) {
+void Layer::deferTransactionUntil(const sp<IBinder>& barrierHandle, uint64_t frameNumber) {
sp<Handle> handle = static_cast<Handle*>(barrierHandle.get());
deferTransactionUntil(handle->owner.promote(), frameNumber);
}
-void Layer::useSurfaceDamage() {
- if (mFlinger->mForceFullDamage) {
- surfaceDamageRegion = Region::INVALID_REGION;
- } else {
- surfaceDamageRegion = mSurfaceFlingerConsumer->getSurfaceDamage();
- }
-}
-
-void Layer::useEmptyDamage() {
- surfaceDamageRegion.clear();
-}
// ----------------------------------------------------------------------------
// pageflip handling...
// ----------------------------------------------------------------------------
-bool Layer::shouldPresentNow(const DispSync& dispSync) const {
- if (mSidebandStreamChanged || mAutoRefresh) {
- return true;
- }
-
- Mutex::Autolock lock(mQueueItemLock);
- if (mQueueItems.empty()) {
- return false;
- }
- auto timestamp = mQueueItems[0].mTimestamp;
- nsecs_t expectedPresent =
- mSurfaceFlingerConsumer->computeExpectedPresent(dispSync);
-
- // Ignore timestamps more than a second in the future
- bool isPlausible = timestamp < (expectedPresent + s2ns(1));
- ALOGW_IF(!isPlausible, "[%s] Timestamp %" PRId64 " seems implausible "
- "relative to expectedPresent %" PRId64, mName.string(), timestamp,
- expectedPresent);
-
- bool isDue = timestamp < expectedPresent;
- return isDue || !isPlausible;
-}
-
-bool Layer::onPreComposition(nsecs_t refreshStartTime) {
- if (mBufferLatched) {
- Mutex::Autolock lock(mFrameEventHistoryMutex);
- mFrameEventHistory.addPreComposition(mCurrentFrameNumber, refreshStartTime);
- }
- mRefreshPending = false;
- return mQueuedFrames > 0 || mSidebandStreamChanged || mAutoRefresh;
-}
-
-bool Layer::onPostComposition(const std::shared_ptr<FenceTime>& glDoneFence,
- const std::shared_ptr<FenceTime>& presentFence,
- const CompositorTiming& compositorTiming) {
- // mFrameLatencyNeeded is true when a new frame was latched for the
- // composition.
- if (!mFrameLatencyNeeded)
- return false;
-
- // Update mFrameEventHistory.
- {
- Mutex::Autolock lock(mFrameEventHistoryMutex);
- mFrameEventHistory.addPostComposition(mCurrentFrameNumber,
- glDoneFence, presentFence, compositorTiming);
- }
-
- // Update mFrameTracker.
- nsecs_t desiredPresentTime = mSurfaceFlingerConsumer->getTimestamp();
- mFrameTracker.setDesiredPresentTime(desiredPresentTime);
-
- std::shared_ptr<FenceTime> frameReadyFence =
- mSurfaceFlingerConsumer->getCurrentFenceTime();
- if (frameReadyFence->isValid()) {
- mFrameTracker.setFrameReadyFence(std::move(frameReadyFence));
- } else {
- // There was no fence for this frame, so assume that it was ready
- // to be presented at the desired present time.
- mFrameTracker.setFrameReadyTime(desiredPresentTime);
- }
-
- if (presentFence->isValid()) {
- mFrameTracker.setActualPresentFence(
- std::shared_ptr<FenceTime>(presentFence));
- } else {
- // The HWC doesn't support present fences, so use the refresh
- // timestamp instead.
- mFrameTracker.setActualPresentTime(
- mFlinger->getHwComposer().getRefreshTimestamp(
- HWC_DISPLAY_PRIMARY));
- }
-
- mFrameTracker.advanceFrame();
- mFrameLatencyNeeded = false;
- return true;
-}
-
-#ifdef USE_HWC2
-void Layer::releasePendingBuffer(nsecs_t dequeueReadyTime) {
- if (!mSurfaceFlingerConsumer->releasePendingBuffer()) {
- return;
- }
-
- auto releaseFenceTime = std::make_shared<FenceTime>(
- mSurfaceFlingerConsumer->getPrevFinalReleaseFence());
- mReleaseTimeline.updateSignalTimes();
- mReleaseTimeline.push(releaseFenceTime);
-
- Mutex::Autolock lock(mFrameEventHistoryMutex);
- if (mPreviousFrameNumber != 0) {
- mFrameEventHistory.addRelease(mPreviousFrameNumber,
- dequeueReadyTime, std::move(releaseFenceTime));
- }
-}
-#endif
-
bool Layer::isHiddenByPolicy() const {
const Layer::State& s(mDrawingState);
const auto& parent = mDrawingParent.promote();
@@ -2140,256 +1418,7 @@
return s.flags & layer_state_t::eLayerHidden;
}
-bool Layer::isVisible() const {
-#ifdef USE_HWC2
- return !(isHiddenByPolicy()) && getAlpha() > 0.0f
- && (mActiveBuffer != NULL || mSidebandStream != NULL);
-#else
- return !(isHiddenByPolicy()) && getAlpha()
- && (mActiveBuffer != NULL || mSidebandStream != NULL);
-#endif
-}
-
-bool Layer::allTransactionsSignaled() {
- auto headFrameNumber = getHeadFrameNumber();
- bool matchingFramesFound = false;
- bool allTransactionsApplied = true;
- Mutex::Autolock lock(mLocalSyncPointMutex);
-
- for (auto& point : mLocalSyncPoints) {
- if (point->getFrameNumber() > headFrameNumber) {
- break;
- }
- matchingFramesFound = true;
-
- if (!point->frameIsAvailable()) {
- // We haven't notified the remote layer that the frame for
- // this point is available yet. Notify it now, and then
- // abort this attempt to latch.
- point->setFrameAvailable();
- allTransactionsApplied = false;
- break;
- }
-
- allTransactionsApplied = allTransactionsApplied && point->transactionIsApplied();
- }
- return !matchingFramesFound || allTransactionsApplied;
-}
-
-Region Layer::latchBuffer(bool& recomputeVisibleRegions, nsecs_t latchTime)
-{
- ATRACE_CALL();
-
- if (android_atomic_acquire_cas(true, false, &mSidebandStreamChanged) == 0) {
- // mSidebandStreamChanged was true
- mSidebandStream = mSurfaceFlingerConsumer->getSidebandStream();
- if (mSidebandStream != NULL) {
- setTransactionFlags(eTransactionNeeded);
- mFlinger->setTransactionFlags(eTraversalNeeded);
- }
- recomputeVisibleRegions = true;
-
- const State& s(getDrawingState());
- return getTransform().transform(Region(Rect(s.active.w, s.active.h)));
- }
-
- Region outDirtyRegion;
- if (mQueuedFrames <= 0 && !mAutoRefresh) {
- return outDirtyRegion;
- }
-
- // if we've already called updateTexImage() without going through
- // a composition step, we have to skip this layer at this point
- // because we cannot call updateTeximage() without a corresponding
- // compositionComplete() call.
- // we'll trigger an update in onPreComposition().
- if (mRefreshPending) {
- return outDirtyRegion;
- }
-
- // If the head buffer's acquire fence hasn't signaled yet, return and
- // try again later
- if (!headFenceHasSignaled()) {
- mFlinger->signalLayerUpdate();
- return outDirtyRegion;
- }
-
- // Capture the old state of the layer for comparisons later
- const State& s(getDrawingState());
- const bool oldOpacity = isOpaque(s);
- sp<GraphicBuffer> oldActiveBuffer = mActiveBuffer;
-
- if (!allTransactionsSignaled()) {
- mFlinger->signalLayerUpdate();
- return outDirtyRegion;
- }
-
- // This boolean is used to make sure that SurfaceFlinger's shadow copy
- // of the buffer queue isn't modified when the buffer queue is returning
- // BufferItem's that weren't actually queued. This can happen in shared
- // buffer mode.
- bool queuedBuffer = false;
- LayerRejecter r(mDrawingState, getCurrentState(), recomputeVisibleRegions,
- getProducerStickyTransform() != 0, mName.string(),
- mOverrideScalingMode, mFreezeGeometryUpdates);
- status_t updateResult = mSurfaceFlingerConsumer->updateTexImage(&r,
- mFlinger->mPrimaryDispSync, &mAutoRefresh, &queuedBuffer,
- mLastFrameNumberReceived);
- if (updateResult == BufferQueue::PRESENT_LATER) {
- // Producer doesn't want buffer to be displayed yet. Signal a
- // layer update so we check again at the next opportunity.
- mFlinger->signalLayerUpdate();
- return outDirtyRegion;
- } else if (updateResult == SurfaceFlingerConsumer::BUFFER_REJECTED) {
- // If the buffer has been rejected, remove it from the shadow queue
- // and return early
- if (queuedBuffer) {
- Mutex::Autolock lock(mQueueItemLock);
- mQueueItems.removeAt(0);
- android_atomic_dec(&mQueuedFrames);
- }
- return outDirtyRegion;
- } else if (updateResult != NO_ERROR || mUpdateTexImageFailed) {
- // This can occur if something goes wrong when trying to create the
- // EGLImage for this buffer. If this happens, the buffer has already
- // been released, so we need to clean up the queue and bug out
- // early.
- if (queuedBuffer) {
- Mutex::Autolock lock(mQueueItemLock);
- mQueueItems.clear();
- android_atomic_and(0, &mQueuedFrames);
- }
-
- // Once we have hit this state, the shadow queue may no longer
- // correctly reflect the incoming BufferQueue's contents, so even if
- // updateTexImage starts working, the only safe course of action is
- // to continue to ignore updates.
- mUpdateTexImageFailed = true;
-
- return outDirtyRegion;
- }
-
- if (queuedBuffer) {
- // Autolock scope
- auto currentFrameNumber = mSurfaceFlingerConsumer->getFrameNumber();
-
- Mutex::Autolock lock(mQueueItemLock);
-
- // Remove any stale buffers that have been dropped during
- // updateTexImage
- while (mQueueItems[0].mFrameNumber != currentFrameNumber) {
- mQueueItems.removeAt(0);
- android_atomic_dec(&mQueuedFrames);
- }
-
- mQueueItems.removeAt(0);
- }
-
-
- // Decrement the queued-frames count. Signal another event if we
- // have more frames pending.
- if ((queuedBuffer && android_atomic_dec(&mQueuedFrames) > 1)
- || mAutoRefresh) {
- mFlinger->signalLayerUpdate();
- }
-
- // update the active buffer
- mActiveBuffer = mSurfaceFlingerConsumer->getCurrentBuffer(
- &mActiveBufferSlot);
- if (mActiveBuffer == NULL) {
- // this can only happen if the very first buffer was rejected.
- return outDirtyRegion;
- }
-
- mBufferLatched = true;
- mPreviousFrameNumber = mCurrentFrameNumber;
- mCurrentFrameNumber = mSurfaceFlingerConsumer->getFrameNumber();
-
- {
- Mutex::Autolock lock(mFrameEventHistoryMutex);
- mFrameEventHistory.addLatch(mCurrentFrameNumber, latchTime);
-#ifndef USE_HWC2
- auto releaseFenceTime = std::make_shared<FenceTime>(
- mSurfaceFlingerConsumer->getPrevFinalReleaseFence());
- mReleaseTimeline.updateSignalTimes();
- mReleaseTimeline.push(releaseFenceTime);
- if (mPreviousFrameNumber != 0) {
- mFrameEventHistory.addRelease(mPreviousFrameNumber,
- latchTime, std::move(releaseFenceTime));
- }
-#endif
- }
-
- mRefreshPending = true;
- mFrameLatencyNeeded = true;
- if (oldActiveBuffer == NULL) {
- // the first time we receive a buffer, we need to trigger a
- // geometry invalidation.
- recomputeVisibleRegions = true;
- }
-
- setDataSpace(mSurfaceFlingerConsumer->getCurrentDataSpace());
-
- Rect crop(mSurfaceFlingerConsumer->getCurrentCrop());
- const uint32_t transform(mSurfaceFlingerConsumer->getCurrentTransform());
- const uint32_t scalingMode(mSurfaceFlingerConsumer->getCurrentScalingMode());
- if ((crop != mCurrentCrop) ||
- (transform != mCurrentTransform) ||
- (scalingMode != mCurrentScalingMode))
- {
- mCurrentCrop = crop;
- mCurrentTransform = transform;
- mCurrentScalingMode = scalingMode;
- recomputeVisibleRegions = true;
- }
-
- if (oldActiveBuffer != NULL) {
- uint32_t bufWidth = mActiveBuffer->getWidth();
- uint32_t bufHeight = mActiveBuffer->getHeight();
- if (bufWidth != uint32_t(oldActiveBuffer->width) ||
- bufHeight != uint32_t(oldActiveBuffer->height)) {
- recomputeVisibleRegions = true;
- }
- }
-
- mCurrentOpacity = getOpacityForFormat(mActiveBuffer->format);
- if (oldOpacity != isOpaque(s)) {
- recomputeVisibleRegions = true;
- }
-
- // Remove any sync points corresponding to the buffer which was just
- // latched
- {
- Mutex::Autolock lock(mLocalSyncPointMutex);
- auto point = mLocalSyncPoints.begin();
- while (point != mLocalSyncPoints.end()) {
- if (!(*point)->frameIsAvailable() ||
- !(*point)->transactionIsApplied()) {
- // This sync point must have been added since we started
- // latching. Don't drop it yet.
- ++point;
- continue;
- }
-
- if ((*point)->getFrameNumber() <= mCurrentFrameNumber) {
- point = mLocalSyncPoints.erase(point);
- } else {
- ++point;
- }
- }
- }
-
- // FIXME: postedRegion should be dirty & bounds
- Region dirtyRegion(Rect(s.active.w, s.active.h));
-
- // transform the dirty region to window-manager space
- outDirtyRegion = (getTransform().transform(dirtyRegion));
-
- return outDirtyRegion;
-}
-
-uint32_t Layer::getEffectiveUsage(uint32_t usage) const
-{
+uint32_t Layer::getEffectiveUsage(uint32_t usage) const {
// TODO: should we do something special if mSecure is set?
if (mProtectedByApp) {
// need a hardware-protected path to external video sink
@@ -2414,7 +1443,7 @@
orientation = 0;
}
}
- mSurfaceFlingerConsumer->setTransformHint(orientation);
+ setTransformHint(orientation);
}
// ----------------------------------------------------------------------------
@@ -2439,7 +1468,7 @@
info.mHeight = ds.active.h;
info.mCrop = ds.crop;
info.mFinalCrop = ds.finalCrop;
- info.mAlpha = ds.alpha;
+ info.mColor = ds.color;
info.mFlags = ds.flags;
info.mPixelFormat = getPixelFormat();
info.mDataSpace = getDataSpace();
@@ -2467,7 +1496,6 @@
info.mContentDirty = contentDirty;
return info;
}
-
#ifdef USE_HWC2
void Layer::miniDumpHeader(String8& result) {
result.append("----------------------------------------");
@@ -2501,15 +1529,12 @@
const Layer::State& layerState(getDrawingState());
const HWCInfo& hwcInfo = mHwcLayers.at(hwcId);
- result.appendFormat(" %10u | ", layerState.z);
- result.appendFormat("%10s | ",
- to_string(getCompositionType(hwcId)).c_str());
+ result.appendFormat(" %10d | ", layerState.z);
+ result.appendFormat("%10s | ", to_string(getCompositionType(hwcId)).c_str());
const Rect& frame = hwcInfo.displayFrame;
- result.appendFormat("%4d %4d %4d %4d | ", frame.left, frame.top,
- frame.right, frame.bottom);
+ result.appendFormat("%4d %4d %4d %4d | ", frame.left, frame.top, frame.right, frame.bottom);
const FloatRect& crop = hwcInfo.sourceCrop;
- result.appendFormat("%6.1f %6.1f %6.1f %6.1f\n", crop.left, crop.top,
- crop.right, crop.bottom);
+ result.appendFormat("%6.1f %6.1f %6.1f %6.1f\n", crop.left, crop.top, crop.right, crop.bottom);
result.append("- - - - - - - - - - - - - - - - - - - - ");
result.append("- - - - - - - - - - - - - - - - - - - -\n");
@@ -2533,8 +1558,7 @@
}
void Layer::dumpFrameEvents(String8& result) {
- result.appendFormat("- Layer %s (%s, %p)\n",
- getName().string(), getTypeId(), this);
+ result.appendFormat("- Layer %s (%s, %p)\n", getName().string(), getTypeId(), this);
Mutex::Autolock lock(mFrameEventHistoryMutex);
mFrameEventHistory.checkFencesForCompletion();
mFrameEventHistory.dump(result);
@@ -2546,7 +1570,7 @@
}
void Layer::addAndGetFrameTimestamps(const NewFrameEventsEntry* newTimestamps,
- FrameEventHistoryDelta *outDelta) {
+ FrameEventHistoryDelta* outDelta) {
Mutex::Autolock lock(mFrameEventHistoryMutex);
if (newTimestamps) {
// If there are any unsignaled fences in the aquire timeline at this
@@ -2564,23 +1588,6 @@
}
}
-std::vector<OccupancyTracker::Segment> Layer::getOccupancyHistory(
- bool forceFlush) {
- std::vector<OccupancyTracker::Segment> history;
- status_t result = mSurfaceFlingerConsumer->getOccupancyHistory(forceFlush,
- &history);
- if (result != NO_ERROR) {
- ALOGW("[%s] Failed to obtain occupancy history (%d)", mName.string(),
- result);
- return {};
- }
- return history;
-}
-
-bool Layer::getTransformToDisplayInverse() const {
- return mSurfaceFlingerConsumer->getTransformToDisplayInverse();
-}
-
size_t Layer::getChildrenCount() const {
size_t count = 0;
for (const sp<Layer>& child : mCurrentChildren) {
@@ -2625,14 +1632,43 @@
return true;
}
+bool Layer::reparent(const sp<IBinder>& newParentHandle) {
+ if (newParentHandle == nullptr) {
+ return false;
+ }
+
+ auto handle = static_cast<Handle*>(newParentHandle.get());
+ sp<Layer> newParent = handle->owner.promote();
+ if (newParent == nullptr) {
+ ALOGE("Unable to promote Layer handle");
+ return false;
+ }
+
+ sp<Layer> parent = getParent();
+ if (parent != nullptr) {
+ parent->removeChild(this);
+ }
+ newParent->addChild(this);
+
+ sp<Client> client(mClientRef.promote());
+ sp<Client> newParentClient(newParent->mClientRef.promote());
+
+ if (client != newParentClient) {
+ client->setParentLayer(newParent);
+ }
+
+ return true;
+}
+
bool Layer::detachChildren() {
traverseInZOrder(LayerVector::StateSet::Drawing, [this](Layer* child) {
if (child == this) {
return;
}
+ sp<Client> parentClient = mClientRef.promote();
sp<Client> client(child->mClientRef.promote());
- if (client != nullptr) {
+ if (client != nullptr && parentClient != client) {
client->detachLayer(child);
}
});
@@ -2660,7 +1696,8 @@
return mDrawingState.z;
}
-LayerVector Layer::makeTraversalList(LayerVector::StateSet stateSet) {
+__attribute__((no_sanitize("unsigned-integer-overflow"))) LayerVector Layer::makeTraversalList(
+ LayerVector::StateSet stateSet) {
LOG_ALWAYS_FATAL_IF(stateSet == LayerVector::StateSet::Invalid,
"makeTraversalList received invalid stateSet");
const bool useDrawing = stateSet == LayerVector::StateSet::Drawing;
@@ -2715,7 +1752,7 @@
LayerVector list = makeTraversalList(stateSet);
int32_t i = 0;
- for (i = list.size()-1; i>=0; i--) {
+ for (i = int32_t(list.size()) - 1; i >= 0; i--) {
const auto& relative = list[i];
if (relative->getZ() < 0) {
break;
@@ -2723,12 +1760,35 @@
relative->traverseInReverseZOrder(stateSet, visitor);
}
visitor(this);
- for (; i>=0; i--) {
+ for (; i >= 0; i--) {
const auto& relative = list[i];
relative->traverseInReverseZOrder(stateSet, visitor);
}
}
+/**
+ * Traverse only children in z order, ignoring relative layers.
+ */
+void Layer::traverseChildrenInZOrder(LayerVector::StateSet stateSet,
+ const LayerVector::Visitor& visitor) {
+ const bool useDrawing = stateSet == LayerVector::StateSet::Drawing;
+ const LayerVector& children = useDrawing ? mDrawingChildren : mCurrentChildren;
+
+ size_t i = 0;
+ for (; i < children.size(); i++) {
+ const auto& relative = children[i];
+ if (relative->getZ() >= 0) {
+ break;
+ }
+ relative->traverseChildrenInZOrder(stateSet, visitor);
+ }
+ visitor(this);
+ for (; i < children.size(); i++) {
+ const auto& relative = children[i];
+ relative->traverseChildrenInZOrder(stateSet, visitor);
+ }
+}
+
Transform Layer::getTransform() const {
Transform t;
const auto& p = mDrawingParent.promote();
@@ -2750,10 +1810,8 @@
bufferHeight = p->mActiveBuffer->getWidth();
bufferWidth = p->mActiveBuffer->getHeight();
}
- float sx = p->getDrawingState().active.w /
- static_cast<float>(bufferWidth);
- float sy = p->getDrawingState().active.h /
- static_cast<float>(bufferHeight);
+ float sx = p->getDrawingState().active.w / static_cast<float>(bufferWidth);
+ float sy = p->getDrawingState().active.h / static_cast<float>(bufferHeight);
Transform extraParentScaling;
extraParentScaling.set(sx, 0, 0, sy);
t = t * extraParentScaling;
@@ -2762,23 +1820,17 @@
return t * getDrawingState().active.transform;
}
-#ifdef USE_HWC2
-float Layer::getAlpha() const {
+half Layer::getAlpha() const {
const auto& p = mDrawingParent.promote();
- float parentAlpha = (p != nullptr) ? p->getAlpha() : 1.0;
- return parentAlpha * getDrawingState().alpha;
+ half parentAlpha = (p != nullptr) ? p->getAlpha() : 1.0_hf;
+ return parentAlpha * getDrawingState().color.a;
}
-#else
-uint8_t Layer::getAlpha() const {
- const auto& p = mDrawingParent.promote();
- float parentAlpha = (p != nullptr) ? (p->getAlpha() / 255.0f) : 1.0;
- float drawingAlpha = getDrawingState().alpha / 255.0f;
- drawingAlpha = drawingAlpha * parentAlpha;
- return static_cast<uint8_t>(std::round(drawingAlpha * 255));
+half4 Layer::getColor() const {
+ const half4 color(getDrawingState().color);
+ return half4(color.r, color.g, color.b, getAlpha());
}
-#endif
void Layer::commitChildList() {
for (size_t i = 0; i < mCurrentChildren.size(); i++) {
@@ -2789,6 +1841,82 @@
mDrawingParent = mCurrentParent;
}
+void Layer::writeToProto(LayerProto* layerInfo, LayerVector::StateSet stateSet) {
+ const bool useDrawing = stateSet == LayerVector::StateSet::Drawing;
+ const LayerVector& children = useDrawing ? mDrawingChildren : mCurrentChildren;
+ const State& state = useDrawing ? mDrawingState : mCurrentState;
+
+ Transform requestedTransform = state.active.transform;
+ Transform transform = getTransform();
+
+ layerInfo->set_id(sequence);
+ layerInfo->set_name(getName().c_str());
+ layerInfo->set_type(String8(getTypeId()));
+
+ for (const auto& child : children) {
+ layerInfo->add_children(child->sequence);
+ }
+
+ for (const wp<Layer>& weakRelative : state.zOrderRelatives) {
+ sp<Layer> strongRelative = weakRelative.promote();
+ if (strongRelative != nullptr) {
+ layerInfo->add_relatives(strongRelative->sequence);
+ }
+ }
+
+ LayerProtoHelper::writeToProto(state.activeTransparentRegion,
+ layerInfo->mutable_transparent_region());
+ LayerProtoHelper::writeToProto(visibleRegion, layerInfo->mutable_visible_region());
+ LayerProtoHelper::writeToProto(surfaceDamageRegion, layerInfo->mutable_damage_region());
+
+ layerInfo->set_layer_stack(getLayerStack());
+ layerInfo->set_z(state.z);
+
+ PositionProto* position = layerInfo->mutable_position();
+ position->set_x(transform.tx());
+ position->set_y(transform.ty());
+
+ PositionProto* requestedPosition = layerInfo->mutable_requested_position();
+ requestedPosition->set_x(requestedTransform.tx());
+ requestedPosition->set_y(requestedTransform.ty());
+
+ SizeProto* size = layerInfo->mutable_size();
+ size->set_w(state.active.w);
+ size->set_h(state.active.h);
+
+ LayerProtoHelper::writeToProto(state.crop, layerInfo->mutable_crop());
+ LayerProtoHelper::writeToProto(state.finalCrop, layerInfo->mutable_final_crop());
+
+ layerInfo->set_is_opaque(isOpaque(state));
+ layerInfo->set_invalidate(contentDirty);
+ layerInfo->set_dataspace(dataspaceDetails(getDataSpace()));
+ layerInfo->set_pixel_format(decodePixelFormat(getPixelFormat()));
+ LayerProtoHelper::writeToProto(getColor(), layerInfo->mutable_color());
+ LayerProtoHelper::writeToProto(state.color, layerInfo->mutable_requested_color());
+ layerInfo->set_flags(state.flags);
+
+ LayerProtoHelper::writeToProto(transform, layerInfo->mutable_transform());
+ LayerProtoHelper::writeToProto(requestedTransform, layerInfo->mutable_requested_transform());
+
+ auto parent = getParent();
+ if (parent != nullptr) {
+ layerInfo->set_parent(parent->sequence);
+ }
+
+ auto zOrderRelativeOf = state.zOrderRelativeOf.promote();
+ if (zOrderRelativeOf != nullptr) {
+ layerInfo->set_z_order_relative_of(zOrderRelativeOf->sequence);
+ }
+
+ auto activeBuffer = getActiveBuffer();
+ if (activeBuffer != nullptr) {
+ LayerProtoHelper::writeToProto(activeBuffer, layerInfo->mutable_active_buffer());
+ }
+
+ layerInfo->set_queued_frames(getQueuedFrameCount());
+ layerInfo->set_refresh_pending(isBufferLatched());
+}
+
// ---------------------------------------------------------------------------
}; // namespace android
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index f7b82e4..0580b9f 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -33,24 +33,28 @@
#include <ui/Region.h>
#include <gui/ISurfaceComposerClient.h>
-
-#include <private/gui/LayerState.h>
+#include <gui/LayerState.h>
#include <list>
-#include "FrameTracker.h"
#include "Client.h"
+#include "FrameTracker.h"
#include "LayerVector.h"
#include "MonitoredProducer.h"
#include "SurfaceFlinger.h"
-#include "SurfaceFlingerConsumer.h"
#include "Transform.h"
+#include <layerproto/LayerProtoHeader.h>
#include "DisplayHardware/HWComposer.h"
#include "DisplayHardware/HWComposerBufferCache.h"
+#include "RenderArea.h"
#include "RenderEngine/Mesh.h"
#include "RenderEngine/Texture.h"
+#include <math/vec4.h>
+
+using namespace android::surfaceflinger;
+
namespace android {
// ---------------------------------------------------------------------------
@@ -64,14 +68,7 @@
// ---------------------------------------------------------------------------
-/*
- * A new BufferQueue and a new SurfaceFlingerConsumer are created when the
- * Layer is first referenced.
- *
- * This also implements onFrameAvailable(), which notifies SurfaceFlinger
- * that new data has arrived.
- */
-class Layer : public SurfaceFlingerConsumer::ContentsChangedListener {
+class Layer : public virtual RefBase {
static int32_t sSequence;
public:
@@ -97,14 +94,11 @@
uint32_t h;
Transform transform;
- inline bool operator ==(const Geometry& rhs) const {
- return (w == rhs.w && h == rhs.h) &&
- (transform.tx() == rhs.transform.tx()) &&
+ inline bool operator==(const Geometry& rhs) const {
+ return (w == rhs.w && h == rhs.h) && (transform.tx() == rhs.transform.tx()) &&
(transform.ty() == rhs.transform.ty());
}
- inline bool operator !=(const Geometry& rhs) const {
- return !operator ==(rhs);
- }
+ inline bool operator!=(const Geometry& rhs) const { return !operator==(rhs); }
};
struct State {
@@ -119,11 +113,6 @@
// to achieve mirroring.
uint32_t layerStack;
-#ifdef USE_HWC2
- float alpha;
-#else
- uint8_t alpha;
-#endif
uint8_t flags;
uint8_t mask;
uint8_t reserved[2];
@@ -158,20 +147,16 @@
// A list of surfaces whose Z-order is interpreted relative to ours.
SortedVector<wp<Layer>> zOrderRelatives;
+
+ half4 color;
};
- // -----------------------------------------------------------------------
-
- Layer(SurfaceFlinger* flinger, const sp<Client>& client,
- const String8& name, uint32_t w, uint32_t h, uint32_t flags);
-
+ Layer(SurfaceFlinger* flinger, const sp<Client>& client, const String8& name, uint32_t w,
+ uint32_t h, uint32_t flags);
virtual ~Layer();
void setPrimaryDisplayOnly() { mPrimaryDisplayOnly = true; }
- // the this layer's size and format
- status_t setBuffers(uint32_t w, uint32_t h, PixelFormat format, uint32_t flags);
-
// ------------------------------------------------------------------------
// Geometry setting functions.
//
@@ -225,11 +210,8 @@
bool setLayer(int32_t z);
bool setRelativeLayer(const sp<IBinder>& relativeToHandle, int32_t relativeZ);
-#ifdef USE_HWC2
bool setAlpha(float alpha);
-#else
- bool setAlpha(uint8_t alpha);
-#endif
+ bool setColor(const half3& color);
bool setTransparentRegionHint(const Region& transparent);
bool setFlags(uint8_t flags, uint8_t mask);
bool setLayerStack(uint32_t layerStack);
@@ -241,13 +223,14 @@
bool setOverrideScalingMode(int32_t overrideScalingMode);
void setInfo(uint32_t type, uint32_t appId);
bool reparentChildren(const sp<IBinder>& layer);
+ bool reparent(const sp<IBinder>& newParentHandle);
bool detachChildren();
// If we have received a new buffer this frame, we will pass its surface
// damage down to hardware composer. Otherwise, we must send a region with
// one empty rect.
- void useSurfaceDamage();
- void useEmptyDamage();
+ virtual void useSurfaceDamage() = 0;
+ virtual void useEmptyDamage() = 0;
uint32_t getTransactionFlags(uint32_t flags);
uint32_t setTransactionFlags(uint32_t flags);
@@ -256,8 +239,7 @@
return getLayerStack() == layerStack && (!mPrimaryDisplayOnly || isPrimaryDisplay);
}
- void computeGeometry(const sp<const DisplayDevice>& hw, Mesh& mesh,
- bool useIdentityTransform) const;
+ void computeGeometry(const RenderArea& renderArea, Mesh& mesh, bool useIdentityTransform) const;
Rect computeBounds(const Region& activeTransparentRegion) const;
Rect computeBounds() const;
@@ -265,8 +247,7 @@
// -----------------------------------------------------------------------
// Virtuals
-
- virtual const char* getTypeId() const { return "Layer"; }
+ virtual const char* getTypeId() const = 0;
/*
* isOpaque - true if this surface is opaque
@@ -275,24 +256,18 @@
* pixel format includes an alpha channel) and the "opaque" flag set
* on the layer. It does not examine the current plane alpha value.
*/
- virtual bool isOpaque(const Layer::State& s) const;
+ virtual bool isOpaque(const Layer::State& s) const = 0;
/*
* isSecure - true if this surface is secure, that is if it prevents
* screenshots or VNC servers.
*/
- virtual bool isSecure() const;
-
- /*
- * isProtected - true if the layer may contain protected content in the
- * GRALLOC_USAGE_PROTECTED sense.
- */
- virtual bool isProtected() const;
+ bool isSecure() const;
/*
* isVisible - true if this layer is visible, false otherwise
*/
- virtual bool isVisible() const;
+ virtual bool isVisible() const = 0;
/*
* isHiddenByPolicy - true if this layer has been forced invisible.
@@ -300,46 +275,45 @@
* For example if this layer has no active buffer, it may not be hidden by
* policy, but it still can not be visible.
*/
- virtual bool isHiddenByPolicy() const;
+ bool isHiddenByPolicy() const;
/*
* isFixedSize - true if content has a fixed size
*/
- virtual bool isFixedSize() const;
+ virtual bool isFixedSize() const = 0;
+
+ bool isPendingRemoval() const { return mPendingRemoval; }
+
+ void writeToProto(LayerProto* layerInfo,
+ LayerVector::StateSet stateSet = LayerVector::StateSet::Drawing);
protected:
/*
* onDraw - draws the surface.
*/
- virtual void onDraw(const sp<const DisplayDevice>& hw, const Region& clip,
- bool useIdentityTransform) const;
+ virtual void onDraw(const RenderArea& renderArea, const Region& clip,
+ bool useIdentityTransform) const = 0;
public:
- // -----------------------------------------------------------------------
+ virtual void setDefaultBufferSize(uint32_t w, uint32_t h) = 0;
#ifdef USE_HWC2
void setGeometry(const sp<const DisplayDevice>& displayDevice, uint32_t z);
void forceClientComposition(int32_t hwcId);
- void setPerFrameData(const sp<const DisplayDevice>& displayDevice);
+ virtual void setPerFrameData(const sp<const DisplayDevice>& displayDevice) = 0;
// callIntoHwc exists so we can update our local state and call
// acceptDisplayChanges without unnecessarily updating the device's state
- void setCompositionType(int32_t hwcId, HWC2::Composition type,
- bool callIntoHwc = true);
+ void setCompositionType(int32_t hwcId, HWC2::Composition type, bool callIntoHwc = true);
HWC2::Composition getCompositionType(int32_t hwcId) const;
-
void setClearClientTarget(int32_t hwcId, bool clear);
bool getClearClientTarget(int32_t hwcId) const;
-
void updateCursorPosition(const sp<const DisplayDevice>& hw);
#else
- void setGeometry(const sp<const DisplayDevice>& hw,
- HWComposer::HWCLayerInterface& layer);
- void setPerFrameData(const sp<const DisplayDevice>& hw,
- HWComposer::HWCLayerInterface& layer);
- void setAcquireFence(const sp<const DisplayDevice>& hw,
- HWComposer::HWCLayerInterface& layer);
-
+ void setGeometry(const sp<const DisplayDevice>& hw, HWComposer::HWCLayerInterface& layer);
+ void setPerFrameData(const sp<const DisplayDevice>& hw, HWComposer::HWCLayerInterface& layer);
+ virtual void setAcquireFence(const sp<const DisplayDevice>& hw,
+ HWComposer::HWCLayerInterface& layer) = 0;
Rect getPosition(const sp<const DisplayDevice>& hw);
#endif
@@ -347,40 +321,43 @@
* called after page-flip
*/
#ifdef USE_HWC2
- void onLayerDisplayed(const sp<Fence>& releaseFence);
+ virtual void onLayerDisplayed(const sp<Fence>& releaseFence);
#else
- void onLayerDisplayed(const sp<const DisplayDevice>& hw,
- HWComposer::HWCLayerInterface* layer);
+ virtual void onLayerDisplayed(const sp<const DisplayDevice>& hw,
+ HWComposer::HWCLayerInterface* layer);
#endif
- bool shouldPresentNow(const DispSync& dispSync) const;
+ virtual void abandon() = 0;
+
+ virtual bool shouldPresentNow(const DispSync& dispSync) const = 0;
+ virtual void setTransformHint(uint32_t orientation) const = 0;
/*
* called before composition.
* returns true if the layer has pending updates.
*/
- bool onPreComposition(nsecs_t refreshStartTime);
+ virtual bool onPreComposition(nsecs_t refreshStartTime) = 0;
/*
* called after composition.
* returns true if the layer latched a new buffer this frame.
*/
- bool onPostComposition(const std::shared_ptr<FenceTime>& glDoneFence,
- const std::shared_ptr<FenceTime>& presentFence,
- const CompositorTiming& compositorTiming);
+ virtual bool onPostComposition(const std::shared_ptr<FenceTime>& glDoneFence,
+ const std::shared_ptr<FenceTime>& presentFence,
+ const CompositorTiming& compositorTiming) = 0;
#ifdef USE_HWC2
// If a buffer was replaced this frame, release the former buffer
- void releasePendingBuffer(nsecs_t dequeueReadyTime);
+ virtual void releasePendingBuffer(nsecs_t dequeueReadyTime) = 0;
#endif
/*
* draw - performs some global clipping optimizations
* and calls onDraw().
*/
- void draw(const sp<const DisplayDevice>& hw, const Region& clip) const;
- void draw(const sp<const DisplayDevice>& hw, bool useIdentityTransform) const;
- void draw(const sp<const DisplayDevice>& hw) const;
+ void draw(const RenderArea& renderArea, const Region& clip) const;
+ void draw(const RenderArea& renderArea, bool useIdentityTransform) const;
+ void draw(const RenderArea& renderArea) const;
/*
* doTransaction - process the transaction. This is a good place to figure
@@ -405,8 +382,7 @@
* setVisibleNonTransparentRegion - called when the visible and
* non-transparent region changes.
*/
- void setVisibleNonTransparentRegion(const Region&
- visibleNonTransparentRegion);
+ void setVisibleNonTransparentRegion(const Region& visibleNonTransparentRegion);
/*
* latchBuffer - called each time the screen is redrawn and returns whether
@@ -414,11 +390,10 @@
* operation, so this should be set only if needed). Typically this is used
* to figure out if the content or size of a surface has changed.
*/
- Region latchBuffer(bool& recomputeVisibleRegions, nsecs_t latchTime);
- bool isBufferLatched() const { return mRefreshPending; }
+ virtual Region latchBuffer(bool& recomputeVisibleRegions, nsecs_t latchTime) = 0;
+ virtual bool isBufferLatched() const = 0;
- bool isPotentialCursor() const { return mPotentialCursor;}
-
+ bool isPotentialCursor() const { return mPotentialCursor; }
/*
* called with the state lock from a binder thread when the layer is
* removed from the current list to the pending removal list
@@ -431,7 +406,6 @@
*/
void onRemoved();
-
// Updates the transform hint in our SurfaceFlingerConsumer to match
// the current orientation of the display device.
void updateTransformHint(const sp<const DisplayDevice>& hw) const;
@@ -445,8 +419,9 @@
/*
* Returns if a frame is queued.
*/
- bool hasQueuedFrame() const { return mQueuedFrames > 0 ||
- mSidebandStreamChanged || mAutoRefresh; }
+ bool hasQueuedFrame() const {
+ return mQueuedFrames > 0 || mSidebandStreamChanged || mAutoRefresh;
+ }
int32_t getQueuedFrameCount() const { return mQueuedFrames; }
@@ -457,9 +432,7 @@
void destroyHwcLayer(int32_t hwcId);
void destroyAllHwcLayers();
- bool hasHwcLayer(int32_t hwcId) {
- return mHwcLayers.count(hwcId) > 0;
- }
+ bool hasHwcLayer(int32_t hwcId) { return mHwcLayers.count(hwcId) > 0; }
HWC2::Layer* getHwcLayer(int32_t hwcId) {
if (mHwcLayers.count(hwcId) == 0) {
@@ -471,16 +444,16 @@
#endif
// -----------------------------------------------------------------------
- void clearWithOpenGL(const sp<const DisplayDevice>& hw) const;
+ void clearWithOpenGL(const RenderArea& renderArea) const;
void setFiltering(bool filtering);
bool getFiltering() const;
// only for debugging
inline const sp<GraphicBuffer>& getActiveBuffer() const { return mActiveBuffer; }
- inline const State& getDrawingState() const { return mDrawingState; }
- inline const State& getCurrentState() const { return mCurrentState; }
- inline State& getCurrentState() { return mCurrentState; }
+ inline const State& getDrawingState() const { return mDrawingState; }
+ inline const State& getCurrentState() const { return mCurrentState; }
+ inline State& getCurrentState() { return mCurrentState; }
LayerDebugInfo getLayerDebugInfo() const;
@@ -495,29 +468,29 @@
void logFrameStats();
void getFrameStats(FrameStats* outStats) const;
- std::vector<OccupancyTracker::Segment> getOccupancyHistory(bool forceFlush);
+ virtual std::vector<OccupancyTracker::Segment> getOccupancyHistory(bool forceFlush) = 0;
void onDisconnect();
void addAndGetFrameTimestamps(const NewFrameEventsEntry* newEntry,
- FrameEventHistoryDelta* outDelta);
+ FrameEventHistoryDelta* outDelta);
- bool getTransformToDisplayInverse() const;
+ virtual bool getTransformToDisplayInverse() const = 0;
Transform getTransform() const;
// Returns the Alpha of the Surface, accounting for the Alpha
// of parent Surfaces in the hierarchy (alpha's will be multiplied
// down the hierarchy).
-#ifdef USE_HWC2
- float getAlpha() const;
-#else
- uint8_t getAlpha() const;
-#endif
+ half getAlpha() const;
+ half4 getColor() const;
void traverseInReverseZOrder(LayerVector::StateSet stateSet,
const LayerVector::Visitor& visitor);
void traverseInZOrder(LayerVector::StateSet stateSet, const LayerVector::Visitor& visitor);
+ void traverseChildrenInZOrder(LayerVector::StateSet stateSet,
+ const LayerVector::Visitor& visitor);
+
size_t getChildrenCount() const;
void addChild(const sp<Layer>& layer);
// Returns index if removed, or negative value otherwise
@@ -525,15 +498,14 @@
ssize_t removeChild(const sp<Layer>& layer);
sp<Layer> getParent() const { return mCurrentParent.promote(); }
bool hasParent() const { return getParent() != nullptr; }
-
Rect computeScreenBounds(bool reduceTransparentRegion = true) const;
bool setChildLayer(const sp<Layer>& childLayer, int32_t z);
// Copy the current list of children to the drawing state. Called by
// SurfaceFlinger to complete a transaction.
void commitChildList();
-
int32_t getZ() const;
+
protected:
// constant
sp<SurfaceFlinger> mFlinger;
@@ -544,56 +516,36 @@
class LayerCleaner {
sp<SurfaceFlinger> mFlinger;
wp<Layer> mLayer;
+
protected:
~LayerCleaner() {
// destroy client resources
mFlinger->onLayerDestroyed(mLayer);
}
- public:
- LayerCleaner(const sp<SurfaceFlinger>& flinger,
- const sp<Layer>& layer)
- : mFlinger(flinger), mLayer(layer) {
- }
- };
+ public:
+ LayerCleaner(const sp<SurfaceFlinger>& flinger, const sp<Layer>& layer)
+ : mFlinger(flinger), mLayer(layer) {}
+ };
virtual void onFirstRef();
-
-
-private:
friend class SurfaceInterceptor;
- // Interface implementation for SurfaceFlingerConsumer::ContentsChangedListener
- virtual void onFrameAvailable(const BufferItem& item) override;
- virtual void onFrameReplaced(const BufferItem& item) override;
- virtual void onSidebandStreamChanged() override;
void commitTransaction(const State& stateToCommit);
- // needsLinearFiltering - true if this surface's state requires filtering
- bool needsFiltering(const sp<const DisplayDevice>& hw) const;
-
uint32_t getEffectiveUsage(uint32_t usage) const;
FloatRect computeCrop(const sp<const DisplayDevice>& hw) const;
- // Compute the initial crop as specified by parent layers and the SurfaceControl
- // for this layer. Does not include buffer crop from the IGraphicBufferProducer
- // client, as that should not affect child clipping. Returns in screen space.
+ // Compute the initial crop as specified by parent layers and the
+ // SurfaceControl for this layer. Does not include buffer crop from the
+ // IGraphicBufferProducer client, as that should not affect child clipping.
+ // Returns in screen space.
Rect computeInitialCrop(const sp<const DisplayDevice>& hw) const;
- bool isCropped() const;
- static bool getOpacityForFormat(uint32_t format);
// drawing
- void clearWithOpenGL(const sp<const DisplayDevice>& hw,
- float r, float g, float b, float alpha) const;
- void drawWithOpenGL(const sp<const DisplayDevice>& hw,
- bool useIdentityTransform) const;
-
- // Temporary - Used only for LEGACY camera mode.
- uint32_t getProducerStickyTransform() const;
-
- // Loads the corresponding system property once per process
- static bool latchUnsignaledBuffers();
+ void clearWithOpenGL(const RenderArea& renderArea, float r, float g, float b,
+ float alpha) const;
void setParent(const sp<Layer>& layer);
@@ -601,33 +553,20 @@
void addZOrderRelative(const wp<Layer>& relative);
void removeZOrderRelative(const wp<Layer>& relative);
- // -----------------------------------------------------------------------
-
- class SyncPoint
- {
+ class SyncPoint {
public:
- explicit SyncPoint(uint64_t frameNumber) : mFrameNumber(frameNumber),
- mFrameIsAvailable(false), mTransactionIsApplied(false) {}
+ explicit SyncPoint(uint64_t frameNumber)
+ : mFrameNumber(frameNumber), mFrameIsAvailable(false), mTransactionIsApplied(false) {}
- uint64_t getFrameNumber() const {
- return mFrameNumber;
- }
+ uint64_t getFrameNumber() const { return mFrameNumber; }
- bool frameIsAvailable() const {
- return mFrameIsAvailable;
- }
+ bool frameIsAvailable() const { return mFrameIsAvailable; }
- void setFrameAvailable() {
- mFrameIsAvailable = true;
- }
+ void setFrameAvailable() { mFrameIsAvailable = true; }
- bool transactionIsApplied() const {
- return mTransactionIsApplied;
- }
+ bool transactionIsApplied() const { return mTransactionIsApplied; }
- void setTransactionApplied() {
- mTransactionIsApplied = true;
- }
+ void setTransactionApplied() { mTransactionIsApplied = true; }
private:
const uint64_t mFrameNumber;
@@ -645,9 +584,6 @@
// is applied
std::list<std::shared_ptr<SyncPoint>> mRemoteSyncPoints;
- uint64_t getHeadFrameNumber() const;
- bool headFenceHasSignaled() const;
-
// Returns false if the relevant frame has already been latched
bool addSyncPoint(const std::shared_ptr<SyncPoint>& point);
@@ -660,7 +596,8 @@
// Returns mCurrentScaling mode (originating from the
// Client) or mOverrideScalingMode mode (originating from
// the Surface Controller) if set.
- uint32_t getEffectiveScalingMode() const;
+ virtual uint32_t getEffectiveScalingMode() const = 0;
+
public:
/*
* The layer handle is just a BBinder object passed to the client
@@ -671,37 +608,25 @@
* this layer when the handle is destroyed.
*/
class Handle : public BBinder, public LayerCleaner {
- public:
- Handle(const sp<SurfaceFlinger>& flinger, const sp<Layer>& layer)
- : LayerCleaner(flinger, layer), owner(layer) {}
+ public:
+ Handle(const sp<SurfaceFlinger>& flinger, const sp<Layer>& layer)
+ : LayerCleaner(flinger, layer), owner(layer) {}
- wp<Layer> owner;
+ wp<Layer> owner;
};
sp<IBinder> getHandle();
- sp<IGraphicBufferProducer> getProducer() const;
const String8& getName() const;
- void notifyAvailableFrames();
+ virtual void notifyAvailableFrames() = 0;
+ virtual PixelFormat getPixelFormat() const = 0;
+ bool getPremultipledAlpha() const;
- PixelFormat getPixelFormat() const { return mFormat; }
-
-private:
-
+protected:
// -----------------------------------------------------------------------
- // Check all of the local sync points to ensure that all transactions
- // which need to have been applied prior to the frame which is about to
- // be latched have signaled
- bool allTransactionsSignaled();
-
- // constants
- sp<SurfaceFlingerConsumer> mSurfaceFlingerConsumer;
- sp<IGraphicBufferProducer> mProducer;
- uint32_t mTextureName; // from GLES
bool mPremultipliedAlpha;
String8 mName;
String8 mTransactionName; // A cached version of "TX - " + mName for systraces
- PixelFormat mFormat;
bool mPrimaryDisplayOnly = false;
@@ -734,14 +659,10 @@
sp<NativeHandle> mSidebandStream;
Rect mCurrentCrop;
uint32_t mCurrentTransform;
- uint32_t mCurrentScalingMode;
// We encode unset as -1.
int32_t mOverrideScalingMode;
bool mCurrentOpacity;
- bool mBufferLatched = false; // TODO: Use mActiveBuffer?
std::atomic<uint64_t> mCurrentFrameNumber;
- uint64_t mPreviousFrameNumber; // Only accessed on the main thread.
- bool mRefreshPending;
bool mFrameLatencyNeeded;
// Whether filtering is forced on or not
bool mFiltering;
@@ -749,18 +670,18 @@
bool mNeedsFiltering;
// The mesh used to draw the layer in GLES composition mode
mutable Mesh mMesh;
- // The texture used to draw the layer in GLES composition mode
- mutable Texture mTexture;
+
+ bool mPendingRemoval = false;
#ifdef USE_HWC2
// HWC items, accessed from the main thread
struct HWCInfo {
HWCInfo()
- : hwc(nullptr),
- layer(nullptr),
- forceClientComposition(false),
- compositionType(HWC2::Composition::Invalid),
- clearClientTarget(false) {}
+ : hwc(nullptr),
+ layer(nullptr),
+ forceClientComposition(false),
+ compositionType(HWC2::Composition::Invalid),
+ clearClientTarget(false) {}
HWComposer* hwc;
HWC2::Layer* layer;
@@ -786,8 +707,7 @@
// protected by mLock
mutable Mutex mLock;
- // Set to true once we've returned this surface's handle
- mutable bool mHasSurface;
+
const wp<Client> mClientRef;
// This layer can be a cursor on some displays.
@@ -798,8 +718,6 @@
Condition mQueueItemCondition;
Vector<BufferItem> mQueueItems;
std::atomic<uint64_t> mLastFrameNumberReceived;
- bool mUpdateTexImageFailed; // This is only accessed on the main thread.
-
bool mAutoRefresh;
bool mFreezeGeometryUpdates;
diff --git a/services/surfaceflinger/LayerDim.cpp b/services/surfaceflinger/LayerDim.cpp
deleted file mode 100644
index daebf8a..0000000
--- a/services/surfaceflinger/LayerDim.cpp
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-// #define LOG_NDEBUG 0
-#undef LOG_TAG
-#define LOG_TAG "LayerDim"
-
-#include <stdlib.h>
-#include <stdint.h>
-#include <sys/types.h>
-
-#include <utils/Errors.h>
-#include <utils/Log.h>
-
-#include <ui/GraphicBuffer.h>
-
-#include "LayerDim.h"
-#include "SurfaceFlinger.h"
-#include "DisplayDevice.h"
-#include "RenderEngine/RenderEngine.h"
-
-namespace android {
-// ---------------------------------------------------------------------------
-
-LayerDim::LayerDim(SurfaceFlinger* flinger, const sp<Client>& client,
- const String8& name, uint32_t w, uint32_t h, uint32_t flags)
- : Layer(flinger, client, name, w, h, flags) {
-}
-
-LayerDim::~LayerDim() {
-}
-
-void LayerDim::onDraw(const sp<const DisplayDevice>& hw,
- const Region& /* clip */, bool useIdentityTransform) const
-{
- const State& s(getDrawingState());
- if (s.alpha>0) {
- Mesh mesh(Mesh::TRIANGLE_FAN, 4, 2);
- computeGeometry(hw, mesh, useIdentityTransform);
- RenderEngine& engine(mFlinger->getRenderEngine());
- engine.setupDimLayerBlending(s.alpha);
- engine.drawMesh(mesh);
- engine.disableBlending();
- }
-}
-
-bool LayerDim::isVisible() const {
- const Layer::State& s(getDrawingState());
- return !isHiddenByPolicy() && s.alpha;
-}
-
-
-// ---------------------------------------------------------------------------
-
-}; // namespace android
diff --git a/services/surfaceflinger/LayerDim.h b/services/surfaceflinger/LayerDim.h
deleted file mode 100644
index a0cfca9..0000000
--- a/services/surfaceflinger/LayerDim.h
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright (C) 2007 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_LAYER_DIM_H
-#define ANDROID_LAYER_DIM_H
-
-#include <stdint.h>
-#include <sys/types.h>
-
-#include "Layer.h"
-
-// ---------------------------------------------------------------------------
-
-namespace android {
-
-class LayerDim : public Layer
-{
-public:
- LayerDim(SurfaceFlinger* flinger, const sp<Client>& client,
- const String8& name, uint32_t w, uint32_t h, uint32_t flags);
- virtual ~LayerDim();
-
- virtual const char* getTypeId() const { return "LayerDim"; }
- virtual void onDraw(const sp<const DisplayDevice>& hw, const Region& clip,
- bool useIdentityTransform) const;
- virtual bool isOpaque(const Layer::State&) const { return false; }
- virtual bool isSecure() const { return false; }
- virtual bool isFixedSize() const { return true; }
- virtual bool isVisible() const;
-};
-
-// ---------------------------------------------------------------------------
-
-}; // namespace android
-
-#endif // ANDROID_LAYER_DIM_H
diff --git a/services/surfaceflinger/LayerProtoHelper.cpp b/services/surfaceflinger/LayerProtoHelper.cpp
new file mode 100644
index 0000000..6a33148
--- /dev/null
+++ b/services/surfaceflinger/LayerProtoHelper.cpp
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "LayerProtoHelper.h"
+
+namespace android {
+namespace surfaceflinger {
+void LayerProtoHelper::writeToProto(const Region& region, RegionProto* regionProto) {
+ Region::const_iterator head = region.begin();
+ Region::const_iterator const tail = region.end();
+ uint64_t address = reinterpret_cast<uint64_t>(®ion);
+ regionProto->set_id(address);
+ while (head != tail) {
+ RectProto* rectProto = regionProto->add_rect();
+ writeToProto(*head, rectProto);
+ head++;
+ }
+}
+
+void LayerProtoHelper::writeToProto(const Rect& rect, RectProto* rectProto) {
+ rectProto->set_left(rect.left);
+ rectProto->set_top(rect.top);
+ rectProto->set_bottom(rect.bottom);
+ rectProto->set_right(rect.right);
+}
+
+void LayerProtoHelper::writeToProto(const half4 color, ColorProto* colorProto) {
+ colorProto->set_r(color.r);
+ colorProto->set_g(color.g);
+ colorProto->set_b(color.b);
+ colorProto->set_a(color.a);
+}
+
+void LayerProtoHelper::writeToProto(const Transform& transform, TransformProto* transformProto) {
+ transformProto->set_dsdx(transform[0][0]);
+ transformProto->set_dtdx(transform[0][1]);
+ transformProto->set_dsdy(transform[1][0]);
+ transformProto->set_dtdy(transform[1][1]);
+}
+
+void LayerProtoHelper::writeToProto(const sp<GraphicBuffer>& buffer,
+ ActiveBufferProto* activeBufferProto) {
+ activeBufferProto->set_width(buffer->getWidth());
+ activeBufferProto->set_height(buffer->getHeight());
+ activeBufferProto->set_stride(buffer->getStride());
+ activeBufferProto->set_format(buffer->format);
+}
+
+} // namespace surfaceflinger
+} // namespace android
diff --git a/services/surfaceflinger/LayerProtoHelper.h b/services/surfaceflinger/LayerProtoHelper.h
new file mode 100644
index 0000000..45a0b5d
--- /dev/null
+++ b/services/surfaceflinger/LayerProtoHelper.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <layerproto/LayerProtoHeader.h>
+
+#include <ui/GraphicBuffer.h>
+#include <ui/Rect.h>
+#include <ui/Region.h>
+
+#include <Transform.h>
+
+#include <math/vec4.h>
+
+namespace android {
+namespace surfaceflinger {
+class LayerProtoHelper {
+public:
+ static void writeToProto(const Rect& rect, RectProto* rectProto);
+ static void writeToProto(const Region& region, RegionProto* regionProto);
+ static void writeToProto(const half4 color, ColorProto* colorProto);
+ static void writeToProto(const Transform& transform, TransformProto* transformProto);
+ static void writeToProto(const sp<GraphicBuffer>& buffer, ActiveBufferProto* activeBufferProto);
+};
+
+} // namespace surfaceflinger
+} // namespace android
\ No newline at end of file
diff --git a/services/surfaceflinger/LayerVector.cpp b/services/surfaceflinger/LayerVector.cpp
index 2233e78..d0f8fbe 100644
--- a/services/surfaceflinger/LayerVector.cpp
+++ b/services/surfaceflinger/LayerVector.cpp
@@ -35,14 +35,17 @@
uint32_t ls = l->getCurrentState().layerStack;
uint32_t rs = r->getCurrentState().layerStack;
if (ls != rs)
- return ls - rs;
+ return (ls > rs) ? 1 : -1;
uint32_t lz = l->getCurrentState().z;
uint32_t rz = r->getCurrentState().z;
if (lz != rz)
- return lz - rz;
+ return (lz > rz) ? 1 : -1;
- return l->sequence - r->sequence;
+ if (l->sequence == r->sequence)
+ return 0;
+
+ return (l->sequence > r->sequence) ? 1 : -1;
}
void LayerVector::traverseInZOrder(StateSet stateSet, const Visitor& visitor) const {
diff --git a/services/surfaceflinger/RenderArea.cpp b/services/surfaceflinger/RenderArea.cpp
new file mode 100644
index 0000000..6225df1
--- /dev/null
+++ b/services/surfaceflinger/RenderArea.cpp
@@ -0,0 +1,34 @@
+#include "RenderArea.h"
+
+namespace android {
+
+/*
+ * Checks that the requested width and height are valid and updates them to the render area
+ * dimensions if they are set to 0
+ */
+status_t RenderArea::updateDimensions() {
+ // get screen geometry
+
+ uint32_t width = getWidth();
+ uint32_t height = getHeight();
+
+ if (mRotationFlags & Transform::ROT_90) {
+ std::swap(width, height);
+ }
+
+ if ((mReqWidth > width) || (mReqHeight > height)) {
+ ALOGE("size mismatch (%d, %d) > (%d, %d)", mReqWidth, mReqHeight, width, height);
+ return BAD_VALUE;
+ }
+
+ if (mReqWidth == 0) {
+ mReqWidth = width;
+ }
+ if (mReqHeight == 0) {
+ mReqHeight = height;
+ }
+
+ return NO_ERROR;
+}
+
+} // namespace android
\ No newline at end of file
diff --git a/services/surfaceflinger/RenderArea.h b/services/surfaceflinger/RenderArea.h
new file mode 100644
index 0000000..faf1ec6
--- /dev/null
+++ b/services/surfaceflinger/RenderArea.h
@@ -0,0 +1,40 @@
+#pragma once
+
+#include "Transform.h"
+
+namespace android {
+
+class RenderArea {
+public:
+ RenderArea(uint32_t reqHeight, uint32_t reqWidth, ISurfaceComposer::Rotation rotation)
+ : mReqHeight(reqHeight), mReqWidth(reqWidth) {
+ mRotationFlags = Transform::fromRotation(rotation);
+ }
+
+ virtual ~RenderArea() = default;
+
+ virtual const Transform& getTransform() const = 0;
+ virtual Rect getBounds() const = 0;
+ virtual int getHeight() const = 0;
+ virtual int getWidth() const = 0;
+ virtual bool isSecure() const = 0;
+ virtual bool needsFiltering() const = 0;
+ virtual Rect getSourceCrop() const = 0;
+
+ int getReqHeight() const { return mReqHeight; };
+ int getReqWidth() const { return mReqWidth; };
+ Transform::orientation_flags getRotationFlags() const { return mRotationFlags; };
+#ifdef USE_HWC2
+ virtual bool getWideColorSupport() const = 0;
+ virtual android_color_mode_t getActiveColorMode() const = 0;
+#endif
+
+ status_t updateDimensions();
+
+private:
+ uint32_t mReqHeight;
+ uint32_t mReqWidth;
+ Transform::orientation_flags mRotationFlags;
+};
+
+} // namespace android
\ No newline at end of file
diff --git a/services/surfaceflinger/RenderEngine/Description.cpp b/services/surfaceflinger/RenderEngine/Description.cpp
index effd319..706960c 100644
--- a/services/surfaceflinger/RenderEngine/Description.cpp
+++ b/services/surfaceflinger/RenderEngine/Description.cpp
@@ -27,22 +27,15 @@
namespace android {
Description::Description() {
- mPlaneAlpha = 1.0f;
mPremultipliedAlpha = false;
mOpaque = true;
mTextureEnabled = false;
mColorMatrixEnabled = false;
-
- memset(mColor, 0, sizeof(mColor));
}
Description::~Description() {
}
-void Description::setPlaneAlpha(GLclampf planeAlpha) {
- mPlaneAlpha = planeAlpha;
-}
-
void Description::setPremultipliedAlpha(bool premultipliedAlpha) {
mPremultipliedAlpha = premultipliedAlpha;
}
@@ -60,11 +53,8 @@
mTextureEnabled = false;
}
-void Description::setColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha) {
- mColor[0] = red;
- mColor[1] = green;
- mColor[2] = blue;
- mColor[3] = alpha;
+void Description::setColor(const half4& color) {
+ mColor = color;
}
void Description::setProjectionMatrix(const mat4& mtx) {
diff --git a/services/surfaceflinger/RenderEngine/Description.h b/services/surfaceflinger/RenderEngine/Description.h
index 3beffdf..cbac855 100644
--- a/services/surfaceflinger/RenderEngine/Description.h
+++ b/services/surfaceflinger/RenderEngine/Description.h
@@ -35,8 +35,6 @@
friend class Program;
friend class ProgramCache;
- // value of the plane-alpha, between 0 and 1
- GLclampf mPlaneAlpha;
// whether textures are premultiplied
bool mPremultipliedAlpha;
// whether this layer is marked as opaque
@@ -46,8 +44,8 @@
Texture mTexture;
bool mTextureEnabled;
- // color used when texturing is disabled
- GLclampf mColor[4];
+ // color used when texturing is disabled or when setting alpha.
+ half4 mColor;
// projection matrix
mat4 mProjectionMatrix;
@@ -60,12 +58,11 @@
Description();
~Description();
- void setPlaneAlpha(GLclampf planeAlpha);
void setPremultipliedAlpha(bool premultipliedAlpha);
void setOpaque(bool opaque);
void setTexture(const Texture& texture);
void disableTexture();
- void setColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);
+ void setColor(const half4& color);
void setProjectionMatrix(const mat4& mtx);
void setColorMatrix(const mat4& mtx);
const mat4& getColorMatrix() const;
diff --git a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp
index 37a530b..daaa11e 100644
--- a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp
+++ b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp
@@ -204,25 +204,17 @@
mVpHeight = vph;
}
-#ifdef USE_HWC2
void GLES20RenderEngine::setupLayerBlending(bool premultipliedAlpha,
- bool opaque, float alpha) {
-#else
-void GLES20RenderEngine::setupLayerBlending(
- bool premultipliedAlpha, bool opaque, int alpha) {
-#endif
-
+ bool opaque, bool disableTexture, const half4& color) {
mState.setPremultipliedAlpha(premultipliedAlpha);
mState.setOpaque(opaque);
-#ifdef USE_HWC2
- mState.setPlaneAlpha(alpha);
+ mState.setColor(color);
- if (alpha < 1.0f || !opaque) {
-#else
- mState.setPlaneAlpha(alpha / 255.0f);
+ if (disableTexture) {
+ mState.disableTexture();
+ }
- if (alpha < 0xFF || !opaque) {
-#endif
+ if (color.a < 1.0f || !opaque) {
glEnable(GL_BLEND);
glBlendFunc(premultipliedAlpha ? GL_ONE : GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
} else {
@@ -231,33 +223,6 @@
}
#ifdef USE_HWC2
-void GLES20RenderEngine::setupDimLayerBlending(float alpha) {
-#else
-void GLES20RenderEngine::setupDimLayerBlending(int alpha) {
-#endif
- mState.setPlaneAlpha(1.0f);
- mState.setPremultipliedAlpha(true);
- mState.setOpaque(false);
-#ifdef USE_HWC2
- mState.setColor(0, 0, 0, alpha);
-#else
- mState.setColor(0, 0, 0, alpha/255.0f);
-#endif
- mState.disableTexture();
-
-#ifdef USE_HWC2
- if (alpha == 1.0f) {
-#else
- if (alpha == 0xFF) {
-#endif
- glDisable(GL_BLEND);
- } else {
- glEnable(GL_BLEND);
- glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
- }
-}
-
-#ifdef USE_HWC2
void GLES20RenderEngine::setColorMode(android_color_mode mode) {
ALOGV("setColorMode: %s (0x%x)", decodeColorMode(mode).c_str(), mode);
@@ -355,10 +320,9 @@
}
void GLES20RenderEngine::setupFillWithColor(float r, float g, float b, float a) {
- mState.setPlaneAlpha(1.0f);
mState.setPremultipliedAlpha(true);
mState.setOpaque(false);
- mState.setColor(r, g, b, a);
+ mState.setColor(half4(r, g, b, a));
mState.disableTexture();
glDisable(GL_BLEND);
}
diff --git a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.h b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.h
index eaf94af..5ac12fc 100644
--- a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.h
+++ b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.h
@@ -68,10 +68,9 @@
virtual void setViewportAndProjection(size_t vpw, size_t vph,
Rect sourceCrop, size_t hwh, bool yswap,
Transform::orientation_flags rotation);
-#ifdef USE_HWC2
virtual void setupLayerBlending(bool premultipliedAlpha, bool opaque,
- float alpha) override;
- virtual void setupDimLayerBlending(float alpha) override;
+ bool disableTexture, const half4& color) override;
+#ifdef USE_HWC2
// Color management related functions and state
void setColorMode(android_color_mode mode);
@@ -92,10 +91,6 @@
// Currently only supporting sRGB and DisplayP3 color spaces
mat4 mSrgbToDisplayP3;
-#else
- virtual void setupLayerBlending(bool premultipliedAlpha, bool opaque,
- int alpha);
- virtual void setupDimLayerBlending(int alpha);
#endif
bool mPlatformHasWideColor = false;
diff --git a/services/surfaceflinger/RenderEngine/Program.cpp b/services/surfaceflinger/RenderEngine/Program.cpp
index 48a8da5..bd2188b 100644
--- a/services/surfaceflinger/RenderEngine/Program.cpp
+++ b/services/surfaceflinger/RenderEngine/Program.cpp
@@ -22,6 +22,7 @@
#include "Program.h"
#include "ProgramCache.h"
#include "Description.h"
+#include <math/mat4.h>
namespace android {
@@ -63,7 +64,6 @@
mTextureMatrixLoc = glGetUniformLocation(programId, "texture");
mSamplerLoc = glGetUniformLocation(programId, "sampler");
mColorLoc = glGetUniformLocation(programId, "color");
- mAlphaPlaneLoc = glGetUniformLocation(programId, "alphaPlane");
// set-up the default values for our uniforms
glUseProgram(programId);
@@ -132,11 +132,9 @@
glUniform1i(mSamplerLoc, 0);
glUniformMatrix4fv(mTextureMatrixLoc, 1, GL_FALSE, desc.mTexture.getMatrix().asArray());
}
- if (mAlphaPlaneLoc >= 0) {
- glUniform1f(mAlphaPlaneLoc, desc.mPlaneAlpha);
- }
if (mColorLoc >= 0) {
- glUniform4fv(mColorLoc, 1, desc.mColor);
+ const float color[4] = {desc.mColor.r, desc.mColor.g, desc.mColor.b, desc.mColor.a};
+ glUniform4fv(mColorLoc, 1, color);
}
if (mColorMatrixLoc >= 0) {
glUniformMatrix4fv(mColorMatrixLoc, 1, GL_FALSE, desc.mColorMatrix.asArray());
diff --git a/services/surfaceflinger/RenderEngine/Program.h b/services/surfaceflinger/RenderEngine/Program.h
index 36bd120..a2ae2ee 100644
--- a/services/surfaceflinger/RenderEngine/Program.h
+++ b/services/surfaceflinger/RenderEngine/Program.h
@@ -79,9 +79,6 @@
/* location of the sampler uniform */
GLint mSamplerLoc;
- /* location of the alpha plane uniform */
- GLint mAlphaPlaneLoc;
-
/* location of the color uniform */
GLint mColorLoc;
};
diff --git a/services/surfaceflinger/RenderEngine/ProgramCache.cpp b/services/surfaceflinger/RenderEngine/ProgramCache.cpp
index 06b2252..b437545 100644
--- a/services/surfaceflinger/RenderEngine/ProgramCache.cpp
+++ b/services/surfaceflinger/RenderEngine/ProgramCache.cpp
@@ -89,7 +89,7 @@
void ProgramCache::primeCache() {
uint32_t shaderCount = 0;
uint32_t keyMask = Key::BLEND_MASK | Key::OPACITY_MASK |
- Key::PLANE_ALPHA_MASK | Key::TEXTURE_MASK;
+ Key::ALPHA_MASK | Key::TEXTURE_MASK;
// Prime the cache for all combinations of the above masks,
// leaving off the experimental color matrix mask options.
@@ -122,8 +122,8 @@
description.mTexture.getTextureTarget() == GL_TEXTURE_EXTERNAL_OES ? Key::TEXTURE_EXT :
description.mTexture.getTextureTarget() == GL_TEXTURE_2D ? Key::TEXTURE_2D :
Key::TEXTURE_OFF)
- .set(Key::PLANE_ALPHA_MASK,
- (description.mPlaneAlpha < 1) ? Key::PLANE_ALPHA_LT_ONE : Key::PLANE_ALPHA_EQ_ONE)
+ .set(Key::ALPHA_MASK,
+ (description.mColor.a < 1) ? Key::ALPHA_LT_ONE : Key::ALPHA_EQ_ONE)
.set(Key::BLEND_MASK,
description.mPremultipliedAlpha ? Key::BLEND_PREMULT : Key::BLEND_NORMAL)
.set(Key::OPACITY_MASK,
@@ -168,12 +168,12 @@
} else if (needs.getTextureTarget() == Key::TEXTURE_2D) {
fs << "uniform sampler2D sampler;"
<< "varying vec2 outTexCoords;";
- } else if (needs.getTextureTarget() == Key::TEXTURE_OFF) {
+ }
+
+ if (needs.getTextureTarget() == Key::TEXTURE_OFF || needs.hasAlpha()) {
fs << "uniform vec4 color;";
}
- if (needs.hasPlaneAlpha()) {
- fs << "uniform float alphaPlane;";
- }
+
if (needs.hasColorMatrix()) {
fs << "uniform mat4 colorMatrix;";
}
@@ -225,18 +225,19 @@
if (needs.isTexturing()) {
fs << "gl_FragColor = texture2D(sampler, outTexCoords);";
} else {
- fs << "gl_FragColor = color;";
+ fs << "gl_FragColor.rgb = color.rgb;";
+ fs << "gl_FragColor.a = 1.0;";
}
if (needs.isOpaque()) {
fs << "gl_FragColor.a = 1.0;";
}
- if (needs.hasPlaneAlpha()) {
- // modulate the alpha value with planeAlpha
+ if (needs.hasAlpha()) {
+ // modulate the current alpha value with alpha set
if (needs.isPremultiplied()) {
// ... and the color too if we're premultiplied
- fs << "gl_FragColor *= alphaPlane;";
+ fs << "gl_FragColor *= color.a;";
} else {
- fs << "gl_FragColor.a *= alphaPlane;";
+ fs << "gl_FragColor.a *= color.a;";
}
}
diff --git a/services/surfaceflinger/RenderEngine/ProgramCache.h b/services/surfaceflinger/RenderEngine/ProgramCache.h
index 5b0fbcd..ff5cf0f 100644
--- a/services/surfaceflinger/RenderEngine/ProgramCache.h
+++ b/services/surfaceflinger/RenderEngine/ProgramCache.h
@@ -57,9 +57,9 @@
OPACITY_TRANSLUCENT = 0x00000000,
OPACITY_MASK = 0x00000002,
- PLANE_ALPHA_LT_ONE = 0x00000004,
- PLANE_ALPHA_EQ_ONE = 0x00000000,
- PLANE_ALPHA_MASK = 0x00000004,
+ ALPHA_LT_ONE = 0x00000004,
+ ALPHA_EQ_ONE = 0x00000000,
+ ALPHA_MASK = 0x00000004,
TEXTURE_OFF = 0x00000000,
TEXTURE_EXT = 0x00000008,
@@ -95,8 +95,8 @@
inline bool isOpaque() const {
return (mKey & OPACITY_MASK) == OPACITY_OPAQUE;
}
- inline bool hasPlaneAlpha() const {
- return (mKey & PLANE_ALPHA_MASK) == PLANE_ALPHA_LT_ONE;
+ inline bool hasAlpha() const {
+ return (mKey & ALPHA_MASK) == ALPHA_LT_ONE;
}
inline bool hasColorMatrix() const {
return (mKey & COLOR_MATRIX_MASK) == COLOR_MATRIX_ON;
diff --git a/services/surfaceflinger/RenderEngine/RenderEngine.h b/services/surfaceflinger/RenderEngine/RenderEngine.h
index 9544579..fa65979 100644
--- a/services/surfaceflinger/RenderEngine/RenderEngine.h
+++ b/services/surfaceflinger/RenderEngine/RenderEngine.h
@@ -25,6 +25,7 @@
#include <EGL/eglext.h>
#include <math/mat4.h>
#include <Transform.h>
+#include <gui/SurfaceControl.h>
#define EGL_NO_CONFIG ((EGLConfig)0)
@@ -98,16 +99,13 @@
virtual void checkErrors() const;
virtual void setViewportAndProjection(size_t vpw, size_t vph,
Rect sourceCrop, size_t hwh, bool yswap, Transform::orientation_flags rotation) = 0;
+ virtual void setupLayerBlending(bool premultipliedAlpha, bool opaque,
+ bool disableTexture, const half4& color) = 0;
#ifdef USE_HWC2
- virtual void setupLayerBlending(bool premultipliedAlpha, bool opaque, float alpha) = 0;
- virtual void setupDimLayerBlending(float alpha) = 0;
virtual void setColorMode(android_color_mode mode) = 0;
virtual void setSourceDataSpace(android_dataspace source) = 0;
virtual void setWideColor(bool hasWideColor) = 0;
virtual bool usesWideColor() = 0;
-#else
- virtual void setupLayerBlending(bool premultipliedAlpha, bool opaque, int alpha) = 0;
- virtual void setupDimLayerBlending(int alpha) = 0;
#endif
virtual void setupLayerTexturing(const Texture& texture) = 0;
virtual void setupLayerBlackedOut() = 0;
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 4157144..d13b188 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -72,8 +72,9 @@
#include "EventControlThread.h"
#include "EventThread.h"
#include "Layer.h"
+#include "BufferLayer.h"
#include "LayerVector.h"
-#include "LayerDim.h"
+#include "ColorLayer.h"
#include "MonitoredProducer.h"
#include "SurfaceFlinger.h"
@@ -90,6 +91,8 @@
#include <android/hardware/configstore/1.0/ISurfaceFlingerConfigs.h>
#include <configstore/Utils.h>
+#include <layerproto/LayerProtoParser.h>
+
#define DISPLAY_COUNT 1
/*
@@ -568,7 +571,7 @@
virtual void onInjectSyncEvent(nsecs_t when) {
std::lock_guard<std::mutex> lock(mCallbackMutex);
- if (mCallback != nullptr) {
+ if (mCallback) {
mCallback->onVSyncEvent(when);
}
}
@@ -1065,42 +1068,29 @@
return NO_ERROR;
}
-void SurfaceFlinger::enableVSyncInjectionsInternal(bool enable) {
- Mutex::Autolock _l(mStateLock);
-
- if (mInjectVSyncs == enable) {
- return;
- }
-
- if (enable) {
- ALOGV("VSync Injections enabled");
- if (mVSyncInjector.get() == nullptr) {
- mVSyncInjector = new InjectVSyncSource();
- mInjectorEventThread = new EventThread(mVSyncInjector, *this, false);
- }
- mEventQueue.setEventThread(mInjectorEventThread);
- } else {
- ALOGV("VSync Injections disabled");
- mEventQueue.setEventThread(mSFEventThread);
- }
-
- mInjectVSyncs = enable;
-}
-
status_t SurfaceFlinger::enableVSyncInjections(bool enable) {
- class MessageEnableVSyncInjections : public MessageBase {
- SurfaceFlinger* mFlinger;
- bool mEnable;
- public:
- MessageEnableVSyncInjections(SurfaceFlinger* flinger, bool enable)
- : mFlinger(flinger), mEnable(enable) { }
- virtual bool handler() {
- mFlinger->enableVSyncInjectionsInternal(mEnable);
- return true;
+ sp<LambdaMessage> enableVSyncInjections = new LambdaMessage([&]() {
+ Mutex::Autolock _l(mStateLock);
+
+ if (mInjectVSyncs == enable) {
+ return;
}
- };
- sp<MessageBase> msg = new MessageEnableVSyncInjections(this, enable);
- postMessageSync(msg);
+
+ if (enable) {
+ ALOGV("VSync Injections enabled");
+ if (mVSyncInjector.get() == nullptr) {
+ mVSyncInjector = new InjectVSyncSource();
+ mInjectorEventThread = new EventThread(mVSyncInjector, *this, false);
+ }
+ mEventQueue.setEventThread(mInjectorEventThread);
+ } else {
+ ALOGV("VSync Injections disabled");
+ mEventQueue.setEventThread(mSFEventThread);
+ }
+
+ mInjectVSyncs = enable;
+ });
+ postMessageSync(enableVSyncInjections);
return NO_ERROR;
}
@@ -1531,6 +1521,7 @@
rebuildLayerStacks();
setUpHWComposer();
doDebugFlashRegions();
+ doTracing("handleRefresh");
doComposition();
postComposition(refreshStartTime);
@@ -1590,6 +1581,14 @@
}
}
+void SurfaceFlinger::doTracing(const char* where) {
+ ATRACE_CALL();
+ ATRACE_NAME(where);
+ if (CC_UNLIKELY(mTracing.isEnabled())) {
+ mTracing.traceLayers(where, dumpProtoInfo());
+ }
+}
+
void SurfaceFlinger::preComposition(nsecs_t refreshStartTime)
{
ATRACE_CALL();
@@ -1774,7 +1773,7 @@
// rebuild the visible layer list per screen
if (CC_UNLIKELY(mVisibleRegionsDirty)) {
- ATRACE_CALL();
+ ATRACE_NAME("rebuildLayerStacks VR Dirty");
mVisibleRegionsDirty = false;
invalidateHwcGeometry();
@@ -2476,7 +2475,7 @@
// compute the opaque region
const int32_t layerOrientation = tr.getOrientation();
- if (s.alpha == 1.0f && !translucent &&
+ if (layer->getAlpha() == 1.0f && !translucent &&
((layerOrientation & Transform::ROT_INVALID) == false)) {
// the opaque region is the layer's footprint
opaqueRegion = visibleRegion;
@@ -2661,6 +2660,7 @@
{
ALOGV("doComposeSurfaces");
+ const DisplayRenderArea renderArea(displayDevice);
const auto hwcId = displayDevice->getHwcDisplayId();
mat4 oldColorMatrix;
@@ -2766,16 +2766,16 @@
case HWC2::Composition::SolidColor: {
const Layer::State& state(layer->getDrawingState());
if (layer->getClearClientTarget(hwcId) && !firstLayer &&
- layer->isOpaque(state) && (state.alpha == 1.0f)
+ layer->isOpaque(state) && (state.color.a == 1.0f)
&& hasClientComposition) {
// never clear the very first layer since we're
// guaranteed the FB is already cleared
- layer->clearWithOpenGL(displayDevice);
+ layer->clearWithOpenGL(renderArea);
}
break;
}
case HWC2::Composition::Client: {
- layer->draw(displayDevice, clip);
+ layer->draw(renderArea, clip);
break;
}
default:
@@ -2792,7 +2792,7 @@
const Region clip(dirty.intersect(
displayTransform.transform(layer->visibleRegion)));
if (!clip.isEmpty()) {
- layer->draw(displayDevice, clip);
+ layer->draw(renderArea, clip);
}
}
}
@@ -2829,7 +2829,14 @@
if (parent == nullptr) {
mCurrentState.layersSortedByZ.add(lbc);
} else {
- if (mCurrentState.layersSortedByZ.indexOf(parent) < 0) {
+ bool found = false;
+ mCurrentState.traverseInZOrder([&](Layer* layer) {
+ if (layer == parent.get()) {
+ found = true;
+ }
+ });
+
+ if (!found) {
ALOGE("addClientLayer called with a removed parent");
return NAME_NOT_FOUND;
}
@@ -2850,6 +2857,10 @@
status_t SurfaceFlinger::removeLayer(const sp<Layer>& layer, bool topLevelOnly) {
Mutex::Autolock _l(mStateLock);
+ if (layer->isPendingRemoval()) {
+ return NO_ERROR;
+ }
+
const auto& p = layer->getParent();
ssize_t index;
if (p != nullptr) {
@@ -3053,122 +3064,139 @@
const sp<Client>& client,
const layer_state_t& s)
{
- uint32_t flags = 0;
sp<Layer> layer(client->getLayerUser(s.surface));
- if (layer != 0) {
- const uint32_t what = s.what;
- bool geometryAppliesWithResize =
- what & layer_state_t::eGeometryAppliesWithResize;
- if (what & layer_state_t::ePositionChanged) {
- if (layer->setPosition(s.x, s.y, !geometryAppliesWithResize)) {
- flags |= eTraversalNeeded;
- }
+ if (layer == nullptr) {
+ return 0;
+ }
+
+ if (layer->isPendingRemoval()) {
+ ALOGW("Attempting to set client state on removed layer: %s", layer->getName().string());
+ return 0;
+ }
+
+ uint32_t flags = 0;
+
+ const uint32_t what = s.what;
+ bool geometryAppliesWithResize =
+ what & layer_state_t::eGeometryAppliesWithResize;
+ if (what & layer_state_t::ePositionChanged) {
+ if (layer->setPosition(s.x, s.y, !geometryAppliesWithResize)) {
+ flags |= eTraversalNeeded;
}
- if (what & layer_state_t::eLayerChanged) {
- // NOTE: index needs to be calculated before we update the state
- const auto& p = layer->getParent();
- if (p == nullptr) {
- ssize_t idx = mCurrentState.layersSortedByZ.indexOf(layer);
- if (layer->setLayer(s.z) && idx >= 0) {
- mCurrentState.layersSortedByZ.removeAt(idx);
- mCurrentState.layersSortedByZ.add(layer);
- // we need traversal (state changed)
- // AND transaction (list changed)
- flags |= eTransactionNeeded|eTraversalNeeded;
- }
- } else {
- if (p->setChildLayer(layer, s.z)) {
- flags |= eTransactionNeeded|eTraversalNeeded;
- }
- }
- }
- if (what & layer_state_t::eRelativeLayerChanged) {
+ }
+ if (what & layer_state_t::eLayerChanged) {
+ // NOTE: index needs to be calculated before we update the state
+ const auto& p = layer->getParent();
+ if (p == nullptr) {
ssize_t idx = mCurrentState.layersSortedByZ.indexOf(layer);
- if (layer->setRelativeLayer(s.relativeLayerHandle, s.z)) {
- mCurrentState.layersSortedByZ.removeAt(idx);
- mCurrentState.layersSortedByZ.add(layer);
- flags |= eTransactionNeeded|eTraversalNeeded;
- }
- }
- if (what & layer_state_t::eSizeChanged) {
- if (layer->setSize(s.w, s.h)) {
- flags |= eTraversalNeeded;
- }
- }
- if (what & layer_state_t::eAlphaChanged) {
- if (layer->setAlpha(s.alpha))
- flags |= eTraversalNeeded;
- }
- if (what & layer_state_t::eMatrixChanged) {
- if (layer->setMatrix(s.matrix))
- flags |= eTraversalNeeded;
- }
- if (what & layer_state_t::eTransparentRegionChanged) {
- if (layer->setTransparentRegionHint(s.transparentRegion))
- flags |= eTraversalNeeded;
- }
- if (what & layer_state_t::eFlagsChanged) {
- if (layer->setFlags(s.flags, s.mask))
- flags |= eTraversalNeeded;
- }
- if (what & layer_state_t::eCropChanged) {
- if (layer->setCrop(s.crop, !geometryAppliesWithResize))
- flags |= eTraversalNeeded;
- }
- if (what & layer_state_t::eFinalCropChanged) {
- if (layer->setFinalCrop(s.finalCrop, !geometryAppliesWithResize))
- flags |= eTraversalNeeded;
- }
- if (what & layer_state_t::eLayerStackChanged) {
- ssize_t idx = mCurrentState.layersSortedByZ.indexOf(layer);
- // We only allow setting layer stacks for top level layers,
- // everything else inherits layer stack from its parent.
- if (layer->hasParent()) {
- ALOGE("Attempt to set layer stack on layer with parent (%s) is invalid",
- layer->getName().string());
- } else if (idx < 0) {
- ALOGE("Attempt to set layer stack on layer without parent (%s) that "
- "that also does not appear in the top level layer list. Something"
- " has gone wrong.", layer->getName().string());
- } else if (layer->setLayerStack(s.layerStack)) {
+ if (layer->setLayer(s.z) && idx >= 0) {
mCurrentState.layersSortedByZ.removeAt(idx);
mCurrentState.layersSortedByZ.add(layer);
// we need traversal (state changed)
// AND transaction (list changed)
flags |= eTransactionNeeded|eTraversalNeeded;
}
- }
- if (what & layer_state_t::eDeferTransaction) {
- if (s.barrierHandle != nullptr) {
- layer->deferTransactionUntil(s.barrierHandle, s.frameNumber);
- } else if (s.barrierGbp != nullptr) {
- const sp<IGraphicBufferProducer>& gbp = s.barrierGbp;
- if (authenticateSurfaceTextureLocked(gbp)) {
- const auto& otherLayer =
- (static_cast<MonitoredProducer*>(gbp.get()))->getLayer();
- layer->deferTransactionUntil(otherLayer, s.frameNumber);
- } else {
- ALOGE("Attempt to defer transaction to to an"
- " unrecognized GraphicBufferProducer");
- }
- }
- // We don't trigger a traversal here because if no other state is
- // changed, we don't want this to cause any more work
- }
- if (what & layer_state_t::eReparentChildren) {
- if (layer->reparentChildren(s.reparentHandle)) {
+ } else {
+ if (p->setChildLayer(layer, s.z)) {
flags |= eTransactionNeeded|eTraversalNeeded;
}
}
- if (what & layer_state_t::eDetachChildren) {
- layer->detachChildren();
+ }
+ if (what & layer_state_t::eRelativeLayerChanged) {
+ ssize_t idx = mCurrentState.layersSortedByZ.indexOf(layer);
+ if (layer->setRelativeLayer(s.relativeLayerHandle, s.z)) {
+ mCurrentState.layersSortedByZ.removeAt(idx);
+ mCurrentState.layersSortedByZ.add(layer);
+ flags |= eTransactionNeeded|eTraversalNeeded;
}
- if (what & layer_state_t::eOverrideScalingModeChanged) {
- layer->setOverrideScalingMode(s.overrideScalingMode);
- // We don't trigger a traversal here because if no other state is
- // changed, we don't want this to cause any more work
+ }
+ if (what & layer_state_t::eSizeChanged) {
+ if (layer->setSize(s.w, s.h)) {
+ flags |= eTraversalNeeded;
}
}
+ if (what & layer_state_t::eAlphaChanged) {
+ if (layer->setAlpha(s.alpha))
+ flags |= eTraversalNeeded;
+ }
+ if (what & layer_state_t::eColorChanged) {
+ if (layer->setColor(s.color))
+ flags |= eTraversalNeeded;
+ }
+ if (what & layer_state_t::eMatrixChanged) {
+ if (layer->setMatrix(s.matrix))
+ flags |= eTraversalNeeded;
+ }
+ if (what & layer_state_t::eTransparentRegionChanged) {
+ if (layer->setTransparentRegionHint(s.transparentRegion))
+ flags |= eTraversalNeeded;
+ }
+ if (what & layer_state_t::eFlagsChanged) {
+ if (layer->setFlags(s.flags, s.mask))
+ flags |= eTraversalNeeded;
+ }
+ if (what & layer_state_t::eCropChanged) {
+ if (layer->setCrop(s.crop, !geometryAppliesWithResize))
+ flags |= eTraversalNeeded;
+ }
+ if (what & layer_state_t::eFinalCropChanged) {
+ if (layer->setFinalCrop(s.finalCrop, !geometryAppliesWithResize))
+ flags |= eTraversalNeeded;
+ }
+ if (what & layer_state_t::eLayerStackChanged) {
+ ssize_t idx = mCurrentState.layersSortedByZ.indexOf(layer);
+ // We only allow setting layer stacks for top level layers,
+ // everything else inherits layer stack from its parent.
+ if (layer->hasParent()) {
+ ALOGE("Attempt to set layer stack on layer with parent (%s) is invalid",
+ layer->getName().string());
+ } else if (idx < 0) {
+ ALOGE("Attempt to set layer stack on layer without parent (%s) that "
+ "that also does not appear in the top level layer list. Something"
+ " has gone wrong.", layer->getName().string());
+ } else if (layer->setLayerStack(s.layerStack)) {
+ mCurrentState.layersSortedByZ.removeAt(idx);
+ mCurrentState.layersSortedByZ.add(layer);
+ // we need traversal (state changed)
+ // AND transaction (list changed)
+ flags |= eTransactionNeeded|eTraversalNeeded;
+ }
+ }
+ if (what & layer_state_t::eDeferTransaction) {
+ if (s.barrierHandle != nullptr) {
+ layer->deferTransactionUntil(s.barrierHandle, s.frameNumber);
+ } else if (s.barrierGbp != nullptr) {
+ const sp<IGraphicBufferProducer>& gbp = s.barrierGbp;
+ if (authenticateSurfaceTextureLocked(gbp)) {
+ const auto& otherLayer =
+ (static_cast<MonitoredProducer*>(gbp.get()))->getLayer();
+ layer->deferTransactionUntil(otherLayer, s.frameNumber);
+ } else {
+ ALOGE("Attempt to defer transaction to to an"
+ " unrecognized GraphicBufferProducer");
+ }
+ }
+ // We don't trigger a traversal here because if no other state is
+ // changed, we don't want this to cause any more work
+ }
+ if (what & layer_state_t::eReparent) {
+ if (layer->reparent(s.parentHandleForChild)) {
+ flags |= eTransactionNeeded|eTraversalNeeded;
+ }
+ }
+ if (what & layer_state_t::eReparentChildren) {
+ if (layer->reparentChildren(s.reparentHandle)) {
+ flags |= eTransactionNeeded|eTraversalNeeded;
+ }
+ }
+ if (what & layer_state_t::eDetachChildren) {
+ layer->detachChildren();
+ }
+ if (what & layer_state_t::eOverrideScalingModeChanged) {
+ layer->setOverrideScalingMode(s.overrideScalingMode);
+ // We don't trigger a traversal here because if no other state is
+ // changed, we don't want this to cause any more work
+ }
return flags;
}
@@ -3193,14 +3221,15 @@
switch (flags & ISurfaceComposerClient::eFXSurfaceMask) {
case ISurfaceComposerClient::eFXSurfaceNormal:
- result = createNormalLayer(client,
+ result = createBufferLayer(client,
uniqueName, w, h, flags, format,
handle, gbp, &layer);
+
break;
- case ISurfaceComposerClient::eFXSurfaceDim:
- result = createDimLayer(client,
+ case ISurfaceComposerClient::eFXSurfaceColor:
+ result = createColorLayer(client,
uniqueName, w, h, flags,
- handle, gbp, &layer);
+ handle, &layer);
break;
default:
result = BAD_VALUE;
@@ -3254,7 +3283,7 @@
return uniqueName;
}
-status_t SurfaceFlinger::createNormalLayer(const sp<Client>& client,
+status_t SurfaceFlinger::createBufferLayer(const sp<Client>& client,
const String8& name, uint32_t w, uint32_t h, uint32_t flags, PixelFormat& format,
sp<IBinder>* handle, sp<IGraphicBufferProducer>* gbp, sp<Layer>* outLayer)
{
@@ -3269,24 +3298,24 @@
break;
}
- *outLayer = new Layer(this, client, name, w, h, flags);
- status_t err = (*outLayer)->setBuffers(w, h, format, flags);
+ sp<BufferLayer> layer = new BufferLayer(this, client, name, w, h, flags);
+ status_t err = layer->setBuffers(w, h, format, flags);
if (err == NO_ERROR) {
- *handle = (*outLayer)->getHandle();
- *gbp = (*outLayer)->getProducer();
+ *handle = layer->getHandle();
+ *gbp = layer->getProducer();
+ *outLayer = layer;
}
- ALOGE_IF(err, "createNormalLayer() failed (%s)", strerror(-err));
+ ALOGE_IF(err, "createBufferLayer() failed (%s)", strerror(-err));
return err;
}
-status_t SurfaceFlinger::createDimLayer(const sp<Client>& client,
+status_t SurfaceFlinger::createColorLayer(const sp<Client>& client,
const String8& name, uint32_t w, uint32_t h, uint32_t flags,
- sp<IBinder>* handle, sp<IGraphicBufferProducer>* gbp, sp<Layer>* outLayer)
+ sp<IBinder>* handle, sp<Layer>* outLayer)
{
- *outLayer = new LayerDim(this, client, name, w, h, flags);
+ *outLayer = new ColorLayer(this, client, name, w, h, flags);
*handle = (*outLayer)->getHandle();
- *gbp = (*outLayer)->getProducer();
return NO_ERROR;
}
@@ -3414,7 +3443,8 @@
ALOGW("Couldn't set SCHED_OTHER on display off");
}
- if (type == DisplayDevice::DISPLAY_PRIMARY) {
+ if (type == DisplayDevice::DISPLAY_PRIMARY &&
+ currentMode != HWC_POWER_MODE_DOZE_SUSPEND) {
disableHardwareVsync(true); // also cancels any in-progress resync
// FIXME: eventthread only knows about the main display right now
@@ -3428,7 +3458,8 @@
mode == HWC_POWER_MODE_NORMAL) {
// Update display while dozing
getHwComposer().setPowerMode(type, mode);
- if (type == DisplayDevice::DISPLAY_PRIMARY) {
+ if (type == DisplayDevice::DISPLAY_PRIMARY &&
+ currentMode == HWC_POWER_MODE_DOZE_SUSPEND) {
// FIXME: eventthread only knows about the main display right now
mEventThread->onScreenAcquired();
resyncToHardwareVsync(true);
@@ -3477,13 +3508,13 @@
// ---------------------------------------------------------------------------
-status_t SurfaceFlinger::dump(int fd, const Vector<String16>& args)
-{
+status_t SurfaceFlinger::doDump(int fd, const Vector<String16>& args, bool asProto) {
String8 result;
IPCThreadState* ipc = IPCThreadState::self();
const int pid = ipc->getCallingPid();
const int uid = ipc->getCallingUid();
+
if ((uid != AID_SHELL) &&
!PermissionCache::checkPermission(sDump, pid, uid)) {
result.appendFormat("Permission Denial: "
@@ -3503,6 +3534,13 @@
bool dumpAll = true;
size_t index = 0;
size_t numArgs = args.size();
+
+ if (asProto) {
+ LayersProto layersProto = dumpProtoInfo();
+ result.append(layersProto.SerializeAsString().c_str(), layersProto.ByteSize());
+ dumpAll = false;
+ }
+
if (numArgs) {
if ((index < numArgs) &&
(args[index] == String16("--list"))) {
@@ -3747,6 +3785,16 @@
result.append("\n");
}
+LayersProto SurfaceFlinger::dumpProtoInfo() const {
+ LayersProto layersProto;
+ mCurrentState.traverseInZOrder([&](Layer* layer) {
+ LayerProto* layerProto = layersProto.add_layers();
+ layer->writeToProto(layerProto, LayerVector::StateSet::Current);
+ });
+
+ return layersProto;
+}
+
void SurfaceFlinger::dumpAllLocked(const Vector<String16>& args, size_t& index,
String8& result) const
{
@@ -3811,9 +3859,10 @@
colorizer.bold(result);
result.appendFormat("Visible layers (count = %zu)\n", mNumLayers);
colorizer.reset(result);
- mCurrentState.traverseInZOrder([&](Layer* layer) {
- result.append(to_string(layer->getLayerDebugInfo()).c_str());
- });
+
+ LayersProto layersProto = dumpProtoInfo();
+ auto layerTree = LayerProtoParser::generateLayerTree(layersProto);
+ result.append(LayerProtoParser::layersToString(layerTree).c_str());
/*
* Dump Display state
@@ -4007,6 +4056,17 @@
}
break;
}
+ case CAPTURE_LAYERS: {
+ IPCThreadState* ipc = IPCThreadState::self();
+ const int pid = ipc->getCallingPid();
+ const int uid = ipc->getCallingUid();
+ if ((uid != AID_GRAPHICS) &&
+ !PermissionCache::checkPermission(sReadFramebuffer, pid, uid)) {
+ ALOGE("Permission Denial: can't read framebuffer pid=%d, uid=%d", pid, uid);
+ return PERMISSION_DENIED;
+ }
+ break;
+ }
}
return OK;
}
@@ -4190,6 +4250,20 @@
reply->writeBool(hasWideColorDisplay);
return NO_ERROR;
}
+ case 1025: { // tracing
+ n = data.readInt32();
+ if (n) {
+ ALOGV("LayerTracing enabled");
+ mTracing.enable();
+ doTracing("tracing.enable");
+ reply->writeInt32(NO_ERROR);
+ } else {
+ ALOGV("LayerTracing disabled");
+ status_t err = mTracing.disable();
+ reply->writeInt32(err);
+ }
+ return NO_ERROR;
+ }
}
}
return err;
@@ -4206,35 +4280,6 @@
repaintEverythingLocked();
}
-// Checks that the requested width and height are valid and updates them to the display dimensions
-// if they are set to 0
-static status_t updateDimensionsLocked(const sp<const DisplayDevice>& displayDevice,
- Transform::orientation_flags rotation,
- uint32_t* requestedWidth, uint32_t* requestedHeight) {
- // get screen geometry
- uint32_t displayWidth = displayDevice->getWidth();
- uint32_t displayHeight = displayDevice->getHeight();
-
- if (rotation & Transform::ROT_90) {
- std::swap(displayWidth, displayHeight);
- }
-
- if ((*requestedWidth > displayWidth) || (*requestedHeight > displayHeight)) {
- ALOGE("size mismatch (%d, %d) > (%d, %d)",
- *requestedWidth, *requestedHeight, displayWidth, displayHeight);
- return BAD_VALUE;
- }
-
- if (*requestedWidth == 0) {
- *requestedWidth = displayWidth;
- }
- if (*requestedHeight == 0) {
- *requestedHeight = displayHeight;
- }
-
- return NO_ERROR;
-}
-
// A simple RAII class to disconnect from an ANativeWindow* when it goes out of scope
class WindowDisconnector {
public:
@@ -4283,50 +4328,86 @@
}
status_t SurfaceFlinger::captureScreen(const sp<IBinder>& display,
- const sp<IGraphicBufferProducer>& producer,
- Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight,
- int32_t minLayerZ, int32_t maxLayerZ,
- bool useIdentityTransform, ISurfaceComposer::Rotation rotation) {
+ const sp<IGraphicBufferProducer>& producer, Rect sourceCrop,
+ uint32_t reqWidth, uint32_t reqHeight, int32_t minLayerZ,
+ int32_t maxLayerZ, bool useIdentityTransform,
+ ISurfaceComposer::Rotation rotation) {
ATRACE_CALL();
- if (CC_UNLIKELY(display == 0))
- return BAD_VALUE;
+ if (CC_UNLIKELY(display == 0)) return BAD_VALUE;
+
+ const sp<const DisplayDevice> device(getDisplayDeviceLocked(display));
+ DisplayRenderArea renderArea(device, sourceCrop, reqHeight, reqWidth, rotation);
+
+ auto traverseLayers = std::bind(std::mem_fn(&SurfaceFlinger::traverseLayersInDisplay), this,
+ device, minLayerZ, maxLayerZ, std::placeholders::_1);
+ return captureScreenCommon(renderArea, traverseLayers, producer, useIdentityTransform);
+}
+
+status_t SurfaceFlinger::captureLayers(const sp<IBinder>& layerHandleBinder,
+ const sp<IGraphicBufferProducer>& producer,
+ ISurfaceComposer::Rotation rotation) {
+ ATRACE_CALL();
+
+ class LayerRenderArea : public RenderArea {
+ public:
+ LayerRenderArea(const sp<Layer>& layer, ISurfaceComposer::Rotation rotation)
+ : RenderArea(layer->getCurrentState().active.h, layer->getCurrentState().active.w,
+ rotation),
+ mLayer(layer) {}
+ const Transform& getTransform() const override {
+ // Make the top level transform the inverse the transform and it's parent so it sets
+ // the whole capture back to 0,0
+ return *new Transform(mLayer->getTransform().inverse());
+ }
+ Rect getBounds() const override {
+ const Layer::State& layerState(mLayer->getDrawingState());
+ return Rect(layerState.active.w, layerState.active.h);
+ }
+ int getHeight() const override { return mLayer->getDrawingState().active.h; }
+ int getWidth() const override { return mLayer->getDrawingState().active.w; }
+ bool isSecure() const override { return false; }
+ bool needsFiltering() const override { return false; }
+
+ Rect getSourceCrop() const override { return getBounds(); }
+ bool getWideColorSupport() const override { return false; }
+ android_color_mode_t getActiveColorMode() const override { return HAL_COLOR_MODE_NATIVE; }
+
+ private:
+ const sp<Layer>& mLayer;
+ };
+
+ auto layerHandle = reinterpret_cast<Layer::Handle*>(layerHandleBinder.get());
+ auto parent = layerHandle->owner.promote();
+
+ LayerRenderArea renderArea(parent, rotation);
+ auto traverseLayers = [parent](const LayerVector::Visitor& visitor) {
+ parent->traverseChildrenInZOrder(LayerVector::StateSet::Drawing, [&](Layer* layer) {
+ if (!layer->isVisible()) {
+ return;
+ }
+ visitor(layer);
+ });
+ };
+ return captureScreenCommon(renderArea, traverseLayers, producer, false);
+}
+
+status_t SurfaceFlinger::captureScreenCommon(RenderArea& renderArea,
+ TraverseLayersFunction traverseLayers,
+ const sp<IGraphicBufferProducer>& producer,
+ bool useIdentityTransform) {
+ ATRACE_CALL();
if (CC_UNLIKELY(producer == 0))
return BAD_VALUE;
+ renderArea.updateDimensions();
+
// if we have secure windows on this display, never allow the screen capture
// unless the producer interface is local (i.e.: we can take a screenshot for
// ourselves).
bool isLocalScreenshot = IInterface::asBinder(producer)->localBinder();
- // Convert to surfaceflinger's internal rotation type.
- Transform::orientation_flags rotationFlags;
- switch (rotation) {
- case ISurfaceComposer::eRotateNone:
- rotationFlags = Transform::ROT_0;
- break;
- case ISurfaceComposer::eRotate90:
- rotationFlags = Transform::ROT_90;
- break;
- case ISurfaceComposer::eRotate180:
- rotationFlags = Transform::ROT_180;
- break;
- case ISurfaceComposer::eRotate270:
- rotationFlags = Transform::ROT_270;
- break;
- default:
- rotationFlags = Transform::ROT_0;
- ALOGE("Invalid rotation passed to captureScreen(): %d\n", rotation);
- break;
- }
-
- { // Autolock scope
- Mutex::Autolock lock(mStateLock);
- sp<const DisplayDevice> displayDevice(getDisplayDeviceLocked(display));
- updateDimensionsLocked(displayDevice, rotationFlags, &reqWidth, &reqHeight);
- }
-
// create a surface (because we're a producer, and we need to
// dequeue/queue a buffer)
sp<Surface> surface = new Surface(producer, false);
@@ -4347,9 +4428,9 @@
WindowDisconnector disconnector(window, NATIVE_WINDOW_API_EGL);
ANativeWindowBuffer* buffer = nullptr;
- result = getWindowBuffer(window, reqWidth, reqHeight,
- hasWideColorDisplay && !mForceNativeColorMode,
- getRenderEngine().usesWideColor(), &buffer);
+ result = getWindowBuffer(window, renderArea.getReqWidth(), renderArea.getReqHeight(),
+ hasWideColorDisplay && !mForceNativeColorMode,
+ getRenderEngine().usesWideColor(), &buffer);
if (result != NO_ERROR) {
return result;
}
@@ -4377,10 +4458,8 @@
int fd = -1;
{
Mutex::Autolock _l(mStateLock);
- sp<const DisplayDevice> device(getDisplayDeviceLocked(display));
- result = captureScreenImplLocked(device, buffer, sourceCrop, reqWidth, reqHeight,
- minLayerZ, maxLayerZ, useIdentityTransform,
- rotationFlags, isLocalScreenshot, &fd);
+ result = captureScreenImplLocked(renderArea, traverseLayers, buffer,
+ useIdentityTransform, isLocalScreenshot, &fd);
}
{
@@ -4409,84 +4488,66 @@
// queueBuffer takes ownership of syncFd
result = window->queueBuffer(window, buffer, syncFd);
}
-
return result;
}
-
-void SurfaceFlinger::renderScreenImplLocked(
- const sp<const DisplayDevice>& hw,
- Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight,
- int32_t minLayerZ, int32_t maxLayerZ,
- bool yswap, bool useIdentityTransform, Transform::orientation_flags rotation)
-{
+void SurfaceFlinger::renderScreenImplLocked(const RenderArea& renderArea,
+ TraverseLayersFunction traverseLayers, bool yswap,
+ bool useIdentityTransform) {
ATRACE_CALL();
+
RenderEngine& engine(getRenderEngine());
// get screen geometry
- const int32_t hw_w = hw->getWidth();
- const int32_t hw_h = hw->getHeight();
- const bool filtering = static_cast<int32_t>(reqWidth) != hw_w ||
- static_cast<int32_t>(reqHeight) != hw_h;
+ const auto raWidth = renderArea.getWidth();
+ const auto raHeight = renderArea.getHeight();
+
+ const auto reqWidth = renderArea.getReqWidth();
+ const auto reqHeight = renderArea.getReqHeight();
+ Rect sourceCrop = renderArea.getSourceCrop();
+
+ const bool filtering = static_cast<int32_t>(reqWidth) != raWidth ||
+ static_cast<int32_t>(reqHeight) != raHeight;
// if a default or invalid sourceCrop is passed in, set reasonable values
- if (sourceCrop.width() == 0 || sourceCrop.height() == 0 ||
- !sourceCrop.isValid()) {
+ if (sourceCrop.width() == 0 || sourceCrop.height() == 0 || !sourceCrop.isValid()) {
sourceCrop.setLeftTop(Point(0, 0));
- sourceCrop.setRightBottom(Point(hw_w, hw_h));
+ sourceCrop.setRightBottom(Point(raWidth, raHeight));
}
// ensure that sourceCrop is inside screen
if (sourceCrop.left < 0) {
ALOGE("Invalid crop rect: l = %d (< 0)", sourceCrop.left);
}
- if (sourceCrop.right > hw_w) {
- ALOGE("Invalid crop rect: r = %d (> %d)", sourceCrop.right, hw_w);
+ if (sourceCrop.right > raWidth) {
+ ALOGE("Invalid crop rect: r = %d (> %d)", sourceCrop.right, raWidth);
}
if (sourceCrop.top < 0) {
ALOGE("Invalid crop rect: t = %d (< 0)", sourceCrop.top);
}
- if (sourceCrop.bottom > hw_h) {
- ALOGE("Invalid crop rect: b = %d (> %d)", sourceCrop.bottom, hw_h);
+ if (sourceCrop.bottom > raHeight) {
+ ALOGE("Invalid crop rect: b = %d (> %d)", sourceCrop.bottom, raHeight);
}
-#ifdef USE_HWC2
- engine.setWideColor(hw->getWideColorSupport() && !mForceNativeColorMode);
- engine.setColorMode(mForceNativeColorMode ? HAL_COLOR_MODE_NATIVE : hw->getActiveColorMode());
-#endif
+ engine.setWideColor(renderArea.getWideColorSupport() && !mForceNativeColorMode);
+ engine.setColorMode(mForceNativeColorMode ? HAL_COLOR_MODE_NATIVE : renderArea.getActiveColorMode());
// make sure to clear all GL error flags
engine.checkErrors();
// set-up our viewport
- engine.setViewportAndProjection(
- reqWidth, reqHeight, sourceCrop, hw_h, yswap, rotation);
+ engine.setViewportAndProjection(reqWidth, reqHeight, sourceCrop, raHeight, yswap,
+ renderArea.getRotationFlags());
engine.disableTexturing();
// redraw the screen entirely...
engine.clearWithColor(0, 0, 0, 1);
- // We loop through the first level of layers without traversing,
- // as we need to interpret min/max layer Z in the top level Z space.
- for (const auto& layer : mDrawingState.layersSortedByZ) {
- if (!layer->belongsToDisplay(hw->getLayerStack(), false)) {
- continue;
- }
- const Layer::State& state(layer->getDrawingState());
- if (state.z < minLayerZ || state.z > maxLayerZ) {
- continue;
- }
- layer->traverseInZOrder(LayerVector::StateSet::Drawing, [&](Layer* layer) {
- if (!layer->isVisible()) {
- return;
- }
- if (filtering) layer->setFiltering(true);
- layer->draw(hw, useIdentityTransform);
- if (filtering) layer->setFiltering(false);
- });
- }
-
- hw->setViewportAndProjection();
+ traverseLayers([&](Layer* layer) {
+ if (filtering) layer->setFiltering(true);
+ layer->draw(renderArea, useIdentityTransform);
+ if (filtering) layer->setFiltering(false);
+ });
}
// A simple RAII class that holds an EGLImage and destroys it either:
@@ -4509,27 +4570,18 @@
EGLImageKHR mImage;
};
-status_t SurfaceFlinger::captureScreenImplLocked(const sp<const DisplayDevice>& hw,
- ANativeWindowBuffer* buffer, Rect sourceCrop,
- uint32_t reqWidth, uint32_t reqHeight,
- int32_t minLayerZ, int32_t maxLayerZ,
- bool useIdentityTransform,
- Transform::orientation_flags rotation,
- bool isLocalScreenshot, int* outSyncFd) {
+status_t SurfaceFlinger::captureScreenImplLocked(const RenderArea& renderArea,
+ TraverseLayersFunction traverseLayers,
+ ANativeWindowBuffer* buffer,
+ bool useIdentityTransform, bool isLocalScreenshot,
+ int* outSyncFd) {
ATRACE_CALL();
bool secureLayerIsVisible = false;
- for (const auto& layer : mDrawingState.layersSortedByZ) {
- const Layer::State& state(layer->getDrawingState());
- if (!layer->belongsToDisplay(hw->getLayerStack(), false) ||
- (state.z < minLayerZ || state.z > maxLayerZ)) {
- continue;
- }
- layer->traverseInZOrder(LayerVector::StateSet::Drawing, [&](Layer *layer) {
- secureLayerIsVisible = secureLayerIsVisible || (layer->isVisible() &&
- layer->isSecure());
- });
- }
+
+ traverseLayers([&](Layer* layer) {
+ secureLayerIsVisible = secureLayerIsVisible || (layer->isVisible() && layer->isSecure());
+ });
if (!isLocalScreenshot && secureLayerIsVisible) {
ALOGW("FB is protected: PERMISSION_DENIED");
@@ -4560,9 +4612,7 @@
// via an FBO, which means we didn't have to create
// an EGLSurface and therefore we're not
// dependent on the context's EGLConfig.
- renderScreenImplLocked(
- hw, sourceCrop, reqWidth, reqHeight, minLayerZ, maxLayerZ, true,
- useIdentityTransform, rotation);
+ renderScreenImplLocked(renderArea, traverseLayers, true, useIdentityTransform);
// Attempt to create a sync khr object that can produce a sync point. If that
// isn't available, create a non-dupable sync object in the fallback path and
@@ -4603,46 +4653,40 @@
*outSyncFd = syncFd;
if (DEBUG_SCREENSHOTS) {
+ const auto reqWidth = renderArea.getReqWidth();
+ const auto reqHeight = renderArea.getReqHeight();
+
uint32_t* pixels = new uint32_t[reqWidth*reqHeight];
getRenderEngine().readPixels(0, 0, reqWidth, reqHeight, pixels);
- checkScreenshot(reqWidth, reqHeight, reqWidth, pixels,
- hw, minLayerZ, maxLayerZ);
+ checkScreenshot(reqWidth, reqHeight, reqWidth, pixels, traverseLayers);
delete [] pixels;
}
// destroy our image
imageHolder.destroy();
-
return NO_ERROR;
}
void SurfaceFlinger::checkScreenshot(size_t w, size_t s, size_t h, void const* vaddr,
- const sp<const DisplayDevice>& hw, int32_t minLayerZ, int32_t maxLayerZ) {
+ TraverseLayersFunction traverseLayers) {
if (DEBUG_SCREENSHOTS) {
- for (size_t y=0 ; y<h ; y++) {
- uint32_t const * p = (uint32_t const *)vaddr + y*s;
- for (size_t x=0 ; x<w ; x++) {
+ for (size_t y = 0; y < h; y++) {
+ uint32_t const* p = (uint32_t const*)vaddr + y * s;
+ for (size_t x = 0; x < w; x++) {
if (p[x] != 0xFF000000) return;
}
}
- ALOGE("*** we just took a black screenshot ***\n"
- "requested minz=%d, maxz=%d, layerStack=%d",
- minLayerZ, maxLayerZ, hw->getLayerStack());
+ ALOGE("*** we just took a black screenshot ***");
size_t i = 0;
- for (const auto& layer : mDrawingState.layersSortedByZ) {
+ traverseLayers([&](Layer* layer) {
const Layer::State& state(layer->getDrawingState());
- if (layer->belongsToDisplay(hw->getLayerStack(), false) && state.z >= minLayerZ &&
- state.z <= maxLayerZ) {
- layer->traverseInZOrder(LayerVector::StateSet::Drawing, [&](Layer* layer) {
- ALOGE("%c index=%zu, name=%s, layerStack=%d, z=%d, visible=%d, flags=%x, alpha=%.3f",
- layer->isVisible() ? '+' : '-',
- i, layer->getName().string(), layer->getLayerStack(), state.z,
- layer->isVisible(), state.flags, state.alpha);
- i++;
- });
- }
- }
+ ALOGE("%c index=%zu, name=%s, layerStack=%d, z=%d, visible=%d, flags=%x, alpha=%.3f",
+ layer->isVisible() ? '+' : '-', i, layer->getName().string(),
+ layer->getLayerStack(), state.z, layer->isVisible(), state.flags,
+ static_cast<float>(state.color.a));
+ i++;
+ });
}
}
@@ -4656,6 +4700,28 @@
layersSortedByZ.traverseInReverseZOrder(stateSet, visitor);
}
+void SurfaceFlinger::traverseLayersInDisplay(const sp<const DisplayDevice>& hw, int32_t minLayerZ,
+ int32_t maxLayerZ,
+ const LayerVector::Visitor& visitor) {
+ // We loop through the first level of layers without traversing,
+ // as we need to interpret min/max layer Z in the top level Z space.
+ for (const auto& layer : mDrawingState.layersSortedByZ) {
+ if (!layer->belongsToDisplay(hw->getLayerStack(), false)) {
+ continue;
+ }
+ const Layer::State& state(layer->getDrawingState());
+ if (state.z < minLayerZ || state.z > maxLayerZ) {
+ continue;
+ }
+ layer->traverseInZOrder(LayerVector::StateSet::Drawing, [&](Layer* layer) {
+ if (!layer->isVisible()) {
+ return;
+ }
+ visitor(layer);
+ });
+ }
+}
+
}; // namespace android
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 231709d..d10b41b 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -43,13 +43,15 @@
#include <gui/FrameTimestamps.h>
#include <gui/ISurfaceComposer.h>
#include <gui/ISurfaceComposerClient.h>
+#include <gui/LayerState.h>
+
#include <gui/OccupancyTracker.h>
#include <hardware/hwcomposer_defs.h>
-#include <system/graphics.h>
+#include <serviceutils/PriorityDumper.h>
-#include <private/gui/LayerState.h>
+#include <system/graphics.h>
#include "Barrier.h"
#include "DisplayDevice.h"
@@ -58,6 +60,7 @@
#include "LayerVector.h"
#include "MessageQueue.h"
#include "SurfaceInterceptor.h"
+#include "SurfaceTracing.h"
#include "StartPropertySetThread.h"
#ifdef USE_HWC2
@@ -75,6 +78,11 @@
#include <string>
#include <thread>
#include <utility>
+#include "RenderArea.h"
+
+#include <layerproto/LayerProtoHeader.h>
+
+using namespace android::surfaceflinger;
namespace android {
@@ -84,13 +92,15 @@
class DisplayEventConnection;
class EventThread;
class Layer;
-class LayerDim;
+class ColorLayer;
class Surface;
class RenderEngine;
class EventControlThread;
class VSyncSource;
class InjectVSyncSource;
+typedef std::function<void(const LayerVector::Visitor&)> TraverseLayersFunction;
+
namespace dvr {
class VrFlinger;
} // namespace dvr
@@ -105,6 +115,7 @@
};
class SurfaceFlinger : public BnSurfaceComposer,
+ public PriorityDumper,
private IBinder::DeathRecipient,
#ifdef USE_HWC2
private HWC2::ComposerCallback
@@ -233,6 +244,7 @@
friend class DisplayEventConnection;
friend class EventThread;
friend class Layer;
+ friend class BufferLayer;
friend class MonitoredProducer;
// This value is specified in number of frames. Log frame stats at most
@@ -272,7 +284,7 @@
*/
virtual status_t onTransact(uint32_t code, const Parcel& data,
Parcel* reply, uint32_t flags);
- virtual status_t dump(int fd, const Vector<String16>& args);
+ virtual status_t dump(int fd, const Vector<String16>& args) { return priorityDump(fd, args); }
/* ------------------------------------------------------------------------
* ISurfaceComposer interface
@@ -296,6 +308,9 @@
Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight,
int32_t minLayerZ, int32_t maxLayerZ,
bool useIdentityTransform, ISurfaceComposer::Rotation rotation);
+ virtual status_t captureLayers(const sp<IBinder>& parentHandle,
+ const sp<IGraphicBufferProducer>& producer,
+ ISurfaceComposer::Rotation rotation);
virtual status_t getDisplayStats(const sp<IBinder>& display,
DisplayStatInfo* stats);
virtual status_t getDisplayConfigs(const sp<IBinder>& display,
@@ -367,9 +382,6 @@
// Called on the main thread in response to setActiveColorMode()
void setActiveColorModeInternal(const sp<DisplayDevice>& hw, android_color_mode_t colorMode);
- // Called on the main thread in response to enableVSyncInjections()
- void enableVSyncInjectionsInternal(bool enable);
-
// Returns whether the transaction actually modified any state
bool handleMessageTransaction();
@@ -408,14 +420,14 @@
uint32_t windowType, uint32_t ownerUid, sp<IBinder>* handle,
sp<IGraphicBufferProducer>* gbp, sp<Layer>* parent);
- status_t createNormalLayer(const sp<Client>& client, const String8& name,
+ status_t createBufferLayer(const sp<Client>& client, const String8& name,
uint32_t w, uint32_t h, uint32_t flags, PixelFormat& format,
sp<IBinder>* outHandle, sp<IGraphicBufferProducer>* outGbp,
sp<Layer>* outLayer);
- status_t createDimLayer(const sp<Client>& client, const String8& name,
+ status_t createColorLayer(const sp<Client>& client, const String8& name,
uint32_t w, uint32_t h, uint32_t flags, sp<IBinder>* outHandle,
- sp<IGraphicBufferProducer>* outGbp, sp<Layer>* outLayer);
+ sp<Layer>* outLayer);
String8 getUniqueLayerName(const String8& name);
@@ -444,28 +456,26 @@
void startBootAnim();
- void renderScreenImplLocked(
- const sp<const DisplayDevice>& hw,
- Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight,
- int32_t minLayerZ, int32_t maxLayerZ,
- bool yswap, bool useIdentityTransform, Transform::orientation_flags rotation);
+ void renderScreenImplLocked(const RenderArea& renderArea, TraverseLayersFunction traverseLayers,
+ bool yswap, bool useIdentityTransform);
+
+ status_t captureScreenCommon(RenderArea& renderArea, TraverseLayersFunction traverseLayers,
+ const sp<IGraphicBufferProducer>& producer,
+ bool useIdentityTransform);
#ifdef USE_HWC2
- status_t captureScreenImplLocked(const sp<const DisplayDevice>& device,
- ANativeWindowBuffer* buffer, Rect sourceCrop,
- uint32_t reqWidth, uint32_t reqHeight, int32_t minLayerZ,
- int32_t maxLayerZ, bool useIdentityTransform,
- Transform::orientation_flags rotation, bool isLocalScreenshot,
- int* outSyncFd);
+ status_t captureScreenImplLocked(const RenderArea& renderArea,
+ TraverseLayersFunction traverseLayers,
+ ANativeWindowBuffer* buffer, bool useIdentityTransform,
+ bool isLocalScreenshot, int* outSyncFd);
#else
- status_t captureScreenImplLocked(
- const sp<const DisplayDevice>& hw,
- const sp<IGraphicBufferProducer>& producer,
- Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight,
- int32_t minLayerZ, int32_t maxLayerZ,
- bool useIdentityTransform, Transform::orientation_flags rotation,
- bool isLocalScreenshot);
+ status_t captureScreenImplLocked(const RenderArea& renderArea,
+ TraverseLayersFunction traverseLayers,
+ const sp<IGraphicBufferProducer>& producer,
+ bool useIdentityTransform, bool isLocalScreenshot);
#endif
+ void traverseLayersInDisplay(const sp<const DisplayDevice>& display, int32_t minLayerZ,
+ int32_t maxLayerZ, const LayerVector::Visitor& visitor);
sp<StartPropertySetThread> mStartPropertySetThread = nullptr;
@@ -567,6 +577,7 @@
void setUpHWComposer();
void doComposition();
void doDebugFlashRegions();
+ void doTracing(const char* where);
void doDisplayComposition(const sp<const DisplayDevice>& displayDevice, const Region& dirtyRegion);
// compose surfaces for display hw. this fails if using GL and the surface
@@ -595,6 +606,16 @@
/* ------------------------------------------------------------------------
* Debugging & dumpsys
*/
+public:
+ status_t dumpCritical(int fd, const Vector<String16>& /*args*/, bool asProto) {
+ return doDump(fd, Vector<String16>(), asProto);
+ }
+
+ status_t dumpAll(int fd, const Vector<String16>& args, bool asProto) {
+ return doDump(fd, args, asProto);
+ }
+
+private:
void listLayersLocked(const Vector<String16>& args, size_t& index, String8& result) const;
void dumpStatsLocked(const Vector<String16>& args, size_t& index, String8& result) const;
void clearStatsLocked(const Vector<String16>& args, size_t& index, String8& result);
@@ -602,8 +623,7 @@
bool startDdmConnection();
void appendSfConfigString(String8& result) const;
void checkScreenshot(size_t w, size_t s, size_t h, void const* vaddr,
- const sp<const DisplayDevice>& hw,
- int32_t minLayerZ, int32_t maxLayerZ);
+ TraverseLayersFunction traverseLayers);
void logFrameStats();
@@ -615,10 +635,12 @@
std::vector<OccupancyTracker::Segment>&& history);
void dumpBufferingStats(String8& result) const;
void dumpWideColorInfo(String8& result) const;
+ LayersProto dumpProtoInfo() const;
bool isLayerTripleBufferingDisabled() const {
return this->mLayerTripleBufferingDisabled;
}
+ status_t doDump(int fd, const Vector<String16>& args, bool asProto);
#ifdef USE_HWC2
/* ------------------------------------------------------------------------
@@ -727,6 +749,7 @@
bool mPropagateBackpressure = true;
#endif
SurfaceInterceptor mInterceptor;
+ SurfaceTracing mTracing;
bool mUseHwcVirtualDisplays = false;
// Restrict layers to use two buffers in their bufferqueues.
diff --git a/services/surfaceflinger/SurfaceFlinger_hwc1.cpp b/services/surfaceflinger/SurfaceFlinger_hwc1.cpp
index 1d6fbaf..ccadd44 100644
--- a/services/surfaceflinger/SurfaceFlinger_hwc1.cpp
+++ b/services/surfaceflinger/SurfaceFlinger_hwc1.cpp
@@ -70,8 +70,9 @@
#include "EventControlThread.h"
#include "EventThread.h"
#include "Layer.h"
+#include "BufferLayer.h"
#include "LayerVector.h"
-#include "LayerDim.h"
+#include "ColorLayer.h"
#include "MonitoredProducer.h"
#include "SurfaceFlinger.h"
@@ -87,6 +88,8 @@
#include <android/hardware/configstore/1.0/ISurfaceFlingerConfigs.h>
#include <configstore/Utils.h>
+#include <layerproto/LayerProtoParser.h>
+
#define DISPLAY_COUNT 1
/*
@@ -2024,7 +2027,7 @@
// compute the opaque region
const int32_t layerOrientation = tr.getOrientation();
- if (s.alpha==255 && !translucent &&
+ if (layer->getAlpha()==1.0f && !translucent &&
((layerOrientation & Transform::ROT_INVALID) == false)) {
// the opaque region is the layer's footprint
opaqueRegion = visibleRegion;
@@ -2210,6 +2213,8 @@
bool SurfaceFlinger::doComposeSurfaces(const sp<const DisplayDevice>& hw, const Region& dirty)
{
+ DisplayRenderArea renderArea(hw);
+
RenderEngine& engine(getRenderEngine());
const int32_t id = hw->getHwcDisplayId();
HWComposer& hwc(getHwComposer());
@@ -2297,16 +2302,16 @@
const Layer::State& state(layer->getDrawingState());
if ((cur->getHints() & HWC_HINT_CLEAR_FB)
&& i
- && layer->isOpaque(state) && (state.alpha == 0xFF)
+ && layer->isOpaque(state) && (state.color.a == 1.0f)
&& hasGlesComposition) {
// never clear the very first layer since we're
// guaranteed the FB is already cleared
- layer->clearWithOpenGL(hw);
+ layer->clearWithOpenGL(renderArea);
}
break;
}
case HWC_FRAMEBUFFER: {
- layer->draw(hw, clip);
+ layer->draw(renderArea, clip);
break;
}
case HWC_FRAMEBUFFER_TARGET: {
@@ -2326,7 +2331,7 @@
const Region clip(dirty.intersect(
tr.transform(layer->visibleRegion)));
if (!clip.isEmpty()) {
- layer->draw(hw, clip);
+ layer->draw(renderArea, clip);
}
}
}
@@ -2622,9 +2627,14 @@
}
}
if (what & layer_state_t::eAlphaChanged) {
- if (layer->setAlpha(uint8_t(255.0f*s.alpha+0.5f)))
+ if (layer->setAlpha(s.alpha))
flags |= eTraversalNeeded;
}
+ if (what & layer_state_t::eColorChanged) {
+ if (layer->setColor(s.color)) {
+ flags |= eTraversalNeeded;
+ }
+ }
if (what & layer_state_t::eMatrixChanged) {
if (layer->setMatrix(s.matrix))
flags |= eTraversalNeeded;
@@ -2681,6 +2691,11 @@
// We don't trigger a traversal here because if no other state is
// changed, we don't want this to cause any more work
}
+ if (what & layer_state_t::eReparent) {
+ if (layer->reparent(s.parentHandleForChild)) {
+ flags |= eTransactionNeeded|eTraversalNeeded;
+ }
+ }
if (what & layer_state_t::eReparentChildren) {
if (layer->reparentChildren(s.reparentHandle)) {
flags |= eTransactionNeeded|eTraversalNeeded;
@@ -2719,14 +2734,14 @@
switch (flags & ISurfaceComposerClient::eFXSurfaceMask) {
case ISurfaceComposerClient::eFXSurfaceNormal:
- result = createNormalLayer(client,
+ result = createBufferLayer(client,
uniqueName, w, h, flags, format,
handle, gbp, &layer);
break;
- case ISurfaceComposerClient::eFXSurfaceDim:
- result = createDimLayer(client,
+ case ISurfaceComposerClient::eFXSurfaceColor:
+ result = createColorLayer(client,
uniqueName, w, h, flags,
- handle, gbp, &layer);
+ handle, &layer);
break;
default:
result = BAD_VALUE;
@@ -2773,7 +2788,7 @@
return uniqueName;
}
-status_t SurfaceFlinger::createNormalLayer(const sp<Client>& client,
+status_t SurfaceFlinger::createBufferLayer(const sp<Client>& client,
const String8& name, uint32_t w, uint32_t h, uint32_t flags, PixelFormat& format,
sp<IBinder>* handle, sp<IGraphicBufferProducer>* gbp, sp<Layer>* outLayer)
{
@@ -2788,24 +2803,24 @@
break;
}
- *outLayer = new Layer(this, client, name, w, h, flags);
- status_t err = (*outLayer)->setBuffers(w, h, format, flags);
+ sp<BufferLayer> layer = new BufferLayer(this, client, name, w, h, flags);
+ status_t err = layer->setBuffers(w, h, format, flags);
if (err == NO_ERROR) {
- *handle = (*outLayer)->getHandle();
- *gbp = (*outLayer)->getProducer();
+ *handle = layer->getHandle();
+ *gbp = layer->getProducer();
+ *outLayer = layer;
}
- ALOGE_IF(err, "createNormalLayer() failed (%s)", strerror(-err));
+ ALOGE_IF(err, "createBufferLayer() failed (%s)", strerror(-err));
return err;
}
-status_t SurfaceFlinger::createDimLayer(const sp<Client>& client,
+status_t SurfaceFlinger::createColorLayer(const sp<Client>& client,
const String8& name, uint32_t w, uint32_t h, uint32_t flags,
- sp<IBinder>* handle, sp<IGraphicBufferProducer>* gbp, sp<Layer>* outLayer)
+ sp<IBinder>* handle, sp<Layer>* outLayer)
{
- *outLayer = new LayerDim(this, client, name, w, h, flags);
+ *outLayer = new ColorLayer(this, client, name, w, h, flags);
*handle = (*outLayer)->getHandle();
- *gbp = (*outLayer)->getProducer();
return NO_ERROR;
}
@@ -2933,7 +2948,8 @@
ALOGW("Couldn't set SCHED_OTHER on display off");
}
- if (type == DisplayDevice::DISPLAY_PRIMARY) {
+ if (type == DisplayDevice::DISPLAY_PRIMARY &&
+ currentMode != HWC_POWER_MODE_DOZE_SUSPEND) {
disableHardwareVsync(true); // also cancels any in-progress resync
// FIXME: eventthread only knows about the main display right now
@@ -2947,7 +2963,8 @@
mode == HWC_POWER_MODE_NORMAL) {
// Update display while dozing
getHwComposer().setPowerMode(type, mode);
- if (type == DisplayDevice::DISPLAY_PRIMARY) {
+ if (type == DisplayDevice::DISPLAY_PRIMARY &&
+ currentMode == HWC_POWER_MODE_DOZE_SUSPEND) {
// FIXME: eventthread only knows about the main display right now
mEventThread->onScreenAcquired();
resyncToHardwareVsync(true);
@@ -2995,13 +3012,18 @@
// ---------------------------------------------------------------------------
-status_t SurfaceFlinger::dump(int fd, const Vector<String16>& args)
-{
+status_t SurfaceFlinger::doDump(int fd, const Vector<String16>& args, bool asProto) {
String8 result;
IPCThreadState* ipc = IPCThreadState::self();
const int pid = ipc->getCallingPid();
const int uid = ipc->getCallingUid();
+
+ if (asProto) {
+ // Return early as SurfaceFlinger does not support dumping sections in proto format
+ return OK;
+ }
+
if ((uid != AID_SHELL) &&
!PermissionCache::checkPermission(sDump, pid, uid)) {
result.appendFormat("Permission Denial: "
@@ -3063,6 +3085,13 @@
dumpFrameEventsLocked(result);
dumpAll = false;
}
+
+ if ((index < numArgs) && (args[index] == String16("--proto"))) {
+ index++;
+ LayersProto layersProto = dumpProtoInfo();
+ result.append(layersProto.SerializeAsString().c_str(), layersProto.ByteSize());
+ dumpAll = false;
+ }
}
if (dumpAll) {
@@ -3233,6 +3262,16 @@
result.append("\n");
}
+LayersProto SurfaceFlinger::dumpProtoInfo() const {
+ LayersProto layersProto;
+ mCurrentState.traverseInZOrder([&](Layer* layer) {
+ LayerProto* layerProto = layersProto.add_layers();
+ layer->writeToProto(layerProto, LayerVector::StateSet::Current);
+ });
+
+ return layersProto;
+}
+
void SurfaceFlinger::dumpAllLocked(const Vector<String16>& args, size_t& index,
String8& result) const
{
@@ -3292,9 +3331,10 @@
colorizer.bold(result);
result.appendFormat("Visible layers (count = %zu)\n", mNumLayers);
colorizer.reset(result);
- mCurrentState.traverseInZOrder([&](Layer* layer) {
- result.append(to_string(layer->getLayerDebugInfo()).c_str());
- });
+
+ LayersProto layersProto = dumpProtoInfo();
+ auto layerTree = LayerProtoParser::generateLayerTree(layersProto);
+ result.append(LayerProtoParser::layersToString(layerTree).c_str());
/*
* Dump Display state
@@ -3463,6 +3503,18 @@
}
break;
}
+ case CAPTURE_LAYERS:
+ {
+ IPCThreadState* ipc = IPCThreadState::self();
+ const int pid = ipc->getCallingPid();
+ const int uid = ipc->getCallingUid();
+ if ((uid != AID_GRAPHICS) &&
+ !PermissionCache::checkPermission(sReadFramebuffer, pid, uid)) {
+ ALOGE("Permission Denial: can't read framebuffer pid=%d, uid=%d", pid, uid);
+ return PERMISSION_DENIED;
+ }
+ break;
+ }
}
status_t err = BnSurfaceComposer::onTransact(code, data, reply, flags);
@@ -3736,16 +3788,72 @@
}
};
-
status_t SurfaceFlinger::captureScreen(const sp<IBinder>& display,
- const sp<IGraphicBufferProducer>& producer,
- Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight,
- int32_t minLayerZ, int32_t maxLayerZ,
- bool useIdentityTransform, ISurfaceComposer::Rotation rotation) {
-
+ const sp<IGraphicBufferProducer>& producer,
+ Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight,
+ int32_t minLayerZ, int32_t maxLayerZ,
+ bool useIdentityTransform, ISurfaceComposer::Rotation rotation) {
+ ATRACE_CALL();
if (CC_UNLIKELY(display == 0))
return BAD_VALUE;
+ const sp<const DisplayDevice> device(getDisplayDeviceLocked(display));
+ DisplayRenderArea renderArea(device, sourceCrop, reqHeight, reqWidth, rotation);
+
+ auto traverseLayers = std::bind(std::mem_fn(&SurfaceFlinger::traverseLayersInDisplay), this,
+ device, minLayerZ, maxLayerZ, std::placeholders::_1);
+ return captureScreenCommon(renderArea, traverseLayers, producer, useIdentityTransform);
+}
+
+status_t SurfaceFlinger::captureLayers(const sp<IBinder>& layerHandleBinder,
+ const sp<IGraphicBufferProducer>& producer,
+ ISurfaceComposer::Rotation rotation) {
+ ATRACE_CALL();
+ class LayerRenderArea : public RenderArea {
+ public:
+ LayerRenderArea(const sp<Layer>& layer, ISurfaceComposer::Rotation rotation)
+ : RenderArea(layer->getCurrentState().active.h, layer->getCurrentState().active.w,
+ rotation),
+ mLayer(layer) {}
+ const Transform& getTransform() const override {
+ // Make the top level transform the inverse the transform and it's parent so it sets
+ // the whole capture back to 0,0
+ return *new Transform(mLayer->getTransform().inverse());
+ }
+ Rect getBounds() const override {
+ const Layer::State& layerState(mLayer->getDrawingState());
+ return Rect(layerState.active.w, layerState.active.h);
+ }
+ int getHeight() const override { return mLayer->getDrawingState().active.h; }
+ int getWidth() const override { return mLayer->getDrawingState().active.w; }
+ bool isSecure() const override { return false; }
+ bool needsFiltering() const override { return false; }
+
+ Rect getSourceCrop() const override { return getBounds(); }
+
+ private:
+ const sp<Layer>& mLayer;
+ };
+
+ auto layerHandle = reinterpret_cast<Layer::Handle*>(layerHandleBinder.get());
+ auto parent = layerHandle->owner.promote();
+
+ LayerRenderArea renderArea(parent, rotation);
+ auto traverseLayers = [parent](const LayerVector::Visitor& visitor) {
+ parent->traverseChildrenInZOrder(LayerVector::StateSet::Drawing, [&](Layer* layer) {
+ if (!layer->isVisible()) {
+ return;
+ }
+ visitor(layer);
+ });
+ };
+ return captureScreenCommon(renderArea, traverseLayers, producer, false);
+}
+
+status_t SurfaceFlinger::captureScreenCommon(RenderArea& renderArea,
+ TraverseLayersFunction traverseLayers,
+ const sp<IGraphicBufferProducer>& producer,
+ bool useIdentityTransform) {
if (CC_UNLIKELY(producer == 0))
return BAD_VALUE;
@@ -3754,64 +3862,33 @@
// ourselves).
bool isLocalScreenshot = IInterface::asBinder(producer)->localBinder();
- // Convert to surfaceflinger's internal rotation type.
- Transform::orientation_flags rotationFlags;
- switch (rotation) {
- case ISurfaceComposer::eRotateNone:
- rotationFlags = Transform::ROT_0;
- break;
- case ISurfaceComposer::eRotate90:
- rotationFlags = Transform::ROT_90;
- break;
- case ISurfaceComposer::eRotate180:
- rotationFlags = Transform::ROT_180;
- break;
- case ISurfaceComposer::eRotate270:
- rotationFlags = Transform::ROT_270;
- break;
- default:
- rotationFlags = Transform::ROT_0;
- ALOGE("Invalid rotation passed to captureScreen(): %d\n", rotation);
- break;
- }
-
class MessageCaptureScreen : public MessageBase {
SurfaceFlinger* flinger;
- sp<IBinder> display;
+ const RenderArea* renderArea;
+ TraverseLayersFunction traverseLayers;
sp<IGraphicBufferProducer> producer;
- Rect sourceCrop;
- uint32_t reqWidth, reqHeight;
- int32_t minLayerZ,maxLayerZ;
bool useIdentityTransform;
- Transform::orientation_flags rotation;
status_t result;
bool isLocalScreenshot;
public:
- MessageCaptureScreen(SurfaceFlinger* flinger,
- const sp<IBinder>& display,
- const sp<IGraphicBufferProducer>& producer,
- Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight,
- int32_t minLayerZ, int32_t maxLayerZ,
- bool useIdentityTransform,
- Transform::orientation_flags rotation,
- bool isLocalScreenshot)
- : flinger(flinger), display(display), producer(producer),
- sourceCrop(sourceCrop), reqWidth(reqWidth), reqHeight(reqHeight),
- minLayerZ(minLayerZ), maxLayerZ(maxLayerZ),
- useIdentityTransform(useIdentityTransform),
- rotation(rotation), result(PERMISSION_DENIED),
- isLocalScreenshot(isLocalScreenshot)
- {
- }
+ MessageCaptureScreen(SurfaceFlinger* flinger, const RenderArea* renderArea,
+ TraverseLayersFunction traverseLayers,
+ const sp<IGraphicBufferProducer>& producer, bool useIdentityTransform,
+ bool isLocalScreenshot)
+ : flinger(flinger),
+ renderArea(renderArea),
+ traverseLayers(traverseLayers),
+ producer(producer),
+ useIdentityTransform(useIdentityTransform),
+ result(PERMISSION_DENIED),
+ isLocalScreenshot(isLocalScreenshot) {}
status_t getResult() const {
return result;
}
virtual bool handler() {
Mutex::Autolock _l(flinger->mStateLock);
- sp<const DisplayDevice> hw(flinger->getDisplayDeviceLocked(display));
- result = flinger->captureScreenImplLocked(hw, producer,
- sourceCrop, reqWidth, reqHeight, minLayerZ, maxLayerZ,
- useIdentityTransform, rotation, isLocalScreenshot);
+ result = flinger->captureScreenImplLocked(*renderArea, traverseLayers, producer,
+ useIdentityTransform, isLocalScreenshot);
static_cast<GraphicProducerWrapper*>(IInterface::asBinder(producer).get())->exit(result);
return true;
}
@@ -3825,9 +3902,8 @@
// the asInterface() call below creates our "fake" BpGraphicBufferProducer
// which does the marshaling work forwards to our "fake remote" above.
sp<MessageBase> msg = new MessageCaptureScreen(this,
- display, IGraphicBufferProducer::asInterface( wrapper ),
- sourceCrop, reqWidth, reqHeight, minLayerZ, maxLayerZ,
- useIdentityTransform, rotationFlags, isLocalScreenshot);
+ &renderArea, traverseLayers, IGraphicBufferProducer::asInterface( wrapper ),
+ useIdentityTransform, isLocalScreenshot);
status_t res = postMessageAsync(msg);
if (res == NO_ERROR) {
@@ -3836,41 +3912,42 @@
return res;
}
-
-void SurfaceFlinger::renderScreenImplLocked(
- const sp<const DisplayDevice>& hw,
- Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight,
- int32_t minLayerZ, int32_t maxLayerZ,
- bool yswap, bool useIdentityTransform, Transform::orientation_flags rotation)
+void SurfaceFlinger::renderScreenImplLocked(const RenderArea& renderArea, TraverseLayersFunction traverseLayers,
+ bool yswap, bool useIdentityTransform)
{
ATRACE_CALL();
RenderEngine& engine(getRenderEngine());
// get screen geometry
- const int32_t hw_w = hw->getWidth();
- const int32_t hw_h = hw->getHeight();
- const bool filtering = static_cast<int32_t>(reqWidth) != hw_w ||
- static_cast<int32_t>(reqHeight) != hw_h;
+ const auto raWidth = renderArea.getWidth();
+ const auto raHeight = renderArea.getHeight();
+
+ const auto reqWidth = renderArea.getReqWidth();
+ const auto reqHeight = renderArea.getReqHeight();
+ Rect sourceCrop = renderArea.getSourceCrop();
+
+ const bool filtering = static_cast<int32_t>(reqWidth) != raWidth ||
+ static_cast<int32_t>(reqHeight) != raHeight;
// if a default or invalid sourceCrop is passed in, set reasonable values
if (sourceCrop.width() == 0 || sourceCrop.height() == 0 ||
!sourceCrop.isValid()) {
sourceCrop.setLeftTop(Point(0, 0));
- sourceCrop.setRightBottom(Point(hw_w, hw_h));
+ sourceCrop.setRightBottom(Point(raWidth, raHeight));
}
// ensure that sourceCrop is inside screen
if (sourceCrop.left < 0) {
ALOGE("Invalid crop rect: l = %d (< 0)", sourceCrop.left);
}
- if (sourceCrop.right > hw_w) {
- ALOGE("Invalid crop rect: r = %d (> %d)", sourceCrop.right, hw_w);
+ if (sourceCrop.right > raWidth) {
+ ALOGE("Invalid crop rect: r = %d (> %d)", sourceCrop.right, raWidth);
}
if (sourceCrop.top < 0) {
ALOGE("Invalid crop rect: t = %d (< 0)", sourceCrop.top);
}
- if (sourceCrop.bottom > hw_h) {
- ALOGE("Invalid crop rect: b = %d (> %d)", sourceCrop.bottom, hw_h);
+ if (sourceCrop.bottom > raHeight) {
+ ALOGE("Invalid crop rect: b = %d (> %d)", sourceCrop.bottom, raHeight);
}
// make sure to clear all GL error flags
@@ -3878,77 +3955,35 @@
// set-up our viewport
engine.setViewportAndProjection(
- reqWidth, reqHeight, sourceCrop, hw_h, yswap, rotation);
+ reqWidth, reqHeight, sourceCrop, raHeight, yswap, renderArea.getRotationFlags());
engine.disableTexturing();
// redraw the screen entirely...
engine.clearWithColor(0, 0, 0, 1);
- // We loop through the first level of layers without traversing,
- // as we need to interpret min/max layer Z in the top level Z space.
- for (const auto& layer : mDrawingState.layersSortedByZ) {
- if (layer->getLayerStack() != hw->getLayerStack()) {
- continue;
- }
- const Layer::State& state(layer->getDrawingState());
- if (state.z < minLayerZ || state.z > maxLayerZ) {
- continue;
- }
- layer->traverseInZOrder(LayerVector::StateSet::Drawing, [&](Layer* layer) {
- if (!layer->isVisible()) {
- return;
- }
- if (filtering) layer->setFiltering(true);
- layer->draw(hw, useIdentityTransform);
- if (filtering) layer->setFiltering(false);
- });
- }
+ traverseLayers([&](Layer* layer) {
+ if (filtering) layer->setFiltering(true);
+ layer->draw(renderArea, useIdentityTransform);
+ if (filtering) layer->setFiltering(false);
+ });
// compositionComplete is needed for older driver
- hw->compositionComplete();
- hw->setViewportAndProjection();
+// hw->compositionComplete();
+// hw->setViewportAndProjection();
}
-
-status_t SurfaceFlinger::captureScreenImplLocked(
- const sp<const DisplayDevice>& hw,
- const sp<IGraphicBufferProducer>& producer,
- Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight,
- int32_t minLayerZ, int32_t maxLayerZ,
- bool useIdentityTransform, Transform::orientation_flags rotation,
- bool isLocalScreenshot)
-{
+status_t SurfaceFlinger::captureScreenImplLocked(const RenderArea& renderArea,
+ TraverseLayersFunction traverseLayers,
+ const sp<IGraphicBufferProducer>& producer,
+ bool useIdentityTransform,
+ bool isLocalScreenshot) {
ATRACE_CALL();
- // get screen geometry
- uint32_t hw_w = hw->getWidth();
- uint32_t hw_h = hw->getHeight();
-
- if (rotation & Transform::ROT_90) {
- std::swap(hw_w, hw_h);
- }
-
- if ((reqWidth > hw_w) || (reqHeight > hw_h)) {
- ALOGE("size mismatch (%d, %d) > (%d, %d)",
- reqWidth, reqHeight, hw_w, hw_h);
- return BAD_VALUE;
- }
-
- reqWidth = (!reqWidth) ? hw_w : reqWidth;
- reqHeight = (!reqHeight) ? hw_h : reqHeight;
-
bool secureLayerIsVisible = false;
- for (const auto& layer : mDrawingState.layersSortedByZ) {
- const Layer::State& state(layer->getDrawingState());
- if ((layer->getLayerStack() != hw->getLayerStack()) ||
- (state.z < minLayerZ || state.z > maxLayerZ)) {
- continue;
- }
- layer->traverseInZOrder(LayerVector::StateSet::Drawing, [&](Layer *layer) {
- secureLayerIsVisible = secureLayerIsVisible || (layer->isVisible() &&
- layer->isSecure());
- });
- }
+ traverseLayers([&](Layer *layer) {
+ secureLayerIsVisible = secureLayerIsVisible || (layer->isVisible() &&
+ layer->isSecure());
+ });
if (!isLocalScreenshot && secureLayerIsVisible) {
ALOGW("FB is protected: PERMISSION_DENIED");
@@ -3966,7 +4001,8 @@
GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_TEXTURE;
int err = 0;
- err = native_window_set_buffers_dimensions(window, reqWidth, reqHeight);
+ err = native_window_set_buffers_dimensions(window, renderArea.getReqWidth(),
+ renderArea.getReqHeight());
err |= native_window_set_scaling_mode(window, NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW);
err |= native_window_set_buffers_format(window, HAL_PIXEL_FORMAT_RGBA_8888);
err |= native_window_set_usage(window, usage);
@@ -3992,9 +4028,7 @@
// via an FBO, which means we didn't have to create
// an EGLSurface and therefore we're not
// dependent on the context's EGLConfig.
- renderScreenImplLocked(
- hw, sourceCrop, reqWidth, reqHeight, minLayerZ, maxLayerZ, true,
- useIdentityTransform, rotation);
+ renderScreenImplLocked(renderArea, traverseLayers, true, useIdentityTransform);
// Attempt to create a sync khr object that can produce a sync point. If that
// isn't available, create a non-dupable sync object in the fallback path and
@@ -4034,10 +4068,12 @@
}
}
if (DEBUG_SCREENSHOTS) {
- uint32_t* pixels = new uint32_t[reqWidth*reqHeight];
- getRenderEngine().readPixels(0, 0, reqWidth, reqHeight, pixels);
- checkScreenshot(reqWidth, reqHeight, reqWidth, pixels,
- hw, minLayerZ, maxLayerZ);
+ uint32_t* pixels = new uint32_t[renderArea.getReqWidth() *
+ renderArea.getReqHeight()];
+ getRenderEngine().readPixels(0, 0, renderArea.getReqWidth(),
+ renderArea.getReqHeight(), pixels);
+ checkScreenshot(renderArea.getReqWidth(), renderArea.getReqHeight(),
+ renderArea.getReqWidth(), pixels, traverseLayers);
delete [] pixels;
}
@@ -4067,7 +4103,7 @@
}
void SurfaceFlinger::checkScreenshot(size_t w, size_t s, size_t h, void const* vaddr,
- const sp<const DisplayDevice>& hw, int32_t minLayerZ, int32_t maxLayerZ) {
+ TraverseLayersFunction traverseLayers) {
if (DEBUG_SCREENSHOTS) {
for (size_t y=0 ; y<h ; y++) {
uint32_t const * p = (uint32_t const *)vaddr + y*s;
@@ -4075,23 +4111,17 @@
if (p[x] != 0xFF000000) return;
}
}
- ALOGE("*** we just took a black screenshot ***\n"
- "requested minz=%d, maxz=%d, layerStack=%d",
- minLayerZ, maxLayerZ, hw->getLayerStack());
+ ALOGE("*** we just took a black screenshot ***");
+
size_t i = 0;
- for (const auto& layer : mDrawingState.layersSortedByZ) {
+ traverseLayers([&](Layer* layer) {
const Layer::State& state(layer->getDrawingState());
- if (layer->getLayerStack() == hw->getLayerStack() && state.z >= minLayerZ &&
- state.z <= maxLayerZ) {
- layer->traverseInZOrder(LayerVector::StateSet::Drawing, [&](Layer* layer) {
- ALOGE("%c index=%zu, name=%s, layerStack=%d, z=%d, visible=%d, flags=%x, alpha=%x",
- layer->isVisible() ? '+' : '-',
- i, layer->getName().string(), layer->getLayerStack(), state.z,
- layer->isVisible(), state.flags, state.alpha);
- i++;
- });
- }
- }
+ ALOGE("%c index=%zu, name=%s, layerStack=%d, z=%d, visible=%d, flags=%x, alpha=%.3f",
+ layer->isVisible() ? '+' : '-',
+ i, layer->getName().string(), layer->getLayerStack(), state.z,
+ layer->isVisible(), state.flags, static_cast<float>(state.color.a));
+ i++;
+ });
}
}
@@ -4105,6 +4135,28 @@
layersSortedByZ.traverseInReverseZOrder(stateSet, visitor);
}
+void SurfaceFlinger::traverseLayersInDisplay(const sp<const DisplayDevice>& hw,
+ int32_t minLayerZ, int32_t maxLayerZ, const LayerVector::Visitor& visitor) {
+
+ // We loop through the first level of layers without traversing,
+ // as we need to interpret min/max layer Z in the top level Z space.
+ for (const auto& layer : mDrawingState.layersSortedByZ) {
+ if (!layer->belongsToDisplay(hw->getLayerStack(), false)) {
+ continue;
+ }
+ const Layer::State& state(layer->getDrawingState());
+ if (state.z < minLayerZ || state.z > maxLayerZ) {
+ continue;
+ }
+ layer->traverseInZOrder(LayerVector::StateSet::Drawing, [&](Layer* layer) {
+ if (!layer->isVisible()) {
+ return;
+ }
+ visitor(layer);
+ });
+ }
+}
+
}; // namespace android
diff --git a/services/surfaceflinger/SurfaceInterceptor.cpp b/services/surfaceflinger/SurfaceInterceptor.cpp
index db489b2..eeb4929 100644
--- a/services/surfaceflinger/SurfaceInterceptor.cpp
+++ b/services/surfaceflinger/SurfaceInterceptor.cpp
@@ -98,7 +98,7 @@
addPositionLocked(transaction, layerId, layer->mCurrentState.active.transform.tx(),
layer->mCurrentState.active.transform.ty());
addDepthLocked(transaction, layerId, layer->mCurrentState.z);
- addAlphaLocked(transaction, layerId, layer->mCurrentState.alpha);
+ addAlphaLocked(transaction, layerId, layer->mCurrentState.color.a);
addTransparentRegionLocked(transaction, layerId, layer->mCurrentState.activeTransparentRegion);
addLayerStackLocked(transaction, layerId, layer->mCurrentState.layerStack);
addCropLocked(transaction, layerId, layer->mCurrentState.crop);
diff --git a/services/surfaceflinger/SurfaceTracing.cpp b/services/surfaceflinger/SurfaceTracing.cpp
new file mode 100644
index 0000000..f8c466e
--- /dev/null
+++ b/services/surfaceflinger/SurfaceTracing.cpp
@@ -0,0 +1,85 @@
+/*
+ * Copyright 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#undef LOG_TAG
+#define LOG_TAG "SurfaceTracing"
+#define ATRACE_TAG ATRACE_TAG_GRAPHICS
+
+#include "SurfaceTracing.h"
+
+#include <android-base/file.h>
+#include <log/log.h>
+#include <utils/SystemClock.h>
+#include <utils/Trace.h>
+
+namespace android {
+
+void SurfaceTracing::enable() {
+ if (mEnabled) {
+ return;
+ }
+ ATRACE_CALL();
+ mEnabled = true;
+ std::lock_guard<std::mutex> protoGuard(mTraceMutex);
+
+ mTrace.set_magic_number(uint64_t(LayersTraceFileProto_MagicNumber_MAGIC_NUMBER_H) << 32 |
+ LayersTraceFileProto_MagicNumber_MAGIC_NUMBER_L);
+}
+
+status_t SurfaceTracing::disable() {
+ if (!mEnabled) {
+ return NO_ERROR;
+ }
+ ATRACE_CALL();
+ std::lock_guard<std::mutex> protoGuard(mTraceMutex);
+ mEnabled = false;
+ status_t err(writeProtoFileLocked());
+ ALOGE_IF(err == PERMISSION_DENIED, "Could not save the proto file! Permission denied");
+ ALOGE_IF(err == NOT_ENOUGH_DATA, "Could not save the proto file! There are missing fields");
+ mTrace.Clear();
+ return err;
+}
+
+bool SurfaceTracing::isEnabled() {
+ return mEnabled;
+}
+
+void SurfaceTracing::traceLayers(const char* where, LayersProto layers) {
+ std::lock_guard<std::mutex> protoGuard(mTraceMutex);
+
+ LayersTraceProto* entry = mTrace.add_entry();
+ entry->set_elapsed_realtime_nanos(elapsedRealtimeNano());
+ entry->set_where(where);
+ entry->mutable_layers()->Swap(&layers);
+}
+
+status_t SurfaceTracing::writeProtoFileLocked() {
+ ATRACE_CALL();
+
+ if (!mTrace.IsInitialized()) {
+ return NOT_ENOUGH_DATA;
+ }
+ std::string output;
+ if (!mTrace.SerializeToString(&output)) {
+ return PERMISSION_DENIED;
+ }
+ if (!android::base::WriteStringToFile(output, mOutputFileName, true)) {
+ return PERMISSION_DENIED;
+ }
+
+ return NO_ERROR;
+}
+
+} // namespace android
diff --git a/services/surfaceflinger/SurfaceTracing.h b/services/surfaceflinger/SurfaceTracing.h
new file mode 100644
index 0000000..9b21989
--- /dev/null
+++ b/services/surfaceflinger/SurfaceTracing.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <layerproto/LayerProtoHeader.h>
+#include <utils/Errors.h>
+
+#include <mutex>
+
+using namespace android::surfaceflinger;
+
+namespace android {
+
+/*
+ * SurfaceTracing records layer states during surface flinging.
+ */
+class SurfaceTracing {
+public:
+ void enable();
+ status_t disable();
+ bool isEnabled();
+
+ void traceLayers(const char* where, LayersProto);
+
+private:
+ static constexpr auto DEFAULT_FILENAME = "/data/misc/trace/layerstrace.pb";
+
+ status_t writeProtoFileLocked();
+
+ bool mEnabled = false;
+ std::string mOutputFileName = DEFAULT_FILENAME;
+ std::mutex mTraceMutex;
+ LayersTraceFileProto mTrace;
+};
+
+} // namespace android
diff --git a/services/surfaceflinger/Transform.cpp b/services/surfaceflinger/Transform.cpp
index 6be9ae2..37925a1 100644
--- a/services/surfaceflinger/Transform.cpp
+++ b/services/surfaceflinger/Transform.cpp
@@ -20,8 +20,8 @@
#include <utils/String8.h>
#include <ui/Region.h>
-#include "clz.h"
#include "Transform.h"
+#include "clz.h"
// ---------------------------------------------------------------------------
@@ -388,6 +388,23 @@
ALOGD("%.4f %.4f %.4f", m[0][2], m[1][2], m[2][2]);
}
+Transform::orientation_flags Transform::fromRotation(ISurfaceComposer::Rotation rotation) {
+ // Convert to surfaceflinger's internal rotation type.
+ switch (rotation) {
+ case ISurfaceComposer::eRotateNone:
+ return Transform::ROT_0;
+ case ISurfaceComposer::eRotate90:
+ return Transform::ROT_90;
+ case ISurfaceComposer::eRotate180:
+ return Transform::ROT_180;
+ case ISurfaceComposer::eRotate270:
+ return Transform::ROT_270;
+ default:
+ ALOGE("Invalid rotation passed to captureScreen(): %d\n", rotation);
+ return Transform::ROT_0;
+ }
+}
+
// ---------------------------------------------------------------------------
}; // namespace android
diff --git a/services/surfaceflinger/Transform.h b/services/surfaceflinger/Transform.h
index 6640a13..bfc66ec 100644
--- a/services/surfaceflinger/Transform.h
+++ b/services/surfaceflinger/Transform.h
@@ -25,6 +25,8 @@
#include <math/vec2.h>
#include <math/vec3.h>
+#include <gui/ISurfaceComposer.h>
+
#include <hardware/hardware.h>
namespace android {
@@ -51,6 +53,8 @@
ROT_INVALID = 0x80
};
+ static orientation_flags fromRotation(ISurfaceComposer::Rotation rotation);
+
enum type_mask {
IDENTITY = 0,
TRANSLATE = 0x1,
diff --git a/services/surfaceflinger/layerproto/Android.bp b/services/surfaceflinger/layerproto/Android.bp
new file mode 100644
index 0000000..8eb218c
--- /dev/null
+++ b/services/surfaceflinger/layerproto/Android.bp
@@ -0,0 +1,36 @@
+cc_library_shared {
+ name: "liblayers_proto",
+ vendor_available: true,
+ export_include_dirs: ["include"],
+
+ srcs: [
+ "LayerProtoParser.cpp",
+ "layers.proto",
+ "layerstrace.proto",
+ ],
+
+ shared_libs: [
+ "libui",
+ "libprotobuf-cpp-lite",
+ "libbase",
+ ],
+
+ proto: {
+ export_proto_headers: true,
+ },
+
+ cppflags: [
+ "-Werror",
+ "-Wno-unused-parameter",
+ "-Wno-format",
+ "-Wno-c++98-compat-pedantic",
+ "-Wno-float-conversion",
+ "-Wno-disabled-macro-expansion",
+ "-Wno-float-equal",
+ "-Wno-sign-conversion",
+ "-Wno-padded",
+ "-Wno-old-style-cast",
+ "-Wno-undef",
+ ],
+
+}
\ No newline at end of file
diff --git a/services/surfaceflinger/layerproto/LayerProtoParser.cpp b/services/surfaceflinger/layerproto/LayerProtoParser.cpp
new file mode 100644
index 0000000..e6f2ce7
--- /dev/null
+++ b/services/surfaceflinger/layerproto/LayerProtoParser.cpp
@@ -0,0 +1,286 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <android-base/stringprintf.h>
+#include <layerproto/LayerProtoParser.h>
+#include <ui/DebugUtils.h>
+
+using android::base::StringAppendF;
+using android::base::StringPrintf;
+
+namespace android {
+namespace surfaceflinger {
+
+bool sortLayers(const LayerProtoParser::Layer* lhs, const LayerProtoParser::Layer* rhs) {
+ uint32_t ls = lhs->layerStack;
+ uint32_t rs = rhs->layerStack;
+ if (ls != rs) return ls < rs;
+
+ uint32_t lz = lhs->z;
+ uint32_t rz = rhs->z;
+ if (lz != rz) return lz < rz;
+
+ return lhs->id < rhs->id;
+}
+
+std::vector<const LayerProtoParser::Layer*> LayerProtoParser::generateLayerTree(
+ const LayersProto& layersProto) {
+ auto layerMap = generateMap(layersProto);
+
+ std::vector<const Layer*> layers;
+ std::for_each(layerMap.begin(), layerMap.end(),
+ [&](const std::pair<const int32_t, Layer*>& ref) {
+ if (ref.second->parent == nullptr) {
+ // only save top level layers
+ layers.push_back(ref.second);
+ }
+ });
+
+ std::sort(layers.begin(), layers.end(), sortLayers);
+ return layers;
+}
+
+std::unordered_map<int32_t, LayerProtoParser::Layer*> LayerProtoParser::generateMap(
+ const LayersProto& layersProto) {
+ std::unordered_map<int32_t, Layer*> layerMap;
+
+ for (int i = 0; i < layersProto.layers_size(); i++) {
+ const LayerProto& layerProto = layersProto.layers(i);
+ layerMap[layerProto.id()] = generateLayer(layerProto);
+ }
+
+ for (int i = 0; i < layersProto.layers_size(); i++) {
+ const LayerProto& layerProto = layersProto.layers(i);
+ updateChildrenAndRelative(layerProto, layerMap);
+ }
+
+ return layerMap;
+}
+
+LayerProtoParser::Layer* LayerProtoParser::generateLayer(const LayerProto& layerProto) {
+ Layer* layer = new Layer();
+ layer->id = layerProto.id();
+ layer->name = layerProto.name();
+ layer->type = layerProto.type();
+ layer->transparentRegion = generateRegion(layerProto.transparent_region());
+ layer->visibleRegion = generateRegion(layerProto.visible_region());
+ layer->damageRegion = generateRegion(layerProto.damage_region());
+ layer->layerStack = layerProto.layer_stack();
+ layer->z = layerProto.z();
+ layer->position = {layerProto.position().x(), layerProto.position().y()};
+ layer->requestedPosition = {layerProto.requested_position().x(),
+ layerProto.requested_position().y()};
+ layer->size = {layerProto.size().w(), layerProto.size().h()};
+ layer->crop = generateRect(layerProto.crop());
+ layer->finalCrop = generateRect(layerProto.final_crop());
+ layer->isOpaque = layerProto.is_opaque();
+ layer->invalidate = layerProto.invalidate();
+ layer->dataspace = layerProto.dataspace();
+ layer->pixelFormat = layerProto.pixel_format();
+ layer->color = {layerProto.color().r(), layerProto.color().g(), layerProto.color().b(),
+ layerProto.color().a()};
+ layer->requestedColor = {layerProto.requested_color().r(), layerProto.requested_color().g(),
+ layerProto.requested_color().b(), layerProto.requested_color().a()};
+ layer->flags = layerProto.flags();
+ layer->transform = generateTransform(layerProto.transform());
+ layer->requestedTransform = generateTransform(layerProto.requested_transform());
+ layer->activeBuffer = generateActiveBuffer(layerProto.active_buffer());
+ layer->queuedFrames = layerProto.queued_frames();
+ layer->refreshPending = layerProto.refresh_pending();
+
+ return layer;
+}
+
+LayerProtoParser::Region LayerProtoParser::generateRegion(const RegionProto& regionProto) {
+ LayerProtoParser::Region region;
+ region.id = regionProto.id();
+ for (int i = 0; i < regionProto.rect_size(); i++) {
+ const RectProto& rectProto = regionProto.rect(i);
+ region.rects.push_back(generateRect(rectProto));
+ }
+
+ return region;
+}
+
+LayerProtoParser::Rect LayerProtoParser::generateRect(const RectProto& rectProto) {
+ LayerProtoParser::Rect rect;
+ rect.left = rectProto.left();
+ rect.top = rectProto.top();
+ rect.right = rectProto.right();
+ rect.bottom = rectProto.bottom();
+
+ return rect;
+}
+
+LayerProtoParser::Transform LayerProtoParser::generateTransform(
+ const TransformProto& transformProto) {
+ LayerProtoParser::Transform transform;
+ transform.dsdx = transformProto.dsdx();
+ transform.dtdx = transformProto.dtdx();
+ transform.dsdy = transformProto.dsdy();
+ transform.dtdy = transformProto.dtdy();
+
+ return transform;
+}
+
+LayerProtoParser::ActiveBuffer LayerProtoParser::generateActiveBuffer(
+ const ActiveBufferProto& activeBufferProto) {
+ LayerProtoParser::ActiveBuffer activeBuffer;
+ activeBuffer.width = activeBufferProto.width();
+ activeBuffer.height = activeBufferProto.height();
+ activeBuffer.stride = activeBufferProto.stride();
+ activeBuffer.format = activeBufferProto.format();
+
+ return activeBuffer;
+}
+
+void LayerProtoParser::updateChildrenAndRelative(const LayerProto& layerProto,
+ std::unordered_map<int32_t, Layer*>& layerMap) {
+ auto currLayer = layerMap[layerProto.id()];
+
+ for (int i = 0; i < layerProto.children_size(); i++) {
+ if (layerMap.count(layerProto.children(i)) > 0) {
+ auto childLayer = layerMap[layerProto.children(i)];
+ currLayer->children.push_back(childLayer);
+ }
+ }
+
+ for (int i = 0; i < layerProto.relatives_size(); i++) {
+ if (layerMap.count(layerProto.relatives(i)) > 0) {
+ auto relativeLayer = layerMap[layerProto.relatives(i)];
+ currLayer->relatives.push_back(relativeLayer);
+ }
+ }
+
+ if (layerProto.has_parent()) {
+ if (layerMap.count(layerProto.parent()) > 0) {
+ auto parentLayer = layerMap[layerProto.parent()];
+ currLayer->parent = parentLayer;
+ }
+ }
+
+ if (layerProto.has_z_order_relative_of()) {
+ if (layerMap.count(layerProto.z_order_relative_of()) > 0) {
+ auto relativeLayer = layerMap[layerProto.z_order_relative_of()];
+ currLayer->zOrderRelativeOf = relativeLayer;
+ }
+ }
+}
+
+std::string LayerProtoParser::layersToString(
+ const std::vector<const LayerProtoParser::Layer*> layers) {
+ std::string result;
+ for (const LayerProtoParser::Layer* layer : layers) {
+ if (layer->zOrderRelativeOf != nullptr) {
+ continue;
+ }
+ result.append(layerToString(layer).c_str());
+ }
+
+ return result;
+}
+
+std::string LayerProtoParser::layerToString(const LayerProtoParser::Layer* layer) {
+ std::string result;
+
+ std::vector<const Layer*> traverse(layer->relatives);
+ for (const LayerProtoParser::Layer* child : layer->children) {
+ if (child->zOrderRelativeOf != nullptr) {
+ continue;
+ }
+
+ traverse.push_back(child);
+ }
+
+ std::sort(traverse.begin(), traverse.end(), sortLayers);
+
+ size_t i = 0;
+ for (; i < traverse.size(); i++) {
+ const auto& relative = traverse[i];
+ if (relative->z >= 0) {
+ break;
+ }
+ result.append(layerToString(relative).c_str());
+ }
+ result.append(layer->to_string().c_str());
+ result.append("\n");
+ for (; i < traverse.size(); i++) {
+ const auto& relative = traverse[i];
+ result.append(layerToString(relative).c_str());
+ }
+
+ return result;
+}
+
+std::string LayerProtoParser::ActiveBuffer::to_string() const {
+ return StringPrintf("[%4ux%4u:%4u,%s]", width, height, stride,
+ decodePixelFormat(format).c_str());
+}
+
+std::string LayerProtoParser::Transform::to_string() const {
+ return StringPrintf("[%.2f, %.2f][%.2f, %.2f]", static_cast<double>(dsdx),
+ static_cast<double>(dtdx), static_cast<double>(dsdy),
+ static_cast<double>(dtdy));
+}
+
+std::string LayerProtoParser::Rect::to_string() const {
+ return StringPrintf("[%3d, %3d, %3d, %3d]", left, top, right, bottom);
+}
+
+std::string LayerProtoParser::Region::to_string(const char* what) const {
+ std::string result =
+ StringPrintf(" Region %s (this=%lx count=%d)\n", what, static_cast<unsigned long>(id),
+ static_cast<int>(rects.size()));
+
+ for (auto& rect : rects) {
+ StringAppendF(&result, " %s\n", rect.to_string().c_str());
+ }
+
+ return result;
+}
+
+std::string LayerProtoParser::Layer::to_string() const {
+ std::string result;
+ StringAppendF(&result, "+ %s (%s)\n", type.c_str(), name.c_str());
+ result.append(transparentRegion.to_string("TransparentRegion").c_str());
+ result.append(visibleRegion.to_string("VisibleRegion").c_str());
+ result.append(damageRegion.to_string("SurfaceDamageRegion").c_str());
+
+ StringAppendF(&result, " layerStack=%4d, z=%9d, pos=(%g,%g), size=(%4d,%4d), ", layerStack,
+ z, static_cast<double>(position.x), static_cast<double>(position.y), size.x,
+ size.y);
+
+ StringAppendF(&result, "crop=%s, finalCrop=%s, ", crop.to_string().c_str(),
+ finalCrop.to_string().c_str());
+ StringAppendF(&result, "isOpaque=%1d, invalidate=%1d, ", isOpaque, invalidate);
+ StringAppendF(&result, "dataspace=%s, ", dataspace.c_str());
+ StringAppendF(&result, "pixelformat=%s, ", pixelFormat.c_str());
+ StringAppendF(&result, "color=(%.3f,%.3f,%.3f,%.3f), flags=0x%08x, ",
+ static_cast<double>(color.r), static_cast<double>(color.g),
+ static_cast<double>(color.b), static_cast<double>(color.a), flags);
+ StringAppendF(&result, "tr=%s", transform.to_string().c_str());
+ result.append("\n");
+ StringAppendF(&result, " parent=%s\n", parent == nullptr ? "none" : parent->name.c_str());
+ StringAppendF(&result, " zOrderRelativeOf=%s\n",
+ zOrderRelativeOf == nullptr ? "none" : zOrderRelativeOf->name.c_str());
+ StringAppendF(&result, " activeBuffer=%s,", activeBuffer.to_string().c_str());
+ StringAppendF(&result, " queued-frames=%d, mRefreshPending=%d", queuedFrames, refreshPending);
+
+ return result;
+}
+
+} // namespace surfaceflinger
+} // namespace android
diff --git a/services/surfaceflinger/layerproto/include/layerproto/LayerProtoHeader.h b/services/surfaceflinger/layerproto/include/layerproto/LayerProtoHeader.h
new file mode 100644
index 0000000..f560562
--- /dev/null
+++ b/services/surfaceflinger/layerproto/include/layerproto/LayerProtoHeader.h
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Projectlayerproto/LayerProtoHeader.h
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// pragma is used here to disable the warnings emitted from the protobuf
+// headers. By adding #pragma before including layer.pb.h, it supresses
+// protobuf warnings, but allows the rest of the files to continuing using
+// the current flags.
+// This file should be included instead of directly including layer.b.h
+#pragma GCC system_header
+#include <layers.pb.h>
+#include <layerstrace.pb.h>
diff --git a/services/surfaceflinger/layerproto/include/layerproto/LayerProtoParser.h b/services/surfaceflinger/layerproto/include/layerproto/LayerProtoParser.h
new file mode 100644
index 0000000..78c6cd1
--- /dev/null
+++ b/services/surfaceflinger/layerproto/include/layerproto/LayerProtoParser.h
@@ -0,0 +1,120 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <layerproto/LayerProtoHeader.h>
+
+#include <math/vec4.h>
+
+#include <unordered_map>
+#include <vector>
+
+namespace android {
+namespace surfaceflinger {
+
+class LayerProtoParser {
+public:
+ class ActiveBuffer {
+ public:
+ uint32_t width;
+ uint32_t height;
+ uint32_t stride;
+ int32_t format;
+
+ std::string to_string() const;
+ };
+
+ class Transform {
+ public:
+ float dsdx;
+ float dtdx;
+ float dsdy;
+ float dtdy;
+
+ std::string to_string() const;
+ };
+
+ class Rect {
+ public:
+ int32_t left;
+ int32_t top;
+ int32_t right;
+ int32_t bottom;
+
+ std::string to_string() const;
+ };
+
+ class Region {
+ public:
+ uint64_t id;
+ std::vector<Rect> rects;
+
+ std::string to_string(const char* what) const;
+ };
+
+ class Layer {
+ public:
+ int32_t id;
+ std::string name;
+ std::vector<const Layer*> children;
+ std::vector<const Layer*> relatives;
+ std::string type;
+ LayerProtoParser::Region transparentRegion;
+ LayerProtoParser::Region visibleRegion;
+ LayerProtoParser::Region damageRegion;
+ uint32_t layerStack;
+ int32_t z;
+ float2 position;
+ float2 requestedPosition;
+ int2 size;
+ LayerProtoParser::Rect crop;
+ LayerProtoParser::Rect finalCrop;
+ bool isOpaque;
+ bool invalidate;
+ std::string dataspace;
+ std::string pixelFormat;
+ half4 color;
+ half4 requestedColor;
+ uint32_t flags;
+ Transform transform;
+ Transform requestedTransform;
+ Layer* parent = 0;
+ Layer* zOrderRelativeOf = 0;
+ LayerProtoParser::ActiveBuffer activeBuffer;
+ int32_t queuedFrames;
+ bool refreshPending;
+
+ std::string to_string() const;
+ };
+
+ static std::vector<const Layer*> generateLayerTree(const LayersProto& layersProto);
+ static std::string layersToString(const std::vector<const LayerProtoParser::Layer*> layers);
+
+private:
+ static std::unordered_map<int32_t, Layer*> generateMap(const LayersProto& layersProto);
+ static LayerProtoParser::Layer* generateLayer(const LayerProto& layerProto);
+ static LayerProtoParser::Region generateRegion(const RegionProto& regionProto);
+ static LayerProtoParser::Rect generateRect(const RectProto& rectProto);
+ static LayerProtoParser::Transform generateTransform(const TransformProto& transformProto);
+ static LayerProtoParser::ActiveBuffer generateActiveBuffer(
+ const ActiveBufferProto& activeBufferProto);
+ static void updateChildrenAndRelative(const LayerProto& layerProto,
+ std::unordered_map<int32_t, Layer*>& layerMap);
+
+ static std::string layerToString(const LayerProtoParser::Layer* layer);
+};
+
+} // namespace surfaceflinger
+} // namespace android
diff --git a/services/surfaceflinger/layerproto/layers.proto b/services/surfaceflinger/layerproto/layers.proto
new file mode 100644
index 0000000..d27dc9b
--- /dev/null
+++ b/services/surfaceflinger/layerproto/layers.proto
@@ -0,0 +1,110 @@
+// Definitions for SurfaceFlinger layers.
+
+syntax = "proto2";
+option optimize_for = LITE_RUNTIME;
+package android.surfaceflinger;
+
+// Contains a list of all layers.
+message LayersProto {
+ repeated LayerProto layers = 1;
+}
+
+// Information about each layer.
+message LayerProto {
+ // unique id per layer.
+ optional int32 id = 1;
+ // unique name per layer.
+ optional string name = 2;
+ // list of children this layer may have. May be empty.
+ repeated int32 children = 3;
+ // list of layers that are z order relative to this layer.
+ repeated int32 relatives = 4;
+ // The type of layer, ex Color, Layer
+ optional string type = 5;
+ optional RegionProto transparent_region = 6;
+ optional RegionProto visible_region = 7;
+ optional RegionProto damage_region = 8;
+ optional uint32 layer_stack = 9;
+ // The layer's z order. Can be z order in layer stack, relative to parent,
+ // or relative to another layer specified in zOrderRelative.
+ optional int32 z = 10;
+ // The layer's position on the display.
+ optional PositionProto position = 11;
+ // The layer's requested position.
+ optional PositionProto requested_position = 12;
+ // The layer's size.
+ optional SizeProto size = 13;
+ // The layer's crop in it's own bounds.
+ optional RectProto crop = 14;
+ // The layer's crop in it's parent's bounds.
+ optional RectProto final_crop = 15;
+ optional bool is_opaque = 16;
+ optional bool invalidate = 17;
+ optional string dataspace = 18;
+ optional string pixel_format = 19;
+ // The layer's actual color.
+ optional ColorProto color = 20;
+ // The layer's requested color.
+ optional ColorProto requested_color = 21;
+ // Can be any combination of
+ // hidden = 0x01
+ // opaque = 0x02,
+ // secure = 0x80,
+ optional uint32 flags = 22;
+ // The layer's actual transform
+ optional TransformProto transform = 23;
+ // The layer's requested transform.
+ optional TransformProto requested_transform = 24;
+ // The parent layer. This value can be null if there is no parent.
+ optional int32 parent = 25 [default = -1];
+ // The layer that this layer has a z order relative to. This value can be null.
+ optional int32 z_order_relative_of = 26 [default = -1];
+ // This value can be null if there's nothing to draw.
+ optional ActiveBufferProto active_buffer = 27;
+ // The number of frames available.
+ optional int32 queued_frames = 28;
+ optional bool refresh_pending = 29;
+}
+
+message PositionProto {
+ optional float x = 1;
+ optional float y = 2;
+}
+
+message SizeProto {
+ optional int32 w = 1;
+ optional int32 h = 2;
+}
+
+message TransformProto {
+ optional float dsdx = 1;
+ optional float dtdx = 2;
+ optional float dsdy = 3;
+ optional float dtdy = 4;
+}
+
+message RegionProto {
+ optional uint64 id = 1;
+ repeated RectProto rect = 2;
+}
+
+message RectProto {
+ optional int32 left = 1;
+ optional int32 top = 2;
+ optional int32 right = 3;
+ optional int32 bottom = 4;
+}
+
+message ActiveBufferProto {
+ optional uint32 width = 1;
+ optional uint32 height = 2;
+ optional uint32 stride = 3;
+ optional int32 format = 4;
+}
+
+message ColorProto {
+ optional float r = 1;
+ optional float g = 2;
+ optional float b = 3;
+ optional float a = 4;
+}
\ No newline at end of file
diff --git a/services/surfaceflinger/layerproto/layerstrace.proto b/services/surfaceflinger/layerproto/layerstrace.proto
new file mode 100644
index 0000000..bee17d2
--- /dev/null
+++ b/services/surfaceflinger/layerproto/layerstrace.proto
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+syntax = "proto2";
+option optimize_for = LITE_RUNTIME;
+
+import "frameworks/native/services/surfaceflinger/layerproto/layers.proto";
+
+package android.surfaceflinger;
+
+/* represents a file full of surface flinger trace entries.
+ Encoded, it should start with 0x4c 0x59 0x52 0x54 0x52 0x41 0x43 0x45 (.LYRTRACE), such
+ that they can be easily identified. */
+message LayersTraceFileProto {
+
+ /* constant; MAGIC_NUMBER = (long) MAGIC_NUMBER_H << 32 | MagicNumber.MAGIC_NUMBER_L
+ (this is needed because enums have to be 32 bits and there's no nice way to put 64bit
+ constants into .proto files. */
+ enum MagicNumber {
+ INVALID = 0;
+ MAGIC_NUMBER_L = 0x5452594c; /* LYRT (little-endian ASCII) */
+ MAGIC_NUMBER_H = 0x45434152; /* RACE (little-endian ASCII) */
+ }
+
+ optional fixed64 magic_number = 1; /* Must be the first field, set to value in MagicNumber */
+ repeated LayersTraceProto entry = 2;
+}
+
+/* one window manager trace entry. */
+message LayersTraceProto {
+ /* required: elapsed realtime in nanos since boot of when this entry was logged */
+ optional fixed64 elapsed_realtime_nanos = 1;
+
+ /* where the trace originated */
+ optional string where = 2;
+
+ optional LayersProto layers = 3;
+}
diff --git a/services/surfaceflinger/main_surfaceflinger.cpp b/services/surfaceflinger/main_surfaceflinger.cpp
index e50f3ce..2a924ae 100644
--- a/services/surfaceflinger/main_surfaceflinger.cpp
+++ b/services/surfaceflinger/main_surfaceflinger.cpp
@@ -105,7 +105,8 @@
// publish surface flinger
sp<IServiceManager> sm(defaultServiceManager());
- sm->addService(String16(SurfaceFlinger::getServiceName()), flinger, false);
+ sm->addService(String16(SurfaceFlinger::getServiceName()), flinger, false,
+ IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL);
// publish GpuService
sp<GpuService> gpuservice = new GpuService();
diff --git a/services/surfaceflinger/tests/SurfaceFlinger_test.filter b/services/surfaceflinger/tests/SurfaceFlinger_test.filter
index 6be708a..5c188dc 100644
--- a/services/surfaceflinger/tests/SurfaceFlinger_test.filter
+++ b/services/surfaceflinger/tests/SurfaceFlinger_test.filter
@@ -1,5 +1,5 @@
{
"presubmit": {
- "filter": "LayerUpdateTest.*:ChildLayerTest.*:SurfaceFlingerStress.*:CropLatchingTest.*:GeometryLatchingTest.*"
+ "filter": "LayerUpdateTest.*:ChildLayerTest.*:SurfaceFlingerStress.*:CropLatchingTest.*:GeometryLatchingTest.*:LayerColorTest.*"
}
}
\ No newline at end of file
diff --git a/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp b/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp
index 0cc763c..ed806b8 100644
--- a/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp
+++ b/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp
@@ -22,10 +22,11 @@
#include <android/native_window.h>
#include <gui/ISurfaceComposer.h>
+#include <gui/LayerState.h>
#include <gui/Surface.h>
#include <gui/SurfaceComposerClient.h>
+
#include <private/gui/ComposerService.h>
-#include <private/gui/LayerState.h>
#include <ui/DisplayInfo.h>
#include <fstream>
@@ -34,6 +35,8 @@
namespace android {
+using Transaction = SurfaceComposerClient::Transaction;
+
constexpr int32_t SCALING_UPDATE = 1;
constexpr uint32_t BUFFER_UPDATES = 18;
constexpr uint32_t LAYER_UPDATE = INT_MAX - 2;
@@ -149,11 +152,11 @@
ASSERT_TRUE(mBGSurfaceControl->isValid());
mBGLayerId = getSurfaceId("BG Interceptor Test Surface");
- SurfaceComposerClient::openGlobalTransaction();
- mComposerClient->setDisplayLayerStack(display, 0);
- ASSERT_EQ(NO_ERROR, mBGSurfaceControl->setLayer(INT_MAX-3));
- ASSERT_EQ(NO_ERROR, mBGSurfaceControl->show());
- SurfaceComposerClient::closeGlobalTransaction(true);
+ Transaction t;
+ t.setDisplayLayerStack(display, 0);
+ ASSERT_EQ(NO_ERROR, t.setLayer(mBGSurfaceControl, INT_MAX-3)
+ .show(mBGSurfaceControl)
+ .apply());
}
virtual void TearDown() {
@@ -169,13 +172,14 @@
int32_t mTargetId;
public:
- void captureTest(void (SurfaceInterceptorTest::* action)(void),
+ void captureTest(void (SurfaceInterceptorTest::* action)(Transaction&),
bool (SurfaceInterceptorTest::* verification)(Trace *));
- void captureTest(void (SurfaceInterceptorTest::* action)(void),
+ void captureTest(void (SurfaceInterceptorTest::* action)(Transaction&),
SurfaceChange::SurfaceChangeCase changeCase);
- void captureTest(void (SurfaceInterceptorTest::* action)(void),
+ void captureTest(void (SurfaceInterceptorTest::* action)(Transaction&),
Increment::IncrementCase incrementCase);
- void runInTransaction(void (SurfaceInterceptorTest::* action)(void), bool intercepted = false);
+ void runInTransaction(void (SurfaceInterceptorTest::* action)(Transaction&),
+ bool intercepted = false);
// Verification of changes to a surface
bool positionUpdateFound(const SurfaceChange& change, bool foundPosition);
@@ -206,28 +210,29 @@
bool bufferUpdatesFound(Trace* trace);
// Perform each of the possible changes to a surface
- void positionUpdate();
- void sizeUpdate();
- void alphaUpdate();
- void layerUpdate();
- void cropUpdate();
- void finalCropUpdate();
- void matrixUpdate();
- void overrideScalingModeUpdate();
- void transparentRegionHintUpdate();
- void layerStackUpdate();
- void hiddenFlagUpdate();
- void opaqueFlagUpdate();
- void secureFlagUpdate();
- void deferredTransactionUpdate();
- void runAllUpdates();
- void surfaceCreation();
+ void positionUpdate(Transaction&);
+ void sizeUpdate(Transaction&);
+ void alphaUpdate(Transaction&);
+ void layerUpdate(Transaction&);
+ void cropUpdate(Transaction&);
+ void finalCropUpdate(Transaction&);
+ void matrixUpdate(Transaction&);
+ void overrideScalingModeUpdate(Transaction&);
+ void transparentRegionHintUpdate(Transaction&);
+ void layerStackUpdate(Transaction&);
+ void hiddenFlagUpdate(Transaction&);
+ void opaqueFlagUpdate(Transaction&);
+ void secureFlagUpdate(Transaction&);
+ void deferredTransactionUpdate(Transaction&);
+ void surfaceCreation(Transaction&);
+ void displayCreation(Transaction&);
+ void displayDeletion(Transaction&);
+
void nBufferUpdates();
- void displayCreation();
- void displayDeletion();
+ void runAllUpdates();
};
-void SurfaceInterceptorTest::captureTest(void (SurfaceInterceptorTest::* action)(void),
+void SurfaceInterceptorTest::captureTest(void (SurfaceInterceptorTest::* action)(Transaction&),
bool (SurfaceInterceptorTest::* verification)(Trace *))
{
runInTransaction(action, true);
@@ -236,7 +241,7 @@
ASSERT_TRUE((this->*verification)(&capturedTrace));
}
-void SurfaceInterceptorTest::captureTest(void (SurfaceInterceptorTest::* action)(void),
+void SurfaceInterceptorTest::captureTest(void (SurfaceInterceptorTest::* action)(Transaction&),
Increment::IncrementCase incrementCase)
{
runInTransaction(action, true);
@@ -245,7 +250,7 @@
ASSERT_TRUE(singleIncrementFound(&capturedTrace, incrementCase));
}
-void SurfaceInterceptorTest::captureTest(void (SurfaceInterceptorTest::* action)(void),
+void SurfaceInterceptorTest::captureTest(void (SurfaceInterceptorTest::* action)(Transaction&),
SurfaceChange::SurfaceChangeCase changeCase)
{
runInTransaction(action, true);
@@ -254,83 +259,84 @@
ASSERT_TRUE(surfaceUpdateFound(&capturedTrace, changeCase));
}
-void SurfaceInterceptorTest::runInTransaction(void (SurfaceInterceptorTest::* action)(void),
+void SurfaceInterceptorTest::runInTransaction(void (SurfaceInterceptorTest::* action)(Transaction&),
bool intercepted)
{
if (intercepted) {
enableInterceptor();
}
- SurfaceComposerClient::openGlobalTransaction();
- (this->*action)();
- SurfaceComposerClient::closeGlobalTransaction(true);
+ Transaction t;
+ (this->*action)(t);
+ t.apply(true);
+
if (intercepted) {
disableInterceptor();
}
}
-void SurfaceInterceptorTest::positionUpdate() {
- mBGSurfaceControl->setPosition(POSITION_UPDATE, POSITION_UPDATE);
+void SurfaceInterceptorTest::positionUpdate(Transaction& t) {
+ t.setPosition(mBGSurfaceControl, POSITION_UPDATE, POSITION_UPDATE);
}
-void SurfaceInterceptorTest::sizeUpdate() {
- mBGSurfaceControl->setSize(SIZE_UPDATE, SIZE_UPDATE);
+void SurfaceInterceptorTest::sizeUpdate(Transaction& t) {
+ t.setSize(mBGSurfaceControl, SIZE_UPDATE, SIZE_UPDATE);
}
-void SurfaceInterceptorTest::alphaUpdate() {
- mBGSurfaceControl->setAlpha(ALPHA_UPDATE);
+void SurfaceInterceptorTest::alphaUpdate(Transaction& t) {
+ t.setAlpha(mBGSurfaceControl, ALPHA_UPDATE);
}
-void SurfaceInterceptorTest::layerUpdate() {
- mBGSurfaceControl->setLayer(LAYER_UPDATE);
+void SurfaceInterceptorTest::layerUpdate(Transaction& t) {
+ t.setLayer(mBGSurfaceControl, LAYER_UPDATE);
}
-void SurfaceInterceptorTest::cropUpdate() {
- mBGSurfaceControl->setCrop(CROP_UPDATE);
+void SurfaceInterceptorTest::cropUpdate(Transaction& t) {
+ t.setCrop(mBGSurfaceControl, CROP_UPDATE);
}
-void SurfaceInterceptorTest::finalCropUpdate() {
- mBGSurfaceControl->setFinalCrop(CROP_UPDATE);
+void SurfaceInterceptorTest::finalCropUpdate(Transaction& t) {
+ t.setFinalCrop(mBGSurfaceControl, CROP_UPDATE);
}
-void SurfaceInterceptorTest::matrixUpdate() {
- mBGSurfaceControl->setMatrix(M_SQRT1_2, M_SQRT1_2, -M_SQRT1_2, M_SQRT1_2);
+void SurfaceInterceptorTest::matrixUpdate(Transaction& t) {
+ t.setMatrix(mBGSurfaceControl, M_SQRT1_2, M_SQRT1_2, -M_SQRT1_2, M_SQRT1_2);
}
-void SurfaceInterceptorTest::overrideScalingModeUpdate() {
- mBGSurfaceControl->setOverrideScalingMode(SCALING_UPDATE);
+void SurfaceInterceptorTest::overrideScalingModeUpdate(Transaction& t) {
+ t.setOverrideScalingMode(mBGSurfaceControl, SCALING_UPDATE);
}
-void SurfaceInterceptorTest::transparentRegionHintUpdate() {
+void SurfaceInterceptorTest::transparentRegionHintUpdate(Transaction& t) {
Region region(CROP_UPDATE);
- mBGSurfaceControl->setTransparentRegionHint(region);
+ t.setTransparentRegionHint(mBGSurfaceControl, region);
}
-void SurfaceInterceptorTest::layerStackUpdate() {
- mBGSurfaceControl->setLayerStack(STACK_UPDATE);
+void SurfaceInterceptorTest::layerStackUpdate(Transaction& t) {
+ t.setLayerStack(mBGSurfaceControl, STACK_UPDATE);
}
-void SurfaceInterceptorTest::hiddenFlagUpdate() {
- mBGSurfaceControl->setFlags(layer_state_t::eLayerHidden, layer_state_t::eLayerHidden);
+void SurfaceInterceptorTest::hiddenFlagUpdate(Transaction& t) {
+ t.setFlags(mBGSurfaceControl, layer_state_t::eLayerHidden, layer_state_t::eLayerHidden);
}
-void SurfaceInterceptorTest::opaqueFlagUpdate() {
- mBGSurfaceControl->setFlags(layer_state_t::eLayerOpaque, layer_state_t::eLayerOpaque);
+void SurfaceInterceptorTest::opaqueFlagUpdate(Transaction& t) {
+ t.setFlags(mBGSurfaceControl, layer_state_t::eLayerOpaque, layer_state_t::eLayerOpaque);
}
-void SurfaceInterceptorTest::secureFlagUpdate() {
- mBGSurfaceControl->setFlags(layer_state_t::eLayerSecure, layer_state_t::eLayerSecure);
+void SurfaceInterceptorTest::secureFlagUpdate(Transaction& t) {
+ t.setFlags(mBGSurfaceControl, layer_state_t::eLayerSecure, layer_state_t::eLayerSecure);
}
-void SurfaceInterceptorTest::deferredTransactionUpdate() {
- mBGSurfaceControl->deferTransactionUntil(mBGSurfaceControl->getHandle(), DEFERRED_UPDATE);
+void SurfaceInterceptorTest::deferredTransactionUpdate(Transaction& t) {
+ t.deferTransactionUntil(mBGSurfaceControl, mBGSurfaceControl->getHandle(), DEFERRED_UPDATE);
}
-void SurfaceInterceptorTest::displayCreation() {
+void SurfaceInterceptorTest::displayCreation(Transaction&) {
sp<IBinder> testDisplay = SurfaceComposerClient::createDisplay(DISPLAY_NAME, true);
SurfaceComposerClient::destroyDisplay(testDisplay);
}
-void SurfaceInterceptorTest::displayDeletion() {
+void SurfaceInterceptorTest::displayDeletion(Transaction&) {
sp<IBinder> testDisplay = SurfaceComposerClient::createDisplay(DISPLAY_NAME, false);
mTargetId = getDisplayId(DISPLAY_NAME.string());
SurfaceComposerClient::destroyDisplay(testDisplay);
@@ -353,7 +359,7 @@
runInTransaction(&SurfaceInterceptorTest::deferredTransactionUpdate);
}
-void SurfaceInterceptorTest::surfaceCreation() {
+void SurfaceInterceptorTest::surfaceCreation(Transaction&) {
mComposerClient->createSurface(String8(LAYER_NAME), SIZE_UPDATE, SIZE_UPDATE,
PIXEL_FORMAT_RGBA_8888, 0);
}
@@ -825,8 +831,10 @@
}
TEST_F(SurfaceInterceptorTest, InterceptBufferUpdateWorks) {
- captureTest(&SurfaceInterceptorTest::nBufferUpdates,
- &SurfaceInterceptorTest::bufferUpdatesFound);
+ nBufferUpdates();
+ Trace capturedTrace;
+ ASSERT_EQ(NO_ERROR, readProtoFile(&capturedTrace));
+ ASSERT_TRUE(bufferUpdatesFound(&capturedTrace));
}
// If the interceptor is enabled while buffer updates are being pushed, the interceptor should
diff --git a/services/surfaceflinger/tests/Transaction_test.cpp b/services/surfaceflinger/tests/Transaction_test.cpp
index 4ce14f8..16a16a5 100644
--- a/services/surfaceflinger/tests/Transaction_test.cpp
+++ b/services/surfaceflinger/tests/Transaction_test.cpp
@@ -19,18 +19,24 @@
#include <android/native_window.h>
#include <gui/ISurfaceComposer.h>
+#include <gui/LayerState.h>
+
#include <gui/Surface.h>
#include <gui/SurfaceComposerClient.h>
#include <private/gui/ComposerService.h>
-#include <private/gui/LayerState.h>
#include <utils/String8.h>
#include <ui/DisplayInfo.h>
#include <math.h>
+#include <math/vec3.h>
+
+#include <functional>
namespace android {
+using Transaction = SurfaceComposerClient::Transaction;
+
// Fill an RGBA_8888 formatted surface with a single color.
static void fillSurfaceRGBA8(const sp<SurfaceControl>& sc,
uint8_t r, uint8_t g, uint8_t b, bool unlock=true) {
@@ -65,8 +71,8 @@
sp<ISurfaceComposer> sf(ComposerService::getComposerService());
sp<IBinder> display(sf->getBuiltInDisplay(
ISurfaceComposer::eDisplayIdMain));
- SurfaceComposerClient::openGlobalTransaction();
- SurfaceComposerClient::closeGlobalTransaction(true);
+ SurfaceComposerClient::Transaction().apply(true);
+
ASSERT_EQ(NO_ERROR, sf->captureScreen(display, producer, Rect(), 0, 0,
0, INT_MAX, false));
*sc = new ScreenCapture(cpuConsumer);
@@ -110,6 +116,60 @@
CpuConsumer::LockedBuffer mBuf;
};
+class CaptureLayer {
+public:
+ static void captureScreen(std::unique_ptr<CaptureLayer>* sc, sp<IBinder>& parentHandle) {
+ sp<IGraphicBufferProducer> producer;
+ sp<IGraphicBufferConsumer> consumer;
+ BufferQueue::createBufferQueue(&producer, &consumer);
+ sp<CpuConsumer> cpuConsumer = new CpuConsumer(consumer, 1);
+ sp<ISurfaceComposer> sf(ComposerService::getComposerService());
+ sp<IBinder> display(sf->getBuiltInDisplay(
+ ISurfaceComposer::eDisplayIdMain));
+ SurfaceComposerClient::Transaction().apply(true);
+ ASSERT_EQ(NO_ERROR, sf->captureLayers(parentHandle, producer));
+ *sc = std::make_unique<CaptureLayer>(cpuConsumer);
+ }
+
+ void checkPixel(uint32_t x, uint32_t y, uint8_t r, uint8_t g, uint8_t b) {
+ ASSERT_EQ(HAL_PIXEL_FORMAT_RGBA_8888, mBuffer.format);
+ const uint8_t* img = static_cast<const uint8_t*>(mBuffer.data);
+ const uint8_t* pixel = img + (4 * (y * mBuffer.stride + x));
+ if (r != pixel[0] || g != pixel[1] || b != pixel[2]) {
+ String8 err(String8::format("pixel @ (%3d, %3d): "
+ "expected [%3d, %3d, %3d], got [%3d, %3d, %3d]",
+ x, y, r, g, b, pixel[0], pixel[1], pixel[2]));
+ EXPECT_EQ(String8(), err) << err.string();
+ }
+ }
+
+ void expectFGColor(uint32_t x, uint32_t y) {
+ checkPixel(x, y, 195, 63, 63);
+ }
+
+ void expectBGColor(uint32_t x, uint32_t y) {
+ checkPixel(x, y, 63, 63, 195);
+ }
+
+ void expectChildColor(uint32_t x, uint32_t y) {
+ checkPixel(x, y, 200, 200, 200);
+ }
+
+ CaptureLayer(const sp<CpuConsumer>& cc) :
+ mCC(cc) {
+ EXPECT_EQ(NO_ERROR, mCC->lockNextBuffer(&mBuffer));
+ }
+
+ ~CaptureLayer() {
+ mCC->unlockBuffer(mBuffer);
+ }
+
+private:
+ sp<CpuConsumer> mCC;
+ CpuConsumer::LockedBuffer mBuffer;
+};
+
+
class LayerUpdateTest : public ::testing::Test {
protected:
virtual void SetUp() {
@@ -148,23 +208,21 @@
fillSurfaceRGBA8(mSyncSurfaceControl, 31, 31, 31);
- SurfaceComposerClient::openGlobalTransaction();
+ asTransaction([&](Transaction& t) {
+ t.setDisplayLayerStack(display, 0);
- mComposerClient->setDisplayLayerStack(display, 0);
+ t.setLayer(mBGSurfaceControl, INT32_MAX-2)
+ .show(mBGSurfaceControl);
- ASSERT_EQ(NO_ERROR, mBGSurfaceControl->setLayer(INT32_MAX-2));
- ASSERT_EQ(NO_ERROR, mBGSurfaceControl->show());
+ t.setLayer(mFGSurfaceControl, INT32_MAX-1)
+ .setPosition(mFGSurfaceControl, 64, 64)
+ .show(mFGSurfaceControl);
- ASSERT_EQ(NO_ERROR, mFGSurfaceControl->setLayer(INT32_MAX-1));
- ASSERT_EQ(NO_ERROR, mFGSurfaceControl->setPosition(64, 64));
- ASSERT_EQ(NO_ERROR, mFGSurfaceControl->show());
-
- ASSERT_EQ(NO_ERROR, mSyncSurfaceControl->setLayer(INT32_MAX-1));
- ASSERT_EQ(NO_ERROR, mSyncSurfaceControl->setPosition(displayWidth-2,
- displayHeight-2));
- ASSERT_EQ(NO_ERROR, mSyncSurfaceControl->show());
-
- SurfaceComposerClient::closeGlobalTransaction(true);
+ t.setLayer(mSyncSurfaceControl, INT32_MAX-1)
+ .setPosition(mSyncSurfaceControl, displayWidth-2,
+ displayHeight-2)
+ .show(mSyncSurfaceControl);
+ });
}
virtual void TearDown() {
@@ -185,6 +243,12 @@
fillSurfaceRGBA8(mSyncSurfaceControl, 31, 31, 31);
}
+ void asTransaction(const std::function<void(Transaction&)>& exec) {
+ Transaction t;
+ exec(t);
+ t.apply(true);
+ }
+
sp<SurfaceComposerClient> mComposerClient;
sp<SurfaceControl> mBGSurfaceControl;
sp<SurfaceControl> mFGSurfaceControl;
@@ -204,9 +268,10 @@
sc->expectBGColor(145, 145);
}
- SurfaceComposerClient::openGlobalTransaction();
- ASSERT_EQ(NO_ERROR, mFGSurfaceControl->setPosition(128, 128));
- SurfaceComposerClient::closeGlobalTransaction(true);
+ asTransaction([&](Transaction& t) {
+ t.setPosition(mFGSurfaceControl, 128, 128);
+ });
+
{
// This should reflect the new position, but not the new color.
SCOPED_TRACE("after move, before redraw");
@@ -239,9 +304,9 @@
}
ALOGD("resizing");
- SurfaceComposerClient::openGlobalTransaction();
- ASSERT_EQ(NO_ERROR, mFGSurfaceControl->setSize(128, 128));
- SurfaceComposerClient::closeGlobalTransaction(true);
+ asTransaction([&](Transaction& t) {
+ t.setSize(mFGSurfaceControl, 128, 128);
+ });
ALOGD("resized");
{
// This should not reflect the new size or color because SurfaceFlinger
@@ -277,10 +342,10 @@
sc->expectBGColor(145, 145);
}
- SurfaceComposerClient::openGlobalTransaction();
- Rect cropRect(16, 16, 32, 32);
- ASSERT_EQ(NO_ERROR, mFGSurfaceControl->setCrop(cropRect));
- SurfaceComposerClient::closeGlobalTransaction(true);
+ asTransaction([&](Transaction& t) {
+ Rect cropRect(16, 16, 32, 32);
+ t.setCrop(mFGSurfaceControl, cropRect);
+ });
{
// This should crop the foreground surface.
SCOPED_TRACE("after crop");
@@ -302,10 +367,10 @@
sc->expectFGColor(75, 75);
sc->expectBGColor(145, 145);
}
- SurfaceComposerClient::openGlobalTransaction();
- Rect cropRect(16, 16, 32, 32);
- ASSERT_EQ(NO_ERROR, mFGSurfaceControl->setFinalCrop(cropRect));
- SurfaceComposerClient::closeGlobalTransaction(true);
+ asTransaction([&](Transaction& t) {
+ Rect cropRect(16, 16, 32, 32);
+ t.setFinalCrop(mFGSurfaceControl, cropRect);
+ });
{
// This should crop the foreground surface.
SCOPED_TRACE("after crop");
@@ -328,9 +393,10 @@
sc->expectBGColor(145, 145);
}
- SurfaceComposerClient::openGlobalTransaction();
- ASSERT_EQ(NO_ERROR, mFGSurfaceControl->setLayer(INT_MAX - 3));
- SurfaceComposerClient::closeGlobalTransaction(true);
+ asTransaction([&](Transaction& t) {
+ t.setLayer(mFGSurfaceControl, INT_MAX - 3);
+ });
+
{
// This should hide the foreground surface beneath the background.
SCOPED_TRACE("after setLayer");
@@ -351,9 +417,10 @@
sc->expectBGColor(145, 145);
}
- SurfaceComposerClient::openGlobalTransaction();
- ASSERT_EQ(NO_ERROR, mFGSurfaceControl->hide());
- SurfaceComposerClient::closeGlobalTransaction(true);
+ asTransaction([&](Transaction& t) {
+ t.hide(mFGSurfaceControl);
+ });
+
{
// This should hide the foreground surface.
SCOPED_TRACE("after hide, before show");
@@ -363,9 +430,10 @@
sc->expectBGColor(145, 145);
}
- SurfaceComposerClient::openGlobalTransaction();
- ASSERT_EQ(NO_ERROR, mFGSurfaceControl->show());
- SurfaceComposerClient::closeGlobalTransaction(true);
+ asTransaction([&](Transaction& t) {
+ t.show(mFGSurfaceControl);
+ });
+
{
// This should show the foreground surface.
SCOPED_TRACE("after show");
@@ -386,9 +454,10 @@
sc->expectBGColor(145, 145);
}
- SurfaceComposerClient::openGlobalTransaction();
- ASSERT_EQ(NO_ERROR, mFGSurfaceControl->setAlpha(0.75f));
- SurfaceComposerClient::closeGlobalTransaction(true);
+ asTransaction([&](Transaction& t) {
+ t.setAlpha(mFGSurfaceControl, 0.75f);
+ });
+
{
// This should set foreground to be 75% opaque.
SCOPED_TRACE("after setAlpha");
@@ -409,9 +478,9 @@
sc->expectBGColor(145, 145);
}
- SurfaceComposerClient::openGlobalTransaction();
- ASSERT_EQ(NO_ERROR, mFGSurfaceControl->setLayerStack(1));
- SurfaceComposerClient::closeGlobalTransaction(true);
+ asTransaction([&](Transaction& t) {
+ t.setLayerStack(mFGSurfaceControl, 1);
+ });
{
// This should hide the foreground surface since it goes to a different
// layer stack.
@@ -433,10 +502,10 @@
sc->expectBGColor(145, 145);
}
- SurfaceComposerClient::openGlobalTransaction();
- ASSERT_EQ(NO_ERROR, mFGSurfaceControl->setFlags(
- layer_state_t::eLayerHidden, layer_state_t::eLayerHidden));
- SurfaceComposerClient::closeGlobalTransaction(true);
+ asTransaction([&](Transaction& t) {
+ t.setFlags(mFGSurfaceControl,
+ layer_state_t::eLayerHidden, layer_state_t::eLayerHidden);
+ });
{
// This should hide the foreground surface
SCOPED_TRACE("after setFlags");
@@ -458,10 +527,11 @@
sc->expectBGColor(145, 145);
}
- SurfaceComposerClient::openGlobalTransaction();
- ASSERT_EQ(NO_ERROR, mFGSurfaceControl->setMatrix(M_SQRT1_2, M_SQRT1_2,
- -M_SQRT1_2, M_SQRT1_2));
- SurfaceComposerClient::closeGlobalTransaction(true);
+ asTransaction([&](Transaction& t) {
+ t.setMatrix(mFGSurfaceControl,
+ M_SQRT1_2, M_SQRT1_2,
+ -M_SQRT1_2, M_SQRT1_2);
+ });
{
SCOPED_TRACE("after setMatrix");
ScreenCapture::captureScreen(&sc);
@@ -497,12 +567,12 @@
waitForPostedBuffers();
}
void restoreInitialState() {
- SurfaceComposerClient::openGlobalTransaction();
- mFGSurfaceControl->setSize(64, 64);
- mFGSurfaceControl->setPosition(64, 64);
- mFGSurfaceControl->setCrop(Rect(0, 0, 64, 64));
- mFGSurfaceControl->setFinalCrop(Rect(0, 0, -1, -1));
- SurfaceComposerClient::closeGlobalTransaction(true);
+ asTransaction([&](Transaction& t) {
+ t.setSize(mFGSurfaceControl, 64, 64);
+ t.setPosition(mFGSurfaceControl, 64, 64);
+ t.setCrop(mFGSurfaceControl, Rect(0, 0, 64, 64));
+ t.setFinalCrop(mFGSurfaceControl, Rect(0, 0, -1, -1));
+ });
EXPECT_INITIAL_STATE("After restoring initial state");
}
@@ -514,10 +584,10 @@
// By default position can be updated even while
// a resize is pending.
- SurfaceComposerClient::openGlobalTransaction();
- mFGSurfaceControl->setSize(32, 32);
- mFGSurfaceControl->setPosition(100, 100);
- SurfaceComposerClient::closeGlobalTransaction(true);
+ asTransaction([&](Transaction& t) {
+ t.setSize(mFGSurfaceControl, 32, 32);
+ t.setPosition(mFGSurfaceControl, 100, 100);
+ });
{
SCOPED_TRACE("After moving surface");
@@ -531,11 +601,11 @@
// Now we repeat with setGeometryAppliesWithResize
// and verify the position DOESN'T latch.
- SurfaceComposerClient::openGlobalTransaction();
- mFGSurfaceControl->setGeometryAppliesWithResize();
- mFGSurfaceControl->setSize(32, 32);
- mFGSurfaceControl->setPosition(100, 100);
- SurfaceComposerClient::closeGlobalTransaction(true);
+ asTransaction([&](Transaction& t) {
+ t.setGeometryAppliesWithResize(mFGSurfaceControl);
+ t.setSize(mFGSurfaceControl, 32, 32);
+ t.setPosition(mFGSurfaceControl, 100, 100);
+ });
{
SCOPED_TRACE("While resize is pending");
@@ -580,20 +650,20 @@
TEST_F(CropLatchingTest, CropLatching) {
EXPECT_INITIAL_STATE("before anything");
// Normally the crop applies immediately even while a resize is pending.
- SurfaceComposerClient::openGlobalTransaction();
- mFGSurfaceControl->setSize(128, 128);
- mFGSurfaceControl->setCrop(Rect(0, 0, 63, 63));
- SurfaceComposerClient::closeGlobalTransaction(true);
+ asTransaction([&](Transaction& t) {
+ t.setSize(mFGSurfaceControl, 128, 128);
+ t.setCrop(mFGSurfaceControl, Rect(0, 0, 63, 63));
+ });
EXPECT_CROPPED_STATE("after setting crop (without geometryAppliesWithResize)");
restoreInitialState();
- SurfaceComposerClient::openGlobalTransaction();
- mFGSurfaceControl->setSize(128, 128);
- mFGSurfaceControl->setGeometryAppliesWithResize();
- mFGSurfaceControl->setCrop(Rect(0, 0, 63, 63));
- SurfaceComposerClient::closeGlobalTransaction(true);
+ asTransaction([&](Transaction& t) {
+ t.setSize(mFGSurfaceControl, 128, 128);
+ t.setGeometryAppliesWithResize(mFGSurfaceControl);
+ t.setCrop(mFGSurfaceControl, Rect(0, 0, 63, 63));
+ });
EXPECT_INITIAL_STATE("after setting crop (with geometryAppliesWithResize)");
@@ -605,20 +675,20 @@
TEST_F(CropLatchingTest, FinalCropLatching) {
EXPECT_INITIAL_STATE("before anything");
// Normally the crop applies immediately even while a resize is pending.
- SurfaceComposerClient::openGlobalTransaction();
- mFGSurfaceControl->setSize(128, 128);
- mFGSurfaceControl->setFinalCrop(Rect(64, 64, 127, 127));
- SurfaceComposerClient::closeGlobalTransaction(true);
+ asTransaction([&](Transaction& t) {
+ t.setSize(mFGSurfaceControl, 128, 128);
+ t.setFinalCrop(mFGSurfaceControl, Rect(64, 64, 127, 127));
+ });
EXPECT_CROPPED_STATE("after setting crop (without geometryAppliesWithResize)");
restoreInitialState();
- SurfaceComposerClient::openGlobalTransaction();
- mFGSurfaceControl->setSize(128, 128);
- mFGSurfaceControl->setGeometryAppliesWithResize();
- mFGSurfaceControl->setFinalCrop(Rect(64, 64, 127, 127));
- SurfaceComposerClient::closeGlobalTransaction(true);
+ asTransaction([&](Transaction& t) {
+ t.setSize(mFGSurfaceControl, 128, 128);
+ t.setGeometryAppliesWithResize(mFGSurfaceControl);
+ t.setFinalCrop(mFGSurfaceControl, Rect(64, 64, 127, 127));
+ });
EXPECT_INITIAL_STATE("after setting crop (with geometryAppliesWithResize)");
@@ -632,10 +702,10 @@
TEST_F(CropLatchingTest, FinalCropLatchingBufferOldSize) {
EXPECT_INITIAL_STATE("before anything");
// Normally the crop applies immediately even while a resize is pending.
- SurfaceComposerClient::openGlobalTransaction();
- mFGSurfaceControl->setSize(128, 128);
- mFGSurfaceControl->setFinalCrop(Rect(64, 64, 127, 127));
- SurfaceComposerClient::closeGlobalTransaction(true);
+ asTransaction([&](Transaction& t) {
+ t.setSize(mFGSurfaceControl, 128, 128);
+ t.setFinalCrop(mFGSurfaceControl, Rect(64, 64, 127, 127));
+ });
EXPECT_CROPPED_STATE("after setting crop (without geometryAppliesWithResize)");
@@ -645,11 +715,11 @@
// initiating the resize.
lockAndFillFGBuffer();
- SurfaceComposerClient::openGlobalTransaction();
- mFGSurfaceControl->setSize(128, 128);
- mFGSurfaceControl->setGeometryAppliesWithResize();
- mFGSurfaceControl->setFinalCrop(Rect(64, 64, 127, 127));
- SurfaceComposerClient::closeGlobalTransaction(true);
+ asTransaction([&](Transaction& t) {
+ t.setSize(mFGSurfaceControl, 128, 128);
+ t.setGeometryAppliesWithResize(mFGSurfaceControl);
+ t.setFinalCrop(mFGSurfaceControl, Rect(64, 64, 127, 127));
+ });
EXPECT_INITIAL_STATE("after setting crop (with geometryAppliesWithResize)");
@@ -669,17 +739,17 @@
// In this scenario, we attempt to set the final crop a second time while the resize
// is still pending, and ensure we are successful. Success meaning the second crop
// is the one which eventually latches and not the first.
- SurfaceComposerClient::openGlobalTransaction();
- mFGSurfaceControl->setSize(128, 128);
- mFGSurfaceControl->setGeometryAppliesWithResize();
- mFGSurfaceControl->setFinalCrop(Rect(64, 64, 127, 127));
- SurfaceComposerClient::closeGlobalTransaction(true);
+ asTransaction([&](Transaction& t) {
+ t.setSize(mFGSurfaceControl, 128, 128);
+ t.setGeometryAppliesWithResize(mFGSurfaceControl);
+ t.setFinalCrop(mFGSurfaceControl, Rect(64, 64, 127, 127));
+ });
EXPECT_INITIAL_STATE("after setting crops with geometryAppliesWithResize");
- SurfaceComposerClient::openGlobalTransaction();
- mFGSurfaceControl->setFinalCrop(Rect(0, 0, -1, -1));
- SurfaceComposerClient::closeGlobalTransaction(true);
+ asTransaction([&](Transaction& t) {
+ t.setFinalCrop(mFGSurfaceControl, Rect(0, 0, -1, -1));
+ });
EXPECT_INITIAL_STATE("after setting another crop");
@@ -699,17 +769,17 @@
}
// set up two deferred transactions on different frames
- SurfaceComposerClient::openGlobalTransaction();
- ASSERT_EQ(NO_ERROR, mFGSurfaceControl->setAlpha(0.75));
- mFGSurfaceControl->deferTransactionUntil(mSyncSurfaceControl->getHandle(),
- mSyncSurfaceControl->getSurface()->getNextFrameNumber());
- SurfaceComposerClient::closeGlobalTransaction(true);
+ asTransaction([&](Transaction& t) {
+ t.setAlpha(mFGSurfaceControl, 0.75);
+ t.deferTransactionUntil(mFGSurfaceControl, mSyncSurfaceControl->getHandle(),
+ mSyncSurfaceControl->getSurface()->getNextFrameNumber());
+ });
- SurfaceComposerClient::openGlobalTransaction();
- ASSERT_EQ(NO_ERROR, mFGSurfaceControl->setPosition(128,128));
- mFGSurfaceControl->deferTransactionUntil(mSyncSurfaceControl->getHandle(),
- mSyncSurfaceControl->getSurface()->getNextFrameNumber() + 1);
- SurfaceComposerClient::closeGlobalTransaction(true);
+ asTransaction([&](Transaction& t) {
+ t.setPosition(mFGSurfaceControl, 128,128);
+ t.deferTransactionUntil(mFGSurfaceControl, mSyncSurfaceControl->getHandle(),
+ mSyncSurfaceControl->getSurface()->getNextFrameNumber() + 1);
+ });
{
SCOPED_TRACE("before any trigger");
@@ -730,9 +800,9 @@
}
// should show up immediately since it's not deferred
- SurfaceComposerClient::openGlobalTransaction();
- ASSERT_EQ(NO_ERROR, mFGSurfaceControl->setAlpha(1.0));
- SurfaceComposerClient::closeGlobalTransaction(true);
+ asTransaction([&](Transaction& t) {
+ t.setAlpha(mFGSurfaceControl, 1.0);
+ });
// trigger the second deferred transaction
fillSurfaceRGBA8(mSyncSurfaceControl, 31, 31, 31);
@@ -761,12 +831,11 @@
waitForPostedBuffers();
// Now we stack the surface above the foreground surface and make sure it is visible.
- SurfaceComposerClient::openGlobalTransaction();
- relativeSurfaceControl->setPosition(64, 64);
- relativeSurfaceControl->show();
- relativeSurfaceControl->setRelativeLayer(mFGSurfaceControl->getHandle(), 1);
- SurfaceComposerClient::closeGlobalTransaction(true);
-
+ asTransaction([&](Transaction& t) {
+ t.setPosition(relativeSurfaceControl, 64, 64);
+ t.show(relativeSurfaceControl);
+ t.setRelativeLayer(relativeSurfaceControl, mFGSurfaceControl->getHandle(), 1);
+ });
{
SCOPED_TRACE("after adding relative surface");
@@ -776,9 +845,9 @@
}
// A call to setLayer will override a call to setRelativeLayer
- SurfaceComposerClient::openGlobalTransaction();
- relativeSurfaceControl->setLayer(0);
- SurfaceComposerClient::closeGlobalTransaction();
+ asTransaction([&](Transaction& t) {
+ t.setLayer(relativeSurfaceControl, 0);
+ });
{
SCOPED_TRACE("after set layer");
@@ -788,6 +857,64 @@
}
}
+TEST_F(LayerUpdateTest, LayerWithNoBuffersResizesImmediately) {
+ sp<ScreenCapture> sc;
+
+ sp<SurfaceControl> childNoBuffer =
+ mComposerClient->createSurface(String8("Bufferless child"),
+ 10, 10, PIXEL_FORMAT_RGBA_8888,
+ 0, mFGSurfaceControl.get());
+ sp<SurfaceControl> childBuffer = mComposerClient->createSurface(
+ String8("Buffered child"), 20, 20,
+ PIXEL_FORMAT_RGBA_8888, 0, childNoBuffer.get());
+ fillSurfaceRGBA8(childBuffer, 200, 200, 200);
+
+ SurfaceComposerClient::Transaction{}
+ .show(childNoBuffer)
+ .show(childBuffer)
+ .apply(true);
+
+ {
+ ScreenCapture::captureScreen(&sc);
+ sc->expectChildColor(73, 73);
+ sc->expectFGColor(74, 74);
+ }
+
+ SurfaceComposerClient::Transaction{}
+ .setSize(childNoBuffer, 20, 20)
+ .apply(true);
+
+ {
+ ScreenCapture::captureScreen(&sc);
+ sc->expectChildColor(73, 73);
+ sc->expectChildColor(74, 74);
+ }
+}
+
+TEST_F(LayerUpdateTest, MergingTransactions) {
+ sp<ScreenCapture> sc;
+ {
+ SCOPED_TRACE("before move");
+ ScreenCapture::captureScreen(&sc);
+ sc->expectBGColor(0, 12);
+ sc->expectFGColor(75, 75);
+ sc->expectBGColor(145, 145);
+ }
+
+ Transaction t1, t2;
+ t1.setPosition(mFGSurfaceControl, 128, 128);
+ t2.setPosition(mFGSurfaceControl, 0, 0);
+ // We expect that the position update from t2 now
+ // overwrites the position update from t1.
+ t1.merge(std::move(t2));
+ t1.apply();
+
+ {
+ ScreenCapture::captureScreen(&sc);
+ sc->expectFGColor(1, 1);
+ }
+}
+
class ChildLayerTest : public LayerUpdateTest {
protected:
void SetUp() override {
@@ -814,11 +941,11 @@
};
TEST_F(ChildLayerTest, ChildLayerPositioning) {
- SurfaceComposerClient::openGlobalTransaction();
- mChild->show();
- mChild->setPosition(10, 10);
- mFGSurfaceControl->setPosition(64, 64);
- SurfaceComposerClient::closeGlobalTransaction(true);
+ asTransaction([&](Transaction& t) {
+ t.show(mChild);
+ t.setPosition(mChild, 10, 10);
+ t.setPosition(mFGSurfaceControl, 64, 64);
+ });
{
ScreenCapture::captureScreen(&mCapture);
@@ -830,9 +957,9 @@
mCapture->expectFGColor(84, 84);
}
- SurfaceComposerClient::openGlobalTransaction();
- ASSERT_EQ(NO_ERROR, mFGSurfaceControl->setPosition(0, 0));
- SurfaceComposerClient::closeGlobalTransaction(true);
+ asTransaction([&](Transaction& t) {
+ t.setPosition(mFGSurfaceControl, 0, 0);
+ });
{
ScreenCapture::captureScreen(&mCapture);
@@ -846,12 +973,12 @@
}
TEST_F(ChildLayerTest, ChildLayerCropping) {
- SurfaceComposerClient::openGlobalTransaction();
- mChild->show();
- mChild->setPosition(0, 0);
- mFGSurfaceControl->setPosition(0, 0);
- mFGSurfaceControl->setCrop(Rect(0, 0, 5, 5));
- SurfaceComposerClient::closeGlobalTransaction(true);
+ asTransaction([&](Transaction& t) {
+ t.show(mChild);
+ t.setPosition(mChild, 0, 0);
+ t.setPosition(mFGSurfaceControl, 0, 0);
+ t.setCrop(mFGSurfaceControl, Rect(0, 0, 5, 5));
+ });
{
ScreenCapture::captureScreen(&mCapture);
@@ -862,12 +989,12 @@
}
TEST_F(ChildLayerTest, ChildLayerFinalCropping) {
- SurfaceComposerClient::openGlobalTransaction();
- mChild->show();
- mChild->setPosition(0, 0);
- mFGSurfaceControl->setPosition(0, 0);
- mFGSurfaceControl->setFinalCrop(Rect(0, 0, 5, 5));
- SurfaceComposerClient::closeGlobalTransaction(true);
+ asTransaction([&](Transaction& t) {
+ t.show(mChild);
+ t.setPosition(mChild, 0, 0);
+ t.setPosition(mFGSurfaceControl, 0, 0);
+ t.setFinalCrop(mFGSurfaceControl, Rect(0, 0, 5, 5));
+ });
{
ScreenCapture::captureScreen(&mCapture);
@@ -878,11 +1005,11 @@
}
TEST_F(ChildLayerTest, ChildLayerConstraints) {
- SurfaceComposerClient::openGlobalTransaction();
- mChild->show();
- mFGSurfaceControl->setPosition(0, 0);
- mChild->setPosition(63, 63);
- SurfaceComposerClient::closeGlobalTransaction(true);
+ asTransaction([&](Transaction& t) {
+ t.show(mChild);
+ t.setPosition(mFGSurfaceControl, 0, 0);
+ t.setPosition(mChild, 63, 63);
+ });
{
ScreenCapture::captureScreen(&mCapture);
@@ -896,9 +1023,9 @@
}
TEST_F(ChildLayerTest, ChildLayerScaling) {
- SurfaceComposerClient::openGlobalTransaction();
- mFGSurfaceControl->setPosition(0, 0);
- SurfaceComposerClient::closeGlobalTransaction(true);
+ asTransaction([&](Transaction& t) {
+ t.setPosition(mFGSurfaceControl, 0, 0);
+ });
// Find the boundary between the parent and child
{
@@ -907,9 +1034,9 @@
mCapture->expectFGColor(10, 10);
}
- SurfaceComposerClient::openGlobalTransaction();
- mFGSurfaceControl->setMatrix(2.0, 0, 0, 2.0);
- SurfaceComposerClient::closeGlobalTransaction(true);
+ asTransaction([&](Transaction& t) {
+ t.setMatrix(mFGSurfaceControl, 2.0, 0, 0, 2.0);
+ });
// The boundary should be twice as far from the origin now.
// The pixels from the last test should all be child now
@@ -928,11 +1055,11 @@
fillSurfaceRGBA8(mChild, 0, 254, 0);
waitForPostedBuffers();
- SurfaceComposerClient::openGlobalTransaction();
- mChild->show();
- mChild->setPosition(0, 0);
- mFGSurfaceControl->setPosition(0, 0);
- SurfaceComposerClient::closeGlobalTransaction(true);
+ asTransaction([&](Transaction& t) {
+ t.show(mChild);
+ t.setPosition(mChild, 0, 0);
+ t.setPosition(mFGSurfaceControl, 0, 0);
+ });
{
ScreenCapture::captureScreen(&mCapture);
@@ -940,9 +1067,9 @@
mCapture->checkPixel(0, 0, 0, 254, 0);
}
- SurfaceComposerClient::openGlobalTransaction();
- ASSERT_EQ(NO_ERROR, mChild->setAlpha(0.5));
- SurfaceComposerClient::closeGlobalTransaction(true);
+ asTransaction([&](Transaction& t) {
+ t.setAlpha(mChild, 0.5);
+ });
{
ScreenCapture::captureScreen(&mCapture);
@@ -950,9 +1077,9 @@
mCapture->checkPixel(0, 0, 127, 127, 0);
}
- SurfaceComposerClient::openGlobalTransaction();
- ASSERT_EQ(NO_ERROR, mFGSurfaceControl->setAlpha(0.5));
- SurfaceComposerClient::closeGlobalTransaction(true);
+ asTransaction([&](Transaction& t) {
+ t.setAlpha(mFGSurfaceControl, 0.5);
+ });
{
ScreenCapture::captureScreen(&mCapture);
@@ -962,11 +1089,11 @@
}
TEST_F(ChildLayerTest, ReparentChildren) {
- SurfaceComposerClient::openGlobalTransaction();
- mChild->show();
- mChild->setPosition(10, 10);
- mFGSurfaceControl->setPosition(64, 64);
- SurfaceComposerClient::closeGlobalTransaction(true);
+ asTransaction([&](Transaction& t) {
+ t.show(mChild);
+ t.setPosition(mChild, 10, 10);
+ t.setPosition(mFGSurfaceControl, 64, 64);
+ });
{
ScreenCapture::captureScreen(&mCapture);
@@ -977,7 +1104,11 @@
// And 10 more pixels we should be back to the foreground surface
mCapture->expectFGColor(84, 84);
}
- mFGSurfaceControl->reparentChildren(mBGSurfaceControl->getHandle());
+
+ asTransaction([&](Transaction& t) {
+ t.reparentChildren(mFGSurfaceControl, mBGSurfaceControl->getHandle());
+ });
+
{
ScreenCapture::captureScreen(&mCapture);
mCapture->expectFGColor(64, 64);
@@ -990,12 +1121,12 @@
}
}
-TEST_F(ChildLayerTest, DetachChildren) {
- SurfaceComposerClient::openGlobalTransaction();
- mChild->show();
- mChild->setPosition(10, 10);
- mFGSurfaceControl->setPosition(64, 64);
- SurfaceComposerClient::closeGlobalTransaction(true);
+TEST_F(ChildLayerTest, DetachChildrenSameClient) {
+ asTransaction([&](Transaction& t) {
+ t.show(mChild);
+ t.setPosition(mChild, 10, 10);
+ t.setPosition(mFGSurfaceControl, 64, 64);
+ });
{
ScreenCapture::captureScreen(&mCapture);
@@ -1007,13 +1138,59 @@
mCapture->expectFGColor(84, 84);
}
- SurfaceComposerClient::openGlobalTransaction();
- mFGSurfaceControl->detachChildren();
- SurfaceComposerClient::closeGlobalTransaction(true);
+ asTransaction([&](Transaction& t) {
+ t.detachChildren(mFGSurfaceControl);
+ });
- SurfaceComposerClient::openGlobalTransaction();
- mChild->hide();
- SurfaceComposerClient::closeGlobalTransaction(true);
+ asTransaction([&](Transaction& t) {
+ t.hide(mChild);
+ });
+
+ // Since the child has the same client as the parent, it will not get
+ // detached and will be hidden.
+ {
+ ScreenCapture::captureScreen(&mCapture);
+ mCapture->expectFGColor(64, 64);
+ mCapture->expectFGColor(74, 74);
+ mCapture->expectFGColor(84, 84);
+ }
+}
+
+TEST_F(ChildLayerTest, DetachChildrenDifferentClient) {
+ sp<SurfaceComposerClient> mNewComposerClient = new SurfaceComposerClient;
+ sp<SurfaceControl> mChildNewClient = mNewComposerClient->createSurface(
+ String8("New Child Test Surface"), 10, 10, PIXEL_FORMAT_RGBA_8888,
+ 0, mFGSurfaceControl.get());
+
+ ASSERT_TRUE(mChildNewClient != NULL);
+ ASSERT_TRUE(mChildNewClient->isValid());
+
+ fillSurfaceRGBA8(mChildNewClient, 200, 200, 200);
+
+ asTransaction([&](Transaction& t) {
+ t.hide(mChild);
+ t.show(mChildNewClient);
+ t.setPosition(mChildNewClient, 10, 10);
+ t.setPosition(mFGSurfaceControl, 64, 64);
+ });
+
+ {
+ ScreenCapture::captureScreen(&mCapture);
+ // Top left of foreground must now be visible
+ mCapture->expectFGColor(64, 64);
+ // But 10 pixels in we should see the child surface
+ mCapture->expectChildColor(74, 74);
+ // And 10 more pixels we should be back to the foreground surface
+ mCapture->expectFGColor(84, 84);
+ }
+
+ asTransaction([&](Transaction& t) {
+ t.detachChildren(mFGSurfaceControl);
+ });
+
+ asTransaction([&](Transaction& t) {
+ t.hide(mChildNewClient);
+ });
// Nothing should have changed.
{
@@ -1025,11 +1202,11 @@
}
TEST_F(ChildLayerTest, ChildrenInheritNonTransformScalingFromParent) {
- SurfaceComposerClient::openGlobalTransaction();
- mChild->show();
- mChild->setPosition(0, 0);
- mFGSurfaceControl->setPosition(0, 0);
- SurfaceComposerClient::closeGlobalTransaction(true);
+ asTransaction([&](Transaction& t) {
+ t.show(mChild);
+ t.setPosition(mChild, 0, 0);
+ t.setPosition(mFGSurfaceControl, 0, 0);
+ });
{
ScreenCapture::captureScreen(&mCapture);
@@ -1039,11 +1216,11 @@
mCapture->expectFGColor(10, 10);
}
- SurfaceComposerClient::openGlobalTransaction();
- mFGSurfaceControl->setOverrideScalingMode(NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW);
- // We cause scaling by 2.
- mFGSurfaceControl->setSize(128, 128);
- SurfaceComposerClient::closeGlobalTransaction();
+ asTransaction([&](Transaction& t) {
+ t.setOverrideScalingMode(mFGSurfaceControl, NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW);
+ // We cause scaling by 2.
+ t.setSize(mFGSurfaceControl, 128, 128);
+ });
{
ScreenCapture::captureScreen(&mCapture);
@@ -1058,11 +1235,11 @@
// Regression test for b/37673612
TEST_F(ChildLayerTest, ChildrenWithParentBufferTransform) {
- SurfaceComposerClient::openGlobalTransaction();
- mChild->show();
- mChild->setPosition(0, 0);
- mFGSurfaceControl->setPosition(0, 0);
- SurfaceComposerClient::closeGlobalTransaction(true);
+ asTransaction([&](Transaction& t) {
+ t.show(mChild);
+ t.setPosition(mChild, 0, 0);
+ t.setPosition(mFGSurfaceControl, 0, 0);
+ });
{
ScreenCapture::captureScreen(&mCapture);
@@ -1071,11 +1248,11 @@
// But it's only 10x10.
mCapture->expectFGColor(10, 10);
}
-
-
// We set things up as in b/37673612 so that there is a mismatch between the buffer size and
// the WM specified state size.
- mFGSurfaceControl->setSize(128, 64);
+ asTransaction([&](Transaction& t) {
+ t.setSize(mFGSurfaceControl, 128, 64);
+ });
sp<Surface> s = mFGSurfaceControl->getSurface();
auto anw = static_cast<ANativeWindow*>(s.get());
native_window_set_buffers_transform(anw, NATIVE_WINDOW_TRANSFORM_ROT_90);
@@ -1102,11 +1279,11 @@
mFGSurfaceControl.get());
// Show the child layer in a deferred transaction
- SurfaceComposerClient::openGlobalTransaction();
- mChild->deferTransactionUntil(mFGSurfaceControl->getHandle(),
- mFGSurfaceControl->getSurface()->getNextFrameNumber());
- mChild->show();
- SurfaceComposerClient::closeGlobalTransaction(true);
+ asTransaction([&](Transaction& t) {
+ t.deferTransactionUntil(mChild, mFGSurfaceControl->getHandle(),
+ mFGSurfaceControl->getSurface()->getNextFrameNumber());
+ t.show(mChild);
+ });
// Render the foreground surface a few times
//
@@ -1123,4 +1300,318 @@
fillSurfaceRGBA8(mFGSurfaceControl, 0, 255, 0);
}
+TEST_F(ChildLayerTest, Reparent) {
+ asTransaction([&](Transaction& t) {
+ t.show(mChild);
+ t.setPosition(mChild, 10, 10);
+ t.setPosition(mFGSurfaceControl, 64, 64);
+ });
+
+ {
+ ScreenCapture::captureScreen(&mCapture);
+ // Top left of foreground must now be visible
+ mCapture->expectFGColor(64, 64);
+ // But 10 pixels in we should see the child surface
+ mCapture->expectChildColor(74, 74);
+ // And 10 more pixels we should be back to the foreground surface
+ mCapture->expectFGColor(84, 84);
+ }
+
+ asTransaction([&](Transaction& t) {
+ t.reparent(mChild, mBGSurfaceControl->getHandle());
+ });
+
+ {
+ ScreenCapture::captureScreen(&mCapture);
+ mCapture->expectFGColor(64, 64);
+ // In reparenting we should have exposed the entire foreground surface.
+ mCapture->expectFGColor(74, 74);
+ // And the child layer should now begin at 10, 10 (since the BG
+ // layer is at (0, 0)).
+ mCapture->expectBGColor(9, 9);
+ mCapture->expectChildColor(10, 10);
+ }
+}
+
+TEST_F(ChildLayerTest, ReparentToNoParent) {
+ asTransaction([&](Transaction& t) {
+ t.show(mChild);
+ t.setPosition(mChild, 10, 10);
+ t.setPosition(mFGSurfaceControl, 64, 64);
+ });
+
+ {
+ ScreenCapture::captureScreen(&mCapture);
+ // Top left of foreground must now be visible
+ mCapture->expectFGColor(64, 64);
+ // But 10 pixels in we should see the child surface
+ mCapture->expectChildColor(74, 74);
+ // And 10 more pixels we should be back to the foreground surface
+ mCapture->expectFGColor(84, 84);
+ }
+ asTransaction([&](Transaction& t) {
+ t.reparent(mChild, nullptr);
+ });
+ {
+ ScreenCapture::captureScreen(&mCapture);
+ // Nothing should have changed.
+ mCapture->expectFGColor(64, 64);
+ mCapture->expectChildColor(74, 74);
+ mCapture->expectFGColor(84, 84);
+ }
+}
+
+TEST_F(ChildLayerTest, ReparentFromNoParent) {
+ sp<SurfaceControl> newSurface = mComposerClient->createSurface(
+ String8("New Surface"), 10, 10, PIXEL_FORMAT_RGBA_8888, 0);
+ ASSERT_TRUE(newSurface != NULL);
+ ASSERT_TRUE(newSurface->isValid());
+
+ fillSurfaceRGBA8(newSurface, 63, 195, 63);
+ asTransaction([&](Transaction& t) {
+ t.hide(mChild);
+ t.show(newSurface);
+ t.setPosition(newSurface, 10, 10);
+ t.setLayer(newSurface, INT32_MAX-2);
+ t.setPosition(mFGSurfaceControl, 64, 64);
+ });
+
+ {
+ ScreenCapture::captureScreen(&mCapture);
+ // Top left of foreground must now be visible
+ mCapture->expectFGColor(64, 64);
+ // At 10, 10 we should see the new surface
+ mCapture->checkPixel(10, 10, 63, 195, 63);
+ }
+
+ asTransaction([&](Transaction& t) {
+ t.reparent(newSurface, mFGSurfaceControl->getHandle());
+ });
+
+ {
+ ScreenCapture::captureScreen(&mCapture);
+ // newSurface will now be a child of mFGSurface so it will be 10, 10 offset from
+ // mFGSurface, putting it at 74, 74.
+ mCapture->expectFGColor(64, 64);
+ mCapture->checkPixel(74, 74, 63, 195, 63);
+ mCapture->expectFGColor(84, 84);
+ }
+}
+
+TEST_F(ChildLayerTest, NestedChildren) {
+ sp<SurfaceControl> grandchild = mComposerClient->createSurface(
+ String8("Grandchild surface"),
+ 10, 10, PIXEL_FORMAT_RGBA_8888,
+ 0, mChild.get());
+ fillSurfaceRGBA8(grandchild, 50, 50, 50);
+
+ {
+ ScreenCapture::captureScreen(&mCapture);
+ // Expect the grandchild to begin at 64, 64 because it's a child of mChild layer
+ // which begins at 64, 64
+ mCapture->checkPixel(64, 64, 50, 50, 50);
+ }
+}
+
+class LayerColorTest : public LayerUpdateTest {
+ protected:
+ void SetUp() override {
+ LayerUpdateTest::SetUp();
+
+ mLayerColorControl = mComposerClient->createSurface(
+ String8("Layer color surface"),
+ 128, 128, PIXEL_FORMAT_RGBA_8888,
+ ISurfaceComposerClient::eFXSurfaceColor);
+
+ ASSERT_TRUE(mLayerColorControl != NULL);
+ ASSERT_TRUE(mLayerColorControl->isValid());
+
+ asTransaction([&](Transaction& t) {
+ t.setLayer(mLayerColorControl, INT32_MAX-1);
+ t.setPosition(mLayerColorControl, 140, 140);
+ t.hide(mLayerColorControl);
+ t.hide(mFGSurfaceControl);
+ });
+ }
+
+ void TearDown() override {
+ LayerUpdateTest::TearDown();
+ mLayerColorControl = 0;
+ }
+
+ sp<SurfaceControl> mLayerColorControl;
+};
+
+TEST_F(LayerColorTest, ColorLayerNoAlpha) {
+ sp<ScreenCapture> sc;
+
+ {
+ SCOPED_TRACE("before setColor");
+ ScreenCapture::captureScreen(&sc);
+ sc->expectBGColor(145, 145);
+ }
+
+ asTransaction([&](Transaction& t) {
+ half3 color(43.0f/255.0f, 207.0f/255.0f, 131.0f/255.0f);
+ t.setColor(mLayerColorControl, color);
+ t.show(mLayerColorControl);
+ });
+
+ {
+ // There should now be a color
+ SCOPED_TRACE("after setColor");
+
+ ScreenCapture::captureScreen(&sc);
+ sc->checkPixel(145, 145, 43, 207, 131);
+ }
+}
+
+TEST_F(LayerColorTest, ColorLayerWithAlpha) {
+ sp<ScreenCapture> sc;
+ {
+ SCOPED_TRACE("before setColor");
+ ScreenCapture::captureScreen(&sc);
+ sc->expectBGColor(145, 145);
+ }
+
+ asTransaction([&](Transaction& t) {
+ half3 color(43.0f/255.0f, 207.0f/255.0f, 131.0f/255.0f);
+ t.setColor(mLayerColorControl, color);
+ t.setAlpha(mLayerColorControl, .75f);
+ t.show(mLayerColorControl);
+ });
+
+ {
+ // There should now be a color with .75 alpha
+ SCOPED_TRACE("after setColor");
+ ScreenCapture::captureScreen(&sc);
+ sc->checkPixel(145, 145, 48, 171, 147);
+ }
+}
+
+TEST_F(LayerColorTest, ColorLayerWithNoColor) {
+ sp<ScreenCapture> sc;
+ {
+ SCOPED_TRACE("before setColor");
+ ScreenCapture::captureScreen(&sc);
+ sc->expectBGColor(145, 145);
+ }
+
+ asTransaction([&](Transaction& t) {
+ t.show(mLayerColorControl);
+ });
+
+ {
+ // There should now be set to 0,0,0 (black) as default.
+ SCOPED_TRACE("after setColor");
+ ScreenCapture::captureScreen(&sc);
+ sc->checkPixel(145, 145, 0, 0, 0);
+ }
+}
+
+class ScreenCaptureTest : public LayerUpdateTest {
+protected:
+ std::unique_ptr<CaptureLayer> mCapture;
+};
+
+TEST_F(ScreenCaptureTest, CaptureSingleLayer) {
+ auto bgHandle = mBGSurfaceControl->getHandle();
+ CaptureLayer::captureScreen(&mCapture, bgHandle);
+ mCapture->expectBGColor(0, 0);
+ // Doesn't capture FG layer which is at 64, 64
+ mCapture->expectBGColor(64, 64);
+}
+
+TEST_F(ScreenCaptureTest, CaptureLayerWithChild) {
+ auto fgHandle = mFGSurfaceControl->getHandle();
+
+ sp<SurfaceControl> child = mComposerClient->createSurface(
+ String8("Child surface"),
+ 10, 10, PIXEL_FORMAT_RGBA_8888,
+ 0, mFGSurfaceControl.get());
+ fillSurfaceRGBA8(child, 200, 200, 200);
+
+ SurfaceComposerClient::Transaction()
+ .show(child)
+ .apply(true);
+
+ // Captures mFGSurfaceControl layer and its child.
+ CaptureLayer::captureScreen(&mCapture, fgHandle);
+ mCapture->expectFGColor(10, 10);
+ mCapture->expectChildColor(0, 0);
+}
+
+TEST_F(ScreenCaptureTest, CaptureLayerWithGrandchild) {
+ auto fgHandle = mFGSurfaceControl->getHandle();
+
+ sp<SurfaceControl> child = mComposerClient->createSurface(
+ String8("Child surface"),
+ 10, 10, PIXEL_FORMAT_RGBA_8888,
+ 0, mFGSurfaceControl.get());
+ fillSurfaceRGBA8(child, 200, 200, 200);
+
+ sp<SurfaceControl> grandchild = mComposerClient->createSurface(
+ String8("Grandchild surface"), 5, 5,
+ PIXEL_FORMAT_RGBA_8888, 0, child.get());
+
+ fillSurfaceRGBA8(grandchild, 50, 50, 50);
+ SurfaceComposerClient::Transaction()
+ .show(child)
+ .setPosition(grandchild, 5, 5)
+ .show(grandchild)
+ .apply(true);
+
+ // Captures mFGSurfaceControl, its child, and the grandchild.
+ CaptureLayer::captureScreen(&mCapture, fgHandle);
+ mCapture->expectFGColor(10, 10);
+ mCapture->expectChildColor(0, 0);
+ mCapture->checkPixel(5, 5, 50, 50, 50);
+}
+
+TEST_F(ScreenCaptureTest, CaptureChildOnly) {
+ sp<SurfaceControl> child = mComposerClient->createSurface(
+ String8("Child surface"),
+ 10, 10, PIXEL_FORMAT_RGBA_8888,
+ 0, mFGSurfaceControl.get());
+ fillSurfaceRGBA8(child, 200, 200, 200);
+ auto childHandle = child->getHandle();
+
+ SurfaceComposerClient::Transaction()
+ .setPosition(child, 5, 5)
+ .show(child)
+ .apply(true);
+
+ // Captures only the child layer, and not the parent.
+ CaptureLayer::captureScreen(&mCapture, childHandle);
+ mCapture->expectChildColor(0, 0);
+ mCapture->expectChildColor(9, 9);
+}
+
+TEST_F(ScreenCaptureTest, CaptureGrandchildOnly) {
+ sp<SurfaceControl> child = mComposerClient->createSurface(
+ String8("Child surface"),
+ 10, 10, PIXEL_FORMAT_RGBA_8888,
+ 0, mFGSurfaceControl.get());
+ fillSurfaceRGBA8(child, 200, 200, 200);
+ auto childHandle = child->getHandle();
+
+ sp<SurfaceControl> grandchild = mComposerClient->createSurface(
+ String8("Grandchild surface"), 5, 5,
+ PIXEL_FORMAT_RGBA_8888, 0, child.get());
+ fillSurfaceRGBA8(grandchild, 50, 50, 50);
+
+ SurfaceComposerClient::Transaction()
+ .show(child)
+ .setPosition(grandchild, 5, 5)
+ .show(grandchild)
+ .apply(true);
+
+ auto grandchildHandle = grandchild->getHandle();
+
+ // Captures only the grandchild.
+ CaptureLayer::captureScreen(&mCapture, grandchildHandle);
+ mCapture->checkPixel(0, 0, 50, 50, 50);
+ mCapture->checkPixel(4, 4, 50, 50, 50);
+}
+
}
diff --git a/services/surfaceflinger/tests/fakehwc/Android.bp b/services/surfaceflinger/tests/fakehwc/Android.bp
index 94f3f25..212b9e7 100644
--- a/services/surfaceflinger/tests/fakehwc/Android.bp
+++ b/services/surfaceflinger/tests/fakehwc/Android.bp
@@ -22,7 +22,8 @@
"libsync",
"libfmq",
"libbase",
- "libhidltransport"
+ "libhidltransport",
+ "liblayers_proto"
],
static_libs: [
"libhwcomposer-client",
diff --git a/services/surfaceflinger/tests/fakehwc/FakeComposerClient.cpp b/services/surfaceflinger/tests/fakehwc/FakeComposerClient.cpp
index 60916f3..d97ffa3 100644
--- a/services/surfaceflinger/tests/fakehwc/FakeComposerClient.cpp
+++ b/services/surfaceflinger/tests/fakehwc/FakeComposerClient.cpp
@@ -36,7 +36,6 @@
#include <thread>
constexpr Config NULL_DISPLAY_CONFIG = static_cast<Config>(0);
-constexpr Display DEFAULT_DISPLAY = static_cast<Display>(1);
using namespace sftest;
@@ -168,7 +167,7 @@
ALOGV("enableCallback");
mCallbacksOn = enable;
if (mCallbacksOn) {
- mClient->onHotplug(DEFAULT_DISPLAY, IComposerCallback::Connection::CONNECTED);
+ mClient->onHotplug(PRIMARY_DISPLAY, IComposerCallback::Connection::CONNECTED);
}
}
@@ -507,7 +506,7 @@
if (mSurfaceComposer != nullptr) {
mSurfaceComposer->injectVSync(timestamp);
} else {
- mClient->onVsync(DEFAULT_DISPLAY, timestamp);
+ mClient->onVsync(PRIMARY_DISPLAY, timestamp);
}
}
}
diff --git a/services/surfaceflinger/tests/fakehwc/FakeComposerClient.h b/services/surfaceflinger/tests/fakehwc/FakeComposerClient.h
index 294abb2..2a5a8ad 100644
--- a/services/surfaceflinger/tests/fakehwc/FakeComposerClient.h
+++ b/services/surfaceflinger/tests/fakehwc/FakeComposerClient.h
@@ -19,6 +19,9 @@
#include "ComposerClient.h"
#include "RenderState.h"
+// Needed for display type/ID enums
+#include <hardware/hwcomposer_defs.h>
+
#include <utils/Condition.h>
#include <chrono>
@@ -40,6 +43,13 @@
namespace sftest {
+// NOTE: The ID's need to be exactly these. VR composer and parts of
+// the SurfaceFlinger assume the display IDs to have these values
+// despite the enum being documented as a display type.
+// TODO: Reference to actual documentation
+constexpr Display PRIMARY_DISPLAY = static_cast<Display>(HWC_DISPLAY_PRIMARY);
+constexpr Display EXTERNAL_DISPLAY = static_cast<Display>(HWC_DISPLAY_EXTERNAL);
+
class FakeComposerClient : public ComposerBase {
public:
FakeComposerClient();
diff --git a/services/surfaceflinger/tests/fakehwc/FakeComposerUtils.h b/services/surfaceflinger/tests/fakehwc/FakeComposerUtils.h
index 74dc0e5..1258a97 100644
--- a/services/surfaceflinger/tests/fakehwc/FakeComposerUtils.h
+++ b/services/surfaceflinger/tests/fakehwc/FakeComposerUtils.h
@@ -87,7 +87,7 @@
/*
* All surface state changes are supposed to happen inside a global
- * transaction. GlobalTransactionScope object at the beginning of
+ * transaction. TransactionScope object at the beginning of
* scope automates the process. The resulting scope gives a visual cue
* on the span of the transaction as well.
*
@@ -96,23 +96,26 @@
* is built to explicitly request vsyncs one at the time. A delayed
* request must be made before closing the transaction or the test
* thread stalls until SurfaceFlinger does an emergency vsync by
- * itself. GlobalTransactionScope encapsulates this vsync magic.
+ * itself. TransactionScope encapsulates this vsync magic.
*/
-class GlobalTransactionScope {
+class TransactionScope : public android::SurfaceComposerClient::Transaction {
public:
- GlobalTransactionScope(FakeComposerClient& composer) : mComposer(composer) {
- android::SurfaceComposerClient::openGlobalTransaction();
+ TransactionScope(FakeComposerClient& composer) :
+ Transaction(),
+ mComposer(composer) {
}
- ~GlobalTransactionScope() {
+
+ ~TransactionScope() {
int frameCount = mComposer.getFrameCount();
mComposer.runVSyncAfter(1ms);
- android::SurfaceComposerClient::closeGlobalTransaction(true);
+ LOG_ALWAYS_FATAL_IF(android::NO_ERROR != apply());
// Make sure that exactly one frame has been rendered.
mComposer.waitUntilFrame(frameCount + 1);
LOG_ALWAYS_FATAL_IF(frameCount + 1 != mComposer.getFrameCount(),
"Unexpected frame advance. Delta: %d",
mComposer.getFrameCount() - frameCount);
}
+
FakeComposerClient& mComposer;
};
diff --git a/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp b/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp
index 8902ede..7f4c58a 100644
--- a/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp
+++ b/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp
@@ -24,11 +24,11 @@
#include <gui/ISurfaceComposer.h>
#include <gui/LayerDebugInfo.h>
+#include <gui/LayerState.h>
#include <gui/Surface.h>
#include <gui/SurfaceComposerClient.h>
#include <private/gui/ComposerService.h>
-#include <private/gui/LayerState.h>
#include <ui/DisplayInfo.h>
@@ -62,6 +62,8 @@
using ::testing::SetArgPointee;
using ::testing::_;
+using Transaction = SurfaceComposerClient::Transaction;
+
///////////////////////////////////////////////
struct TestColor {
@@ -168,17 +170,15 @@
android::hardware::ProcessState::self()->startThreadPool();
android::ProcessState::self()->startThreadPool();
- EXPECT_CALL(*mMockComposer, getDisplayType(1, _))
+ EXPECT_CALL(*mMockComposer, getDisplayType(PRIMARY_DISPLAY, _))
.WillOnce(DoAll(SetArgPointee<1>(IComposerClient::DisplayType::PHYSICAL),
Return(Error::NONE)));
- // Seems to be doubled right now, once for display ID 1 and once for 0. This sounds fishy
- // but encoding that here exactly.
- EXPECT_CALL(*mMockComposer, getDisplayAttribute(1, 1, _, _))
- .Times(5)
- .WillRepeatedly(Invoke(mMockComposer, &MockComposerClient::getDisplayAttributeFake));
- // TODO: Find out what code is generating the ID 0.
- EXPECT_CALL(*mMockComposer, getDisplayAttribute(0, 1, _, _))
- .Times(5)
+ // Primary display will be queried twice for all 5 attributes. One
+ // set of queries comes from the SurfaceFlinger proper an the
+ // other set from the VR composer.
+ // TODO: Is VR composer always present? Change to atLeast(5)?
+ EXPECT_CALL(*mMockComposer, getDisplayAttribute(PRIMARY_DISPLAY, 1, _, _))
+ .Times(2 * 5)
.WillRepeatedly(Invoke(mMockComposer, &MockComposerClient::getDisplayAttributeFake));
startSurfaceFlinger();
@@ -207,31 +207,32 @@
TEST_F(DisplayTest, Hotplug) {
ALOGD("DisplayTest::Hotplug");
- EXPECT_CALL(*mMockComposer, getDisplayType(2, _))
+ EXPECT_CALL(*mMockComposer, getDisplayType(EXTERNAL_DISPLAY, _))
.Times(2)
.WillRepeatedly(DoAll(SetArgPointee<1>(IComposerClient::DisplayType::PHYSICAL),
Return(Error::NONE)));
// The attribute queries will get done twice. This is for defaults
- EXPECT_CALL(*mMockComposer, getDisplayAttribute(2, 1, _, _))
+ EXPECT_CALL(*mMockComposer, getDisplayAttribute(EXTERNAL_DISPLAY, 1, _, _))
.Times(2 * 3)
.WillRepeatedly(Invoke(mMockComposer, &MockComposerClient::getDisplayAttributeFake));
// ... and then special handling for dimensions. Specifying this
// rules later means that gmock will try them first, i.e.,
// ordering of width/height vs. the default implementation for
// other queries is significant.
- EXPECT_CALL(*mMockComposer, getDisplayAttribute(2, 1, IComposerClient::Attribute::WIDTH, _))
+ EXPECT_CALL(*mMockComposer,
+ getDisplayAttribute(EXTERNAL_DISPLAY, 1, IComposerClient::Attribute::WIDTH, _))
.Times(2)
.WillRepeatedly(DoAll(SetArgPointee<3>(400), Return(Error::NONE)));
- EXPECT_CALL(*mMockComposer, getDisplayAttribute(2, 1, IComposerClient::Attribute::HEIGHT, _))
+ EXPECT_CALL(*mMockComposer,
+ getDisplayAttribute(EXTERNAL_DISPLAY, 1, IComposerClient::Attribute::HEIGHT, _))
.Times(2)
.WillRepeatedly(DoAll(SetArgPointee<3>(200), Return(Error::NONE)));
// TODO: Width and height queries are not actually called. Display
// info returns dimensions 0x0 in display info. Why?
- mMockComposer->hotplugDisplay(static_cast<Display>(2),
- IComposerCallback::Connection::CONNECTED);
+ mMockComposer->hotplugDisplay(EXTERNAL_DISPLAY, IComposerCallback::Connection::CONNECTED);
{
sp<android::IBinder> display(
@@ -249,21 +250,19 @@
fillSurfaceRGBA8(surfaceControl, BLUE);
{
- GlobalTransactionScope gts(*mMockComposer);
- mComposerClient->setDisplayLayerStack(display, 0);
+ TransactionScope ts(*mMockComposer);
+ ts.setDisplayLayerStack(display, 0);
- ASSERT_EQ(NO_ERROR, surfaceControl->setLayer(INT32_MAX - 2));
- ASSERT_EQ(NO_ERROR, surfaceControl->show());
+ ts.setLayer(surfaceControl, INT32_MAX - 2)
+ .show(surfaceControl);
}
}
- mMockComposer->hotplugDisplay(static_cast<Display>(2),
- IComposerCallback::Connection::DISCONNECTED);
+ mMockComposer->hotplugDisplay(EXTERNAL_DISPLAY, IComposerCallback::Connection::DISCONNECTED);
mMockComposer->clearFrames();
- mMockComposer->hotplugDisplay(static_cast<Display>(2),
- IComposerCallback::Connection::CONNECTED);
+ mMockComposer->hotplugDisplay(EXTERNAL_DISPLAY, IComposerCallback::Connection::CONNECTED);
{
sp<android::IBinder> display(
@@ -281,15 +280,14 @@
fillSurfaceRGBA8(surfaceControl, BLUE);
{
- GlobalTransactionScope gts(*mMockComposer);
- mComposerClient->setDisplayLayerStack(display, 0);
+ TransactionScope ts(*mMockComposer);
+ ts.setDisplayLayerStack(display, 0);
- ASSERT_EQ(NO_ERROR, surfaceControl->setLayer(INT32_MAX - 2));
- ASSERT_EQ(NO_ERROR, surfaceControl->show());
+ ts.setLayer(surfaceControl, INT32_MAX - 2)
+ .show(surfaceControl);
}
}
- mMockComposer->hotplugDisplay(static_cast<Display>(2),
- IComposerCallback::Connection::DISCONNECTED);
+ mMockComposer->hotplugDisplay(EXTERNAL_DISPLAY, IComposerCallback::Connection::DISCONNECTED);
}
////////////////////////////////////////////////
@@ -374,25 +372,24 @@
fillSurfaceRGBA8(mFGSurfaceControl, RED);
- SurfaceComposerClient::openGlobalTransaction();
+ Transaction t;
+ t.setDisplayLayerStack(display, 0);
- mComposerClient->setDisplayLayerStack(display, 0);
+ t.setLayer(mBGSurfaceControl, INT32_MAX - 2);
+ t.show(mBGSurfaceControl);
- ASSERT_EQ(NO_ERROR, mBGSurfaceControl->setLayer(INT32_MAX - 2));
- ASSERT_EQ(NO_ERROR, mBGSurfaceControl->show());
-
- ASSERT_EQ(NO_ERROR, mFGSurfaceControl->setLayer(INT32_MAX - 1));
- ASSERT_EQ(NO_ERROR, mFGSurfaceControl->setPosition(64, 64));
- ASSERT_EQ(NO_ERROR, mFGSurfaceControl->show());
+ t.setLayer(mFGSurfaceControl, INT32_MAX - 1);
+ t.setPosition(mFGSurfaceControl, 64, 64);
+ t.show(mFGSurfaceControl);
// Synchronous transaction will stop this thread, so we set up a
// delayed, off-thread vsync request before closing the
// transaction. In the test code this is usually done with
- // GlobalTransactionScope. Leaving here in the 'vanilla' form for
+ // TransactionScope. Leaving here in the 'vanilla' form for
// reference.
ASSERT_EQ(0, sFakeComposer->getFrameCount());
sFakeComposer->runVSyncAfter(1ms);
- SurfaceComposerClient::closeGlobalTransaction(true);
+ t.apply();
sFakeComposer->waitUntilFrame(1);
// Reference data. This is what the HWC should see.
@@ -449,8 +446,8 @@
// should be available in the latest frame stored by the fake
// composer.
{
- GlobalTransactionScope gts(*sFakeComposer);
- ASSERT_EQ(NO_ERROR, mFGSurfaceControl->setPosition(128, 128));
+ TransactionScope ts(*sFakeComposer);
+ ts.setPosition(mFGSurfaceControl, 128, 128);
// NOTE: No changes yet, so vsync will do nothing, HWC does not get any calls.
// (How to verify that? Throw in vsync and wait a 2x frame time? Separate test?)
//
@@ -477,8 +474,8 @@
TEST_F(TransactionTest, LayerResize) {
ALOGD("TransactionTest::LayerResize");
{
- GlobalTransactionScope gts(*sFakeComposer);
- ASSERT_EQ(NO_ERROR, mFGSurfaceControl->setSize(128, 128));
+ TransactionScope ts(*sFakeComposer);
+ ts.setSize(mFGSurfaceControl, 128, 128);
}
fillSurfaceRGBA8(mFGSurfaceControl, GREEN);
@@ -501,9 +498,9 @@
TEST_F(TransactionTest, LayerCrop) {
// TODO: Add scaling to confirm that crop happens in buffer space?
{
- GlobalTransactionScope gts(*sFakeComposer);
+ TransactionScope ts(*sFakeComposer);
Rect cropRect(16, 16, 32, 32);
- ASSERT_EQ(NO_ERROR, mFGSurfaceControl->setCrop(cropRect));
+ ts.setCrop(mFGSurfaceControl, cropRect);
}
ASSERT_EQ(2, sFakeComposer->getFrameCount());
@@ -516,9 +513,9 @@
TEST_F(TransactionTest, LayerFinalCrop) {
// TODO: Add scaling to confirm that crop happens in display space?
{
- GlobalTransactionScope gts(*sFakeComposer);
+ TransactionScope ts(*sFakeComposer);
Rect cropRect(32, 32, 32 + 64, 32 + 64);
- ASSERT_EQ(NO_ERROR, mFGSurfaceControl->setFinalCrop(cropRect));
+ ts.setFinalCrop(mFGSurfaceControl, cropRect);
}
ASSERT_EQ(2, sFakeComposer->getFrameCount());
@@ -534,9 +531,9 @@
TEST_F(TransactionTest, LayerFinalCropEmpty) {
// TODO: Add scaling to confirm that crop happens in display space?
{
- GlobalTransactionScope gts(*sFakeComposer);
+ TransactionScope ts(*sFakeComposer);
Rect cropRect(16, 16, 32, 32);
- ASSERT_EQ(NO_ERROR, mFGSurfaceControl->setFinalCrop(cropRect));
+ ts.setFinalCrop(mFGSurfaceControl, cropRect);
}
ASSERT_EQ(2, sFakeComposer->getFrameCount());
@@ -549,8 +546,8 @@
TEST_F(TransactionTest, LayerSetLayer) {
{
- GlobalTransactionScope gts(*sFakeComposer);
- ASSERT_EQ(NO_ERROR, mFGSurfaceControl->setLayer(INT_MAX - 3));
+ TransactionScope ts(*sFakeComposer);
+ ts.setLayer(mFGSurfaceControl, INT_MAX - 3);
}
ASSERT_EQ(2, sFakeComposer->getFrameCount());
@@ -564,11 +561,10 @@
TEST_F(TransactionTest, LayerSetLayerOpaque) {
{
- GlobalTransactionScope gts(*sFakeComposer);
- ASSERT_EQ(NO_ERROR, mFGSurfaceControl->setLayer(INT_MAX - 3));
- ASSERT_EQ(NO_ERROR,
- mBGSurfaceControl->setFlags(layer_state_t::eLayerOpaque,
- layer_state_t::eLayerOpaque));
+ TransactionScope ts(*sFakeComposer);
+ ts.setLayer(mFGSurfaceControl, INT_MAX - 3);
+ ts.setFlags(mBGSurfaceControl, layer_state_t::eLayerOpaque,
+ layer_state_t::eLayerOpaque);
}
ASSERT_EQ(2, sFakeComposer->getFrameCount());
@@ -581,8 +577,8 @@
TEST_F(TransactionTest, SetLayerStack) {
ALOGD("TransactionTest::SetLayerStack");
{
- GlobalTransactionScope gts(*sFakeComposer);
- ASSERT_EQ(NO_ERROR, mFGSurfaceControl->setLayerStack(1));
+ TransactionScope ts(*sFakeComposer);
+ ts.setLayerStack(mFGSurfaceControl, 1);
}
// Foreground layer should have disappeared.
@@ -595,8 +591,8 @@
TEST_F(TransactionTest, LayerShowHide) {
ALOGD("TransactionTest::LayerShowHide");
{
- GlobalTransactionScope gts(*sFakeComposer);
- ASSERT_EQ(NO_ERROR, mFGSurfaceControl->hide());
+ TransactionScope ts(*sFakeComposer);
+ ts.hide(mFGSurfaceControl);
}
// Foreground layer should have disappeared.
@@ -606,8 +602,8 @@
EXPECT_TRUE(framesAreSame(refFrame, sFakeComposer->getLatestFrame()));
{
- GlobalTransactionScope gts(*sFakeComposer);
- ASSERT_EQ(NO_ERROR, mFGSurfaceControl->show());
+ TransactionScope ts(*sFakeComposer);
+ ts.show(mFGSurfaceControl);
}
// Foreground layer should be back
@@ -617,8 +613,8 @@
TEST_F(TransactionTest, LayerSetAlpha) {
{
- GlobalTransactionScope gts(*sFakeComposer);
- ASSERT_EQ(NO_ERROR, mFGSurfaceControl->setAlpha(0.75f));
+ TransactionScope ts(*sFakeComposer);
+ ts.setAlpha(mFGSurfaceControl, 0.75f);
}
ASSERT_EQ(2, sFakeComposer->getFrameCount());
@@ -629,10 +625,9 @@
TEST_F(TransactionTest, LayerSetFlags) {
{
- GlobalTransactionScope gts(*sFakeComposer);
- ASSERT_EQ(NO_ERROR,
- mFGSurfaceControl->setFlags(layer_state_t::eLayerHidden,
- layer_state_t::eLayerHidden));
+ TransactionScope ts(*sFakeComposer);
+ ts.setFlags(mFGSurfaceControl, layer_state_t::eLayerHidden,
+ layer_state_t::eLayerHidden);
}
// Foreground layer should have disappeared.
@@ -664,17 +659,16 @@
{{0.f, 1.f, 1.f, 0.f}, HWC_TRANSFORM_FLIP_H_ROT_90, {64, 64, 128, 128}},
{{0.f, 1.f, 1.f, 0.f}, HWC_TRANSFORM_FLIP_V_ROT_90, {64, 64, 128, 128}}};
// clang-format on
- constexpr int TEST_COUNT = sizeof(MATRIX_TESTS)/sizeof(matrixTestData);
+ constexpr int TEST_COUNT = sizeof(MATRIX_TESTS) / sizeof(matrixTestData);
for (int i = 0; i < TEST_COUNT; i++) {
// TODO: How to leverage the HWC2 stringifiers?
const matrixTestData& xform = MATRIX_TESTS[i];
SCOPED_TRACE(i);
{
- GlobalTransactionScope gts(*sFakeComposer);
- ASSERT_EQ(NO_ERROR,
- mFGSurfaceControl->setMatrix(xform.matrix[0], xform.matrix[1],
- xform.matrix[2], xform.matrix[3]));
+ TransactionScope ts(*sFakeComposer);
+ ts.setMatrix(mFGSurfaceControl, xform.matrix[0], xform.matrix[1],
+ xform.matrix[2], xform.matrix[3]);
}
auto referenceFrame = mBaseFrame;
@@ -688,10 +682,10 @@
#if 0
TEST_F(TransactionTest, LayerSetMatrix2) {
{
- GlobalTransactionScope gts(*sFakeComposer);
+ TransactionScope ts(*sFakeComposer);
// TODO: PLEASE SPEC THE FUNCTION!
- ASSERT_EQ(NO_ERROR, mFGSurfaceControl->setMatrix(0.11f, 0.123f,
- -2.33f, 0.22f));
+ ts.setMatrix(mFGSurfaceControl, 0.11f, 0.123f,
+ -2.33f, 0.22f);
}
auto referenceFrame = mBaseFrame;
// TODO: Is this correct for sure?
@@ -712,10 +706,10 @@
fillSurfaceRGBA8(syncSurfaceControl, DARK_GRAY);
{
- GlobalTransactionScope gts(*sFakeComposer);
- ASSERT_EQ(NO_ERROR, syncSurfaceControl->setLayer(INT32_MAX - 1));
- ASSERT_EQ(NO_ERROR, syncSurfaceControl->setPosition(mDisplayWidth - 2, mDisplayHeight - 2));
- ASSERT_EQ(NO_ERROR, syncSurfaceControl->show());
+ TransactionScope ts(*sFakeComposer);
+ ts.setLayer(syncSurfaceControl, INT32_MAX - 1);
+ ts.setPosition(syncSurfaceControl, mDisplayWidth - 2, mDisplayHeight - 2);
+ ts.show(syncSurfaceControl);
}
auto referenceFrame = mBaseFrame;
referenceFrame.push_back(makeSimpleRect(mDisplayWidth - 2, mDisplayHeight - 2,
@@ -727,20 +721,20 @@
// set up two deferred transactions on different frames - these should not yield composited
// frames
{
- GlobalTransactionScope gts(*sFakeComposer);
- ASSERT_EQ(NO_ERROR, mFGSurfaceControl->setAlpha(0.75));
- mFGSurfaceControl
- ->deferTransactionUntil(syncSurfaceControl->getHandle(),
- syncSurfaceControl->getSurface()->getNextFrameNumber());
+ TransactionScope ts(*sFakeComposer);
+ ts.setAlpha(mFGSurfaceControl, 0.75);
+ ts.deferTransactionUntil(mFGSurfaceControl,
+ syncSurfaceControl->getHandle(),
+ syncSurfaceControl->getSurface()->getNextFrameNumber());
}
EXPECT_TRUE(framesAreSame(referenceFrame, sFakeComposer->getLatestFrame()));
{
- GlobalTransactionScope gts(*sFakeComposer);
- ASSERT_EQ(NO_ERROR, mFGSurfaceControl->setPosition(128, 128));
- mFGSurfaceControl
- ->deferTransactionUntil(syncSurfaceControl->getHandle(),
- syncSurfaceControl->getSurface()->getNextFrameNumber() + 1);
+ TransactionScope ts(*sFakeComposer);
+ ts.setPosition(mFGSurfaceControl, 128, 128);
+ ts.deferTransactionUntil(mFGSurfaceControl,
+ syncSurfaceControl->getHandle(),
+ syncSurfaceControl->getSurface()->getNextFrameNumber() + 1);
}
EXPECT_EQ(4, sFakeComposer->getFrameCount());
EXPECT_TRUE(framesAreSame(referenceFrame, sFakeComposer->getLatestFrame()));
@@ -756,8 +750,8 @@
// should show up immediately since it's not deferred
{
- GlobalTransactionScope gts(*sFakeComposer);
- ASSERT_EQ(NO_ERROR, mFGSurfaceControl->setAlpha(1.0));
+ TransactionScope ts(*sFakeComposer);
+ ts.setAlpha(mFGSurfaceControl, 1.0);
}
referenceFrame[FG_LAYER].mPlaneAlpha = 1.f;
EXPECT_EQ(6, sFakeComposer->getFrameCount());
@@ -781,10 +775,10 @@
// Now we stack the surface above the foreground surface and make sure it is visible.
{
- GlobalTransactionScope gts(*sFakeComposer);
- relativeSurfaceControl->setPosition(64, 64);
- relativeSurfaceControl->show();
- relativeSurfaceControl->setRelativeLayer(mFGSurfaceControl->getHandle(), 1);
+ TransactionScope ts(*sFakeComposer);
+ ts.setPosition(relativeSurfaceControl, 64, 64);
+ ts.show(relativeSurfaceControl);
+ ts.setRelativeLayer(relativeSurfaceControl, mFGSurfaceControl->getHandle(), 1);
}
auto referenceFrame = mBaseFrame;
// NOTE: All three layers will be visible as the surfaces are
@@ -795,8 +789,8 @@
// A call to setLayer will override a call to setRelativeLayer
{
- GlobalTransactionScope gts(*sFakeComposer);
- relativeSurfaceControl->setLayer(0);
+ TransactionScope ts(*sFakeComposer);
+ ts.setLayer(relativeSurfaceControl, 0);
}
// Previous top layer will now appear at the bottom.
@@ -832,11 +826,11 @@
TEST_F(ChildLayerTest, Positioning) {
{
- GlobalTransactionScope gts(*sFakeComposer);
- mChild->show();
- mChild->setPosition(10, 10);
+ TransactionScope ts(*sFakeComposer);
+ ts.show(mChild);
+ ts.setPosition(mChild, 10, 10);
// Move to the same position as in the original setup.
- mFGSurfaceControl->setPosition(64, 64);
+ ts.setPosition(mFGSurfaceControl, 64, 64);
}
auto referenceFrame = mBaseFrame;
@@ -846,8 +840,8 @@
EXPECT_TRUE(framesAreSame(referenceFrame, sFakeComposer->getLatestFrame()));
{
- GlobalTransactionScope gts(*sFakeComposer);
- ASSERT_EQ(NO_ERROR, mFGSurfaceControl->setPosition(0, 0));
+ TransactionScope ts(*sFakeComposer);
+ ts.setPosition(mFGSurfaceControl, 0, 0);
}
auto referenceFrame2 = mBaseFrame;
@@ -859,11 +853,11 @@
TEST_F(ChildLayerTest, Cropping) {
{
- GlobalTransactionScope gts(*sFakeComposer);
- mChild->show();
- mChild->setPosition(0, 0);
- mFGSurfaceControl->setPosition(0, 0);
- mFGSurfaceControl->setCrop(Rect(0, 0, 5, 5));
+ TransactionScope ts(*sFakeComposer);
+ ts.show(mChild);
+ ts.setPosition(mChild, 0, 0);
+ ts.setPosition(mFGSurfaceControl, 0, 0);
+ ts.setCrop(mFGSurfaceControl, Rect(0, 0, 5, 5));
}
// NOTE: The foreground surface would be occluded by the child
// now, but is included in the stack because the child is
@@ -878,11 +872,11 @@
TEST_F(ChildLayerTest, FinalCropping) {
{
- GlobalTransactionScope gts(*sFakeComposer);
- mChild->show();
- mChild->setPosition(0, 0);
- mFGSurfaceControl->setPosition(0, 0);
- mFGSurfaceControl->setFinalCrop(Rect(0, 0, 5, 5));
+ TransactionScope ts(*sFakeComposer);
+ ts.show(mChild);
+ ts.setPosition(mChild, 0, 0);
+ ts.setPosition(mFGSurfaceControl, 0, 0);
+ ts.setFinalCrop(mFGSurfaceControl, Rect(0, 0, 5, 5));
}
auto referenceFrame = mBaseFrame;
referenceFrame[FG_LAYER].mDisplayFrame = hwc_rect_t{0, 0, 0 + 5, 0 + 5};
@@ -894,10 +888,10 @@
TEST_F(ChildLayerTest, Constraints) {
{
- GlobalTransactionScope gts(*sFakeComposer);
- mChild->show();
- mFGSurfaceControl->setPosition(0, 0);
- mChild->setPosition(63, 63);
+ TransactionScope ts(*sFakeComposer);
+ ts.show(mChild);
+ ts.setPosition(mFGSurfaceControl, 0, 0);
+ ts.setPosition(mChild, 63, 63);
}
auto referenceFrame = mBaseFrame;
referenceFrame[FG_LAYER].mDisplayFrame = hwc_rect_t{0, 0, 64, 64};
@@ -908,8 +902,8 @@
TEST_F(ChildLayerTest, Scaling) {
{
- GlobalTransactionScope gts(*sFakeComposer);
- mFGSurfaceControl->setPosition(0, 0);
+ TransactionScope ts(*sFakeComposer);
+ ts.setPosition(mFGSurfaceControl, 0, 0);
}
auto referenceFrame = mBaseFrame;
referenceFrame[FG_LAYER].mDisplayFrame = hwc_rect_t{0, 0, 64, 64};
@@ -917,8 +911,8 @@
EXPECT_TRUE(framesAreSame(referenceFrame, sFakeComposer->getLatestFrame()));
{
- GlobalTransactionScope gts(*sFakeComposer);
- mFGSurfaceControl->setMatrix(2.0, 0, 0, 2.0);
+ TransactionScope ts(*sFakeComposer);
+ ts.setMatrix(mFGSurfaceControl, 2.0, 0, 0, 2.0);
}
auto referenceFrame2 = mBaseFrame;
@@ -929,11 +923,11 @@
TEST_F(ChildLayerTest, LayerAlpha) {
{
- GlobalTransactionScope gts(*sFakeComposer);
- mChild->show();
- mChild->setPosition(0, 0);
- mFGSurfaceControl->setPosition(0, 0);
- ASSERT_EQ(NO_ERROR, mChild->setAlpha(0.5));
+ TransactionScope ts(*sFakeComposer);
+ ts.show(mChild);
+ ts.setPosition(mChild, 0, 0);
+ ts.setPosition(mFGSurfaceControl, 0, 0);
+ ts.setAlpha(mChild, 0.5);
}
auto referenceFrame = mBaseFrame;
@@ -943,8 +937,8 @@
EXPECT_TRUE(framesAreSame(referenceFrame, sFakeComposer->getLatestFrame()));
{
- GlobalTransactionScope gts(*sFakeComposer);
- ASSERT_EQ(NO_ERROR, mFGSurfaceControl->setAlpha(0.5));
+ TransactionScope ts(*sFakeComposer);
+ ts.setAlpha(mFGSurfaceControl, 0.5);
}
auto referenceFrame2 = referenceFrame;
@@ -955,10 +949,10 @@
TEST_F(ChildLayerTest, ReparentChildren) {
{
- GlobalTransactionScope gts(*sFakeComposer);
- mChild->show();
- mChild->setPosition(10, 10);
- mFGSurfaceControl->setPosition(64, 64);
+ TransactionScope ts(*sFakeComposer);
+ ts.show(mChild);
+ ts.setPosition(mChild, 10, 10);
+ ts.setPosition(mFGSurfaceControl, 64, 64);
}
auto referenceFrame = mBaseFrame;
referenceFrame[FG_LAYER].mDisplayFrame = hwc_rect_t{64, 64, 64 + 64, 64 + 64};
@@ -967,8 +961,8 @@
EXPECT_TRUE(framesAreSame(referenceFrame, sFakeComposer->getLatestFrame()));
{
- GlobalTransactionScope gts(*sFakeComposer);
- mFGSurfaceControl->reparentChildren(mBGSurfaceControl->getHandle());
+ TransactionScope ts(*sFakeComposer);
+ ts.reparentChildren(mFGSurfaceControl, mBGSurfaceControl->getHandle());
}
auto referenceFrame2 = referenceFrame;
@@ -979,10 +973,10 @@
TEST_F(ChildLayerTest, DetachChildren) {
{
- GlobalTransactionScope gts(*sFakeComposer);
- mChild->show();
- mChild->setPosition(10, 10);
- mFGSurfaceControl->setPosition(64, 64);
+ TransactionScope ts(*sFakeComposer);
+ ts.show(mChild);
+ ts.setPosition(mChild, 10, 10);
+ ts.setPosition(mFGSurfaceControl, 64, 64);
}
auto referenceFrame = mBaseFrame;
@@ -992,13 +986,13 @@
EXPECT_TRUE(framesAreSame(referenceFrame, sFakeComposer->getLatestFrame()));
{
- GlobalTransactionScope gts(*sFakeComposer);
- mFGSurfaceControl->detachChildren();
+ TransactionScope ts(*sFakeComposer);
+ ts.detachChildren(mFGSurfaceControl);
}
{
- GlobalTransactionScope gts(*sFakeComposer);
- mChild->hide();
+ TransactionScope ts(*sFakeComposer);
+ ts.hide(mChild);
}
// Nothing should have changed. The child control becomes a no-op
@@ -1009,17 +1003,17 @@
TEST_F(ChildLayerTest, InheritNonTransformScalingFromParent) {
{
- GlobalTransactionScope gts(*sFakeComposer);
- mChild->show();
- mChild->setPosition(0, 0);
- mFGSurfaceControl->setPosition(0, 0);
+ TransactionScope ts(*sFakeComposer);
+ ts.show(mChild);
+ ts.setPosition(mChild, 0, 0);
+ ts.setPosition(mFGSurfaceControl, 0, 0);
}
{
- GlobalTransactionScope gts(*sFakeComposer);
- mFGSurfaceControl->setOverrideScalingMode(NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW);
+ TransactionScope ts(*sFakeComposer);
+ ts.setOverrideScalingMode(mFGSurfaceControl, NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW);
// We cause scaling by 2.
- mFGSurfaceControl->setSize(128, 128);
+ ts.setSize(mFGSurfaceControl, 128, 128);
}
auto referenceFrame = mBaseFrame;
@@ -1033,17 +1027,17 @@
// Regression test for b/37673612
TEST_F(ChildLayerTest, ChildrenWithParentBufferTransform) {
{
- GlobalTransactionScope gts(*sFakeComposer);
- mChild->show();
- mChild->setPosition(0, 0);
- mFGSurfaceControl->setPosition(0, 0);
+ TransactionScope ts(*sFakeComposer);
+ ts.show(mChild);
+ ts.setPosition(mChild, 0, 0);
+ ts.setPosition(mFGSurfaceControl, 0, 0);
}
// We set things up as in b/37673612 so that there is a mismatch between the buffer size and
// the WM specified state size.
{
- GlobalTransactionScope gts(*sFakeComposer);
- mFGSurfaceControl->setSize(128, 64);
+ TransactionScope ts(*sFakeComposer);
+ ts.setSize(mFGSurfaceControl, 128, 64);
}
sp<Surface> s = mFGSurfaceControl->getSurface();
@@ -1074,10 +1068,10 @@
// Show the child layer in a deferred transaction
{
- GlobalTransactionScope gts(*sFakeComposer);
- mChild->deferTransactionUntil(mFGSurfaceControl->getHandle(),
+ TransactionScope ts(*sFakeComposer);
+ ts.deferTransactionUntil(mChild, mFGSurfaceControl->getHandle(),
mFGSurfaceControl->getSurface()->getNextFrameNumber());
- mChild->show();
+ ts.show(mChild);
}
// Render the foreground surface a few times
@@ -1114,11 +1108,11 @@
sFakeComposer->runVSyncAndWait();
}
void restoreInitialState() {
- GlobalTransactionScope gts(*sFakeComposer);
- mFGSurfaceControl->setSize(64, 64);
- mFGSurfaceControl->setPosition(64, 64);
- mFGSurfaceControl->setCrop(Rect(0, 0, 64, 64));
- mFGSurfaceControl->setFinalCrop(Rect(0, 0, -1, -1));
+ TransactionScope ts(*sFakeComposer);
+ ts.setSize(mFGSurfaceControl, 64, 64);
+ ts.setPosition(mFGSurfaceControl, 64, 64);
+ ts.setCrop(mFGSurfaceControl, Rect(0, 0, 64, 64));
+ ts.setFinalCrop(mFGSurfaceControl, Rect(0, 0, -1, -1));
}
};
@@ -1126,9 +1120,9 @@
// By default position can be updated even while
// a resize is pending.
{
- GlobalTransactionScope gts(*sFakeComposer);
- mFGSurfaceControl->setSize(32, 32);
- mFGSurfaceControl->setPosition(100, 100);
+ TransactionScope ts(*sFakeComposer);
+ ts.setSize(mFGSurfaceControl, 32, 32);
+ ts.setPosition(mFGSurfaceControl, 100, 100);
}
// The size should not have updated as we have not provided a new buffer.
@@ -1141,10 +1135,10 @@
// Now we repeat with setGeometryAppliesWithResize
// and verify the position DOESN'T latch.
{
- GlobalTransactionScope gts(*sFakeComposer);
- mFGSurfaceControl->setGeometryAppliesWithResize();
- mFGSurfaceControl->setSize(32, 32);
- mFGSurfaceControl->setPosition(100, 100);
+ TransactionScope ts(*sFakeComposer);
+ ts.setGeometryAppliesWithResize(mFGSurfaceControl);
+ ts.setSize(mFGSurfaceControl, 32, 32);
+ ts.setPosition(mFGSurfaceControl, 100, 100);
}
EXPECT_TRUE(framesAreSame(mBaseFrame, sFakeComposer->getLatestFrame()));
@@ -1160,9 +1154,9 @@
TEST_F(LatchingTest, CropLatching) {
// Normally the crop applies immediately even while a resize is pending.
{
- GlobalTransactionScope gts(*sFakeComposer);
- mFGSurfaceControl->setSize(128, 128);
- mFGSurfaceControl->setCrop(Rect(0, 0, 63, 63));
+ TransactionScope ts(*sFakeComposer);
+ ts.setSize(mFGSurfaceControl, 128, 128);
+ ts.setCrop(mFGSurfaceControl, Rect(0, 0, 63, 63));
}
auto referenceFrame1 = mBaseFrame;
@@ -1173,10 +1167,10 @@
restoreInitialState();
{
- GlobalTransactionScope gts(*sFakeComposer);
- mFGSurfaceControl->setSize(128, 128);
- mFGSurfaceControl->setGeometryAppliesWithResize();
- mFGSurfaceControl->setCrop(Rect(0, 0, 63, 63));
+ TransactionScope ts(*sFakeComposer);
+ ts.setSize(mFGSurfaceControl, 128, 128);
+ ts.setGeometryAppliesWithResize(mFGSurfaceControl);
+ ts.setCrop(mFGSurfaceControl, Rect(0, 0, 63, 63));
}
EXPECT_TRUE(framesAreSame(mBaseFrame, sFakeComposer->getLatestFrame()));
@@ -1192,9 +1186,9 @@
TEST_F(LatchingTest, FinalCropLatching) {
// Normally the crop applies immediately even while a resize is pending.
{
- GlobalTransactionScope gts(*sFakeComposer);
- mFGSurfaceControl->setSize(128, 128);
- mFGSurfaceControl->setFinalCrop(Rect(64, 64, 127, 127));
+ TransactionScope ts(*sFakeComposer);
+ ts.setSize(mFGSurfaceControl, 128, 128);
+ ts.setFinalCrop(mFGSurfaceControl, Rect(64, 64, 127, 127));
}
auto referenceFrame1 = mBaseFrame;
@@ -1206,10 +1200,10 @@
restoreInitialState();
{
- GlobalTransactionScope gts(*sFakeComposer);
- mFGSurfaceControl->setSize(128, 128);
- mFGSurfaceControl->setGeometryAppliesWithResize();
- mFGSurfaceControl->setFinalCrop(Rect(64, 64, 127, 127));
+ TransactionScope ts(*sFakeComposer);
+ ts.setSize(mFGSurfaceControl, 128, 128);
+ ts.setGeometryAppliesWithResize(mFGSurfaceControl);
+ ts.setFinalCrop(mFGSurfaceControl, Rect(64, 64, 127, 127));
}
EXPECT_TRUE(framesAreSame(mBaseFrame, sFakeComposer->getLatestFrame()));
@@ -1228,9 +1222,9 @@
TEST_F(LatchingTest, FinalCropLatchingBufferOldSize) {
// Normally the crop applies immediately even while a resize is pending.
{
- GlobalTransactionScope gts(*sFakeComposer);
- mFGSurfaceControl->setSize(128, 128);
- mFGSurfaceControl->setFinalCrop(Rect(64, 64, 127, 127));
+ TransactionScope ts(*sFakeComposer);
+ ts.setSize(mFGSurfaceControl, 128, 128);
+ ts.setFinalCrop(mFGSurfaceControl, Rect(64, 64, 127, 127));
}
auto referenceFrame1 = mBaseFrame;
@@ -1246,10 +1240,10 @@
lockAndFillFGBuffer();
{
- GlobalTransactionScope gts(*sFakeComposer);
- mFGSurfaceControl->setSize(128, 128);
- mFGSurfaceControl->setGeometryAppliesWithResize();
- mFGSurfaceControl->setFinalCrop(Rect(64, 64, 127, 127));
+ TransactionScope ts(*sFakeComposer);
+ ts.setSize(mFGSurfaceControl, 128, 128);
+ ts.setGeometryAppliesWithResize(mFGSurfaceControl);
+ ts.setFinalCrop(mFGSurfaceControl, Rect(64, 64, 127, 127));
}
EXPECT_TRUE(framesAreSame(mBaseFrame, sFakeComposer->getLatestFrame()));
@@ -1275,15 +1269,15 @@
// is still pending, and ensure we are successful. Success meaning the second crop
// is the one which eventually latches and not the first.
{
- GlobalTransactionScope gts(*sFakeComposer);
- mFGSurfaceControl->setSize(128, 128);
- mFGSurfaceControl->setGeometryAppliesWithResize();
- mFGSurfaceControl->setFinalCrop(Rect(64, 64, 127, 127));
+ TransactionScope ts(*sFakeComposer);
+ ts.setSize(mFGSurfaceControl, 128, 128);
+ ts.setGeometryAppliesWithResize(mFGSurfaceControl);
+ ts.setFinalCrop(mFGSurfaceControl, Rect(64, 64, 127, 127));
}
{
- GlobalTransactionScope gts(*sFakeComposer);
- mFGSurfaceControl->setFinalCrop(Rect(0, 0, -1, -1));
+ TransactionScope ts(*sFakeComposer);
+ ts.setFinalCrop(mFGSurfaceControl, Rect(0, 0, -1, -1));
}
EXPECT_TRUE(framesAreSame(mBaseFrame, sFakeComposer->getLatestFrame()));
diff --git a/services/surfaceflinger/tests/hwc2/Android.mk b/services/surfaceflinger/tests/hwc2/Android.mk
index 203ced5..010ac9c 100644
--- a/services/surfaceflinger/tests/hwc2/Android.mk
+++ b/services/surfaceflinger/tests/hwc2/Android.mk
@@ -36,7 +36,9 @@
libui \
libgui \
liblog \
- libsync
+ libsync \
+ libhwui \
+ android.hardware.graphics.common@1.0
LOCAL_STATIC_LIBRARIES := \
libbase \
libadf \
@@ -49,6 +51,7 @@
Hwc2TestLayers.cpp \
Hwc2TestBuffer.cpp \
Hwc2TestClientTarget.cpp \
- Hwc2TestVirtualDisplay.cpp
+ Hwc2TestVirtualDisplay.cpp \
+ Hwc2TestPixelComparator.cpp
include $(BUILD_NATIVE_TEST)
diff --git a/services/surfaceflinger/tests/hwc2/Hwc2Test.cpp b/services/surfaceflinger/tests/hwc2/Hwc2Test.cpp
index 4055527..4878c14 100644
--- a/services/surfaceflinger/tests/hwc2/Hwc2Test.cpp
+++ b/services/surfaceflinger/tests/hwc2/Hwc2Test.cpp
@@ -1775,6 +1775,145 @@
}
}
+ void createAndPresentVirtualDisplay(size_t layerCnt,
+ Hwc2TestCoverage coverage,
+ const std::unordered_map<Hwc2TestPropertyName, Hwc2TestCoverage>&
+ coverageExceptions)
+ {
+ Hwc2TestVirtualDisplay testVirtualDisplay(coverage);
+ hwc2_display_t display;
+ android_pixel_format_t desiredFormat = HAL_PIXEL_FORMAT_RGBA_8888;
+
+ do {
+ // Items dependent on the display dimensions
+ hwc2_error_t err = HWC2_ERROR_NONE;
+ const UnsignedArea& dimension =
+ testVirtualDisplay.getDisplayDimension();
+ ASSERT_NO_FATAL_FAILURE(createVirtualDisplay(dimension.width,
+ dimension.height, &desiredFormat, &display, &err));
+ ASSERT_TRUE(err == HWC2_ERROR_NONE)
+ << "Cannot allocate virtual display";
+
+ ASSERT_NO_FATAL_FAILURE(setPowerMode(display, HWC2_POWER_MODE_ON));
+ ASSERT_NO_FATAL_FAILURE(enableVsync(display));
+
+ std::vector<hwc2_config_t> configs;
+ ASSERT_NO_FATAL_FAILURE(getDisplayConfigs(display, &configs));
+
+ for (auto config : configs) {
+ ASSERT_NO_FATAL_FAILURE(setActiveConfig(display, config));
+
+ Area displayArea;
+ ASSERT_NO_FATAL_FAILURE(getActiveDisplayArea(display,
+ &displayArea));
+
+ std::vector<hwc2_layer_t> layers;
+ ASSERT_NO_FATAL_FAILURE(createLayers(display, &layers,
+ layerCnt));
+ Hwc2TestLayers testLayers(layers, coverage, displayArea,
+ coverageExceptions);
+
+ /*
+ * Layouts that do not cover an entire virtual display will
+ * cause undefined behavior.
+ * Enable optimizeLayouts to avoid this.
+ */
+ testLayers.optimizeLayouts();
+ do {
+ // Items dependent on the testLayers properties
+ std::set<hwc2_layer_t> clientLayers;
+ std::set<hwc2_layer_t> clearLayers;
+ uint32_t numTypes, numRequests;
+ bool hasChanges, skip;
+ bool flipClientTarget;
+ int32_t presentFence;
+ Hwc2TestClientTarget testClientTarget;
+ buffer_handle_t outputBufferHandle;
+ android::base::unique_fd outputBufferReleaseFence;
+
+ ASSERT_NO_FATAL_FAILURE(setLayerProperties(display, layers,
+ &testLayers, &skip));
+
+ if (skip)
+ continue;
+
+ ASSERT_NO_FATAL_FAILURE(validateDisplay(display, &numTypes,
+ &numRequests, &hasChanges));
+
+ if (hasChanges)
+ EXPECT_LE(numTypes, static_cast<uint32_t>(layers.size()))
+ << "wrong number of requests";
+
+ ASSERT_NO_FATAL_FAILURE(handleCompositionChanges(display,
+ testLayers, layers, numTypes, &clientLayers));
+
+ ASSERT_NO_FATAL_FAILURE(handleRequests(display, layers,
+ numRequests, &clearLayers, &flipClientTarget));
+ ASSERT_NO_FATAL_FAILURE(setClientTarget(display,
+ &testClientTarget, testLayers, clientLayers,
+ clearLayers, flipClientTarget, displayArea));
+ ASSERT_NO_FATAL_FAILURE(acceptDisplayChanges(display));
+
+ ASSERT_EQ(testVirtualDisplay.getOutputBuffer(
+ &outputBufferHandle, &outputBufferReleaseFence), 0);
+ ASSERT_NO_FATAL_FAILURE(setOutputBuffer(display,
+ outputBufferHandle, outputBufferReleaseFence));
+
+ EXPECT_NO_FATAL_FAILURE(presentDisplay(display,
+ &presentFence));
+ ASSERT_NO_FATAL_FAILURE(closeFences(display, presentFence));
+
+ ASSERT_EQ(testVirtualDisplay.verifyOutputBuffer(&testLayers,
+ &layers, &clearLayers), 0);
+
+ /*
+ * Upscaling the image causes minor pixel differences.
+ * Work around this by using some threshold.
+ *
+ * Fail test if we are off by more than 1% of our
+ * pixels.
+ */
+ ComparatorResult& comparatorResult = ComparatorResult::get();
+ int threshold = (dimension.width * dimension.height) / 100;
+ double diffPercent = (comparatorResult.getDifferentPixelCount() * 100.0) /
+ (dimension.width * dimension.height);
+
+ if (comparatorResult.getDifferentPixelCount() != 0)
+ EXPECT_TRUE(false)
+ << comparatorResult.getDifferentPixelCount() << " pixels ("
+ << diffPercent << "%) are different.";
+
+ if (comparatorResult.getDifferentPixelCount() > threshold) {
+ EXPECT_TRUE(false)
+ << "Mismatched pixel count exceeds threshold. "
+ << "Writing buffers to file.";
+
+ const ::testing::TestInfo* const test_info =
+ ::testing::UnitTest::GetInstance()
+ ->current_test_info();
+
+ EXPECT_EQ(testVirtualDisplay.writeBuffersToFile(
+ test_info->name()), 0)
+ << "Failed to write buffers.";
+ }
+
+ ASSERT_LE(comparatorResult.getDifferentPixelCount(), threshold)
+ << comparatorResult.getDifferentPixelCount() << " pixels ("
+ << diffPercent << "%) are different. "
+ << "Exceeds 1% threshold, terminating test. "
+ << "Test case: " << testLayers.dump();
+
+ } while (testLayers.advance());
+
+ ASSERT_NO_FATAL_FAILURE(destroyLayers(display,
+ std::move(layers)));
+ }
+ ASSERT_NO_FATAL_FAILURE(disableVsync(display));
+ ASSERT_NO_FATAL_FAILURE(setPowerMode(display, HWC2_POWER_MODE_OFF));
+ ASSERT_NO_FATAL_FAILURE(destroyVirtualDisplay(display));
+ } while (testVirtualDisplay.advance());
+ }
+
hwc2_device_t* mHwc2Device = nullptr;
enum class Hwc2TestHotplugStatus {
@@ -4479,7 +4618,7 @@
buffer_handle_t handle;
android::base::unique_fd acquireFence;
- if (testVirtualDisplay->getBuffer(&handle, &acquireFence) >= 0)
+ if (testVirtualDisplay->getOutputBuffer(&handle, &acquireFence) >= 0)
EXPECT_NO_FATAL_FAILURE(test->setOutputBuffer(display,
handle, acquireFence));
}));
@@ -4499,7 +4638,7 @@
ASSERT_NO_FATAL_FAILURE(test->getBadDisplay(&badDisplay));
- if (testVirtualDisplay->getBuffer(&handle, &acquireFence) < 0)
+ if (testVirtualDisplay->getOutputBuffer(&handle, &acquireFence) < 0)
return;
ASSERT_NO_FATAL_FAILURE(test->setOutputBuffer(badDisplay,
@@ -4539,7 +4678,7 @@
android::base::unique_fd acquireFence;
hwc2_error_t err = HWC2_ERROR_NONE;
- if (testVirtualDisplay.getBuffer(&handle, &acquireFence) < 0)
+ if (testVirtualDisplay.getOutputBuffer(&handle, &acquireFence) < 0)
continue;
ASSERT_NO_FATAL_FAILURE(setOutputBuffer(display, handle,
@@ -4557,3 +4696,74 @@
ASSERT_NO_FATAL_FAILURE(dump(&buffer));
}
+
+/*
+ * TODO(b/64724708): Hwc2TestPropertyName::BufferArea MUST be default for all
+ * virtual display tests as we don't handle this case correctly.
+ *
+ * Only default dataspace is supported in our drawing code.
+ */
+const std::unordered_map<Hwc2TestPropertyName, Hwc2TestCoverage>
+ virtualDisplayExceptions =
+ {{Hwc2TestPropertyName::BufferArea, Hwc2TestCoverage::Default},
+ {Hwc2TestPropertyName::Dataspace, Hwc2TestCoverage::Default}};
+
+/* TESTCASE: Tests that the HWC2 can present 1 layer with default coverage on a
+ * virtual display. */
+TEST_F(Hwc2Test, PRESENT_VIRTUAL_DISPLAY_default_1)
+{
+ Hwc2TestCoverage coverage = Hwc2TestCoverage::Default;
+ const size_t layerCnt = 1;
+ ASSERT_NO_FATAL_FAILURE(createAndPresentVirtualDisplay(layerCnt, coverage,
+ virtualDisplayExceptions));
+}
+
+/* TESTCASE: Tests that the HWC2 can present 1 layer with basic coverage on a
+ * virtual display. */
+TEST_F(Hwc2Test, PRESENT_VIRTUAL_DISPLAY_basic_1)
+{
+ Hwc2TestCoverage coverage = Hwc2TestCoverage::Basic;
+ const size_t layerCnt = 1;
+ ASSERT_NO_FATAL_FAILURE(createAndPresentVirtualDisplay(layerCnt, coverage,
+ virtualDisplayExceptions));
+}
+
+/* TESTCASE: Tests that the HWC2 can present 2 layers with default coverage on a
+ * virtual display. */
+TEST_F(Hwc2Test, PRESENT_VIRTUAL_DISPLAY_default_2)
+{
+ Hwc2TestCoverage coverage = Hwc2TestCoverage::Default;
+ const size_t layerCnt = 2;
+ ASSERT_NO_FATAL_FAILURE(createAndPresentVirtualDisplay(layerCnt, coverage,
+ virtualDisplayExceptions));
+}
+
+/* TESTCASE: Tests that the HWC2 can present 3 layers with default coverage on a
+ * virtual display. */
+TEST_F(Hwc2Test, PRESENT_VIRTUAL_DISPLAY_default_3)
+{
+ Hwc2TestCoverage coverage = Hwc2TestCoverage::Default;
+ const size_t layerCnt = 3;
+ ASSERT_NO_FATAL_FAILURE(createAndPresentVirtualDisplay(layerCnt, coverage,
+ virtualDisplayExceptions));
+}
+
+/* TESTCASE: Tests that the HWC2 can present 4 layers with default coverage on a
+ * virtual display. */
+TEST_F(Hwc2Test, PRESENT_VIRTUAL_DISPLAY_default_4)
+{
+ Hwc2TestCoverage coverage = Hwc2TestCoverage::Default;
+ const size_t layerCnt = 4;
+ ASSERT_NO_FATAL_FAILURE(createAndPresentVirtualDisplay(layerCnt, coverage,
+ virtualDisplayExceptions));
+}
+
+/* TESTCASE: Tests that the HWC2 can present 5 layers with default coverage on a
+ * virtual display. */
+TEST_F(Hwc2Test, PRESENT_VIRTUAL_DISPLAY_default_5)
+{
+ Hwc2TestCoverage coverage = Hwc2TestCoverage::Default;
+ const size_t layerCnt = 5;
+ ASSERT_NO_FATAL_FAILURE(createAndPresentVirtualDisplay(layerCnt, coverage,
+ virtualDisplayExceptions));
+}
diff --git a/services/surfaceflinger/tests/hwc2/Hwc2TestBuffer.cpp b/services/surfaceflinger/tests/hwc2/Hwc2TestBuffer.cpp
index 1d3a1d3..6484562 100644
--- a/services/surfaceflinger/tests/hwc2/Hwc2TestBuffer.cpp
+++ b/services/surfaceflinger/tests/hwc2/Hwc2TestBuffer.cpp
@@ -23,14 +23,17 @@
#include <gui/BufferItemConsumer.h>
#include <ui/GraphicBuffer.h>
+#include <android/hardware/graphics/common/1.0/types.h>
#include <math/vec4.h>
#include <GLES3/gl3.h>
-
+#include <SkImageEncoder.h>
+#include <SkStream.h>
#include "Hwc2TestBuffer.h"
#include "Hwc2TestLayers.h"
using namespace android;
+using android::hardware::graphics::common::V1_0::BufferUsage;
/* Returns a fence from egl */
typedef void (*FenceCallback)(int32_t fence, void* callbackArgs);
@@ -396,8 +399,9 @@
{
/* Create new graphic buffer with correct dimensions */
mGraphicBuffer = new GraphicBuffer(mBufferArea.width, mBufferArea.height,
- mFormat, GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_HW_RENDER,
- "hwc2_test_buffer");
+ mFormat, BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN |
+ BufferUsage::COMPOSER_OVERLAY, "hwc2_test_buffer");
+
int ret = mGraphicBuffer->initCheck();
if (ret) {
return ret;
@@ -408,7 +412,8 @@
/* Locks the buffer for writing */
uint8_t* img;
- mGraphicBuffer->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&img));
+ mGraphicBuffer->lock(static_cast<uint32_t>(BufferUsage::CPU_WRITE_OFTEN),
+ (void**)(&img));
uint32_t stride = mGraphicBuffer->getStride();
@@ -458,31 +463,22 @@
Hwc2TestClientTargetBuffer::~Hwc2TestClientTargetBuffer() { }
-/* Generates a client target buffer using the layers assigned for client
- * composition. Takes into account the individual layer properties such as
+/* Generates a buffer from layersToDraw.
+ * Takes into account the individual layer properties such as
* transform, blend mode, source crop, etc. */
-int Hwc2TestClientTargetBuffer::get(buffer_handle_t* outHandle,
- int32_t* outFence, const Area& bufferArea,
+static void compositeBufferFromLayers(
+ const android::sp<android::GraphicBuffer>& graphicBuffer,
+ android_pixel_format_t format, const Area& bufferArea,
const Hwc2TestLayers* testLayers,
- const std::set<hwc2_layer_t>* clientLayers,
+ const std::set<hwc2_layer_t>* layersToDraw,
const std::set<hwc2_layer_t>* clearLayers)
{
- /* Create new graphic buffer with correct dimensions */
- mGraphicBuffer = new GraphicBuffer(bufferArea.width, bufferArea.height,
- mFormat, GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_HW_RENDER,
- "hwc2_test_buffer");
- int ret = mGraphicBuffer->initCheck();
- if (ret) {
- return ret;
- }
- if (!mGraphicBuffer->handle) {
- return -EINVAL;
- }
-
+ /* Locks the buffer for writing */
uint8_t* img;
- mGraphicBuffer->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&img));
+ graphicBuffer->lock(static_cast<uint32_t>(BufferUsage::CPU_WRITE_OFTEN),
+ (void**)(&img));
- uint32_t stride = mGraphicBuffer->getStride();
+ uint32_t stride = graphicBuffer->getStride();
float bWDiv3 = bufferArea.width / 3;
float bW2Div3 = bufferArea.width * 2 / 3;
@@ -497,10 +493,10 @@
uint8_t r = 0, g = 0, b = 0;
float a = 0.0f;
- /* Cycle through each client layer from back to front and
+ /* Cycle through each layer from back to front and
* update the pixel color. */
- for (auto layer = clientLayers->rbegin();
- layer != clientLayers->rend(); ++layer) {
+ for (auto layer = layersToDraw->rbegin();
+ layer != layersToDraw->rend(); ++layer) {
const hwc_rect_t df = testLayers->getDisplayFrame(*layer);
@@ -570,8 +566,8 @@
* (100x50) at the end of the transformation. */
if (transform & HWC_TRANSFORM_ROT_90) {
float tmp = xPos;
- xPos = -yPos * dfW / dfH;
- yPos = tmp * dfH / dfW;
+ xPos = yPos * dfW / dfH;
+ yPos = -tmp * dfH / dfW;
}
/* Change origin back to the top left corner of the
@@ -682,14 +678,114 @@
}
/* Set the pixel color */
- setColor(x, y, mFormat, stride, img, r, g, b, a * 255);
+ setColor(x, y, format, stride, img, r, g, b, a * 255);
}
}
- mGraphicBuffer->unlock();
+ graphicBuffer->unlock();
+}
+
+/* Generates a client target buffer using the layers assigned for client
+ * composition. Takes into account the individual layer properties such as
+ * transform, blend mode, source crop, etc. */
+int Hwc2TestClientTargetBuffer::get(buffer_handle_t* outHandle,
+ int32_t* outFence, const Area& bufferArea,
+ const Hwc2TestLayers* testLayers,
+ const std::set<hwc2_layer_t>* clientLayers,
+ const std::set<hwc2_layer_t>* clearLayers)
+{
+ /* Create new graphic buffer with correct dimensions */
+ mGraphicBuffer = new GraphicBuffer(bufferArea.width, bufferArea.height,
+ mFormat, BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN |
+ BufferUsage::COMPOSER_OVERLAY, "hwc2_test_buffer");
+
+ int ret = mGraphicBuffer->initCheck();
+ if (ret)
+ return ret;
+
+ if (!mGraphicBuffer->handle)
+ return -EINVAL;
+
+ compositeBufferFromLayers(mGraphicBuffer, mFormat, bufferArea, testLayers,
+ clientLayers, clearLayers);
*outFence = mFenceGenerator->get();
*outHandle = mGraphicBuffer->handle;
return 0;
}
+
+void Hwc2TestVirtualBuffer::updateBufferArea(const Area& bufferArea)
+{
+ mBufferArea.width = bufferArea.width;
+ mBufferArea.height = bufferArea.height;
+}
+
+bool Hwc2TestVirtualBuffer::writeBufferToFile(std::string path)
+{
+ SkFILEWStream file(path.c_str());
+ const SkImageInfo info = SkImageInfo::Make(mBufferArea.width,
+ mBufferArea.height, SkColorType::kRGBA_8888_SkColorType,
+ SkAlphaType::kPremul_SkAlphaType);
+
+ uint8_t* img;
+ mGraphicBuffer->lock(static_cast<uint32_t>(BufferUsage::CPU_WRITE_OFTEN),
+ (void**)(&img));
+
+ SkPixmap pixmap(info, img, mGraphicBuffer->getStride());
+ bool result = file.isValid() && SkEncodeImage(&file, pixmap,
+ SkEncodedImageFormat::kPNG, 100);
+
+ mGraphicBuffer->unlock();
+ return result;
+}
+
+/* Generates a buffer that holds the expected result of compositing all of our
+ * layers */
+int Hwc2TestExpectedBuffer::generateExpectedBuffer(
+ const Hwc2TestLayers* testLayers,
+ const std::vector<hwc2_layer_t>* allLayers,
+ const std::set<hwc2_layer_t>* clearLayers)
+{
+ mGraphicBuffer = new GraphicBuffer(mBufferArea.width, mBufferArea.height,
+ mFormat, BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN,
+ "hwc2_test_buffer");
+
+ int ret = mGraphicBuffer->initCheck();
+ if (ret)
+ return ret;
+
+ if (!mGraphicBuffer->handle)
+ return -EINVAL;
+
+ const std::set<hwc2_layer_t> allLayerSet(allLayers->begin(),
+ allLayers->end());
+
+ compositeBufferFromLayers(mGraphicBuffer, mFormat, mBufferArea, testLayers,
+ &allLayerSet, clearLayers);
+
+ return 0;
+}
+
+int Hwc2TestOutputBuffer::getOutputBuffer(buffer_handle_t* outHandle,
+ int32_t* outFence)
+{
+ if (mBufferArea.width == -1 || mBufferArea.height == -1)
+ return -EINVAL;
+
+ mGraphicBuffer = new GraphicBuffer(mBufferArea.width, mBufferArea.height,
+ mFormat, BufferUsage::CPU_READ_OFTEN |
+ BufferUsage::GPU_RENDER_TARGET, "hwc2_test_buffer");
+
+ int ret = mGraphicBuffer->initCheck();
+ if (ret)
+ return ret;
+
+ if (!mGraphicBuffer->handle)
+ return -EINVAL;
+
+ *outFence = -1;
+ *outHandle = mGraphicBuffer->handle;
+
+ return 0;
+}
diff --git a/services/surfaceflinger/tests/hwc2/Hwc2TestBuffer.h b/services/surfaceflinger/tests/hwc2/Hwc2TestBuffer.h
index b2b3a66..fd54fef 100644
--- a/services/surfaceflinger/tests/hwc2/Hwc2TestBuffer.h
+++ b/services/surfaceflinger/tests/hwc2/Hwc2TestBuffer.h
@@ -71,4 +71,38 @@
const android_pixel_format_t mFormat = HAL_PIXEL_FORMAT_RGBA_8888;
};
+
+class Hwc2TestVirtualBuffer {
+public:
+ void updateBufferArea(const Area& bufferArea);
+
+ bool writeBufferToFile(std::string path);
+
+ android::sp<android::GraphicBuffer>& graphicBuffer()
+ {
+ return mGraphicBuffer;
+ }
+
+protected:
+ android::sp<android::GraphicBuffer> mGraphicBuffer;
+
+ Area mBufferArea = {-1, -1};
+
+ const android_pixel_format_t mFormat = HAL_PIXEL_FORMAT_RGBA_8888;
+};
+
+
+class Hwc2TestExpectedBuffer : public Hwc2TestVirtualBuffer {
+public:
+ int generateExpectedBuffer(const Hwc2TestLayers* testLayers,
+ const std::vector<hwc2_layer_t>* allLayers,
+ const std::set<hwc2_layer_t>* clearLayers);
+};
+
+
+class Hwc2TestOutputBuffer : public Hwc2TestVirtualBuffer {
+public:
+ int getOutputBuffer(buffer_handle_t* outHandle, int32_t* outFence);
+};
+
#endif /* ifndef _HWC2_TEST_BUFFER_H */
diff --git a/services/surfaceflinger/tests/hwc2/Hwc2TestPixelComparator.cpp b/services/surfaceflinger/tests/hwc2/Hwc2TestPixelComparator.cpp
new file mode 100644
index 0000000..904b927
--- /dev/null
+++ b/services/surfaceflinger/tests/hwc2/Hwc2TestPixelComparator.cpp
@@ -0,0 +1,113 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <sstream>
+#include <android/hardware/graphics/common/1.0/types.h>
+
+#include "Hwc2TestPixelComparator.h"
+
+using android::hardware::graphics::common::V1_0::BufferUsage;
+
+uint32_t ComparatorResult::getPixel(int32_t x, int32_t y, uint32_t stride,
+ uint8_t* img) const
+{
+ uint32_t r = img[(y * stride + x) * 4 + 0];
+ uint32_t g = img[(y * stride + x) * 4 + 1];
+ uint32_t b = img[(y * stride + x) * 4 + 2];
+ uint32_t a = img[(y * stride + x) * 4 + 3];
+
+ uint32_t pixel = 0;
+ pixel |= r;
+ pixel |= g << 8;
+ pixel |= b << 16;
+ pixel |= a << 24;
+ return pixel;
+}
+
+void ComparatorResult::CompareBuffers(
+ android::sp<android::GraphicBuffer>& resultBuffer,
+ android::sp<android::GraphicBuffer>& expectedBuffer)
+{
+ uint8_t* resultBufferImg;
+ uint8_t* expectedBufferImg;
+ resultBuffer->lock(static_cast<uint32_t>(BufferUsage::CPU_READ_OFTEN),
+ (void**)(&resultBufferImg));
+
+ expectedBuffer->lock(static_cast<uint32_t>(BufferUsage::CPU_READ_OFTEN),
+ (void**)(&expectedBufferImg));
+ mComparisons.clear();
+ int32_t mDifferentPixelCount = 0;
+ int32_t mBlankPixelCount = 0;
+
+ for (uint32_t y = 0; y < resultBuffer->getHeight(); y++) {
+ for (uint32_t x = 0; x < resultBuffer->getWidth(); x++) {
+ uint32_t result = getPixel(x, y, resultBuffer->getStride(),
+ resultBufferImg);
+ uint32_t expected = getPixel(x, y, expectedBuffer->getStride(),
+ expectedBufferImg);
+
+ if (result == 0)
+ mBlankPixelCount++;
+
+ if (result != expected)
+ mDifferentPixelCount++;
+
+ mComparisons.emplace_back(std::make_tuple(x, y, result, expected));
+ }
+ }
+ resultBuffer->unlock();
+ expectedBuffer->unlock();
+}
+
+std::string ComparatorResult::pixelDiff(uint32_t x, uint32_t y,
+ uint32_t resultPixel, uint32_t expectedPixel) const
+{
+ uint32_t resultAlpha = (resultPixel >> 24) & 0xFF;
+ uint32_t resultBlue = (resultPixel >> 16) & 0xFF;
+ uint32_t resultGreen = (resultPixel >> 8) & 0xFF;
+ uint32_t resultRed = resultPixel & 0xFF;
+
+ uint32_t expectedAlpha = (expectedPixel >> 24) & 0xFF;
+ uint32_t expectedBlue = (expectedPixel >> 16) & 0xFF;
+ uint32_t expectedGreen = (expectedPixel >> 8) & 0xFF;
+ uint32_t expectedRed = expectedPixel & 0xFF;
+
+ std::ostringstream stream;
+
+ stream << "x: " << x << " y: " << y << std::endl;
+ stream << std::hex;
+ stream << "Result pixel: " << resultRed << "|" << resultGreen << "|"
+ << resultBlue << "|" << resultAlpha << std::endl;
+
+ stream << "Expected pixel: " << expectedRed << "|" << expectedGreen << "|"
+ << expectedBlue << "|" << expectedAlpha << std::endl;
+
+ return stream.str();
+}
+
+std::string ComparatorResult::dumpComparison() const
+{
+ std::ostringstream stream;
+ stream << "Number of different pixels: " << mDifferentPixelCount;
+
+ for (const auto& comparison : mComparisons) {
+ if (std::get<2>(comparison) != std::get<3>(comparison))
+ stream << pixelDiff(std::get<0>(comparison),
+ std::get<1>(comparison), std::get<2>(comparison),
+ std::get<3>(comparison));
+ }
+ return stream.str();
+}
diff --git a/services/surfaceflinger/tests/hwc2/Hwc2TestPixelComparator.h b/services/surfaceflinger/tests/hwc2/Hwc2TestPixelComparator.h
new file mode 100644
index 0000000..55fa936
--- /dev/null
+++ b/services/surfaceflinger/tests/hwc2/Hwc2TestPixelComparator.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef _HWC2_TEST_PIXEL_COMPARATOR_H
+#define _HWC2_TEST_PIXEL_COMPARATOR_H
+
+#include <ui/GraphicBuffer.h>
+#include <cstdint>
+#include <string>
+#include <utility>
+#include <vector>
+
+class ComparatorResult {
+public:
+ static ComparatorResult& get()
+ {
+ static ComparatorResult instance;
+ return instance;
+ }
+
+ void CompareBuffers(android::sp<android::GraphicBuffer>& resultBuffer,
+ android::sp<android::GraphicBuffer>& expectedBuffer);
+
+ std::string dumpComparison() const;
+
+ ComparatorResult(const ComparatorResult&) = delete;
+ ComparatorResult(ComparatorResult&&) = delete;
+ ComparatorResult& operator=(ComparatorResult const&) = delete;
+ ComparatorResult& operator=(ComparatorResult&&) = delete;
+
+ int32_t getDifferentPixelCount() const { return mDifferentPixelCount; }
+ int32_t getBlankPixelCount() const { return mBlankPixelCount; }
+
+private:
+ ComparatorResult() = default;
+ uint32_t getPixel(int32_t x, int32_t y, uint32_t stride, uint8_t* img) const;
+ std::string pixelDiff(uint32_t x, uint32_t y, uint32_t resultPixel,
+ uint32_t expectedPixel) const;
+
+ int32_t mDifferentPixelCount;
+ int32_t mBlankPixelCount;
+ /* std::tuple<X coordinate, Y coordinate, resultPixel, expectedPixel> */
+ std::vector<std::tuple<uint32_t, uint32_t, uint32_t, uint32_t>>
+ mComparisons;
+};
+
+#endif /* ifndef _HWC2_TEST_PIXEL_COMPARATOR_H */
diff --git a/services/surfaceflinger/tests/hwc2/Hwc2TestProperties.cpp b/services/surfaceflinger/tests/hwc2/Hwc2TestProperties.cpp
index b5522de..5b3bbeb 100644
--- a/services/surfaceflinger/tests/hwc2/Hwc2TestProperties.cpp
+++ b/services/surfaceflinger/tests/hwc2/Hwc2TestProperties.cpp
@@ -335,9 +335,9 @@
return dmp.str();
}
-void Hwc2TestDisplayDimension::setDependent(Hwc2TestBuffer* buffer)
+void Hwc2TestDisplayDimension::setDependent(Hwc2TestVirtualBuffer* buffer)
{
- mBuffer = buffer;
+ mBuffers.insert(buffer);
updateDependents();
}
@@ -345,8 +345,8 @@
{
const UnsignedArea& curr = get();
- if (mBuffer)
- mBuffer->updateBufferArea({static_cast<int32_t>(curr.width),
+ for (Hwc2TestVirtualBuffer* buffer : mBuffers)
+ buffer->updateBufferArea({static_cast<int32_t>(curr.width),
static_cast<int32_t>(curr.height)});
}
diff --git a/services/surfaceflinger/tests/hwc2/Hwc2TestProperties.h b/services/surfaceflinger/tests/hwc2/Hwc2TestProperties.h
index c2029ab..cb811e0 100644
--- a/services/surfaceflinger/tests/hwc2/Hwc2TestProperties.h
+++ b/services/surfaceflinger/tests/hwc2/Hwc2TestProperties.h
@@ -243,6 +243,7 @@
static const std::array<bool, 6> mCompositionSupport;
};
+class Hwc2TestVirtualBuffer;
class Hwc2TestDisplayDimension : public Hwc2TestProperty<UnsignedArea> {
public:
@@ -250,12 +251,12 @@
std::string dump() const;
- void setDependent(Hwc2TestBuffer* buffer);
+ void setDependent(Hwc2TestVirtualBuffer* buffer);
private:
void updateDependents();
- Hwc2TestBuffer* mBuffer;
+ std::set<Hwc2TestVirtualBuffer*> mBuffers;
static const std::vector<UnsignedArea> mDefaultDisplayDimensions;
static const std::vector<UnsignedArea> mBasicDisplayDimensions;
diff --git a/services/surfaceflinger/tests/hwc2/Hwc2TestVirtualDisplay.cpp b/services/surfaceflinger/tests/hwc2/Hwc2TestVirtualDisplay.cpp
index d0fbc0b..e6cceb8 100644
--- a/services/surfaceflinger/tests/hwc2/Hwc2TestVirtualDisplay.cpp
+++ b/services/surfaceflinger/tests/hwc2/Hwc2TestVirtualDisplay.cpp
@@ -15,14 +15,18 @@
*/
#include <sstream>
+#include <sys/stat.h>
#include "Hwc2TestVirtualDisplay.h"
+#define DIR_NAME "images"
+
Hwc2TestVirtualDisplay::Hwc2TestVirtualDisplay(
Hwc2TestCoverage coverage)
: mDisplayDimension(coverage)
{
- mDisplayDimension.setDependent(&mBuffer);
+ mDisplayDimension.setDependent(&mOutputBuffer);
+ mDisplayDimension.setDependent(&mExpectedBuffer);
}
std::string Hwc2TestVirtualDisplay::dump() const
@@ -36,11 +40,11 @@
return dmp.str();
}
-int Hwc2TestVirtualDisplay::getBuffer(buffer_handle_t* outHandle,
+int Hwc2TestVirtualDisplay::getOutputBuffer(buffer_handle_t* outHandle,
android::base::unique_fd* outAcquireFence)
{
int32_t acquireFence;
- int ret = mBuffer.get(outHandle, &acquireFence);
+ int ret = mOutputBuffer.getOutputBuffer(outHandle, &acquireFence);
outAcquireFence->reset(acquireFence);
return ret;
}
@@ -59,3 +63,36 @@
{
return mDisplayDimension.get();
}
+
+int Hwc2TestVirtualDisplay::verifyOutputBuffer(const Hwc2TestLayers* testLayers,
+ const std::vector<hwc2_layer_t>* allLayers,
+ const std::set<hwc2_layer_t>* clearLayers)
+{
+ int ret = mExpectedBuffer.generateExpectedBuffer(testLayers, allLayers,
+ clearLayers);
+ if (ret)
+ return ret;
+
+ ComparatorResult::get().CompareBuffers(mOutputBuffer.graphicBuffer(),
+ mExpectedBuffer.graphicBuffer());
+
+ return 0;
+}
+
+int Hwc2TestVirtualDisplay::writeBuffersToFile(std::string name)
+{
+ std::ostringstream expectedPath;
+ std::ostringstream resultPath;
+ int ret = mkdir(DIR_NAME, DEFFILEMODE);
+ if (ret && errno != EEXIST)
+ return ret;
+
+ expectedPath << DIR_NAME << "/expected-" << name << ".png";
+ resultPath << DIR_NAME << "/result-" << name << ".png";
+
+ if (!mExpectedBuffer.writeBufferToFile(expectedPath.str()) ||
+ !mOutputBuffer.writeBufferToFile(resultPath.str()))
+ return -1;
+
+ return 0;
+}
diff --git a/services/surfaceflinger/tests/hwc2/Hwc2TestVirtualDisplay.h b/services/surfaceflinger/tests/hwc2/Hwc2TestVirtualDisplay.h
index 09420ef..10c8ef0 100644
--- a/services/surfaceflinger/tests/hwc2/Hwc2TestVirtualDisplay.h
+++ b/services/surfaceflinger/tests/hwc2/Hwc2TestVirtualDisplay.h
@@ -18,6 +18,7 @@
#define _HWC2_TEST_VIRTUAL_DISPLAY_H
#include "Hwc2TestBuffer.h"
+#include "Hwc2TestPixelComparator.h"
#include "Hwc2TestProperties.h"
#define HWC2_INCLUDE_STRINGIFICATION
@@ -32,17 +33,22 @@
std::string dump() const;
- int getBuffer(buffer_handle_t* outHandle,
+ int getOutputBuffer(buffer_handle_t* outHandle,
android::base::unique_fd* outAcquireFence);
+ int verifyOutputBuffer(const Hwc2TestLayers* testLayers,
+ const std::vector<hwc2_layer_t>* allLayers,
+ const std::set<hwc2_layer_t>* clearLayers);
+
+ int writeBuffersToFile(std::string name);
void reset();
bool advance();
UnsignedArea getDisplayDimension() const;
private:
- Hwc2TestBuffer mBuffer;
-
+ Hwc2TestOutputBuffer mOutputBuffer;
+ Hwc2TestExpectedBuffer mExpectedBuffer;
Hwc2TestDisplayDimension mDisplayDimension;
};
diff --git a/services/thermalservice/thermalservice.rc b/services/thermalservice/thermalservice.rc
index b9836ce..94c2c78 100644
--- a/services/thermalservice/thermalservice.rc
+++ b/services/thermalservice/thermalservice.rc
@@ -1,2 +1,4 @@
service thermalservice /system/bin/thermalserviced
class core
+ user system
+ group system
diff --git a/services/utils/Android.bp b/services/utils/Android.bp
new file mode 100644
index 0000000..6132956
--- /dev/null
+++ b/services/utils/Android.bp
@@ -0,0 +1,34 @@
+// Copyright (C) 2017 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+//
+// Static library used in testing and executables
+//
+cc_library_static {
+ name: "libserviceutils",
+
+ cflags: [
+ "-Wall",
+ "-Werror",
+ ],
+
+ srcs: [
+ "PriorityDumper.cpp",
+ ],
+
+ clang: true,
+ export_include_dirs: ["include"],
+}
+
+subdirs = ["tests"]
diff --git a/services/utils/PriorityDumper.cpp b/services/utils/PriorityDumper.cpp
new file mode 100644
index 0000000..967dee5
--- /dev/null
+++ b/services/utils/PriorityDumper.cpp
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "include/serviceutils/PriorityDumper.h"
+
+namespace android {
+
+const char16_t PriorityDumper::PROTO_ARG[] = u"--proto";
+const char16_t PriorityDumper::PRIORITY_ARG[] = u"--dump-priority";
+const char16_t PriorityDumper::PRIORITY_ARG_CRITICAL[] = u"CRITICAL";
+const char16_t PriorityDumper::PRIORITY_ARG_HIGH[] = u"HIGH";
+const char16_t PriorityDumper::PRIORITY_ARG_NORMAL[] = u"NORMAL";
+
+enum class PriorityType { INVALID, CRITICAL, HIGH, NORMAL };
+
+static PriorityType getPriorityType(const String16& arg) {
+ if (arg == PriorityDumper::PRIORITY_ARG_CRITICAL) {
+ return PriorityType::CRITICAL;
+ } else if (arg == PriorityDumper::PRIORITY_ARG_HIGH) {
+ return PriorityType::HIGH;
+ } else if (arg == PriorityDumper::PRIORITY_ARG_NORMAL) {
+ return PriorityType::NORMAL;
+ }
+ return PriorityType::INVALID;
+}
+
+status_t PriorityDumper::dumpAll(int fd, const Vector<String16>& args, bool asProto) {
+ status_t status;
+ status = dumpCritical(fd, args, asProto);
+ if (status != OK) return status;
+ status = dumpHigh(fd, args, asProto);
+ if (status != OK) return status;
+ status = dumpNormal(fd, args, asProto);
+ if (status != OK) return status;
+ return status;
+}
+
+status_t PriorityDumper::priorityDump(int fd, const Vector<String16>& args) {
+ status_t status;
+ bool asProto = false;
+ PriorityType priority = PriorityType::INVALID;
+
+ Vector<String16> strippedArgs;
+ for (uint32_t argIndex = 0; argIndex < args.size(); argIndex++) {
+ if (args[argIndex] == PROTO_ARG) {
+ asProto = true;
+ } else if (args[argIndex] == PRIORITY_ARG) {
+ if (argIndex + 1 < args.size()) {
+ argIndex++;
+ priority = getPriorityType(args[argIndex]);
+ }
+ } else {
+ strippedArgs.add(args[argIndex]);
+ }
+ }
+
+ switch (priority) {
+ case PriorityType::CRITICAL:
+ status = dumpCritical(fd, strippedArgs, asProto);
+ break;
+ case PriorityType::HIGH:
+ status = dumpHigh(fd, strippedArgs, asProto);
+ break;
+ case PriorityType::NORMAL:
+ status = dumpNormal(fd, strippedArgs, asProto);
+ break;
+ default:
+ status = dumpAll(fd, strippedArgs, asProto);
+ break;
+ }
+ return status;
+}
+} // namespace android
diff --git a/services/utils/include/serviceutils/PriorityDumper.h b/services/utils/include/serviceutils/PriorityDumper.h
new file mode 100644
index 0000000..d01a102
--- /dev/null
+++ b/services/utils/include/serviceutils/PriorityDumper.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_UTILS_PRIORITYDUMPER_H
+#define ANDROID_UTILS_PRIORITYDUMPER_H
+
+#include <utils/Errors.h>
+#include <utils/String16.h>
+#include <utils/Vector.h>
+
+namespace android {
+
+// Helper class to parse common arguments responsible for splitting dumps into
+// various priority buckets and changing the output format of the dump.
+class PriorityDumper {
+public:
+ static const char16_t PRIORITY_ARG[];
+ static const char16_t PRIORITY_ARG_CRITICAL[];
+ static const char16_t PRIORITY_ARG_HIGH[];
+ static const char16_t PRIORITY_ARG_NORMAL[];
+ static const char16_t PROTO_ARG[];
+
+ // Parses the argument list searching for --dump_priority with a priority type
+ // (HIGH, CRITICAL or NORMAL) and --proto. Matching arguments are stripped.
+ // If a valid priority type is found, the associated PriorityDumper
+ // method is called otherwise all supported sections are dumped.
+ // If --proto is found, the dumpAsProto flag is set to dump sections in proto
+ // format.
+ status_t priorityDump(int fd, const Vector<String16>& args);
+
+ // Dumps CRITICAL priority sections.
+ virtual status_t dumpCritical(int /*fd*/, const Vector<String16>& /*args*/, bool /*asProto*/) {
+ return OK;
+ }
+
+ // Dumps HIGH priority sections.
+ virtual status_t dumpHigh(int /*fd*/, const Vector<String16>& /*args*/, bool /*asProto*/) {
+ return OK;
+ }
+
+ // Dumps normal priority sections.
+ virtual status_t dumpNormal(int /*fd*/, const Vector<String16>& /*args*/, bool /*asProto*/) {
+ return OK;
+ }
+
+ // Dumps all sections.
+ // This method is called when priorityDump is called without priority
+ // arguments. By default, it calls all three dump methods.
+ virtual status_t dumpAll(int fd, const Vector<String16>& args, bool asProto);
+ virtual ~PriorityDumper() = default;
+};
+
+} // namespace android
+
+#endif // ANDROID_UTILS_PRIORITYDUMPER_H
diff --git a/services/utils/tests/Android.bp b/services/utils/tests/Android.bp
new file mode 100644
index 0000000..15829fa
--- /dev/null
+++ b/services/utils/tests/Android.bp
@@ -0,0 +1,29 @@
+// Copyright (C) 2017 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Build unit tests.
+
+cc_test {
+ name: "prioritydumper_test",
+ test_suites: ["device-tests"],
+ srcs: [ "PriorityDumper_test.cpp"],
+ shared_libs: [
+ "libutils",
+ ],
+ static_libs = [
+ "libgmock",
+ "libserviceutils"
+ ],
+ clang: true,
+}
\ No newline at end of file
diff --git a/services/utils/tests/AndroidTest.xml b/services/utils/tests/AndroidTest.xml
new file mode 100644
index 0000000..83c890d
--- /dev/null
+++ b/services/utils/tests/AndroidTest.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<configuration description="Config for prioritydumper_test">
+ <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
+ <option name="cleanup" value="true" />
+ <option name="push" value="prioritydumper_test->/data/local/tmp/prioritydumper_test" />
+ </target_preparer>
+ <option name="test-suite-tag" value="apct" />
+ <test class="com.android.tradefed.testtype.GTest" >
+ <option name="native-test-device-path" value="/data/local/tmp" />
+ <option name="module-name" value="prioritydumper_test" />
+ </test>
+</configuration>
\ No newline at end of file
diff --git a/services/utils/tests/PriorityDumper_test.cpp b/services/utils/tests/PriorityDumper_test.cpp
new file mode 100644
index 0000000..90cc6de
--- /dev/null
+++ b/services/utils/tests/PriorityDumper_test.cpp
@@ -0,0 +1,219 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "serviceutils/PriorityDumper.h"
+
+#include <vector>
+
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+
+#include <utils/String16.h>
+#include <utils/Vector.h>
+
+using namespace android;
+
+using ::testing::ElementsAreArray;
+using ::testing::Mock;
+using ::testing::Test;
+
+class PriorityDumperMock : public PriorityDumper {
+public:
+ MOCK_METHOD3(dumpCritical, status_t(int, const Vector<String16>&, bool));
+ MOCK_METHOD3(dumpHigh, status_t(int, const Vector<String16>&, bool));
+ MOCK_METHOD3(dumpNormal, status_t(int, const Vector<String16>&, bool));
+ MOCK_METHOD3(dumpAll, status_t(int, const Vector<String16>&, bool));
+};
+
+class DumpAllMock : public PriorityDumper {
+public:
+ MOCK_METHOD3(dumpCritical, status_t(int, const Vector<String16>&, bool));
+ MOCK_METHOD3(dumpHigh, status_t(int, const Vector<String16>&, bool));
+ MOCK_METHOD3(dumpNormal, status_t(int, const Vector<String16>&, bool));
+};
+
+class PriorityDumperTest : public Test {
+public:
+ PriorityDumperTest() : dumper_(), dumpAlldumper_(), fd(1) {}
+ PriorityDumperMock dumper_;
+ DumpAllMock dumpAlldumper_;
+ int fd;
+};
+
+static void addAll(Vector<String16>& av, const std::vector<std::string>& v) {
+ for (auto element : v) {
+ av.add(String16(element.c_str()));
+ }
+}
+
+TEST_F(PriorityDumperTest, noArgsPassed) {
+ Vector<String16> args;
+ EXPECT_CALL(dumper_, dumpAll(fd, ElementsAreArray(args), /*asProto=*/false));
+ dumper_.priorityDump(fd, args);
+}
+
+TEST_F(PriorityDumperTest, noPriorityArgsPassed) {
+ Vector<String16> args;
+ addAll(args, {"bunch", "of", "args"});
+ EXPECT_CALL(dumper_, dumpAll(fd, ElementsAreArray(args), /*asProto=*/false));
+ dumper_.priorityDump(fd, args);
+}
+
+TEST_F(PriorityDumperTest, priorityArgsOnly) {
+ Vector<String16> args;
+ addAll(args, {"--dump-priority", "CRITICAL"});
+ Vector<String16> strippedArgs;
+ EXPECT_CALL(dumper_, dumpCritical(fd, ElementsAreArray(strippedArgs), /*asProto=*/false));
+ dumper_.priorityDump(fd, args);
+}
+
+TEST_F(PriorityDumperTest, dumpCritical) {
+ Vector<String16> args;
+ addAll(args, {"--dump-priority", "CRITICAL", "args", "left", "behind"});
+ Vector<String16> strippedArgs;
+ addAll(strippedArgs, {"args", "left", "behind"});
+
+ EXPECT_CALL(dumper_, dumpCritical(fd, ElementsAreArray(strippedArgs), /*asProto=*/false));
+ dumper_.priorityDump(fd, args);
+}
+
+TEST_F(PriorityDumperTest, dumpCriticalInMiddle) {
+ Vector<String16> args;
+ addAll(args, {"args", "left", "--dump-priority", "CRITICAL", "behind"});
+ Vector<String16> strippedArgs;
+ addAll(strippedArgs, {"args", "left", "behind"});
+
+ EXPECT_CALL(dumper_, dumpCritical(fd, ElementsAreArray(strippedArgs), /*asProto=*/false));
+ dumper_.priorityDump(fd, args);
+}
+
+TEST_F(PriorityDumperTest, dumpHigh) {
+ Vector<String16> args;
+ addAll(args, {"--dump-priority", "HIGH", "args", "left", "behind"});
+ Vector<String16> strippedArgs;
+ addAll(strippedArgs, {"args", "left", "behind"});
+
+ EXPECT_CALL(dumper_, dumpHigh(fd, ElementsAreArray(strippedArgs), /*asProto=*/false));
+ dumper_.priorityDump(fd, args);
+}
+
+TEST_F(PriorityDumperTest, dumpHighInEnd) {
+ Vector<String16> args;
+ addAll(args, {"args", "left", "behind", "--dump-priority", "HIGH"});
+ Vector<String16> strippedArgs;
+ addAll(strippedArgs, {"args", "left", "behind"});
+
+ EXPECT_CALL(dumper_, dumpHigh(fd, ElementsAreArray(strippedArgs), /*asProto=*/false));
+ dumper_.priorityDump(fd, args);
+}
+
+TEST_F(PriorityDumperTest, dumpNormal) {
+ Vector<String16> args;
+ addAll(args, {"--dump-priority", "NORMAL", "args", "left", "behind"});
+ Vector<String16> strippedArgs;
+ addAll(strippedArgs, {"args", "left", "behind"});
+
+ EXPECT_CALL(dumper_, dumpNormal(fd, ElementsAreArray(strippedArgs), /*asProto=*/false));
+ dumper_.priorityDump(fd, args);
+}
+
+TEST_F(PriorityDumperTest, dumpAll) {
+ Vector<String16> args;
+ addAll(args, {"args", "left", "behind"});
+
+ EXPECT_CALL(dumpAlldumper_, dumpCritical(fd, ElementsAreArray(args), /*asProto=*/false));
+ EXPECT_CALL(dumpAlldumper_, dumpHigh(fd, ElementsAreArray(args), /*asProto=*/false));
+ EXPECT_CALL(dumpAlldumper_, dumpNormal(fd, ElementsAreArray(args), /*asProto=*/false));
+
+ dumpAlldumper_.priorityDump(fd, args);
+}
+
+TEST_F(PriorityDumperTest, priorityArgWithPriorityMissing) {
+ Vector<String16> args;
+ addAll(args, {"--dump-priority"});
+ Vector<String16> strippedArgs;
+ EXPECT_CALL(dumper_, dumpAll(fd, ElementsAreArray(strippedArgs), /*asProto=*/false));
+
+ dumper_.priorityDump(fd, args);
+}
+
+TEST_F(PriorityDumperTest, priorityArgWithInvalidPriority) {
+ Vector<String16> args;
+ addAll(args, {"--dump-priority", "REALLY_HIGH"});
+ Vector<String16> strippedArgs;
+ EXPECT_CALL(dumper_, dumpAll(fd, ElementsAreArray(strippedArgs), /*asProto=*/false));
+
+ dumper_.priorityDump(fd, args);
+}
+
+TEST_F(PriorityDumperTest, protoArg) {
+ Vector<String16> args;
+ addAll(args, {"--proto"});
+ Vector<String16> strippedArgs;
+ EXPECT_CALL(dumper_, dumpAll(fd, ElementsAreArray(strippedArgs), /*asProto=*/true));
+
+ dumper_.priorityDump(fd, args);
+}
+
+TEST_F(PriorityDumperTest, protoArgWithPriorityArgs) {
+ Vector<String16> args;
+ addAll(args, {"--proto", "args", "--dump-priority", "NORMAL", "left", "behind"});
+ Vector<String16> strippedArgs;
+ addAll(strippedArgs, {"args", "left", "behind"});
+ EXPECT_CALL(dumper_, dumpNormal(fd, ElementsAreArray(strippedArgs), /*asProto=*/true));
+
+ dumper_.priorityDump(fd, args);
+}
+
+TEST_F(PriorityDumperTest, protoArgWithPriorityArgsInReverseOrder) {
+ Vector<String16> args;
+ addAll(args, {"--dump-priority", "NORMAL", "--proto", "args", "left", "behind"});
+ Vector<String16> strippedArgs;
+ addAll(strippedArgs, {"args", "left", "behind"});
+ EXPECT_CALL(dumper_, dumpNormal(fd, ElementsAreArray(strippedArgs), /*asProto=*/true));
+
+ dumper_.priorityDump(fd, args);
+}
+
+TEST_F(PriorityDumperTest, protoArgInMiddle) {
+ Vector<String16> args;
+ addAll(args, {"--unknown", "args", "--proto", "args", "left", "behind"});
+ Vector<String16> strippedArgs;
+ addAll(strippedArgs, {"--unknown", "args", "args", "left", "behind"});
+ EXPECT_CALL(dumper_, dumpAll(fd, ElementsAreArray(strippedArgs), /*asProto=*/true));
+
+ dumper_.priorityDump(fd, args);
+}
+
+TEST_F(PriorityDumperTest, protoArgAtEnd) {
+ Vector<String16> args;
+ addAll(args, {"--unknown", "args", "args", "left", "behind", "--proto"});
+ Vector<String16> strippedArgs;
+ addAll(strippedArgs, {"--unknown", "args", "args", "left", "behind"});
+ EXPECT_CALL(dumper_, dumpAll(fd, ElementsAreArray(strippedArgs), /*asProto=*/true));
+
+ dumper_.priorityDump(fd, args);
+}
+
+TEST_F(PriorityDumperTest, protoArgWithInvalidPriorityType) {
+ Vector<String16> args;
+ addAll(args, {"--dump-priority", "NOT_SO_HIGH", "--proto", "args", "left", "behind"});
+ Vector<String16> strippedArgs;
+ addAll(strippedArgs, {"args", "left", "behind"});
+ EXPECT_CALL(dumper_, dumpAll(fd, ElementsAreArray(strippedArgs), /*asProto=*/true));
+
+ dumper_.priorityDump(fd, args);
+}
\ No newline at end of file
diff --git a/services/vr/bufferhubd/Android.mk b/services/vr/bufferhubd/Android.mk
index 28cf53d..e1997d7 100644
--- a/services/vr/bufferhubd/Android.mk
+++ b/services/vr/bufferhubd/Android.mk
@@ -32,6 +32,7 @@
sharedLibraries := \
libbase \
+ libbinder \
libcutils \
liblog \
libsync \
diff --git a/services/vr/hardware_composer/Android.bp b/services/vr/hardware_composer/Android.bp
index e92b8d8..76ec42d 100644
--- a/services/vr/hardware_composer/Android.bp
+++ b/services/vr/hardware_composer/Android.bp
@@ -20,6 +20,7 @@
"android.hardware.graphics.composer@2.1",
"android.hardware.graphics.mapper@2.0",
"libbase",
+ "libbinder",
"libcutils",
"libfmq",
"libhardware",
diff --git a/vulkan/api/vulkan.api b/vulkan/api/vulkan.api
index 2981a95..2bbe5e6 100644
--- a/vulkan/api/vulkan.api
+++ b/vulkan/api/vulkan.api
@@ -27,7 +27,7 @@
// API version (major.minor.patch)
define VERSION_MAJOR 1
-define VERSION_MINOR 0
+define VERSION_MINOR 1
define VERSION_PATCH 61
// API limits
@@ -37,11 +37,10 @@
define VK_MAX_DESCRIPTION_SIZE 256
define VK_MAX_MEMORY_TYPES 32
define VK_MAX_MEMORY_HEAPS 16 /// The maximum number of unique memory heaps, each of which supporting 1 or more memory types.
-define VK_MAX_DEVICE_GROUP_SIZE_KHX 32
-//@extension("VK_KHR_external_memory_capabilities")
-define VK_LUID_SIZE_KHR 8
-//@extension("VK_KHR_external_memory")
-define VK_QUEUE_FAMILY_EXTERNAL_KHR -2
+@vulkan1_1
+define VK_MAX_DEVICE_GROUP_SIZE 32
+define VK_LUID_SIZE 8
+define VK_QUEUE_FAMILY_EXTERNAL -2
// API keywords
define VK_TRUE 1
@@ -55,7 +54,7 @@
@extension("VK_KHR_surface") define VK_KHR_SURFACE_EXTENSION_NAME "VK_KHR_surface"
// 2
-@extension("VK_KHR_swapchain") define VK_KHR_SWAPCHAIN_SPEC_VERSION 68
+@extension("VK_KHR_swapchain") define VK_KHR_SWAPCHAIN_SPEC_VERSION 70
@extension("VK_KHR_swapchain") define VK_KHR_SWAPCHAIN_EXTENSION_NAME "VK_KHR_swapchain"
// 3
@@ -95,7 +94,7 @@
@extension("VK_ANDROID_native_buffer") define VK_ANDROID_NATIVE_BUFFER_NAME "VK_ANDROID_native_buffer"
// 12
-@extension("VK_EXT_debug_report") define VK_EXT_DEBUG_REPORT_SPEC_VERSION 8
+@extension("VK_EXT_debug_report") define VK_EXT_DEBUG_REPORT_SPEC_VERSION 9
@extension("VK_EXT_debug_report") define VK_EXT_DEBUG_REPORT_NAME "VK_EXT_debug_report"
// 13
@@ -163,8 +162,8 @@
@extension("VK_AMD_texture_gather_bias_lod") define VK_AMD_TEXTURE_GATHER_BIAS_LOD_EXTENSION_NAME "VK_AMD_texture_gather_bias_lod"
// 54
-@extension("VK_KHX_multiview") define VK_KHX_MULTIVIEW_SPEC_VERSION 1
-@extension("VK_KHX_multiview") define VK_KHX_MULTIVIEW_EXTENSION_NAME "VK_KHX_multiview"
+@extension("VK_KHR_multiview") define VK_KHR_MULTIVIEW_SPEC_VERSION 1
+@extension("VK_KHR_multiview") define VK_KHR_MULTIVIEW_EXTENSION_NAME "VK_KHR_multiview"
// 56
@extension("VK_NV_external_memory_capabilities") define VK_NV_EXTERNAL_MEMORY_CAPABILITIES_SPEC_VERSION 1
@@ -187,8 +186,8 @@
@extension("VK_KHR_get_physical_device_properties2") define VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME "VK_KHR_get_physical_device_properties2"
// 61
-@extension("VK_KHX_device_group") define VK_KHX_DEVICE_GROUP_SPEC_VERSION 2
-@extension("VK_KHX_device_group") define VK_KHX_DEVICE_GROUP_EXTENSION_NAME "VK_KHX_device_group"
+@extension("VK_KHR_device_group") define VK_KHR_DEVICE_GROUP_SPEC_VERSION 3
+@extension("VK_KHR_device_group") define VK_KHR_DEVICE_GROUP_EXTENSION_NAME "VK_KHR_device_group"
// 62
@extension("VK_EXT_validation_flags") define VK_EXT_VALIDATION_FLAGS_SPEC_VERSION 1
@@ -215,8 +214,8 @@
@extension("VK_KHR_maintenance1") define VK_KHR_MAINTENANCE1_EXTENSION_NAME "VK_KHR_maintenance1"
// 71
-@extension("VK_KHX_device_group_creation") define VK_KHX_DEVICE_GROUP_CREATION_SPEC_VERSION 1
-@extension("VK_KHX_device_group_creation") define VK_KHX_DEVICE_GROUP_CREATION_EXTENSION_NAME "VK_KHX_device_group_creation"
+@extension("VK_KHR_device_group_creation") define VK_KHR_DEVICE_GROUP_CREATION_SPEC_VERSION 1
+@extension("VK_KHR_device_group_creation") define VK_KHR_DEVICE_GROUP_CREATION_EXTENSION_NAME "VK_KHR_device_group_creation"
// 72
@extension("VK_KHR_external_memory_capabilities") define VK_KHR_EXTERNAL_MEMORY_CAPABILITIES_SPEC_VERSION 1
@@ -255,7 +254,7 @@
@extension("VK_KHR_external_semaphore_fd") define VK_KHR_EXTERNAL_SEMAPHORE_FD_EXTENSION_NAME "VK_KHR_external_semaphore_fd"
// 81
-@extension("VK_KHR_push_descriptor") define VK_KHR_PUSH_DESCRIPTOR_SPEC_VERSION 1
+@extension("VK_KHR_push_descriptor") define VK_KHR_PUSH_DESCRIPTOR_SPEC_VERSION 2
@extension("VK_KHR_push_descriptor") define VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME "VK_KHR_push_descriptor"
// 84
@@ -450,6 +449,10 @@
@extension("VK_EXT_shader_viewport_index_layer") define VK_EXT_SHADER_VIEWPORT_INDEX_LAYER_SPEC_VERSION 1
@extension("VK_EXT_shader_viewport_index_layer") define VK_EXT_SHADER_VIEWPORT_INDEX_LAYER_EXTENSION_NAME "VK_EXT_shader_viewport_index_layer"
+// 169
+@extension("VK_KHR_maintenance3") define VK_KHR_MAINTENANCE3_SPEC_VERSION 1
+@extension("VK_KHR_maintenance3") define VK_KHR_MAINTENANCE3_EXTENSION_NAME "VK_KHR_maintenance3"
+
/////////////
// Types //
/////////////
@@ -488,6 +491,10 @@
@nonDispatchHandle type u64 VkRenderPass
@nonDispatchHandle type u64 VkPipelineCache
+@vulkan1_1
+@nonDispatchHandle type u64 VkSamplerYcbcrConversion
+@nonDispatchHandle type u64 VkDescriptorUpdateTemplate
+
// 1
@extension("VK_KHR_surface") @nonDispatchHandle type u64 VkSurfaceKHR
@@ -529,6 +536,10 @@
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL = 0x00000007, /// Optimal layout when image is used only as destination of transfer operations
VK_IMAGE_LAYOUT_PREINITIALIZED = 0x00000008, /// Initial layout used when the data is populated by the CPU
+ //@vulkan1_1
+ VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL = 1000117000,
+ VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL = 1000117001,
+
//@extension("VK_KHR_swapchain") // 2
VK_IMAGE_LAYOUT_PRESENT_SRC_KHR = 1000001002,
@@ -1012,6 +1023,42 @@
VK_FORMAT_ASTC_12x12_UNORM_BLOCK = 183,
VK_FORMAT_ASTC_12x12_SRGB_BLOCK = 184,
+ //@vulkan1_1
+ VK_FORMAT_G8B8G8R8_422_UNORM = 1000156000,
+ VK_FORMAT_B8G8R8G8_422_UNORM = 1000156001,
+ VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM = 1000156002,
+ VK_FORMAT_G8_B8R8_2PLANE_420_UNORM = 1000156003,
+ VK_FORMAT_G8_B8_R8_3PLANE_422_UNORM = 1000156004,
+ VK_FORMAT_G8_B8R8_2PLANE_422_UNORM = 1000156005,
+ VK_FORMAT_G8_B8_R8_3PLANE_444_UNORM = 1000156006,
+ VK_FORMAT_R10X6_UNORM_PACK16 = 1000156007,
+ VK_FORMAT_R10X6G10X6_UNORM_2PACK16 = 1000156008,
+ VK_FORMAT_R10X6G10X6B10X6A10X6_UNORM_4PACK16 = 1000156009,
+ VK_FORMAT_G10X6B10X6G10X6R10X6_422_UNORM_4PACK16 = 1000156010,
+ VK_FORMAT_B10X6G10X6R10X6G10X6_422_UNORM_4PACK16 = 1000156011,
+ VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_420_UNORM_3PACK16 = 1000156012,
+ VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16 = 1000156013,
+ VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_422_UNORM_3PACK16 = 1000156014,
+ VK_FORMAT_G10X6_B10X6R10X6_2PLANE_422_UNORM_3PACK16 = 1000156015,
+ VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_444_UNORM_3PACK16 = 1000156016,
+ VK_FORMAT_R12X4_UNORM_PACK16 = 1000156017,
+ VK_FORMAT_R12X4G12X4_UNORM_2PACK16 = 1000156018,
+ VK_FORMAT_R12X4G12X4B12X4A12X4_UNORM_4PACK16 = 1000156019,
+ VK_FORMAT_G12X4B12X4G12X4R12X4_422_UNORM_4PACK16 = 1000156020,
+ VK_FORMAT_B12X4G12X4R12X4G12X4_422_UNORM_4PACK16 = 1000156021,
+ VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_420_UNORM_3PACK16 = 1000156022,
+ VK_FORMAT_G12X4_B12X4R12X4_2PLANE_420_UNORM_3PACK16 = 1000156023,
+ VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_422_UNORM_3PACK16 = 1000156024,
+ VK_FORMAT_G12X4_B12X4R12X4_2PLANE_422_UNORM_3PACK16 = 1000156025,
+ VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_444_UNORM_3PACK16 = 1000156026,
+ VK_FORMAT_G16B16G16R16_422_UNORM = 1000156027,
+ VK_FORMAT_B16G16R16G16_422_UNORM = 1000156028,
+ VK_FORMAT_G16_B16_R16_3PLANE_420_UNORM = 1000156029,
+ VK_FORMAT_G16_B16R16_2PLANE_420_UNORM = 1000156030,
+ VK_FORMAT_G16_B16_R16_3PLANE_422_UNORM = 1000156031,
+ VK_FORMAT_G16_B16R16_2PLANE_422_UNORM = 1000156032,
+ VK_FORMAT_G16_B16_R16_3PLANE_444_UNORM = 1000156033,
+
//@extension("VK_IMG_format_pvrtc") // 28
VK_FORMAT_PVRTC1_2BPP_UNORM_BLOCK_IMG = 1000054000,
VK_FORMAT_PVRTC1_4BPP_UNORM_BLOCK_IMG = 1000054001,
@@ -1111,9 +1158,83 @@
VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFO = 47,
VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFO = 48,
+ //@vulkan1_1
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_PROPERTIES = 1000094000,
+ VK_STRUCTURE_TYPE_BIND_BUFFER_MEMORY_INFO = 1000157000,
+ VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_INFO = 1000157001,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_16BIT_STORAGE_FEATURES = 1000083000,
+ VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS = 1000127000,
+ VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO = 1000127001,
+ VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_FLAGS_INFO = 1000060000,
+ VK_STRUCTURE_TYPE_DEVICE_GROUP_RENDER_PASS_BEGIN_INFO = 1000060003,
+ VK_STRUCTURE_TYPE_DEVICE_GROUP_COMMAND_BUFFER_BEGIN_INFO = 1000060004,
+ VK_STRUCTURE_TYPE_DEVICE_GROUP_SUBMIT_INFO = 1000060005,
+ VK_STRUCTURE_TYPE_DEVICE_GROUP_BIND_SPARSE_INFO = 1000060006,
+ VK_STRUCTURE_TYPE_BIND_BUFFER_MEMORY_DEVICE_GROUP_INFO = 1000060013,
+ VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_DEVICE_GROUP_INFO = 1000060014,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GROUP_PROPERTIES = 1000070000,
+ VK_STRUCTURE_TYPE_DEVICE_GROUP_DEVICE_CREATE_INFO = 1000070001,
+ VK_STRUCTURE_TYPE_BUFFER_MEMORY_REQUIREMENTS_INFO_2 = 1000146000,
+ VK_STRUCTURE_TYPE_IMAGE_MEMORY_REQUIREMENTS_INFO_2 = 1000146001,
+ VK_STRUCTURE_TYPE_IMAGE_SPARSE_MEMORY_REQUIREMENTS_INFO_2 = 1000146002,
+ VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2 = 1000146003,
+ VK_STRUCTURE_TYPE_SPARSE_IMAGE_MEMORY_REQUIREMENTS_2 = 1000146004,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2 = 1000059000,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2 = 1000059001,
+ VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2 = 1000059002,
+ VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2 = 1000059003,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2 = 1000059004,
+ VK_STRUCTURE_TYPE_QUEUE_FAMILY_PROPERTIES_2 = 1000059005,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_PROPERTIES_2 = 1000059006,
+ VK_STRUCTURE_TYPE_SPARSE_IMAGE_FORMAT_PROPERTIES_2 = 1000059007,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SPARSE_IMAGE_FORMAT_INFO_2 = 1000059008,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_POINT_CLIPPING_PROPERTIES = 1000117000,
+ VK_STRUCTURE_TYPE_RENDER_PASS_INPUT_ATTACHMENT_ASPECT_CREATE_INFO = 1000117001,
+ VK_STRUCTURE_TYPE_IMAGE_VIEW_USAGE_CREATE_INFO = 1000117002,
+ VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_DOMAIN_ORIGIN_STATE_CREATE_INFO = 1000117003,
+ VK_STRUCTURE_TYPE_RENDER_PASS_MULTIVIEW_CREATE_INFO = 1000053000,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_FEATURES = 1000053001,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_PROPERTIES = 1000053002,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VARIABLE_POINTER_FEATURES = 1000120000,
+ VK_STRUCTURE_TYPE_PROTECTED_SUBMIT_INFO = 1000145000,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROTECTED_MEMORY_FEATURES = 1000145001,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROTECTED_MEMORY_PROPERTIES = 1000145002,
+ VK_STRUCTURE_TYPE_DEVICE_QUEUE_INFO_2 = 1000145003,
+ VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_CREATE_INFO = 1000156000,
+ VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_INFO = 1000156001,
+ VK_STRUCTURE_TYPE_BIND_IMAGE_PLANE_MEMORY_INFO = 1000156002,
+ VK_STRUCTURE_TYPE_IMAGE_PLANE_MEMORY_REQUIREMENTS_INFO = 1000156003,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_YCBCR_CONVERSION_FEATURES = 1000156004,
+ VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_IMAGE_FORMAT_PROPERTIES = 1000156005,
+ VK_STRUCTURE_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_CREATE_INFO = 1000085000,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO = 1000071000,
+ VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES = 1000071001,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_BUFFER_INFO = 1000071002,
+ VK_STRUCTURE_TYPE_EXTERNAL_BUFFER_PROPERTIES = 1000071003,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ID_PROPERTIES = 1000071004,
+ VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_BUFFER_CREATE_INFO = 1000072000,
+ VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO = 1000072001,
+ VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO = 1000072002,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_FENCE_INFO = 1000112000,
+ VK_STRUCTURE_TYPE_EXTERNAL_FENCE_PROPERTIES = 1000112001,
+ VK_STRUCTURE_TYPE_EXPORT_FENCE_CREATE_INFO = 1000113000,
+ VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_CREATE_INFO = 1000077000,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_SEMAPHORE_INFO = 1000076000,
+ VK_STRUCTURE_TYPE_EXTERNAL_SEMAPHORE_PROPERTIES = 1000076001,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_3_PROPERTIES = 1000168000,
+ VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_SUPPORT = 1000168001,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_DRAW_PARAMETER_FEATURES = 1000063000,
+ VK_STRUCTURE_TYPE_DEVICE_GROUP_PRESENT_CAPABILITIES_KHR = 1000060007,
+
//@extension("VK_KHR_swapchain") // 2
VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR = 1000001000,
VK_STRUCTURE_TYPE_PRESENT_INFO_KHR = 1000001001,
+ // added as interaction from VK_KHR_device_group / VK 1.1
+ VK_STRUCTURE_TYPE_IMAGE_SWAPCHAIN_CREATE_INFO_KHR = 1000060008,
+ VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_SWAPCHAIN_INFO_KHR = 1000060009,
+ VK_STRUCTURE_TYPE_ACQUIRE_NEXT_IMAGE_INFO_KHR = 1000060010,
+ VK_STRUCTURE_TYPE_DEVICE_GROUP_PRESENT_INFO_KHR = 1000060011,
+ VK_STRUCTURE_TYPE_DEVICE_GROUP_SWAPCHAIN_CREATE_INFO_KHR = 1000060012,
//@extension("VK_KHR_display") // 3
VK_STRUCTURE_TYPE_DISPLAY_MODE_CREATE_INFO_KHR = 1000002000,
@@ -1164,10 +1285,10 @@
//@extension("VK_AMD_texture_gather_bias_lod") // 42
VK_STRUCTURE_TYPE_TEXTURE_LOD_GATHER_FORMAT_PROPERTIES_AMD = 1000041000,
- //@extension("VK_KHX_multiview") // 54
- VK_STRUCTURE_TYPE_RENDER_PASS_MULTIVIEW_CREATE_INFO_KHX = 1000053000,
- VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_FEATURES_KHX = 1000053001,
- VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_PROPERTIES_KHX = 1000053002,
+ //@extension("VK_KHR_multiview") // 54
+ VK_STRUCTURE_TYPE_RENDER_PASS_MULTIVIEW_CREATE_INFO_KHR = 1000053000,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_FEATURES_KHR = 1000053001,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_PROPERTIES_KHR = 1000053002,
//@extension("VK_NV_external_memory") // 57
VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO_NV = 1000056000,
@@ -1191,20 +1312,16 @@
VK_STRUCTURE_TYPE_SPARSE_IMAGE_FORMAT_PROPERTIES_2_KHR = 1000059007,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SPARSE_IMAGE_FORMAT_INFO_2_KHR = 1000059008,
- //@extension("VK_KHX_device_group") // 61
- VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_FLAGS_INFO_KHX = 1000060000,
- VK_STRUCTURE_TYPE_DEVICE_GROUP_RENDER_PASS_BEGIN_INFO_KHX = 1000060003,
- VK_STRUCTURE_TYPE_DEVICE_GROUP_COMMAND_BUFFER_BEGIN_INFO_KHX = 1000060004,
- VK_STRUCTURE_TYPE_DEVICE_GROUP_SUBMIT_INFO_KHX = 1000060005,
- VK_STRUCTURE_TYPE_DEVICE_GROUP_BIND_SPARSE_INFO_KHX = 1000060006,
- VK_STRUCTURE_TYPE_DEVICE_GROUP_PRESENT_CAPABILITIES_KHX = 1000060007,
- VK_STRUCTURE_TYPE_IMAGE_SWAPCHAIN_CREATE_INFO_KHX = 1000060008,
- VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_SWAPCHAIN_INFO_KHX = 1000060009,
- VK_STRUCTURE_TYPE_ACQUIRE_NEXT_IMAGE_INFO_KHX = 1000060010,
- VK_STRUCTURE_TYPE_DEVICE_GROUP_PRESENT_INFO_KHX = 1000060011,
- VK_STRUCTURE_TYPE_DEVICE_GROUP_SWAPCHAIN_CREATE_INFO_KHX = 1000060012,
- VK_STRUCTURE_TYPE_BIND_BUFFER_MEMORY_DEVICE_GROUP_INFO_KHX = 1000060013,
- VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_DEVICE_GROUP_INFO_KHX = 1000060014,
+ //@extension("VK_KHR_device_group") // 61
+ VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_FLAGS_INFO_KHR = 1000060000,
+ VK_STRUCTURE_TYPE_DEVICE_GROUP_RENDER_PASS_BEGIN_INFO_KHR = 1000060003,
+ VK_STRUCTURE_TYPE_DEVICE_GROUP_COMMAND_BUFFER_BEGIN_INFO_KHR = 1000060004,
+ VK_STRUCTURE_TYPE_DEVICE_GROUP_SUBMIT_INFO_KHR = 1000060005,
+ VK_STRUCTURE_TYPE_DEVICE_GROUP_BIND_SPARSE_INFO_KHR = 1000060006,
+ VK_STRUCTURE_TYPE_DEVICE_GROUP_PRESENT_CAPABILITIES_KHR = 1000060007,
+ // tokens 08-12 are listed with VK_KHR_swapchain
+ VK_STRUCTURE_TYPE_BIND_BUFFER_MEMORY_DEVICE_GROUP_INFO_KHR = 1000060013,
+ VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_DEVICE_GROUP_INFO_KHR = 1000060014,
//@extension("VK_EXT_validation_flags") // 62
VK_STRUCTURE_TYPE_VALIDATION_FLAGS_EXT = 1000061000,
@@ -1212,9 +1329,9 @@
//@extension("VK_NN_vi_surface") // 63
VK_STRUCTURE_TYPE_VI_SURFACE_CREATE_INFO_NN = 1000062000,
- //@extension("VK_KHX_device_group_creation") // 71
- VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GROUP_PROPERTIES_KHX = 1000070000,
- VK_STRUCTURE_TYPE_DEVICE_GROUP_DEVICE_CREATE_INFO_KHX = 1000070001,
+ //@extension("VK_KHR_device_group_creation") // 71
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GROUP_PROPERTIES_KHR = 1000070000,
+ VK_STRUCTURE_TYPE_DEVICE_GROUP_DEVICE_CREATE_INFO_KHR = 1000070001,
//@extension("VK_KHR_external_memory_capabilities") // 72
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO_KHR = 1000071000,
@@ -1394,6 +1511,10 @@
//@extension("VK_EXT_validation_cache") // 161
VK_STRUCTURE_TYPE_VALIDATION_CACHE_CREATE_INFO_EXT = 1000160000,
VK_STRUCTURE_TYPE_SHADER_MODULE_VALIDATION_CACHE_CREATE_INFO_EXT = 1000160001,
+
+ //@extension("VK_KHR_maintenance3") // 169
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_3_PROPERTIES_KHR = 1000168000,
+ VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_SUPPORT_KHR = 1000168001,
}
enum VkSubpassContents {
@@ -1433,6 +1554,10 @@
VK_ERROR_FORMAT_NOT_SUPPORTED = 0xFFFFFFF5, // -11
VK_ERROR_FRAGMENTED_POOL = 0xFFFFFFF4, // -12
+ //@vulkan1_1
+ VK_ERROR_OUT_OF_POOL_MEMORY = 0xC4642878, // -1000069000
+ VK_ERROR_INVALID_EXTERNAL_HANDLE = 0xC4641CBD, // -1000072003
+
//@extension("VK_KHR_surface") // 1
VK_ERROR_SURFACE_LOST_KHR = 0xC4653600, // -1000000000
VK_ERROR_NATIVE_WINDOW_IN_USE_KHR = 0xC46535FF, // -1000000001
@@ -1505,6 +1630,10 @@
VK_OBJECT_TYPE_FRAMEBUFFER = 24,
VK_OBJECT_TYPE_COMMAND_POOL = 25,
+ //@vulkan1_1
+ VK_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION = 1000156000,
+ VK_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE = 1000085000,
+
//@extension("VK_KHR_surface") // 1
VK_OBJECT_TYPE_SURFACE_KHR = 1000000000,
@@ -1532,6 +1661,42 @@
VK_OBJECT_TYPE_VALIDATION_CACHE_EXT = 1000160000,
}
+
+//@vulkan1_1 enums
+
+enum VkPointClippingBehavior {
+ VK_POINT_CLIPPING_BEHAVIOR_ALL_CLIP_PLANES = 0,
+ VK_POINT_CLIPPING_BEHAVIOR_USER_CLIP_PLANES_ONLY = 1,
+}
+
+enum VkTessellationDomainOrigin {
+ VK_TESSELLATION_DOMAIN_ORIGIN_UPPER_LEFT = 0,
+ VK_TESSELLATION_DOMAIN_ORIGIN_LOWER_LEFT = 1,
+}
+
+enum VkSamplerYcbcrModelConversion {
+ VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY = 0,
+ VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_IDENTITY = 1,
+ VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_709 = 2,
+ VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_601 = 3,
+ VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_2020 = 4,
+}
+
+enum VkSamplerYcbcrRange {
+ VK_SAMPLER_YCBCR_RANGE_ITU_FULL = 0,
+ VK_SAMPLER_YCBCR_RANGE_ITU_NARROW = 1,
+}
+
+enum VkChromaLocation {
+ VK_CHROMA_LOCATION_COSITED_EVEN = 0,
+ VK_CHROMA_LOCATION_MIDPOINT = 1,
+}
+
+enum VkDescriptorUpdateTemplateType {
+ VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET = 0,
+ VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_PUSH_DESCRIPTORS_KHR = 1,
+}
+
@extension("VK_KHR_surface") // 1
enum VkPresentModeKHR {
VK_PRESENT_MODE_IMMEDIATE_KHR = 0x00000000,
@@ -1546,7 +1711,7 @@
@extension("VK_KHR_surface") // 1
enum VkColorSpaceKHR {
- VK_COLORSPACE_SRGB_NONLINEAR_KHR = 0x00000000,
+ VK_COLOR_SPACE_SRGB_NONLINEAR_KHR = 0x00000000,
//@extension("VK_EXT_swapchain_colorspace") // 105
VK_COLOR_SPACE_DISPLAY_P3_NONLINEAR_EXT = 1000104001,
@@ -1756,6 +1921,9 @@
VK_QUEUE_COMPUTE_BIT = 0x00000002, /// Queue supports compute operations
VK_QUEUE_TRANSFER_BIT = 0x00000004, /// Queue supports transfer operations
VK_QUEUE_SPARSE_BINDING_BIT = 0x00000008, /// Queue supports sparse resource memory management operations
+
+ //@vulkan1_1
+ VK_QUEUE_PROTECTED_BIT = 0x00000010,
}
/// Memory properties passed into vkAllocMemory().
@@ -1766,6 +1934,9 @@
VK_MEMORY_PROPERTY_HOST_COHERENT_BIT = 0x00000004,
VK_MEMORY_PROPERTY_HOST_CACHED_BIT = 0x00000008,
VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT = 0x00000010,
+
+ //@vulkan1_1
+ VK_MEMORY_PROPERTY_PROTECTED_BIT = 0x00000020,
}
/// Memory heap flags
@@ -1773,8 +1944,11 @@
bitfield VkMemoryHeapFlagBits {
VK_MEMORY_HEAP_DEVICE_LOCAL_BIT = 0x00000001,
- //@extension("VK_KHX_device_group_creation") // 71
- VK_MEMORY_HEAP_MULTI_INSTANCE_BIT_KHX = 0x00000002,
+ //@vulkan1_1
+ VK_MEMORY_HEAP_MULTI_INSTANCE_BIT = 0x00000002,
+
+ //@extension("VK_KHR_device_group_creation") // 71
+ VK_MEMORY_HEAP_MULTI_INSTANCE_BIT_KHR = 0x00000002,
}
/// Access flags
@@ -1826,6 +2000,9 @@
VK_BUFFER_CREATE_SPARSE_BINDING_BIT = 0x00000001, /// Buffer should support sparse backing
VK_BUFFER_CREATE_SPARSE_RESIDENCY_BIT = 0x00000002, /// Buffer should support sparse backing with partial residency
VK_BUFFER_CREATE_SPARSE_ALIASED_BIT = 0x00000004, /// Buffer should support constent data access to physical memory blocks mapped into multiple locations of sparse buffers
+
+ //@vulkan1_1
+ VK_BUFFER_CREATE_PROTECTED_BIT = 0x00000008,
}
/// Shader stage flags
@@ -1875,14 +2052,20 @@
VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT = 0x00000008, /// Allows image views to have different format than the base image
VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT = 0x00000010, /// Allows creating image views with cube type from the created image
+ //@vulkan1_1
+ VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT = 0x00000020,
+ VK_IMAGE_CREATE_BIND_SFR_BIT = 0x00000040,
+ VK_IMAGE_CREATE_BLOCK_TEXEL_VIEW_COMPATIBLE_BIT = 0x00000080,
+ VK_IMAGE_CREATE_EXTENDED_USAGE_BIT = 0x00000100,
+ VK_IMAGE_CREATE_DISJOINT_BIT = 0x00000200,
+ VK_IMAGE_CREATE_ALIAS_BIT = 0x00000400,
+ VK_IMAGE_CREATE_PROTECTED_BIT = 0x00000800,
+
//@extension("VK_KHR_maintenance1") // 70
VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT_KHR = 0x00000020,
- //@extension("VK_KHX_device_group") // 61
- VK_IMAGE_CREATE_BIND_SFR_BIT_KHX = 0x00000040,
-
- //@extension("VK_EXT_sample_locations") // 144
- VK_IMAGE_CREATE_SAMPLE_LOCATIONS_COMPATIBLE_DEPTH_BIT_EXT = 0x00001000,
+ //@extension("VK_KHR_device_group") // 61
+ VK_IMAGE_CREATE_BIND_SFR_BIT_KHR = 0x00000040,
//@extension("VK_KHR_maintenance2") // 118
VK_IMAGE_CREATE_BLOCK_TEXEL_VIEW_COMPATIBLE_BIT_KHR = 0x00000080,
@@ -1893,6 +2076,9 @@
//@extension("VK_KHR_bind_memory2") // 158
VK_IMAGE_CREATE_ALIAS_BIT_KHR = 0x00000400,
+
+ //@extension("VK_EXT_sample_locations") // 144
+ VK_IMAGE_CREATE_SAMPLE_LOCATIONS_COMPATIBLE_DEPTH_BIT_EXT = 0x00001000,
}
/// Image view creation flags
@@ -1907,9 +2093,13 @@
VK_PIPELINE_CREATE_ALLOW_DERIVATIVES_BIT = 0x00000002,
VK_PIPELINE_CREATE_DERIVATIVE_BIT = 0x00000004,
- //@extension("VK_KHX_device_group") // 61
- VK_PIPELINE_CREATE_VIEW_INDEX_FROM_DEVICE_INDEX_BIT_KHX = 0x00000008,
- VK_PIPELINE_CREATE_DISPATCH_BASE_KHX = 0x00000010,
+ //@vulkan1_1
+ VK_PIPELINE_CREATE_VIEW_INDEX_FROM_DEVICE_INDEX_BIT = 0x00000008,
+ VK_PIPELINE_CREATE_DISPATCH_BASE = 0x00000010,
+
+ //@extension("VK_KHR_device_group") // 61
+ VK_PIPELINE_CREATE_VIEW_INDEX_FROM_DEVICE_INDEX_BIT_KHR = 0x00000008,
+ VK_PIPELINE_CREATE_DISPATCH_BASE_KHR = 0x00000010,
}
/// Color component flags
@@ -1949,6 +2139,17 @@
VK_FORMAT_FEATURE_BLIT_DST_BIT = 0x00000800, /// Format can be used as the destination image of blits with vkCommandBlitImage
VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT = 0x00001000,
+ //@vulkan1_1
+ VK_FORMAT_FEATURE_TRANSFER_SRC_BIT = 0x00004000,
+ VK_FORMAT_FEATURE_TRANSFER_DST_BIT = 0x00008000,
+ VK_FORMAT_FEATURE_MIDPOINT_CHROMA_SAMPLES_BIT = 0x00020000,
+ VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_LINEAR_FILTER_BIT = 0x00040000,
+ VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_SEPARATE_RECONSTRUCTION_FILTER_BIT = 0x00080000,
+ VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_BIT = 0x00100000,
+ VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_FORCEABLE_BIT = 0x00200000,
+ VK_FORMAT_FEATURE_DISJOINT_BIT = 0x00400000,
+ VK_FORMAT_FEATURE_COSITED_CHROMA_SAMPLES_BIT = 0x00800000,
+
//@extension("VK_IMG_filter_cubic") // 16
VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_CUBIC_BIT_IMG = 0x00002000,
@@ -2031,6 +2232,11 @@
VK_IMAGE_ASPECT_STENCIL_BIT = 0x00000004,
VK_IMAGE_ASPECT_METADATA_BIT = 0x00000008,
+ //@vulkan1_1
+ VK_IMAGE_ASPECT_PLANE_0_BIT = 0x00000010,
+ VK_IMAGE_ASPECT_PLANE_1_BIT = 0x00000020,
+ VK_IMAGE_ASPECT_PLANE_2_BIT = 0x00000040,
+
//@extension("VK_KHR_sampler_ycbcr_conversion") // 157
VK_IMAGE_ASPECT_PLANE_0_BIT_KHR = 0x00000010,
VK_IMAGE_ASPECT_PLANE_1_BIT_KHR = 0x00000020,
@@ -2096,6 +2302,9 @@
bitfield VkCommandPoolCreateFlagBits {
VK_COMMAND_POOL_CREATE_TRANSIENT_BIT = 0x00000001, /// Command buffers have a short lifetime
VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT = 0x00000002, /// Command buffers may release their memory individually
+
+ //@vulkan1_1
+ VK_COMMAND_POOL_CREATE_PROTECTED_BIT = 0x00000004,
}
/// Command pool reset flags
@@ -2139,8 +2348,10 @@
/// Device queue creation flags
type VkFlags VkDeviceQueueCreateFlags
-//bitfield VkDeviceQueueCreateFlagBits {
-//}
+@vulkan1_1
+bitfield VkDeviceQueueCreateFlagBits {
+ VK_DEVICE_QUEUE_CREATE_PROTECTED_BIT = 0x00000001,
+}
/// Query pool creation flags
type VkFlags VkQueryPoolCreateFlags
@@ -2239,11 +2450,15 @@
bitfield VkDependencyFlagBits {
VK_DEPENDENCY_BY_REGION_BIT = 0x00000001,
- //@extension("VK_KHX_multiview") // 54
- VK_DEPENDENCY_VIEW_LOCAL_BIT_KHX = 0x00000002,
+ //@vulkan1_1
+ VK_DEPENDENCY_DEVICE_GROUP_BIT = 0x00000004,
+ VK_DEPENDENCY_VIEW_LOCAL_BIT = 0x00000002,
- //@extension("VK_KHX_device_group") // 61
- VK_DEPENDENCY_DEVICE_GROUP_BIT_KHX = 0x00000004,
+ //@extension("VK_KHR_multiview") // 54
+ VK_DEPENDENCY_VIEW_LOCAL_BIT_KHR = 0x00000002,
+
+ //@extension("VK_KHR_device_group") // 61
+ VK_DEPENDENCY_DEVICE_GROUP_BIT_KHR = 0x00000004,
}
/// Cull mode flags
@@ -2255,6 +2470,109 @@
VK_CULL_MODE_FRONT_AND_BACK = 0x00000003,
}
+//@vulkan1_1 flags
+
+/// Subgroup feature flags
+type VkFlags VkSubgroupFeatureFlags
+bitfield VkSubgroupFeatureFlagBits {
+ VK_SUBGROUP_FEATURE_BASIC_BIT = 0x00000001,
+ VK_SUBGROUP_FEATURE_VOTE_BIT = 0x00000002,
+ VK_SUBGROUP_FEATURE_ARITHMETIC_BIT = 0x00000004,
+ VK_SUBGROUP_FEATURE_BALLOT_BIT = 0x00000008,
+ VK_SUBGROUP_FEATURE_SHUFFLE_BIT = 0x00000010,
+ VK_SUBGROUP_FEATURE_SHUFFLE_RELATIVE_BIT = 0x00000020,
+ VK_SUBGROUP_FEATURE_CLUSTERED_BIT = 0x00000040,
+ VK_SUBGROUP_FEATURE_QUAD_BIT = 0x00000080,
+}
+
+/// Peer memory feature flags
+type VkFlags VkPeerMemoryFeatureFlags
+bitfield VkPeerMemoryFeatureFlagBits {
+ VK_PEER_MEMORY_FEATURE_COPY_SRC_BIT = 0x00000001,
+ VK_PEER_MEMORY_FEATURE_COPY_DST_BIT = 0x00000002,
+ VK_PEER_MEMORY_FEATURE_GENERIC_SRC_BIT = 0x00000004,
+ VK_PEER_MEMORY_FEATURE_GENERIC_DST_BIT = 0x00000008,
+}
+
+/// Memory allocation flags
+type VkFlags VkMemoryAllocateFlags
+bitfield VkMemoryAllocateFlagBits {
+ VK_MEMORY_ALLOCATE_DEVICE_MASK_BIT = 0x00000001,
+}
+
+type VkFlags VkCommandPoolTrimFlags
+//bitfield VkCommandPoolTrimFlagBits {
+//}
+
+type VkFlags VkDescriptorUpdateTemplateCreateFlags
+//bitfield VkDescriptorUpdateTemplateCreateFlagBits {
+//}
+
+/// External memory handle type flags
+type VkFlags VkExternalMemoryHandleTypeFlags
+bitfield VkExternalMemoryHandleTypeFlagBits {
+ VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT = 0x00000001,
+ VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT = 0x00000002,
+ VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT = 0x00000004,
+ VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_BIT = 0x00000008,
+ VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_KMT_BIT = 0x00000010,
+ VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_HEAP_BIT = 0x00000020,
+ VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_RESOURCE_BIT = 0x00000040,
+}
+
+/// External memory feature flags
+type VkFlags VkExternalMemoryFeatureFlags
+bitfield VkExternalMemoryFeatureFlagBits {
+ VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT = 0x00000001,
+ VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT = 0x00000002,
+ VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT = 0x00000004,
+}
+
+/// External fence handle type flags
+type VkFlags VkExternalFenceHandleTypeFlags
+bitfield VkExternalFenceHandleTypeFlagBits {
+ VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_FD_BIT = 0x00000001,
+ VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_BIT = 0x00000002,
+ VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT = 0x00000004,
+ VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT = 0x00000008,
+}
+
+/// External fence feature flags
+type VkFlags VkExternalFenceFeatureFlags
+bitfield VkExternalFenceFeatureFlagBits {
+ VK_EXTERNAL_FENCE_FEATURE_EXPORTABLE_BIT = 0x00000001,
+ VK_EXTERNAL_FENCE_FEATURE_IMPORTABLE_BIT = 0x00000002,
+}
+
+/// Fence import flags
+type VkFlags VkFenceImportFlags
+bitfield VkFenceImportFlagBits {
+ VK_FENCE_IMPORT_TEMPORARY_BIT = 0x00000001,
+}
+
+/// Semaphore import flags
+type VkFlags VkSemaphoreImportFlags
+bitfield VkSemaphoreImportFlagBits {
+ VK_SEMAPHORE_IMPORT_TEMPORARY_BIT = 0x00000001,
+}
+
+/// External semaphore handle type flags
+type VkFlags VkExternalSemaphoreHandleTypeFlags
+bitfield VkExternalSemaphoreHandleTypeFlagBits {
+ VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT = 0x00000001,
+ VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT = 0x00000002,
+ VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT = 0x00000004,
+ VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_D3D12_FENCE_BIT = 0x00000008,
+ VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT = 0x00000010,
+}
+
+/// External semaphore feature flags
+type VkFlags VkExternalSemaphoreFeatureFlags
+bitfield VkExternalSemaphoreFeatureFlagBits {
+ VK_EXTERNAL_SEMAPHORE_FEATURE_EXPORTABLE_BIT = 0x00000001,
+ VK_EXTERNAL_SEMAPHORE_FEATURE_IMPORTABLE_BIT = 0x00000002,
+}
+
@extension("VK_KHR_surface") // 1
type VkFlags VkSurfaceTransformFlagsKHR
@extension("VK_KHR_surface") // 1
@@ -2284,8 +2602,21 @@
type VkFlags VkSwapchainCreateFlagsKHR
@extension("VK_KHR_swapchain") // 2
bitfield VkSwapchainCreateFlagBitsKHR {
- //@extension("VK_KHX_device_group") // 61
- VK_SWAPCHAIN_CREATE_BIND_SFR_BIT_KHX = 0x00000001,
+ //@vulkan1_1
+ VK_SWAPCHAIN_CREATE_BIND_SFR_BIT_KHR = 0x00000001,
+ VK_SWAPCHAIN_CREATE_PROTECTED_BIT_KHR = 0x00000002,
+}
+
+@vulkan1_1
+@extension("VK_KHR_swapchain") // 2
+type VkFlags VkDeviceGroupPresentModeFlagsKHR
+@vulkan1_1
+@extension("VK_KHR_swapchain") // 2
+bitfield VkDeviceGroupPresentModeFlagBitsKHR {
+ VK_DEVICE_GROUP_PRESENT_MODE_LOCAL_BIT_KHR = 0x00000001,
+ VK_DEVICE_GROUP_PRESENT_MODE_REMOTE_BIT_KHR = 0x00000002,
+ VK_DEVICE_GROUP_PRESENT_MODE_SUM_BIT_KHR = 0x00000004,
+ VK_DEVICE_GROUP_PRESENT_MODE_LOCAL_MULTI_DEVICE_BIT_KHR = 0x00000008,
}
@extension("VK_KHR_display") // 3
@@ -2383,31 +2714,21 @@
VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT_NV = 0x00000004,
}
-@extension("VK_KHX_device_group") // 61
-type VkFlags VkPeerMemoryFeatureFlagsKHX
-@extension("VK_KHX_device_group") // 61
-bitfield VkPeerMemoryFeatureFlagBitsKHX {
- VK_PEER_MEMORY_FEATURE_COPY_SRC_BIT_KHX = 0x00000001,
- VK_PEER_MEMORY_FEATURE_COPY_DST_BIT_KHX = 0x00000002,
- VK_PEER_MEMORY_FEATURE_GENERIC_SRC_BIT_KHX = 0x00000004,
- VK_PEER_MEMORY_FEATURE_GENERIC_DST_BIT_KHX = 0x00000008,
+@extension("VK_KHR_device_group") // 61
+type VkFlags VkPeerMemoryFeatureFlagsKHR
+@extension("VK_KHR_device_group") // 61
+bitfield VkPeerMemoryFeatureFlagBitsKHR {
+ VK_PEER_MEMORY_FEATURE_COPY_SRC_BIT_KHR = 0x00000001,
+ VK_PEER_MEMORY_FEATURE_COPY_DST_BIT_KHR = 0x00000002,
+ VK_PEER_MEMORY_FEATURE_GENERIC_SRC_BIT_KHR = 0x00000004,
+ VK_PEER_MEMORY_FEATURE_GENERIC_DST_BIT_KHR = 0x00000008,
}
-@extension("VK_KHX_device_group") // 61
-type VkFlags VkMemoryAllocateFlagsKHX
-@extension("VK_KHX_device_group") // 61
-bitfield VkMemoryAllocateFlagBitsKHX {
- VK_MEMORY_ALLOCATE_DEVICE_MASK_BIT_KHX = 0x00000001,
-}
-
-@extension("VK_KHX_device_group") // 61
-type VkFlags VkDeviceGroupPresentModeFlagsKHX
-@extension("VK_KHX_device_group") // 61
-bitfield VkDeviceGroupPresentModeFlagBitsKHX {
- VK_DEVICE_GROUP_PRESENT_MODE_LOCAL_BIT_KHX = 0x00000001,
- VK_DEVICE_GROUP_PRESENT_MODE_REMOTE_BIT_KHX = 0x00000002,
- VK_DEVICE_GROUP_PRESENT_MODE_SUM_BIT_KHX = 0x00000004,
- VK_DEVICE_GROUP_PRESENT_MODE_LOCAL_MULTI_DEVICE_BIT_KHX = 0x00000008,
+@extension("VK_KHR_device_group") // 61
+type VkFlags VkMemoryAllocateFlagsKHR
+@extension("VK_KHR_device_group") // 61
+bitfield VkMemoryAllocateFlagBitsKHR {
+ VK_MEMORY_ALLOCATE_DEVICE_MASK_BIT_KHR = 0x00000001,
}
@extension("VK_NN_vi_surface") // 63
@@ -3672,6 +3993,493 @@
u32 z
}
+//@vulkan1_1 structures
+
+class VkPhysicalDeviceSubgroupProperties {
+ VkStructureType sType
+ void* pNext
+ u32 subgroupSize
+ VkShaderStageFlags supportedStages
+ VkSubgroupFeatureFlags supportedOperations
+ VkBool32 quadOperationsInAllStages
+}
+
+class VkBindBufferMemoryInfo {
+ VkStructureType sType
+ const void* pNext
+ VkBuffer buffer
+ VkDeviceMemory memory
+ VkDeviceSize memoryOffset
+}
+
+class VkBindImageMemoryInfo {
+ VkStructureType sType
+ const void* pNext
+ VkImage image
+ VkDeviceMemory memory
+ VkDeviceSize memoryOffset
+}
+
+class VkPhysicalDevice16BitStorageFeatures {
+ VkStructureType sType
+ void* pNext
+ VkBool32 storageBuffer16BitAccess
+ VkBool32 uniformAndStorageBuffer16BitAccess
+ VkBool32 storagePushConstant16
+ VkBool32 storageInputOutput16
+}
+
+class VkMemoryDedicatedRequirements {
+ VkStructureType sType
+ void* pNext
+ VkBool32 prefersDedicatedAllocation
+ VkBool32 requiresDedicatedAllocation
+}
+
+class VkMemoryDedicatedAllocateInfo {
+ VkStructureType sType
+ const void* pNext
+ VkImage image
+ VkBuffer buffer
+}
+
+class VkMemoryAllocateFlagsInfo {
+ VkStructureType sType
+ const void* pNext
+ VkMemoryAllocateFlags flags
+ u32 deviceMask
+}
+
+class VkDeviceGroupRenderPassBeginInfo {
+ VkStructureType sType
+ const void* pNext
+ u32 deviceMask
+ u32 deviceRenderAreaCount
+ const VkRect2D* pDeviceRenderAreas
+}
+
+class VkDeviceGroupCommandBufferBeginInfo {
+ VkStructureType sType
+ const void* pNext
+ u32 deviceMask
+}
+
+class VkDeviceGroupSubmitInfo {
+ VkStructureType sType
+ const void* pNext
+ u32 waitSemaphoreCount
+ const u32* pWaitSemaphoreDeviceIndices
+ u32 commandBufferCount
+ const u32* pCommandBufferDeviceMasks
+ u32 signalSemaphoreCount
+ const u32* pSignalSemaphoreDeviceIndices
+}
+
+class VkDeviceGroupBindSparseInfo {
+ VkStructureType sType
+ const void* pNext
+ u32 resourceDeviceIndex
+ u32 memoryDeviceIndex
+}
+
+class VkBindBufferMemoryDeviceGroupInfo {
+ VkStructureType sType
+ const void* pNext
+ u32 deviceIndexCount
+ const u32* pDeviceIndices
+}
+
+class VkBindImageMemoryDeviceGroupInfo {
+ VkStructureType sType
+ const void* pNext
+ u32 deviceIndexCount
+ const u32* pDeviceIndices
+ u32 SFRRectCount
+ const VkRect2D* pSFRRects
+}
+
+class VkPhysicalDeviceGroupProperties {
+ VkStructureType sType
+ void* pNext
+ u32 physicalDeviceCount
+ VkPhysicalDevice[VK_MAX_DEVICE_GROUP_SIZE] physicalDevices
+ VkBool32 subsetAllocation
+}
+
+class VkDeviceGroupDeviceCreateInfo {
+ VkStructureType sType
+ const void* pNext
+ u32 physicalDeviceCount
+ const VkPhysicalDevice* pPhysicalDevices
+}
+
+class VkBufferMemoryRequirementsInfo2 {
+ VkStructureType sType
+ const void* pNext
+ VkBuffer buffer
+}
+
+class VkImageMemoryRequirementsInfo2 {
+ VkStructureType sType
+ const void* pNext
+ VkImage image
+}
+
+class VkImageSparseMemoryRequirementsInfo2 {
+ VkStructureType sType
+ const void* pNext
+ VkImage image
+}
+
+class VkMemoryRequirements2 {
+ VkStructureType sType
+ void* pNext
+ VkMemoryRequirements memoryRequirements
+}
+
+class VkSparseImageMemoryRequirements2 {
+ VkStructureType sType
+ void* pNext
+ VkSparseImageMemoryRequirements memoryRequirements
+}
+
+class VkPhysicalDeviceFeatures2 {
+ VkStructureType sType
+ void* pNext
+ VkPhysicalDeviceFeatures features
+}
+
+class VkPhysicalDeviceProperties2 {
+ VkStructureType sType
+ void* pNext
+ VkPhysicalDeviceProperties properties
+}
+
+class VkFormatProperties2 {
+ VkStructureType sType
+ void* pNext
+ VkFormatProperties formatProperties
+}
+
+class VkImageFormatProperties2 {
+ VkStructureType sType
+ void* pNext
+ VkImageFormatProperties imageFormatProperties
+}
+
+class VkPhysicalDeviceImageFormatInfo2 {
+ VkStructureType sType
+ const void* pNext
+ VkFormat format
+ VkImageType type
+ VkImageTiling tiling
+ VkImageUsageFlags usage
+ VkImageCreateFlags flags
+}
+
+class VkQueueFamilyProperties2 {
+ VkStructureType sType
+ void* pNext
+ VkQueueFamilyProperties queueFamilyProperties
+}
+
+class VkPhysicalDeviceMemoryProperties2 {
+ VkStructureType sType
+ void* pNext
+ VkPhysicalDeviceMemoryProperties memoryProperties
+}
+
+class VkSparseImageFormatProperties2 {
+ VkStructureType sType
+ void* pNext
+ VkSparseImageFormatProperties properties
+}
+
+class VkPhysicalDeviceSparseImageFormatInfo2 {
+ VkStructureType sType
+ const void* pNext
+ VkFormat format
+ VkImageType type
+ VkSampleCountFlagBits samples
+ VkImageUsageFlags usage
+ VkImageTiling tiling
+}
+
+class VkPhysicalDevicePointClippingProperties {
+ VkStructureType sType
+ void* pNext
+ VkPointClippingBehavior pointClippingBehavior
+}
+
+class VkInputAttachmentAspectReference {
+ u32 subpass
+ u32 inputAttachmentIndex
+ VkImageAspectFlags aspectMask
+}
+
+class VkRenderPassInputAttachmentAspectCreateInfo {
+ VkStructureType sType
+ const void* pNext
+ u32 aspectReferenceCount
+ const VkInputAttachmentAspectReference* pAspectReferences
+}
+
+class VkImageViewUsageCreateInfo {
+ VkStructureType sType
+ const void* pNext
+ VkImageUsageFlags usage
+}
+
+class VkPipelineTessellationDomainOriginStateCreateInfo {
+ VkStructureType sType
+ const void* pNext
+ VkTessellationDomainOrigin domainOrigin
+}
+
+class VkRenderPassMultiviewCreateInfo {
+ VkStructureType sType
+ const void* pNext
+ u32 subpassCount
+ const u32* pViewMasks
+ u32 dependencyCount
+ const s32* pViewOffsets
+ u32 correlationMaskCount
+ const u32* pCorrelationMasks
+}
+
+class VkPhysicalDeviceMultiviewFeatures {
+ VkStructureType sType
+ void* pNext
+ VkBool32 multiview
+ VkBool32 multiviewGeometryShader
+ VkBool32 multiviewTessellationShader
+}
+
+class VkPhysicalDeviceMultiviewProperties {
+ VkStructureType sType
+ void* pNext
+ u32 maxMultiviewViewCount
+ u32 maxMultiviewInstanceIndex
+}
+
+class VkPhysicalDeviceVariablePointerFeatures {
+ VkStructureType sType
+ void* pNext
+ VkBool32 variablePointersStorageBuffer
+ VkBool32 variablePointers
+}
+
+class VkPhysicalDeviceProtectedMemoryFeatures {
+ VkStructureType sType
+ void* pNext
+ VkBool32 protectedMemory
+}
+
+class VkPhysicalDeviceProtectedMemoryProperties {
+ VkStructureType sType
+ void* pNext
+ VkBool32 protectedNoFault
+}
+
+class VkDeviceQueueInfo2 {
+ VkStructureType sType
+ const void* pNext
+ VkDeviceQueueCreateFlags flags
+ u32 queueFamilyIndex
+ u32 queueIndex
+}
+
+class VkProtectedSubmitInfo {
+ VkStructureType sType
+ const void* pNext
+ VkBool32 protectedSubmit
+}
+
+class VkSamplerYcbcrConversionCreateInfo {
+ VkStructureType sType
+ const void* pNext
+ VkFormat format
+ VkSamplerYcbcrModelConversion ycbcrModel
+ VkSamplerYcbcrRange ycbcrRange
+ VkComponentMapping components
+ VkChromaLocation xChromaOffset
+ VkChromaLocation yChromaOffset
+ VkFilter chromaFilter
+ VkBool32 forceExplicitReconstruction
+}
+
+class VkSamplerYcbcrConversionInfo {
+ VkStructureType sType
+ const void* pNext
+ VkSamplerYcbcrConversion conversion
+}
+
+class VkBindImagePlaneMemoryInfo {
+ VkStructureType sType
+ const void* pNext
+ VkImageAspectFlagBits planeAspect
+}
+
+class VkImagePlaneMemoryRequirementsInfo {
+ VkStructureType sType
+ const void* pNext
+ VkImageAspectFlagBits planeAspect
+}
+
+class VkPhysicalDeviceSamplerYcbcrConversionFeatures {
+ VkStructureType sType
+ void* pNext
+ VkBool32 samplerYcbcrConversion
+}
+
+class VkSamplerYcbcrConversionImageFormatProperties {
+ VkStructureType sType
+ void* pNext
+ u32 combinedImageSamplerDescriptorCount
+}
+
+class VkDescriptorUpdateTemplateEntry {
+ u32 dstBinding
+ u32 dstArrayElement
+ u32 descriptorCount
+ VkDescriptorType descriptorType
+ platform.size_t offset
+ platform.size_t stride
+}
+
+class VkDescriptorUpdateTemplateCreateInfo {
+ VkStructureType sType
+ void* pNext
+ VkDescriptorUpdateTemplateCreateFlags flags
+ u32 descriptorUpdateEntryCount
+ const VkDescriptorUpdateTemplateEntry* pDescriptorUpdateEntries
+ VkDescriptorUpdateTemplateType templateType
+ VkDescriptorSetLayout descriptorSetLayout
+ VkPipelineBindPoint pipelineBindPoint
+ VkPipelineLayout pipelineLayout
+ u32 set
+}
+
+class VkExternalMemoryProperties {
+ VkExternalMemoryFeatureFlags externalMemoryFeatures
+ VkExternalMemoryHandleTypeFlags exportFromImportedHandleTypes
+ VkExternalMemoryHandleTypeFlags compatibleHandleTypes
+}
+
+class VkPhysicalDeviceExternalImageFormatInfo {
+ VkStructureType sType
+ const void* pNext
+ VkExternalMemoryHandleTypeFlagBits handleType
+}
+
+class VkExternalImageFormatProperties {
+ VkStructureType sType
+ void* pNext
+ VkExternalMemoryProperties externalMemoryProperties
+}
+
+class VkPhysicalDeviceExternalBufferInfo {
+ VkStructureType sType
+ const void* pNext
+ VkBufferCreateFlags flags
+ VkBufferUsageFlags usage
+ VkExternalMemoryHandleTypeFlagBits handleType
+}
+
+class VkExternalBufferProperties {
+ VkStructureType sType
+ void* pNext
+ VkExternalMemoryProperties externalMemoryProperties
+}
+
+class VkPhysicalDeviceIDProperties {
+ VkStructureType sType
+ void* pNext
+ u8[VK_UUID_SIZE] deviceUUID
+ u8[VK_UUID_SIZE] driverUUID
+ u8[VK_LUID_SIZE] deviceLUID
+ u32 deviceNodeMask
+ VkBool32 deviceLUIDValid
+}
+
+class VkExternalMemoryImageCreateInfo {
+ VkStructureType sType
+ const void* pNext
+ VkExternalMemoryHandleTypeFlags handleTypes
+}
+
+class VkExternalMemoryBufferCreateInfo {
+ VkStructureType sType
+ const void* pNext
+ VkExternalMemoryHandleTypeFlags handleTypes
+}
+
+class VkExportMemoryAllocateInfo {
+ VkStructureType sType
+ const void* pNext
+ VkExternalMemoryHandleTypeFlags handleTypes
+}
+
+class VkPhysicalDeviceExternalFenceInfo {
+ VkStructureType sType
+ const void* pNext
+ VkExternalFenceHandleTypeFlagBits handleType
+}
+
+class VkExternalFenceProperties {
+ VkStructureType sType
+ void* pNext
+ VkExternalFenceHandleTypeFlags exportFromImportedHandleTypes
+ VkExternalFenceHandleTypeFlags compatibleHandleTypes
+ VkExternalFenceFeatureFlags externalFenceFeatures
+}
+
+class VkExportFenceCreateInfo {
+ VkStructureType sType
+ const void* pNext
+ VkExternalFenceHandleTypeFlags handleTypes
+}
+
+class VkExportSemaphoreCreateInfo {
+ VkStructureType sType
+ const void* pNext
+ VkExternalSemaphoreHandleTypeFlags handleTypes
+}
+
+class VkPhysicalDeviceExternalSemaphoreInfo {
+ VkStructureType sType
+ const void* pNext
+ VkExternalSemaphoreHandleTypeFlagBits handleType
+}
+
+class VkExternalSemaphoreProperties {
+ VkStructureType sType
+ void* pNext
+ VkExternalSemaphoreHandleTypeFlags exportFromImportedHandleTypes
+ VkExternalSemaphoreHandleTypeFlags compatibleHandleTypes
+ VkExternalSemaphoreFeatureFlags externalSemaphoreFeatures
+}
+
+class VkPhysicalDeviceMaintenance3Properties {
+ VkStructureType sType
+ void* pNext
+ u32 maxPerSetDescriptors
+ VkDeviceSize maxMemoryAllocationSize
+}
+
+class VkDescriptorSetLayoutSupport {
+ VkStructureType sType
+ void* pNext
+ VkBool32 supported
+}
+
+class VkPhysicalDeviceShaderDrawParameterFeatures {
+ VkStructureType sType
+ void* pNext
+ VkBool32 shaderDrawParameters
+}
+
+
@extension("VK_KHR_surface") // 1
class VkSurfaceCapabilitiesKHR {
u32 minImageCount
@@ -3726,6 +4534,62 @@
VkResult* pResults
}
+@vulkan1_1
+@extension("VK_KHR_swapchain") // 2
+class VkImageSwapchainCreateInfoKHR {
+ VkStructureType sType
+ const void* pNext
+ VkSwapchainKHR swapchain
+}
+
+@vulkan1_1
+@extension("VK_KHR_swapchain") // 2
+class VkBindImageMemorySwapchainInfoKHR {
+ VkStructureType sType
+ const void* pNext
+ VkSwapchainKHR swapchain
+ u32 imageIndex
+}
+
+@vulkan1_1
+@extension("VK_KHR_swapchain") // 2
+class VkAcquireNextImageInfoKHR {
+ VkStructureType sType
+ const void* pNext
+ VkSwapchainKHR swapchain
+ u64 timeout
+ VkSemaphore semaphore
+ VkFence fence
+ u32 deviceMask
+}
+
+@vulkan1_1
+@extension("VK_KHR_swapchain") // 2
+class VkDeviceGroupPresentCapabilitiesKHR {
+ VkStructureType sType
+ const void* pNext
+ u32[VK_MAX_DEVICE_GROUP_SIZE] presentMask
+ VkDeviceGroupPresentModeFlagsKHR modes
+}
+
+@vulkan1_1
+@extension("VK_KHR_swapchain") // 2
+class VkDeviceGroupPresentInfoKHR {
+ VkStructureType sType
+ const void* pNext
+ u32 swapchainCount
+ const u32* pDeviceMasks
+ VkDeviceGroupPresentModeFlagBitsKHR mode
+}
+
+@vulkan1_1
+@extension("VK_KHR_swapchain") // 2
+class VkDeviceGroupSwapchainCreateInfoKHR {
+ VkStructureType sType
+ const void* pNext
+ VkDeviceGroupPresentModeFlagsKHR modes
+}
+
@extension("VK_KHR_display") // 3
class VkDisplayPropertiesKHR {
VkDisplayKHR display
@@ -3956,8 +4820,8 @@
VkBool32 supportsTextureGatherLODBiasAMD
}
-@extension("VK_KHX_multiview") // 54
-class VkRenderPassMultiviewCreateInfoKHX {
+@extension("VK_KHR_multiview") // 54
+class VkRenderPassMultiviewCreateInfoKHR {
VkStructureType sType
const void* pNext
u32 subpassCount
@@ -3968,8 +4832,8 @@
const u32* pCorrelationMasks
}
-@extension("VK_KHX_multiview") // 54
-class VkPhysicalDeviceMultiviewFeaturesKHX {
+@extension("VK_KHR_multiview") // 54
+class VkPhysicalDeviceMultiviewFeaturesKHR {
VkStructureType sType
void* pNext
VkBool32 multiview
@@ -3977,8 +4841,8 @@
VkBool32 multiviewTessellationShader
}
-@extension("VK_KHX_multiview") // 54
-class VkPhysicalDeviceMultiviewPropertiesKHX {
+@extension("VK_KHR_multiview") // 54
+class VkPhysicalDeviceMultiviewPropertiesKHR {
VkStructureType sType
void* pNext
u32 maxMultiviewViewCount
@@ -4107,24 +4971,24 @@
VkImageTiling tiling
}
-@extension("VK_KHX_device_group") // 61
-class VkMemoryAllocateFlagsInfoKHX {
+@extension("VK_KHR_device_group") // 61
+class VkMemoryAllocateFlagsInfoKHR {
VkStructureType sType
const void* pNext
- VkMemoryAllocateFlagsKHX flags
+ VkMemoryAllocateFlagsKHR flags
u32 deviceMask
}
-@extension("VK_KHX_device_group") // 61
-class VkBindBufferMemoryDeviceGroupInfoKHX {
+@extension("VK_KHR_device_group") // 61
+class VkBindBufferMemoryDeviceGroupInfoKHR {
VkStructureType sType
const void* pNext
u32 deviceIndexCount
const u32* pDeviceIndices
}
-@extension("VK_KHX_device_group") // 61
-class VkBindImageMemoryDeviceGroupInfoKHX {
+@extension("VK_KHR_device_group") // 61
+class VkBindImageMemoryDeviceGroupInfoKHR {
VkStructureType sType
const void* pNext
u32 deviceIndexCount
@@ -4133,8 +4997,8 @@
const VkRect2D* pSFRRects
}
-@extension("VK_KHX_device_group") // 61
-class VkDeviceGroupRenderPassBeginInfoKHX {
+@extension("VK_KHR_device_group") // 61
+class VkDeviceGroupRenderPassBeginInfoKHR {
VkStructureType sType
const void* pNext
u32 deviceMask
@@ -4142,15 +5006,15 @@
const VkRect2D* pDeviceRenderAreas
}
-@extension("VK_KHX_device_group") // 61
-class VkDeviceGroupCommandBufferBeginInfoKHX {
+@extension("VK_KHR_device_group") // 61
+class VkDeviceGroupCommandBufferBeginInfoKHR {
VkStructureType sType
const void* pNext
u32 deviceMask
}
-@extension("VK_KHX_device_group") // 61
-class VkDeviceGroupSubmitInfoKHX {
+@extension("VK_KHR_device_group") // 61
+class VkDeviceGroupSubmitInfoKHR {
VkStructureType sType
const void* pNext
u32 waitSemaphoreCount
@@ -4161,64 +5025,14 @@
const u32* pSignalSemaphoreDeviceIndices
}
-@extension("VK_KHX_device_group") // 61
-class VkDeviceGroupBindSparseInfoKHX {
+@extension("VK_KHR_device_group") // 61
+class VkDeviceGroupBindSparseInfoKHR {
VkStructureType sType
const void* pNext
u32 resourceDeviceIndex
u32 memoryDeviceIndex
}
-@extension("VK_KHX_device_group") // 61
-class VkDeviceGroupPresentCapabilitiesKHX {
- VkStructureType sType
- const void* pNext
- u32[VK_MAX_DEVICE_GROUP_SIZE_KHX] presentMask
- VkDeviceGroupPresentModeFlagsKHX modes
-}
-
-@extension("VK_KHX_device_group") // 61
-class VkImageSwapchainCreateInfoKHX {
- VkStructureType sType
- const void* pNext
- VkSwapchainKHR swapchain
-}
-
-@extension("VK_KHX_device_group") // 61
-class VkBindImageMemorySwapchainInfoKHX {
- VkStructureType sType
- const void* pNext
- VkSwapchainKHR swapchain
- u32 imageIndex
-}
-
-@extension("VK_KHX_device_group") // 61
-class VkAcquireNextImageInfoKHX {
- VkStructureType sType
- const void* pNext
- VkSwapchainKHR swapchain
- u64 timeout
- VkSemaphore semaphore
- VkFence fence
- u32 deviceMask
-}
-
-@extension("VK_KHX_device_group") // 61
-class VkDeviceGroupPresentInfoKHX {
- VkStructureType sType
- const void* pNext
- u32 swapchainCount
- const u32* pDeviceMasks
- VkDeviceGroupPresentModeFlagBitsKHX mode
-}
-
-@extension("VK_KHX_device_group") // 61
-class VkDeviceGroupSwapchainCreateInfoKHX {
- VkStructureType sType
- const void* pNext
- VkDeviceGroupPresentModeFlagsKHX modes
-}
-
@extension("VK_EXT_validation_flags") // 62
class VkValidationFlagsEXT {
VkStructureType sType
@@ -4235,17 +5049,17 @@
void* window
}
-@extension("VK_KHX_device_group_creation") // 71
-class VkPhysicalDeviceGroupPropertiesKHX {
+@extension("VK_KHR_device_group_creation") // 71
+class VkPhysicalDeviceGroupPropertiesKHR {
VkStructureType sType
void* pNext
u32 physicalDeviceCount
- VkPhysicalDevice[VK_MAX_DEVICE_GROUP_SIZE_KHX] physicalDevices
+ VkPhysicalDevice[VK_MAX_DEVICE_GROUP_SIZE] physicalDevices
VkBool32 subsetAllocation
}
-@extension("VK_KHX_device_group_creation") // 71
-class VkDeviceGroupDeviceCreateInfoKHX {
+@extension("VK_KHR_device_group_creation") // 71
+class VkDeviceGroupDeviceCreateInfoKHR {
VkStructureType sType
const void* pNext
u32 physicalDeviceCount
@@ -4295,7 +5109,7 @@
void* pNext
u8[VK_UUID_SIZE] deviceUUID
u8[VK_UUID_SIZE] driverUUID
- u8[VK_LUID_SIZE_KHR] deviceLUID
+ u8[VK_LUID_SIZE] deviceLUID
u32 deviceNodeMask
VkBool32 deviceLUIDValid
}
@@ -5233,6 +6047,22 @@
VkValidationCacheEXT validationCache
}
+@extension("VK_KHR_maintenance3") // 169
+class VkPhysicalDeviceMaintenance3PropertiesKHR {
+ VkStructureType sType
+ void* pNext
+ u32 maxPerSetDescriptors
+ VkDeviceSize maxMemoryAllocationSize
+}
+
+@extension("VK_KHR_maintenance3") // 169
+class VkDescriptorSetLayoutSupportKHR {
+ VkStructureType sType
+ void* pNext
+ VkBool32 supported
+}
+
+
////////////////
// Commands //
////////////////
@@ -7428,6 +8258,241 @@
}
}
+//@vulkan1_1 functions
+
+@vulkan1_1
+cmd VkResult vkEnumerateInstanceVersion(
+ u32* pApiVersion) {
+ return ?
+}
+
+@vulkan1_1
+cmd VkResult vkBindBufferMemory2(
+ VkDevice device,
+ u32 bindInfoCount,
+ const VkBindBufferMemoryInfo* pBindInfos) {
+ return ?
+}
+
+@vulkan1_1
+cmd VkResult vkBindImageMemory2(
+ VkDevice device,
+ u32 bindInfoCount,
+ const VkBindImageMemoryInfo* pBindInfos) {
+ return ?
+}
+
+@vulkan1_1
+cmd void vkGetDeviceGroupPeerMemoryFeatures(
+ VkDevice device,
+ u32 heapIndex,
+ u32 localDeviceIndex,
+ u32 remoteDeviceIndex,
+ VkPeerMemoryFeatureFlags* pPeerMemoryFeatures) {
+}
+
+@vulkan1_1
+cmd void vkCmdSetDeviceMask(
+ VkCommandBuffer commandBuffer,
+ u32 deviceMask) {
+}
+
+@vulkan1_1
+cmd void vkCmdDispatchBase(
+ VkCommandBuffer commandBuffer,
+ u32 baseGroupX,
+ u32 baseGroupY,
+ u32 baseGroupZ,
+ u32 groupCountX,
+ u32 groupCountY,
+ u32 groupCountZ) {
+}
+
+@threadSafety("system")
+@vulkan1_1
+cmd VkResult vkEnumeratePhysicalDeviceGroups(
+ VkInstance instance,
+ u32* pPhysicalDeviceGroupCount,
+ VkPhysicalDeviceGroupProperties* pPhysicalDeviceGroupProperties) {
+ instanceObject := GetInstance(instance)
+
+ physicalDeviceGroupCount := as!u32(?)
+ pPhysicalDeviceGroupCount[0] = physicalDeviceGroupCount
+ physicalDevices := pPhysicalDeviceGroupProperties[0:physicalDeviceGroupCount]
+
+ for i in (0 .. physicalDeviceGroupCount) {
+ physicalDevice := ?
+ physicalDevices[i] = physicalDevice
+ if !(physicalDevice in State.PhysicalDevices) {
+ State.PhysicalDevices[physicalDevice] = new!PhysicalDeviceObject(instance: instance)
+ }
+ }
+
+ return ?
+}
+
+@vulkan1_1
+cmd void vkGetImageMemoryRequirements2(
+ VkDevice device,
+ const VkImageMemoryRequirementsInfo2* pInfo,
+ VkMemoryRequirements2* pMemoryRequirements) {
+}
+
+@vulkan1_1
+cmd void vkGetBufferMemoryRequirements2(
+ VkDevice device,
+ const VkBufferMemoryRequirementsInfo2* pInfo,
+ VkMemoryRequirements2* pMemoryRequirements) {
+}
+
+@vulkan1_1
+cmd void vkGetImageSparseMemoryRequirements2(
+ VkDevice device,
+ const VkImageSparseMemoryRequirementsInfo2* pInfo,
+ u32* pSparseMemoryRequirementCount,
+ VkSparseImageMemoryRequirements2* pSparseMemoryRequirements) {
+}
+
+@vulkan1_1
+cmd void vkGetPhysicalDeviceFeatures2(
+ VkPhysicalDevice physicalDevice,
+ VkPhysicalDeviceFeatures2* pFeatures) {
+}
+
+@vulkan1_1
+cmd void vkGetPhysicalDeviceProperties2(
+ VkPhysicalDevice physicalDevice,
+ VkPhysicalDeviceProperties2* pProperties) {
+}
+
+@vulkan1_1
+cmd void vkGetPhysicalDeviceFormatProperties2(
+ VkPhysicalDevice physicalDevice,
+ VkFormat format,
+ VkFormatProperties2* pFormatProperties) {
+}
+
+@vulkan1_1
+cmd VkResult vkGetPhysicalDeviceImageFormatProperties2(
+ VkPhysicalDevice physicalDevice,
+ const VkPhysicalDeviceImageFormatInfo2* pImageFormatInfo,
+ VkImageFormatProperties2* pImageFormatProperties) {
+ return ?
+}
+
+@vulkan1_1
+cmd void vkGetPhysicalDeviceQueueFamilyProperties2(
+ VkPhysicalDevice physicalDevice,
+ u32* pQueueFamilyPropertyCount,
+ VkQueueFamilyProperties2* pQueueFamilyProperties) {
+}
+
+@vulkan1_1
+cmd void vkGetPhysicalDeviceMemoryProperties2(
+ VkPhysicalDevice physicalDevice,
+ VkPhysicalDeviceMemoryProperties2* pMemoryProperties) {
+}
+
+@vulkan1_1
+cmd void vkGetPhysicalDeviceSparseImageFormatProperties2(
+ VkPhysicalDevice physicalDevice,
+ const VkPhysicalDeviceSparseImageFormatInfo2* pFormatInfo,
+ u32* pPropertyCount,
+ VkSparseImageFormatProperties2* pProperties) {
+}
+
+@vulkan1_1
+cmd void vkTrimCommandPool(
+ VkDevice device,
+ VkCommandPool commandPool,
+ VkCommandPoolTrimFlags flags) {
+}
+
+
+@vulkan1_1
+cmd void vkGetDeviceQueue2(
+ VkDevice device,
+ const VkDeviceQueueInfo2* pQueueInfo,
+ VkQueue* pQueue) {
+ deviceObject := GetDevice(device)
+
+ queue := ?
+ pQueue[0] = queue
+
+ if !(queue in State.Queues) {
+ State.Queues[queue] = new!QueueObject(device: device)
+ }
+}
+
+@vulkan1_1
+cmd VkResult vkCreateSamplerYcbcrConversion(
+ VkDevice device,
+ const VkSamplerYcbcrConversionCreateInfo* pCreateInfo,
+ const VkAllocationCallbacks* pAllocator,
+ VkSamplerYcbcrConversion* pYcbcrConversion) {
+ return ?
+}
+
+@vulkan1_1
+cmd void vkDestroySamplerYcbcrConversion(
+ VkDevice device,
+ VkSamplerYcbcrConversion ycbcrConversion,
+ const VkAllocationCallbacks* pAllocator) {
+}
+
+@vulkan1_1
+cmd VkResult vkCreateDescriptorUpdateTemplate(
+ VkDevice device,
+ const VkDescriptorUpdateTemplateCreateInfo* pCreateInfo,
+ const VkAllocationCallbacks* pAllocator,
+ VkDescriptorUpdateTemplate* pDescriptorUpdateTemplate) {
+ return ?
+}
+
+@vulkan1_1
+cmd void vkDestroyDescriptorUpdateTemplate(
+ VkDevice device,
+ VkDescriptorUpdateTemplate descriptorUpdateTemplate,
+ const VkAllocationCallbacks* pAllocator) {
+}
+
+@vulkan1_1
+cmd void vkUpdateDescriptorSetWithTemplate(
+ VkDevice device,
+ VkDescriptorSet descriptorSet,
+ VkDescriptorUpdateTemplate descriptorUpdateTemplate,
+ const void* pData) {
+}
+
+@vulkan1_1
+cmd void vkGetPhysicalDeviceExternalBufferProperties(
+ VkPhysicalDevice physicalDevice,
+ const VkPhysicalDeviceExternalBufferInfo* pExternalBufferInfo,
+ VkExternalBufferProperties* pExternalBufferProperties) {
+}
+
+@vulkan1_1
+cmd void vkGetPhysicalDeviceExternalFenceProperties(
+ VkPhysicalDevice physicalDevice,
+ const VkPhysicalDeviceExternalFenceInfo* pExternalFenceInfo,
+ VkExternalFenceProperties* pExternalFenceProperties) {
+}
+
+@vulkan1_1
+cmd void vkGetPhysicalDeviceExternalSemaphoreProperties(
+ VkPhysicalDevice physicalDevice,
+ const VkPhysicalDeviceExternalSemaphoreInfo* pExternalSemaphoreInfo,
+ VkExternalSemaphoreProperties* pExternalSemaphoreProperties) {
+}
+
+@vulkan1_1
+cmd void vkGetDescriptorSetLayoutSupport(
+ VkDevice device,
+ const VkDescriptorSetLayoutCreateInfo* pCreateInfo,
+ VkDescriptorSetLayoutSupport* pSupport) {
+}
+
+
@extension("VK_KHR_surface") // 1
cmd void vkDestroySurfaceKHR(
VkInstance instance,
@@ -7582,6 +8647,42 @@
return ?
}
+@vulkan1_1
+@extension("VK_KHR_swapchain") // 2
+cmd VkResult vkGetDeviceGroupPresentCapabilitiesKHR(
+ VkDevice device,
+ VkDeviceGroupPresentCapabilitiesKHR* pDeviceGroupPresentCapabilities) {
+ return ?
+}
+
+@vulkan1_1
+@extension("VK_KHR_swapchain") // 2
+cmd VkResult vkGetDeviceGroupSurfacePresentModesKHR(
+ VkDevice device,
+ VkSurfaceKHR surface,
+ VkDeviceGroupPresentModeFlagsKHR* pModes) {
+ return ?
+}
+
+@vulkan1_1
+@extension("VK_KHR_swapchain") // 2
+cmd VkResult vkGetPhysicalDevicePresentRectanglesKHR(
+ VkPhysicalDevice physicalDevice,
+ VkSurfaceKHR surface,
+ u32* pRectCount,
+ VkRect2D* pRects) {
+ return ?
+}
+
+@vulkan1_1
+@extension("VK_KHR_swapchain") // 2
+cmd VkResult vkAcquireNextImage2KHR(
+ VkDevice device,
+ const VkAcquireNextImageInfoKHR* pAcquireInfo,
+ u32* pImageIndex) {
+ return ?
+}
+
@extension("VK_KHR_display") // 3
cmd VkResult vkGetPhysicalDeviceDisplayPropertiesKHR(
VkPhysicalDevice physicalDevice,
@@ -7974,46 +9075,24 @@
VkSparseImageFormatProperties2KHR* pProperties) {
}
-@extension("VK_KHX_device_group") // 61
-cmd void vkGetDeviceGroupPeerMemoryFeaturesKHX(
+@extension("VK_KHR_device_group") // 61
+cmd void vkGetDeviceGroupPeerMemoryFeaturesKHR(
VkDevice device,
u32 heapIndex,
u32 localDeviceIndex,
u32 remoteDeviceIndex,
- VkPeerMemoryFeatureFlagsKHX* pPeerMemoryFeatures) {
+ VkPeerMemoryFeatureFlagsKHR* pPeerMemoryFeatures) {
}
-@extension("VK_KHX_device_group") // 61
-cmd void vkCmdSetDeviceMaskKHX(
+@extension("VK_KHR_device_group") // 61
+cmd void vkCmdSetDeviceMaskKHR(
VkCommandBuffer commandBuffer,
u32 deviceMask) {
}
-@extension("VK_KHX_device_group") // 61
-cmd VkResult vkGetDeviceGroupPresentCapabilitiesKHX(
- VkDevice device,
- VkDeviceGroupPresentCapabilitiesKHX* pDeviceGroupPresentCapabilities) {
- return ?
-}
-@extension("VK_KHX_device_group") // 61
-cmd VkResult vkGetDeviceGroupSurfacePresentModesKHX(
- VkDevice device,
- VkSurfaceKHR surface,
- VkDeviceGroupPresentModeFlagsKHX* pModes) {
- return ?
-}
-
-@extension("VK_KHX_device_group") // 61
-cmd VkResult vkAcquireNextImage2KHX(
- VkDevice device,
- const VkAcquireNextImageInfoKHX* pAcquireInfo,
- u32* pImageIndex) {
- return ?
-}
-
-@extension("VK_KHX_device_group") // 61
-cmd void vkCmdDispatchBaseKHX(
+@extension("VK_KHR_device_group") // 61
+cmd void vkCmdDispatchBaseKHR(
VkCommandBuffer commandBuffer,
u32 baseGroupX,
u32 baseGroupY,
@@ -8023,15 +9102,6 @@
u32 groupCountZ) {
}
-@extension("VK_KHX_device_group") // 61
-cmd VkResult vkGetPhysicalDevicePresentRectanglesKHX(
- VkPhysicalDevice physicalDevice,
- VkSurfaceKHR surface,
- u32* pRectCount,
- VkRect2D* pRects) {
- return ?
-}
-
@extension("VK_NN_vi_surface") // 63
cmd VkResult vkCreateViSurfaceNN(
VkInstance instance,
@@ -8048,11 +9118,26 @@
VkCommandPoolTrimFlagsKHR flags) {
}
-@extension("VK_KHX_device_group_creation") // 71
-cmd VkResult vkEnumeratePhysicalDeviceGroupsKHX(
+@extension("VK_KHR_device_group_creation") // 71
+@threadSafety("system")
+cmd VkResult vkEnumeratePhysicalDeviceGroupsKHR(
VkInstance instance,
u32* pPhysicalDeviceGroupCount,
- VkPhysicalDeviceGroupPropertiesKHX* pPhysicalDeviceGroupProperties) {
+ VkPhysicalDeviceGroupPropertiesKHR* pPhysicalDeviceGroupProperties) {
+ instanceObject := GetInstance(instance)
+
+ physicalDeviceGroupCount := as!u32(?)
+ pPhysicalDeviceGroupCount[0] = physicalDeviceGroupCount
+ physicalDevices := pPhysicalDeviceGroupProperties[0:physicalDeviceGroupCount]
+
+ for i in (0 .. physicalDeviceGroupCount) {
+ physicalDevice := ?
+ physicalDevices[i] = physicalDevice
+ if !(physicalDevice in State.PhysicalDevices) {
+ State.PhysicalDevices[physicalDevice] = new!PhysicalDeviceObject(instance: instance)
+ }
+ }
+
return ?
}
@@ -8543,6 +9628,13 @@
return ?
}
+@extension("VK_KHR_maintenance3") // 169
+cmd void vkGetDescriptorSetLayoutSupportKHR(
+ VkDevice device,
+ const VkDescriptorSetLayoutCreateInfo* pCreateInfo,
+ VkDescriptorSetLayoutSupportKHR* pSupport) {
+}
+
////////////////
// Validation //
////////////////
diff --git a/vulkan/include/vulkan/vulkan.h b/vulkan/include/vulkan/vulkan.h
index 7813e4b..f96a9fa 100644
--- a/vulkan/include/vulkan/vulkan.h
+++ b/vulkan/include/vulkan/vulkan.h
@@ -138,6 +138,8 @@
VK_ERROR_TOO_MANY_OBJECTS = -10,
VK_ERROR_FORMAT_NOT_SUPPORTED = -11,
VK_ERROR_FRAGMENTED_POOL = -12,
+ VK_ERROR_OUT_OF_POOL_MEMORY = -1000069000,
+ VK_ERROR_INVALID_EXTERNAL_HANDLE = -1000072003,
VK_ERROR_SURFACE_LOST_KHR = -1000000000,
VK_ERROR_NATIVE_WINDOW_IN_USE_KHR = -1000000001,
VK_SUBOPTIMAL_KHR = 1000001003,
@@ -145,8 +147,6 @@
VK_ERROR_INCOMPATIBLE_DISPLAY_KHR = -1000003001,
VK_ERROR_VALIDATION_FAILED_EXT = -1000011001,
VK_ERROR_INVALID_SHADER_NV = -1000012000,
- VK_ERROR_OUT_OF_POOL_MEMORY_KHR = -1000069000,
- VK_ERROR_INVALID_EXTERNAL_HANDLE_KHR = -1000072003,
VK_RESULT_BEGIN_RANGE = VK_ERROR_FRAGMENTED_POOL,
VK_RESULT_END_RANGE = VK_INCOMPLETE,
VK_RESULT_RANGE_SIZE = (VK_INCOMPLETE - VK_ERROR_FRAGMENTED_POOL + 1),
@@ -203,8 +203,79 @@
VK_STRUCTURE_TYPE_MEMORY_BARRIER = 46,
VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFO = 47,
VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFO = 48,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_PROPERTIES = 1000094000,
+ VK_STRUCTURE_TYPE_BIND_BUFFER_MEMORY_INFO = 1000157000,
+ VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_INFO = 1000157001,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_16BIT_STORAGE_FEATURES = 1000083000,
+ VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS = 1000127000,
+ VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO = 1000127001,
+ VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_FLAGS_INFO = 1000060000,
+ VK_STRUCTURE_TYPE_DEVICE_GROUP_RENDER_PASS_BEGIN_INFO = 1000060003,
+ VK_STRUCTURE_TYPE_DEVICE_GROUP_COMMAND_BUFFER_BEGIN_INFO = 1000060004,
+ VK_STRUCTURE_TYPE_DEVICE_GROUP_SUBMIT_INFO = 1000060005,
+ VK_STRUCTURE_TYPE_DEVICE_GROUP_BIND_SPARSE_INFO = 1000060006,
+ VK_STRUCTURE_TYPE_BIND_BUFFER_MEMORY_DEVICE_GROUP_INFO = 1000060013,
+ VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_DEVICE_GROUP_INFO = 1000060014,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GROUP_PROPERTIES = 1000070000,
+ VK_STRUCTURE_TYPE_DEVICE_GROUP_DEVICE_CREATE_INFO = 1000070001,
+ VK_STRUCTURE_TYPE_BUFFER_MEMORY_REQUIREMENTS_INFO_2 = 1000146000,
+ VK_STRUCTURE_TYPE_IMAGE_MEMORY_REQUIREMENTS_INFO_2 = 1000146001,
+ VK_STRUCTURE_TYPE_IMAGE_SPARSE_MEMORY_REQUIREMENTS_INFO_2 = 1000146002,
+ VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2 = 1000146003,
+ VK_STRUCTURE_TYPE_SPARSE_IMAGE_MEMORY_REQUIREMENTS_2 = 1000146004,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2 = 1000059000,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2 = 1000059001,
+ VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2 = 1000059002,
+ VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2 = 1000059003,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2 = 1000059004,
+ VK_STRUCTURE_TYPE_QUEUE_FAMILY_PROPERTIES_2 = 1000059005,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_PROPERTIES_2 = 1000059006,
+ VK_STRUCTURE_TYPE_SPARSE_IMAGE_FORMAT_PROPERTIES_2 = 1000059007,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SPARSE_IMAGE_FORMAT_INFO_2 = 1000059008,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_POINT_CLIPPING_PROPERTIES = 1000117000,
+ VK_STRUCTURE_TYPE_RENDER_PASS_INPUT_ATTACHMENT_ASPECT_CREATE_INFO = 1000117001,
+ VK_STRUCTURE_TYPE_IMAGE_VIEW_USAGE_CREATE_INFO = 1000117002,
+ VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_DOMAIN_ORIGIN_STATE_CREATE_INFO = 1000117003,
+ VK_STRUCTURE_TYPE_RENDER_PASS_MULTIVIEW_CREATE_INFO = 1000053000,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_FEATURES = 1000053001,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_PROPERTIES = 1000053002,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VARIABLE_POINTER_FEATURES = 1000120000,
+ VK_STRUCTURE_TYPE_PROTECTED_SUBMIT_INFO = 1000145000,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROTECTED_MEMORY_FEATURES = 1000145001,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROTECTED_MEMORY_PROPERTIES = 1000145002,
+ VK_STRUCTURE_TYPE_DEVICE_QUEUE_INFO_2 = 1000145003,
+ VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_CREATE_INFO = 1000156000,
+ VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_INFO = 1000156001,
+ VK_STRUCTURE_TYPE_BIND_IMAGE_PLANE_MEMORY_INFO = 1000156002,
+ VK_STRUCTURE_TYPE_IMAGE_PLANE_MEMORY_REQUIREMENTS_INFO = 1000156003,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_YCBCR_CONVERSION_FEATURES = 1000156004,
+ VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_IMAGE_FORMAT_PROPERTIES = 1000156005,
+ VK_STRUCTURE_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_CREATE_INFO = 1000085000,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO = 1000071000,
+ VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES = 1000071001,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_BUFFER_INFO = 1000071002,
+ VK_STRUCTURE_TYPE_EXTERNAL_BUFFER_PROPERTIES = 1000071003,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ID_PROPERTIES = 1000071004,
+ VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_BUFFER_CREATE_INFO = 1000072000,
+ VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO = 1000072001,
+ VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO = 1000072002,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_FENCE_INFO = 1000112000,
+ VK_STRUCTURE_TYPE_EXTERNAL_FENCE_PROPERTIES = 1000112001,
+ VK_STRUCTURE_TYPE_EXPORT_FENCE_CREATE_INFO = 1000113000,
+ VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_CREATE_INFO = 1000077000,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_SEMAPHORE_INFO = 1000076000,
+ VK_STRUCTURE_TYPE_EXTERNAL_SEMAPHORE_PROPERTIES = 1000076001,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_3_PROPERTIES = 1000168000,
+ VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_SUPPORT = 1000168001,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_DRAW_PARAMETER_FEATURES = 1000063000,
+ VK_STRUCTURE_TYPE_DEVICE_GROUP_PRESENT_CAPABILITIES_KHR = 1000060007,
VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR = 1000001000,
VK_STRUCTURE_TYPE_PRESENT_INFO_KHR = 1000001001,
+ VK_STRUCTURE_TYPE_IMAGE_SWAPCHAIN_CREATE_INFO_KHR = 1000060008,
+ VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_SWAPCHAIN_INFO_KHR = 1000060009,
+ VK_STRUCTURE_TYPE_ACQUIRE_NEXT_IMAGE_INFO_KHR = 1000060010,
+ VK_STRUCTURE_TYPE_DEVICE_GROUP_PRESENT_INFO_KHR = 1000060011,
+ VK_STRUCTURE_TYPE_DEVICE_GROUP_SWAPCHAIN_CREATE_INFO_KHR = 1000060012,
VK_STRUCTURE_TYPE_DISPLAY_MODE_CREATE_INFO_KHR = 1000002000,
VK_STRUCTURE_TYPE_DISPLAY_SURFACE_CREATE_INFO_KHR = 1000002001,
VK_STRUCTURE_TYPE_DISPLAY_PRESENT_INFO_KHR = 1000003000,
@@ -223,48 +294,13 @@
VK_STRUCTURE_TYPE_DEDICATED_ALLOCATION_BUFFER_CREATE_INFO_NV = 1000026001,
VK_STRUCTURE_TYPE_DEDICATED_ALLOCATION_MEMORY_ALLOCATE_INFO_NV = 1000026002,
VK_STRUCTURE_TYPE_TEXTURE_LOD_GATHER_FORMAT_PROPERTIES_AMD = 1000041000,
- VK_STRUCTURE_TYPE_RENDER_PASS_MULTIVIEW_CREATE_INFO_KHX = 1000053000,
- VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_FEATURES_KHX = 1000053001,
- VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_PROPERTIES_KHX = 1000053002,
VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO_NV = 1000056000,
VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO_NV = 1000056001,
VK_STRUCTURE_TYPE_IMPORT_MEMORY_WIN32_HANDLE_INFO_NV = 1000057000,
VK_STRUCTURE_TYPE_EXPORT_MEMORY_WIN32_HANDLE_INFO_NV = 1000057001,
VK_STRUCTURE_TYPE_WIN32_KEYED_MUTEX_ACQUIRE_RELEASE_INFO_NV = 1000058000,
- VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2_KHR = 1000059000,
- VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2_KHR = 1000059001,
- VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR = 1000059002,
- VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2_KHR = 1000059003,
- VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2_KHR = 1000059004,
- VK_STRUCTURE_TYPE_QUEUE_FAMILY_PROPERTIES_2_KHR = 1000059005,
- VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_PROPERTIES_2_KHR = 1000059006,
- VK_STRUCTURE_TYPE_SPARSE_IMAGE_FORMAT_PROPERTIES_2_KHR = 1000059007,
- VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SPARSE_IMAGE_FORMAT_INFO_2_KHR = 1000059008,
- VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_FLAGS_INFO_KHX = 1000060000,
- VK_STRUCTURE_TYPE_DEVICE_GROUP_RENDER_PASS_BEGIN_INFO_KHX = 1000060003,
- VK_STRUCTURE_TYPE_DEVICE_GROUP_COMMAND_BUFFER_BEGIN_INFO_KHX = 1000060004,
- VK_STRUCTURE_TYPE_DEVICE_GROUP_SUBMIT_INFO_KHX = 1000060005,
- VK_STRUCTURE_TYPE_DEVICE_GROUP_BIND_SPARSE_INFO_KHX = 1000060006,
- VK_STRUCTURE_TYPE_ACQUIRE_NEXT_IMAGE_INFO_KHX = 1000060010,
- VK_STRUCTURE_TYPE_BIND_BUFFER_MEMORY_DEVICE_GROUP_INFO_KHX = 1000060013,
- VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_DEVICE_GROUP_INFO_KHX = 1000060014,
- VK_STRUCTURE_TYPE_DEVICE_GROUP_PRESENT_CAPABILITIES_KHX = 1000060007,
- VK_STRUCTURE_TYPE_IMAGE_SWAPCHAIN_CREATE_INFO_KHX = 1000060008,
- VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_SWAPCHAIN_INFO_KHX = 1000060009,
- VK_STRUCTURE_TYPE_DEVICE_GROUP_PRESENT_INFO_KHX = 1000060011,
- VK_STRUCTURE_TYPE_DEVICE_GROUP_SWAPCHAIN_CREATE_INFO_KHX = 1000060012,
VK_STRUCTURE_TYPE_VALIDATION_FLAGS_EXT = 1000061000,
VK_STRUCTURE_TYPE_VI_SURFACE_CREATE_INFO_NN = 1000062000,
- VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GROUP_PROPERTIES_KHX = 1000070000,
- VK_STRUCTURE_TYPE_DEVICE_GROUP_DEVICE_CREATE_INFO_KHX = 1000070001,
- VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO_KHR = 1000071000,
- VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES_KHR = 1000071001,
- VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_BUFFER_INFO_KHR = 1000071002,
- VK_STRUCTURE_TYPE_EXTERNAL_BUFFER_PROPERTIES_KHR = 1000071003,
- VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ID_PROPERTIES_KHR = 1000071004,
- VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_BUFFER_CREATE_INFO_KHR = 1000072000,
- VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO_KHR = 1000072001,
- VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO_KHR = 1000072002,
VK_STRUCTURE_TYPE_IMPORT_MEMORY_WIN32_HANDLE_INFO_KHR = 1000073000,
VK_STRUCTURE_TYPE_EXPORT_MEMORY_WIN32_HANDLE_INFO_KHR = 1000073001,
VK_STRUCTURE_TYPE_MEMORY_WIN32_HANDLE_PROPERTIES_KHR = 1000073002,
@@ -273,9 +309,6 @@
VK_STRUCTURE_TYPE_MEMORY_FD_PROPERTIES_KHR = 1000074001,
VK_STRUCTURE_TYPE_MEMORY_GET_FD_INFO_KHR = 1000074002,
VK_STRUCTURE_TYPE_WIN32_KEYED_MUTEX_ACQUIRE_RELEASE_INFO_KHR = 1000075000,
- VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_SEMAPHORE_INFO_KHR = 1000076000,
- VK_STRUCTURE_TYPE_EXTERNAL_SEMAPHORE_PROPERTIES_KHR = 1000076001,
- VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_CREATE_INFO_KHR = 1000077000,
VK_STRUCTURE_TYPE_IMPORT_SEMAPHORE_WIN32_HANDLE_INFO_KHR = 1000078000,
VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_WIN32_HANDLE_INFO_KHR = 1000078001,
VK_STRUCTURE_TYPE_D3D12_FENCE_SUBMIT_INFO_KHR = 1000078002,
@@ -283,9 +316,7 @@
VK_STRUCTURE_TYPE_IMPORT_SEMAPHORE_FD_INFO_KHR = 1000079000,
VK_STRUCTURE_TYPE_SEMAPHORE_GET_FD_INFO_KHR = 1000079001,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PUSH_DESCRIPTOR_PROPERTIES_KHR = 1000080000,
- VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_16BIT_STORAGE_FEATURES_KHR = 1000083000,
VK_STRUCTURE_TYPE_PRESENT_REGIONS_KHR = 1000084000,
- VK_STRUCTURE_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_CREATE_INFO_KHR = 1000085000,
VK_STRUCTURE_TYPE_OBJECT_TABLE_CREATE_INFO_NVX = 1000086000,
VK_STRUCTURE_TYPE_INDIRECT_COMMANDS_LAYOUT_CREATE_INFO_NVX = 1000086001,
VK_STRUCTURE_TYPE_CMD_PROCESS_COMMANDS_INFO_NVX = 1000086002,
@@ -305,26 +336,16 @@
VK_STRUCTURE_TYPE_PIPELINE_DISCARD_RECTANGLE_STATE_CREATE_INFO_EXT = 1000099001,
VK_STRUCTURE_TYPE_HDR_METADATA_EXT = 1000105000,
VK_STRUCTURE_TYPE_SHARED_PRESENT_SURFACE_CAPABILITIES_KHR = 1000111000,
- VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_FENCE_INFO_KHR = 1000112000,
- VK_STRUCTURE_TYPE_EXTERNAL_FENCE_PROPERTIES_KHR = 1000112001,
- VK_STRUCTURE_TYPE_EXPORT_FENCE_CREATE_INFO_KHR = 1000113000,
VK_STRUCTURE_TYPE_IMPORT_FENCE_WIN32_HANDLE_INFO_KHR = 1000114000,
VK_STRUCTURE_TYPE_EXPORT_FENCE_WIN32_HANDLE_INFO_KHR = 1000114001,
VK_STRUCTURE_TYPE_FENCE_GET_WIN32_HANDLE_INFO_KHR = 1000114002,
VK_STRUCTURE_TYPE_IMPORT_FENCE_FD_INFO_KHR = 1000115000,
VK_STRUCTURE_TYPE_FENCE_GET_FD_INFO_KHR = 1000115001,
- VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_POINT_CLIPPING_PROPERTIES_KHR = 1000117000,
- VK_STRUCTURE_TYPE_RENDER_PASS_INPUT_ATTACHMENT_ASPECT_CREATE_INFO_KHR = 1000117001,
- VK_STRUCTURE_TYPE_IMAGE_VIEW_USAGE_CREATE_INFO_KHR = 1000117002,
- VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_DOMAIN_ORIGIN_STATE_CREATE_INFO_KHR = 1000117003,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SURFACE_INFO_2_KHR = 1000119000,
VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_2_KHR = 1000119001,
VK_STRUCTURE_TYPE_SURFACE_FORMAT_2_KHR = 1000119002,
- VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VARIABLE_POINTER_FEATURES_KHR = 1000120000,
VK_STRUCTURE_TYPE_IOS_SURFACE_CREATE_INFO_MVK = 1000122000,
VK_STRUCTURE_TYPE_MACOS_SURFACE_CREATE_INFO_MVK = 1000123000,
- VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS_KHR = 1000127000,
- VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO_KHR = 1000127001,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_FILTER_MINMAX_PROPERTIES_EXT = 1000130000,
VK_STRUCTURE_TYPE_SAMPLER_REDUCTION_MODE_CREATE_INFO_EXT = 1000130001,
VK_STRUCTURE_TYPE_SAMPLE_LOCATIONS_INFO_EXT = 1000143000,
@@ -332,25 +353,12 @@
VK_STRUCTURE_TYPE_PIPELINE_SAMPLE_LOCATIONS_STATE_CREATE_INFO_EXT = 1000143002,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLE_LOCATIONS_PROPERTIES_EXT = 1000143003,
VK_STRUCTURE_TYPE_MULTISAMPLE_PROPERTIES_EXT = 1000143004,
- VK_STRUCTURE_TYPE_BUFFER_MEMORY_REQUIREMENTS_INFO_2_KHR = 1000146000,
- VK_STRUCTURE_TYPE_IMAGE_MEMORY_REQUIREMENTS_INFO_2_KHR = 1000146001,
- VK_STRUCTURE_TYPE_IMAGE_SPARSE_MEMORY_REQUIREMENTS_INFO_2_KHR = 1000146002,
- VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2_KHR = 1000146003,
- VK_STRUCTURE_TYPE_SPARSE_IMAGE_MEMORY_REQUIREMENTS_2_KHR = 1000146004,
VK_STRUCTURE_TYPE_IMAGE_FORMAT_LIST_CREATE_INFO_KHR = 1000147000,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BLEND_OPERATION_ADVANCED_FEATURES_EXT = 1000148000,
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BLEND_OPERATION_ADVANCED_PROPERTIES_EXT = 1000148001,
VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_ADVANCED_STATE_CREATE_INFO_EXT = 1000148002,
VK_STRUCTURE_TYPE_PIPELINE_COVERAGE_TO_COLOR_STATE_CREATE_INFO_NV = 1000149000,
VK_STRUCTURE_TYPE_PIPELINE_COVERAGE_MODULATION_STATE_CREATE_INFO_NV = 1000152000,
- VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_CREATE_INFO_KHR = 1000156000,
- VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_INFO_KHR = 1000156001,
- VK_STRUCTURE_TYPE_BIND_IMAGE_PLANE_MEMORY_INFO_KHR = 1000156002,
- VK_STRUCTURE_TYPE_IMAGE_PLANE_MEMORY_REQUIREMENTS_INFO_KHR = 1000156003,
- VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_YCBCR_CONVERSION_FEATURES_KHR = 1000156004,
- VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_IMAGE_FORMAT_PROPERTIES_KHR = 1000156005,
- VK_STRUCTURE_TYPE_BIND_BUFFER_MEMORY_INFO_KHR = 1000157000,
- VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_INFO_KHR = 1000157001,
VK_STRUCTURE_TYPE_VALIDATION_CACHE_CREATE_INFO_EXT = 1000160000,
VK_STRUCTURE_TYPE_SHADER_MODULE_VALIDATION_CACHE_CREATE_INFO_EXT = 1000160001,
VK_STRUCTURE_TYPE_BEGIN_RANGE = VK_STRUCTURE_TYPE_APPLICATION_INFO,
@@ -565,6 +573,40 @@
VK_FORMAT_ASTC_12x10_SRGB_BLOCK = 182,
VK_FORMAT_ASTC_12x12_UNORM_BLOCK = 183,
VK_FORMAT_ASTC_12x12_SRGB_BLOCK = 184,
+ VK_FORMAT_G8B8G8R8_422_UNORM = 1000156000,
+ VK_FORMAT_B8G8R8G8_422_UNORM = 1000156001,
+ VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM = 1000156002,
+ VK_FORMAT_G8_B8R8_2PLANE_420_UNORM = 1000156003,
+ VK_FORMAT_G8_B8_R8_3PLANE_422_UNORM = 1000156004,
+ VK_FORMAT_G8_B8R8_2PLANE_422_UNORM = 1000156005,
+ VK_FORMAT_G8_B8_R8_3PLANE_444_UNORM = 1000156006,
+ VK_FORMAT_R10X6_UNORM_PACK16 = 1000156007,
+ VK_FORMAT_R10X6G10X6_UNORM_2PACK16 = 1000156008,
+ VK_FORMAT_R10X6G10X6B10X6A10X6_UNORM_4PACK16 = 1000156009,
+ VK_FORMAT_G10X6B10X6G10X6R10X6_422_UNORM_4PACK16 = 1000156010,
+ VK_FORMAT_B10X6G10X6R10X6G10X6_422_UNORM_4PACK16 = 1000156011,
+ VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_420_UNORM_3PACK16 = 1000156012,
+ VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16 = 1000156013,
+ VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_422_UNORM_3PACK16 = 1000156014,
+ VK_FORMAT_G10X6_B10X6R10X6_2PLANE_422_UNORM_3PACK16 = 1000156015,
+ VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_444_UNORM_3PACK16 = 1000156016,
+ VK_FORMAT_R12X4_UNORM_PACK16 = 1000156017,
+ VK_FORMAT_R12X4G12X4_UNORM_2PACK16 = 1000156018,
+ VK_FORMAT_R12X4G12X4B12X4A12X4_UNORM_4PACK16 = 1000156019,
+ VK_FORMAT_G12X4B12X4G12X4R12X4_422_UNORM_4PACK16 = 1000156020,
+ VK_FORMAT_B12X4G12X4R12X4G12X4_422_UNORM_4PACK16 = 1000156021,
+ VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_420_UNORM_3PACK16 = 1000156022,
+ VK_FORMAT_G12X4_B12X4R12X4_2PLANE_420_UNORM_3PACK16 = 1000156023,
+ VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_422_UNORM_3PACK16 = 1000156024,
+ VK_FORMAT_G12X4_B12X4R12X4_2PLANE_422_UNORM_3PACK16 = 1000156025,
+ VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_444_UNORM_3PACK16 = 1000156026,
+ VK_FORMAT_G16B16G16R16_422_UNORM = 1000156027,
+ VK_FORMAT_B16G16R16G16_422_UNORM = 1000156028,
+ VK_FORMAT_G16_B16_R16_3PLANE_420_UNORM = 1000156029,
+ VK_FORMAT_G16_B16R16_2PLANE_420_UNORM = 1000156030,
+ VK_FORMAT_G16_B16_R16_3PLANE_422_UNORM = 1000156031,
+ VK_FORMAT_G16_B16R16_2PLANE_422_UNORM = 1000156032,
+ VK_FORMAT_G16_B16_R16_3PLANE_444_UNORM = 1000156033,
VK_FORMAT_PVRTC1_2BPP_UNORM_BLOCK_IMG = 1000054000,
VK_FORMAT_PVRTC1_4BPP_UNORM_BLOCK_IMG = 1000054001,
VK_FORMAT_PVRTC2_2BPP_UNORM_BLOCK_IMG = 1000054002,
@@ -573,40 +615,6 @@
VK_FORMAT_PVRTC1_4BPP_SRGB_BLOCK_IMG = 1000054005,
VK_FORMAT_PVRTC2_2BPP_SRGB_BLOCK_IMG = 1000054006,
VK_FORMAT_PVRTC2_4BPP_SRGB_BLOCK_IMG = 1000054007,
- VK_FORMAT_G8B8G8R8_422_UNORM_KHR = 1000156000,
- VK_FORMAT_B8G8R8G8_422_UNORM_KHR = 1000156001,
- VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM_KHR = 1000156002,
- VK_FORMAT_G8_B8R8_2PLANE_420_UNORM_KHR = 1000156003,
- VK_FORMAT_G8_B8_R8_3PLANE_422_UNORM_KHR = 1000156004,
- VK_FORMAT_G8_B8R8_2PLANE_422_UNORM_KHR = 1000156005,
- VK_FORMAT_G8_B8_R8_3PLANE_444_UNORM_KHR = 1000156006,
- VK_FORMAT_R10X6_UNORM_PACK16_KHR = 1000156007,
- VK_FORMAT_R10X6G10X6_UNORM_2PACK16_KHR = 1000156008,
- VK_FORMAT_R10X6G10X6B10X6A10X6_UNORM_4PACK16_KHR = 1000156009,
- VK_FORMAT_G10X6B10X6G10X6R10X6_422_UNORM_4PACK16_KHR = 1000156010,
- VK_FORMAT_B10X6G10X6R10X6G10X6_422_UNORM_4PACK16_KHR = 1000156011,
- VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_420_UNORM_3PACK16_KHR = 1000156012,
- VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16_KHR = 1000156013,
- VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_422_UNORM_3PACK16_KHR = 1000156014,
- VK_FORMAT_G10X6_B10X6R10X6_2PLANE_422_UNORM_3PACK16_KHR = 1000156015,
- VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_444_UNORM_3PACK16_KHR = 1000156016,
- VK_FORMAT_R12X4_UNORM_PACK16_KHR = 1000156017,
- VK_FORMAT_R12X4G12X4_UNORM_2PACK16_KHR = 1000156018,
- VK_FORMAT_R12X4G12X4B12X4A12X4_UNORM_4PACK16_KHR = 1000156019,
- VK_FORMAT_G12X4B12X4G12X4R12X4_422_UNORM_4PACK16_KHR = 1000156020,
- VK_FORMAT_B12X4G12X4R12X4G12X4_422_UNORM_4PACK16_KHR = 1000156021,
- VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_420_UNORM_3PACK16_KHR = 1000156022,
- VK_FORMAT_G12X4_B12X4R12X4_2PLANE_420_UNORM_3PACK16_KHR = 1000156023,
- VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_422_UNORM_3PACK16_KHR = 1000156024,
- VK_FORMAT_G12X4_B12X4R12X4_2PLANE_422_UNORM_3PACK16_KHR = 1000156025,
- VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_444_UNORM_3PACK16_KHR = 1000156026,
- VK_FORMAT_G16B16G16R16_422_UNORM_KHR = 1000156027,
- VK_FORMAT_B16G16R16G16_422_UNORM_KHR = 1000156028,
- VK_FORMAT_G16_B16_R16_3PLANE_420_UNORM_KHR = 1000156029,
- VK_FORMAT_G16_B16R16_2PLANE_420_UNORM_KHR = 1000156030,
- VK_FORMAT_G16_B16_R16_3PLANE_422_UNORM_KHR = 1000156031,
- VK_FORMAT_G16_B16R16_2PLANE_422_UNORM_KHR = 1000156032,
- VK_FORMAT_G16_B16_R16_3PLANE_444_UNORM_KHR = 1000156033,
VK_FORMAT_BEGIN_RANGE = VK_FORMAT_UNDEFINED,
VK_FORMAT_END_RANGE = VK_FORMAT_ASTC_12x12_SRGB_BLOCK,
VK_FORMAT_RANGE_SIZE = (VK_FORMAT_ASTC_12x12_SRGB_BLOCK - VK_FORMAT_UNDEFINED + 1),
@@ -673,10 +681,10 @@
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL = 6,
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL = 7,
VK_IMAGE_LAYOUT_PREINITIALIZED = 8,
+ VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL = 1000117000,
+ VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL = 1000117001,
VK_IMAGE_LAYOUT_PRESENT_SRC_KHR = 1000001002,
VK_IMAGE_LAYOUT_SHARED_PRESENT_KHR = 1000111000,
- VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL_KHR = 1000117000,
- VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL_KHR = 1000117001,
VK_IMAGE_LAYOUT_BEGIN_RANGE = VK_IMAGE_LAYOUT_UNDEFINED,
VK_IMAGE_LAYOUT_END_RANGE = VK_IMAGE_LAYOUT_PREINITIALIZED,
VK_IMAGE_LAYOUT_RANGE_SIZE = (VK_IMAGE_LAYOUT_PREINITIALIZED - VK_IMAGE_LAYOUT_UNDEFINED + 1),
@@ -1058,15 +1066,15 @@
VK_OBJECT_TYPE_DESCRIPTOR_SET = 23,
VK_OBJECT_TYPE_FRAMEBUFFER = 24,
VK_OBJECT_TYPE_COMMAND_POOL = 25,
+ VK_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION = 1000156000,
+ VK_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE = 1000085000,
VK_OBJECT_TYPE_SURFACE_KHR = 1000000000,
VK_OBJECT_TYPE_SWAPCHAIN_KHR = 1000001000,
VK_OBJECT_TYPE_DISPLAY_KHR = 1000002000,
VK_OBJECT_TYPE_DISPLAY_MODE_KHR = 1000002001,
VK_OBJECT_TYPE_DEBUG_REPORT_CALLBACK_EXT = 1000011000,
- VK_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_KHR = 1000085000,
VK_OBJECT_TYPE_OBJECT_TABLE_NVX = 1000086000,
VK_OBJECT_TYPE_INDIRECT_COMMANDS_LAYOUT_NVX = 1000086001,
- VK_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION_KHR = 1000156000,
VK_OBJECT_TYPE_VALIDATION_CACHE_EXT = 1000160000,
VK_OBJECT_TYPE_BEGIN_RANGE = VK_OBJECT_TYPE_UNKNOWN,
VK_OBJECT_TYPE_END_RANGE = VK_OBJECT_TYPE_COMMAND_POOL,
@@ -1090,17 +1098,17 @@
VK_FORMAT_FEATURE_BLIT_SRC_BIT = 0x00000400,
VK_FORMAT_FEATURE_BLIT_DST_BIT = 0x00000800,
VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT = 0x00001000,
+ VK_FORMAT_FEATURE_TRANSFER_SRC_BIT = 0x00004000,
+ VK_FORMAT_FEATURE_TRANSFER_DST_BIT = 0x00008000,
+ VK_FORMAT_FEATURE_MIDPOINT_CHROMA_SAMPLES_BIT = 0x00020000,
+ VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_LINEAR_FILTER_BIT = 0x00040000,
+ VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_SEPARATE_RECONSTRUCTION_FILTER_BIT = 0x00080000,
+ VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_BIT = 0x00100000,
+ VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_FORCEABLE_BIT = 0x00200000,
+ VK_FORMAT_FEATURE_DISJOINT_BIT = 0x00400000,
+ VK_FORMAT_FEATURE_COSITED_CHROMA_SAMPLES_BIT = 0x00800000,
VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_CUBIC_BIT_IMG = 0x00002000,
- VK_FORMAT_FEATURE_TRANSFER_SRC_BIT_KHR = 0x00004000,
- VK_FORMAT_FEATURE_TRANSFER_DST_BIT_KHR = 0x00008000,
VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_MINMAX_BIT_EXT = 0x00010000,
- VK_FORMAT_FEATURE_MIDPOINT_CHROMA_SAMPLES_BIT_KHR = 0x00020000,
- VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_LINEAR_FILTER_BIT_KHR = 0x00040000,
- VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_SEPARATE_RECONSTRUCTION_FILTER_BIT_KHR = 0x00080000,
- VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_BIT_KHR = 0x00100000,
- VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_FORCEABLE_BIT_KHR = 0x00200000,
- VK_FORMAT_FEATURE_DISJOINT_BIT_KHR = 0x00400000,
- VK_FORMAT_FEATURE_COSITED_CHROMA_SAMPLES_BIT_KHR = 0x00800000,
VK_FORMAT_FEATURE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
} VkFormatFeatureFlagBits;
typedef VkFlags VkFormatFeatureFlags;
@@ -1124,13 +1132,14 @@
VK_IMAGE_CREATE_SPARSE_ALIASED_BIT = 0x00000004,
VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT = 0x00000008,
VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT = 0x00000010,
- VK_IMAGE_CREATE_BIND_SFR_BIT_KHX = 0x00000040,
- VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT_KHR = 0x00000020,
- VK_IMAGE_CREATE_BLOCK_TEXEL_VIEW_COMPATIBLE_BIT_KHR = 0x00000080,
- VK_IMAGE_CREATE_EXTENDED_USAGE_BIT_KHR = 0x00000100,
+ VK_IMAGE_CREATE_ALIAS_BIT = 0x00000400,
+ VK_IMAGE_CREATE_BIND_SFR_BIT = 0x00000040,
+ VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT = 0x00000020,
+ VK_IMAGE_CREATE_BLOCK_TEXEL_VIEW_COMPATIBLE_BIT = 0x00000080,
+ VK_IMAGE_CREATE_EXTENDED_USAGE_BIT = 0x00000100,
+ VK_IMAGE_CREATE_PROTECTED_BIT = 0x00000800,
+ VK_IMAGE_CREATE_DISJOINT_BIT = 0x00000200,
VK_IMAGE_CREATE_SAMPLE_LOCATIONS_COMPATIBLE_DEPTH_BIT_EXT = 0x00001000,
- VK_IMAGE_CREATE_DISJOINT_BIT_KHR = 0x00000200,
- VK_IMAGE_CREATE_ALIAS_BIT_KHR = 0x00000400,
VK_IMAGE_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
} VkImageCreateFlagBits;
typedef VkFlags VkImageCreateFlags;
@@ -1152,6 +1161,7 @@
VK_QUEUE_COMPUTE_BIT = 0x00000002,
VK_QUEUE_TRANSFER_BIT = 0x00000004,
VK_QUEUE_SPARSE_BINDING_BIT = 0x00000008,
+ VK_QUEUE_PROTECTED_BIT = 0x00000010,
VK_QUEUE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
} VkQueueFlagBits;
typedef VkFlags VkQueueFlags;
@@ -1162,17 +1172,23 @@
VK_MEMORY_PROPERTY_HOST_COHERENT_BIT = 0x00000004,
VK_MEMORY_PROPERTY_HOST_CACHED_BIT = 0x00000008,
VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT = 0x00000010,
+ VK_MEMORY_PROPERTY_PROTECTED_BIT = 0x00000020,
VK_MEMORY_PROPERTY_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
} VkMemoryPropertyFlagBits;
typedef VkFlags VkMemoryPropertyFlags;
typedef enum VkMemoryHeapFlagBits {
VK_MEMORY_HEAP_DEVICE_LOCAL_BIT = 0x00000001,
- VK_MEMORY_HEAP_MULTI_INSTANCE_BIT_KHX = 0x00000002,
+ VK_MEMORY_HEAP_MULTI_INSTANCE_BIT = 0x00000002,
VK_MEMORY_HEAP_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
} VkMemoryHeapFlagBits;
typedef VkFlags VkMemoryHeapFlags;
typedef VkFlags VkDeviceCreateFlags;
+
+typedef enum VkDeviceQueueCreateFlagBits {
+ VK_DEVICE_QUEUE_CREATE_PROTECTED_BIT = 0x00000001,
+ VK_DEVICE_QUEUE_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
+} VkDeviceQueueCreateFlagBits;
typedef VkFlags VkDeviceQueueCreateFlags;
typedef enum VkPipelineStageFlagBits {
@@ -1204,9 +1220,9 @@
VK_IMAGE_ASPECT_DEPTH_BIT = 0x00000002,
VK_IMAGE_ASPECT_STENCIL_BIT = 0x00000004,
VK_IMAGE_ASPECT_METADATA_BIT = 0x00000008,
- VK_IMAGE_ASPECT_PLANE_0_BIT_KHR = 0x00000010,
- VK_IMAGE_ASPECT_PLANE_1_BIT_KHR = 0x00000020,
- VK_IMAGE_ASPECT_PLANE_2_BIT_KHR = 0x00000040,
+ VK_IMAGE_ASPECT_PLANE_0_BIT = 0x00000010,
+ VK_IMAGE_ASPECT_PLANE_1_BIT = 0x00000020,
+ VK_IMAGE_ASPECT_PLANE_2_BIT = 0x00000040,
VK_IMAGE_ASPECT_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
} VkImageAspectFlagBits;
typedef VkFlags VkImageAspectFlags;
@@ -1263,6 +1279,7 @@
VK_BUFFER_CREATE_SPARSE_BINDING_BIT = 0x00000001,
VK_BUFFER_CREATE_SPARSE_RESIDENCY_BIT = 0x00000002,
VK_BUFFER_CREATE_SPARSE_ALIASED_BIT = 0x00000004,
+ VK_BUFFER_CREATE_PROTECTED_BIT = 0x00000008,
VK_BUFFER_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
} VkBufferCreateFlagBits;
typedef VkFlags VkBufferCreateFlags;
@@ -1289,8 +1306,8 @@
VK_PIPELINE_CREATE_DISABLE_OPTIMIZATION_BIT = 0x00000001,
VK_PIPELINE_CREATE_ALLOW_DERIVATIVES_BIT = 0x00000002,
VK_PIPELINE_CREATE_DERIVATIVE_BIT = 0x00000004,
- VK_PIPELINE_CREATE_VIEW_INDEX_FROM_DEVICE_INDEX_BIT_KHX = 0x00000008,
- VK_PIPELINE_CREATE_DISPATCH_BASE_KHX = 0x00000010,
+ VK_PIPELINE_CREATE_VIEW_INDEX_FROM_DEVICE_INDEX_BIT = 0x00000008,
+ VK_PIPELINE_CREATE_DISPATCH_BASE = 0x00000010,
VK_PIPELINE_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
} VkPipelineCreateFlagBits;
typedef VkFlags VkPipelineCreateFlags;
@@ -1393,8 +1410,8 @@
typedef enum VkDependencyFlagBits {
VK_DEPENDENCY_BY_REGION_BIT = 0x00000001,
- VK_DEPENDENCY_VIEW_LOCAL_BIT_KHX = 0x00000002,
- VK_DEPENDENCY_DEVICE_GROUP_BIT_KHX = 0x00000004,
+ VK_DEPENDENCY_DEVICE_GROUP_BIT = 0x00000004,
+ VK_DEPENDENCY_VIEW_LOCAL_BIT = 0x00000002,
VK_DEPENDENCY_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
} VkDependencyFlagBits;
typedef VkFlags VkDependencyFlags;
@@ -1402,6 +1419,7 @@
typedef enum VkCommandPoolCreateFlagBits {
VK_COMMAND_POOL_CREATE_TRANSIENT_BIT = 0x00000001,
VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT = 0x00000002,
+ VK_COMMAND_POOL_CREATE_PROTECTED_BIT = 0x00000004,
VK_COMMAND_POOL_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
} VkCommandPoolCreateFlagBits;
typedef VkFlags VkCommandPoolCreateFlags;
@@ -3483,10 +3501,837 @@
const VkCommandBuffer* pCommandBuffers);
#endif
+#define VK_VERSION_1_1 1
+// Vulkan 1.1 version number
+#define VK_API_VERSION_1_1 VK_MAKE_VERSION(1, 1, 0)// Patch version should always be set to 0
+
+
+VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkSamplerYcbcrConversion)
+VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkDescriptorUpdateTemplate)
+
+#define VK_MAX_DEVICE_GROUP_SIZE 32
+#define VK_LUID_SIZE 8
+#define VK_QUEUE_FAMILY_EXTERNAL (~0U-1)
+
+
+typedef enum VkPointClippingBehavior {
+ VK_POINT_CLIPPING_BEHAVIOR_ALL_CLIP_PLANES = 0,
+ VK_POINT_CLIPPING_BEHAVIOR_USER_CLIP_PLANES_ONLY = 1,
+ VK_POINT_CLIPPING_BEHAVIOR_BEGIN_RANGE = VK_POINT_CLIPPING_BEHAVIOR_ALL_CLIP_PLANES,
+ VK_POINT_CLIPPING_BEHAVIOR_END_RANGE = VK_POINT_CLIPPING_BEHAVIOR_USER_CLIP_PLANES_ONLY,
+ VK_POINT_CLIPPING_BEHAVIOR_RANGE_SIZE = (VK_POINT_CLIPPING_BEHAVIOR_USER_CLIP_PLANES_ONLY - VK_POINT_CLIPPING_BEHAVIOR_ALL_CLIP_PLANES + 1),
+ VK_POINT_CLIPPING_BEHAVIOR_MAX_ENUM = 0x7FFFFFFF
+} VkPointClippingBehavior;
+
+typedef enum VkTessellationDomainOrigin {
+ VK_TESSELLATION_DOMAIN_ORIGIN_UPPER_LEFT = 0,
+ VK_TESSELLATION_DOMAIN_ORIGIN_LOWER_LEFT = 1,
+ VK_TESSELLATION_DOMAIN_ORIGIN_BEGIN_RANGE = VK_TESSELLATION_DOMAIN_ORIGIN_UPPER_LEFT,
+ VK_TESSELLATION_DOMAIN_ORIGIN_END_RANGE = VK_TESSELLATION_DOMAIN_ORIGIN_LOWER_LEFT,
+ VK_TESSELLATION_DOMAIN_ORIGIN_RANGE_SIZE = (VK_TESSELLATION_DOMAIN_ORIGIN_LOWER_LEFT - VK_TESSELLATION_DOMAIN_ORIGIN_UPPER_LEFT + 1),
+ VK_TESSELLATION_DOMAIN_ORIGIN_MAX_ENUM = 0x7FFFFFFF
+} VkTessellationDomainOrigin;
+
+typedef enum VkSamplerYcbcrModelConversion {
+ VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY = 0,
+ VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_IDENTITY = 1,
+ VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_709 = 2,
+ VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_601 = 3,
+ VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_2020 = 4,
+ VK_SAMPLER_YCBCR_MODEL_CONVERSION_BEGIN_RANGE = VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY,
+ VK_SAMPLER_YCBCR_MODEL_CONVERSION_END_RANGE = VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_2020,
+ VK_SAMPLER_YCBCR_MODEL_CONVERSION_RANGE_SIZE = (VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_2020 - VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY + 1),
+ VK_SAMPLER_YCBCR_MODEL_CONVERSION_MAX_ENUM = 0x7FFFFFFF
+} VkSamplerYcbcrModelConversion;
+
+typedef enum VkSamplerYcbcrRange {
+ VK_SAMPLER_YCBCR_RANGE_ITU_FULL = 0,
+ VK_SAMPLER_YCBCR_RANGE_ITU_NARROW = 1,
+ VK_SAMPLER_YCBCR_RANGE_BEGIN_RANGE = VK_SAMPLER_YCBCR_RANGE_ITU_FULL,
+ VK_SAMPLER_YCBCR_RANGE_END_RANGE = VK_SAMPLER_YCBCR_RANGE_ITU_NARROW,
+ VK_SAMPLER_YCBCR_RANGE_RANGE_SIZE = (VK_SAMPLER_YCBCR_RANGE_ITU_NARROW - VK_SAMPLER_YCBCR_RANGE_ITU_FULL + 1),
+ VK_SAMPLER_YCBCR_RANGE_MAX_ENUM = 0x7FFFFFFF
+} VkSamplerYcbcrRange;
+
+typedef enum VkChromaLocation {
+ VK_CHROMA_LOCATION_COSITED_EVEN = 0,
+ VK_CHROMA_LOCATION_MIDPOINT = 1,
+ VK_CHROMA_LOCATION_BEGIN_RANGE = VK_CHROMA_LOCATION_COSITED_EVEN,
+ VK_CHROMA_LOCATION_END_RANGE = VK_CHROMA_LOCATION_MIDPOINT,
+ VK_CHROMA_LOCATION_RANGE_SIZE = (VK_CHROMA_LOCATION_MIDPOINT - VK_CHROMA_LOCATION_COSITED_EVEN + 1),
+ VK_CHROMA_LOCATION_MAX_ENUM = 0x7FFFFFFF
+} VkChromaLocation;
+
+typedef enum VkDescriptorUpdateTemplateType {
+ VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET = 0,
+ VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_PUSH_DESCRIPTORS_KHR = 1,
+ VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_BEGIN_RANGE = VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET,
+ VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_END_RANGE = VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET,
+ VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_RANGE_SIZE = (VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET - VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET + 1),
+ VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_MAX_ENUM = 0x7FFFFFFF
+} VkDescriptorUpdateTemplateType;
+
+
+typedef enum VkSubgroupFeatureFlagBits {
+ VK_SUBGROUP_FEATURE_BASIC_BIT = 0x00000001,
+ VK_SUBGROUP_FEATURE_VOTE_BIT = 0x00000002,
+ VK_SUBGROUP_FEATURE_ARITHMETIC_BIT = 0x00000004,
+ VK_SUBGROUP_FEATURE_BALLOT_BIT = 0x00000008,
+ VK_SUBGROUP_FEATURE_SHUFFLE_BIT = 0x00000010,
+ VK_SUBGROUP_FEATURE_SHUFFLE_RELATIVE_BIT = 0x00000020,
+ VK_SUBGROUP_FEATURE_CLUSTERED_BIT = 0x00000040,
+ VK_SUBGROUP_FEATURE_QUAD_BIT = 0x00000080,
+ VK_SUBGROUP_FEATURE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
+} VkSubgroupFeatureFlagBits;
+typedef VkFlags VkSubgroupFeatureFlags;
+
+typedef enum VkPeerMemoryFeatureFlagBits {
+ VK_PEER_MEMORY_FEATURE_COPY_SRC_BIT = 0x00000001,
+ VK_PEER_MEMORY_FEATURE_COPY_DST_BIT = 0x00000002,
+ VK_PEER_MEMORY_FEATURE_GENERIC_SRC_BIT = 0x00000004,
+ VK_PEER_MEMORY_FEATURE_GENERIC_DST_BIT = 0x00000008,
+ VK_PEER_MEMORY_FEATURE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
+} VkPeerMemoryFeatureFlagBits;
+typedef VkFlags VkPeerMemoryFeatureFlags;
+
+typedef enum VkMemoryAllocateFlagBits {
+ VK_MEMORY_ALLOCATE_DEVICE_MASK_BIT = 0x00000001,
+ VK_MEMORY_ALLOCATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
+} VkMemoryAllocateFlagBits;
+typedef VkFlags VkMemoryAllocateFlags;
+typedef VkFlags VkCommandPoolTrimFlags;
+typedef VkFlags VkDescriptorUpdateTemplateCreateFlags;
+
+typedef enum VkExternalMemoryHandleTypeFlagBits {
+ VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT = 0x00000001,
+ VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT = 0x00000002,
+ VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT = 0x00000004,
+ VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_BIT = 0x00000008,
+ VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_KMT_BIT = 0x00000010,
+ VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_HEAP_BIT = 0x00000020,
+ VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_RESOURCE_BIT = 0x00000040,
+ VK_EXTERNAL_MEMORY_HANDLE_TYPE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
+} VkExternalMemoryHandleTypeFlagBits;
+typedef VkFlags VkExternalMemoryHandleTypeFlags;
+
+typedef enum VkExternalMemoryFeatureFlagBits {
+ VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT = 0x00000001,
+ VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT = 0x00000002,
+ VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT = 0x00000004,
+ VK_EXTERNAL_MEMORY_FEATURE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
+} VkExternalMemoryFeatureFlagBits;
+typedef VkFlags VkExternalMemoryFeatureFlags;
+
+typedef enum VkExternalFenceHandleTypeFlagBits {
+ VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_FD_BIT = 0x00000001,
+ VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_BIT = 0x00000002,
+ VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT = 0x00000004,
+ VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT = 0x00000008,
+ VK_EXTERNAL_FENCE_HANDLE_TYPE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
+} VkExternalFenceHandleTypeFlagBits;
+typedef VkFlags VkExternalFenceHandleTypeFlags;
+
+typedef enum VkExternalFenceFeatureFlagBits {
+ VK_EXTERNAL_FENCE_FEATURE_EXPORTABLE_BIT = 0x00000001,
+ VK_EXTERNAL_FENCE_FEATURE_IMPORTABLE_BIT = 0x00000002,
+ VK_EXTERNAL_FENCE_FEATURE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
+} VkExternalFenceFeatureFlagBits;
+typedef VkFlags VkExternalFenceFeatureFlags;
+
+typedef enum VkFenceImportFlagBits {
+ VK_FENCE_IMPORT_TEMPORARY_BIT = 0x00000001,
+ VK_FENCE_IMPORT_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
+} VkFenceImportFlagBits;
+typedef VkFlags VkFenceImportFlags;
+
+typedef enum VkSemaphoreImportFlagBits {
+ VK_SEMAPHORE_IMPORT_TEMPORARY_BIT = 0x00000001,
+ VK_SEMAPHORE_IMPORT_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
+} VkSemaphoreImportFlagBits;
+typedef VkFlags VkSemaphoreImportFlags;
+
+typedef enum VkExternalSemaphoreHandleTypeFlagBits {
+ VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT = 0x00000001,
+ VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT = 0x00000002,
+ VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT = 0x00000004,
+ VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_D3D12_FENCE_BIT = 0x00000008,
+ VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT = 0x00000010,
+ VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
+} VkExternalSemaphoreHandleTypeFlagBits;
+typedef VkFlags VkExternalSemaphoreHandleTypeFlags;
+
+typedef enum VkExternalSemaphoreFeatureFlagBits {
+ VK_EXTERNAL_SEMAPHORE_FEATURE_EXPORTABLE_BIT = 0x00000001,
+ VK_EXTERNAL_SEMAPHORE_FEATURE_IMPORTABLE_BIT = 0x00000002,
+ VK_EXTERNAL_SEMAPHORE_FEATURE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
+} VkExternalSemaphoreFeatureFlagBits;
+typedef VkFlags VkExternalSemaphoreFeatureFlags;
+
+typedef struct VkPhysicalDeviceSubgroupProperties {
+ VkStructureType sType;
+ void* pNext;
+ uint32_t subgroupSize;
+ VkShaderStageFlags supportedStages;
+ VkSubgroupFeatureFlags supportedOperations;
+ VkBool32 quadOperationsInAllStages;
+} VkPhysicalDeviceSubgroupProperties;
+
+typedef struct VkBindBufferMemoryInfo {
+ VkStructureType sType;
+ const void* pNext;
+ VkBuffer buffer;
+ VkDeviceMemory memory;
+ VkDeviceSize memoryOffset;
+} VkBindBufferMemoryInfo;
+
+typedef struct VkBindImageMemoryInfo {
+ VkStructureType sType;
+ const void* pNext;
+ VkImage image;
+ VkDeviceMemory memory;
+ VkDeviceSize memoryOffset;
+} VkBindImageMemoryInfo;
+
+typedef struct VkPhysicalDevice16BitStorageFeatures {
+ VkStructureType sType;
+ void* pNext;
+ VkBool32 storageBuffer16BitAccess;
+ VkBool32 uniformAndStorageBuffer16BitAccess;
+ VkBool32 storagePushConstant16;
+ VkBool32 storageInputOutput16;
+} VkPhysicalDevice16BitStorageFeatures;
+
+typedef struct VkMemoryDedicatedRequirements {
+ VkStructureType sType;
+ void* pNext;
+ VkBool32 prefersDedicatedAllocation;
+ VkBool32 requiresDedicatedAllocation;
+} VkMemoryDedicatedRequirements;
+
+typedef struct VkMemoryDedicatedAllocateInfo {
+ VkStructureType sType;
+ const void* pNext;
+ VkImage image;
+ VkBuffer buffer;
+} VkMemoryDedicatedAllocateInfo;
+
+typedef struct VkMemoryAllocateFlagsInfo {
+ VkStructureType sType;
+ const void* pNext;
+ VkMemoryAllocateFlags flags;
+ uint32_t deviceMask;
+} VkMemoryAllocateFlagsInfo;
+
+typedef struct VkDeviceGroupRenderPassBeginInfo {
+ VkStructureType sType;
+ const void* pNext;
+ uint32_t deviceMask;
+ uint32_t deviceRenderAreaCount;
+ const VkRect2D* pDeviceRenderAreas;
+} VkDeviceGroupRenderPassBeginInfo;
+
+typedef struct VkDeviceGroupCommandBufferBeginInfo {
+ VkStructureType sType;
+ const void* pNext;
+ uint32_t deviceMask;
+} VkDeviceGroupCommandBufferBeginInfo;
+
+typedef struct VkDeviceGroupSubmitInfo {
+ VkStructureType sType;
+ const void* pNext;
+ uint32_t waitSemaphoreCount;
+ const uint32_t* pWaitSemaphoreDeviceIndices;
+ uint32_t commandBufferCount;
+ const uint32_t* pCommandBufferDeviceMasks;
+ uint32_t signalSemaphoreCount;
+ const uint32_t* pSignalSemaphoreDeviceIndices;
+} VkDeviceGroupSubmitInfo;
+
+typedef struct VkDeviceGroupBindSparseInfo {
+ VkStructureType sType;
+ const void* pNext;
+ uint32_t resourceDeviceIndex;
+ uint32_t memoryDeviceIndex;
+} VkDeviceGroupBindSparseInfo;
+
+typedef struct VkBindBufferMemoryDeviceGroupInfo {
+ VkStructureType sType;
+ const void* pNext;
+ uint32_t deviceIndexCount;
+ const uint32_t* pDeviceIndices;
+} VkBindBufferMemoryDeviceGroupInfo;
+
+typedef struct VkBindImageMemoryDeviceGroupInfo {
+ VkStructureType sType;
+ const void* pNext;
+ uint32_t deviceIndexCount;
+ const uint32_t* pDeviceIndices;
+ uint32_t SFRRectCount;
+ const VkRect2D* pSFRRects;
+} VkBindImageMemoryDeviceGroupInfo;
+
+typedef struct VkPhysicalDeviceGroupProperties {
+ VkStructureType sType;
+ void* pNext;
+ uint32_t physicalDeviceCount;
+ VkPhysicalDevice physicalDevices[VK_MAX_DEVICE_GROUP_SIZE];
+ VkBool32 subsetAllocation;
+} VkPhysicalDeviceGroupProperties;
+
+typedef struct VkDeviceGroupDeviceCreateInfo {
+ VkStructureType sType;
+ const void* pNext;
+ uint32_t physicalDeviceCount;
+ const VkPhysicalDevice* pPhysicalDevices;
+} VkDeviceGroupDeviceCreateInfo;
+
+typedef struct VkBufferMemoryRequirementsInfo2 {
+ VkStructureType sType;
+ const void* pNext;
+ VkBuffer buffer;
+} VkBufferMemoryRequirementsInfo2;
+
+typedef struct VkImageMemoryRequirementsInfo2 {
+ VkStructureType sType;
+ const void* pNext;
+ VkImage image;
+} VkImageMemoryRequirementsInfo2;
+
+typedef struct VkImageSparseMemoryRequirementsInfo2 {
+ VkStructureType sType;
+ const void* pNext;
+ VkImage image;
+} VkImageSparseMemoryRequirementsInfo2;
+
+typedef struct VkMemoryRequirements2 {
+ VkStructureType sType;
+ void* pNext;
+ VkMemoryRequirements memoryRequirements;
+} VkMemoryRequirements2;
+
+typedef struct VkSparseImageMemoryRequirements2 {
+ VkStructureType sType;
+ void* pNext;
+ VkSparseImageMemoryRequirements memoryRequirements;
+} VkSparseImageMemoryRequirements2;
+
+typedef struct VkPhysicalDeviceFeatures2 {
+ VkStructureType sType;
+ void* pNext;
+ VkPhysicalDeviceFeatures features;
+} VkPhysicalDeviceFeatures2;
+
+typedef struct VkPhysicalDeviceProperties2 {
+ VkStructureType sType;
+ void* pNext;
+ VkPhysicalDeviceProperties properties;
+} VkPhysicalDeviceProperties2;
+
+typedef struct VkFormatProperties2 {
+ VkStructureType sType;
+ void* pNext;
+ VkFormatProperties formatProperties;
+} VkFormatProperties2;
+
+typedef struct VkImageFormatProperties2 {
+ VkStructureType sType;
+ void* pNext;
+ VkImageFormatProperties imageFormatProperties;
+} VkImageFormatProperties2;
+
+typedef struct VkPhysicalDeviceImageFormatInfo2 {
+ VkStructureType sType;
+ const void* pNext;
+ VkFormat format;
+ VkImageType type;
+ VkImageTiling tiling;
+ VkImageUsageFlags usage;
+ VkImageCreateFlags flags;
+} VkPhysicalDeviceImageFormatInfo2;
+
+typedef struct VkQueueFamilyProperties2 {
+ VkStructureType sType;
+ void* pNext;
+ VkQueueFamilyProperties queueFamilyProperties;
+} VkQueueFamilyProperties2;
+
+typedef struct VkPhysicalDeviceMemoryProperties2 {
+ VkStructureType sType;
+ void* pNext;
+ VkPhysicalDeviceMemoryProperties memoryProperties;
+} VkPhysicalDeviceMemoryProperties2;
+
+typedef struct VkSparseImageFormatProperties2 {
+ VkStructureType sType;
+ void* pNext;
+ VkSparseImageFormatProperties properties;
+} VkSparseImageFormatProperties2;
+
+typedef struct VkPhysicalDeviceSparseImageFormatInfo2 {
+ VkStructureType sType;
+ const void* pNext;
+ VkFormat format;
+ VkImageType type;
+ VkSampleCountFlagBits samples;
+ VkImageUsageFlags usage;
+ VkImageTiling tiling;
+} VkPhysicalDeviceSparseImageFormatInfo2;
+
+typedef struct VkPhysicalDevicePointClippingProperties {
+ VkStructureType sType;
+ void* pNext;
+ VkPointClippingBehavior pointClippingBehavior;
+} VkPhysicalDevicePointClippingProperties;
+
+typedef struct VkInputAttachmentAspectReference {
+ uint32_t subpass;
+ uint32_t inputAttachmentIndex;
+ VkImageAspectFlags aspectMask;
+} VkInputAttachmentAspectReference;
+
+typedef struct VkRenderPassInputAttachmentAspectCreateInfo {
+ VkStructureType sType;
+ const void* pNext;
+ uint32_t aspectReferenceCount;
+ const VkInputAttachmentAspectReference* pAspectReferences;
+} VkRenderPassInputAttachmentAspectCreateInfo;
+
+typedef struct VkImageViewUsageCreateInfo {
+ VkStructureType sType;
+ const void* pNext;
+ VkImageUsageFlags usage;
+} VkImageViewUsageCreateInfo;
+
+typedef struct VkPipelineTessellationDomainOriginStateCreateInfo {
+ VkStructureType sType;
+ const void* pNext;
+ VkTessellationDomainOrigin domainOrigin;
+} VkPipelineTessellationDomainOriginStateCreateInfo;
+
+typedef struct VkRenderPassMultiviewCreateInfo {
+ VkStructureType sType;
+ const void* pNext;
+ uint32_t subpassCount;
+ const uint32_t* pViewMasks;
+ uint32_t dependencyCount;
+ const int32_t* pViewOffsets;
+ uint32_t correlationMaskCount;
+ const uint32_t* pCorrelationMasks;
+} VkRenderPassMultiviewCreateInfo;
+
+typedef struct VkPhysicalDeviceMultiviewFeatures {
+ VkStructureType sType;
+ void* pNext;
+ VkBool32 multiview;
+ VkBool32 multiviewGeometryShader;
+ VkBool32 multiviewTessellationShader;
+} VkPhysicalDeviceMultiviewFeatures;
+
+typedef struct VkPhysicalDeviceMultiviewProperties {
+ VkStructureType sType;
+ void* pNext;
+ uint32_t maxMultiviewViewCount;
+ uint32_t maxMultiviewInstanceIndex;
+} VkPhysicalDeviceMultiviewProperties;
+
+typedef struct VkPhysicalDeviceVariablePointerFeatures {
+ VkStructureType sType;
+ void* pNext;
+ VkBool32 variablePointersStorageBuffer;
+ VkBool32 variablePointers;
+} VkPhysicalDeviceVariablePointerFeatures;
+
+typedef struct VkPhysicalDeviceProtectedMemoryFeatures {
+ VkStructureType sType;
+ void* pNext;
+ VkBool32 protectedMemory;
+} VkPhysicalDeviceProtectedMemoryFeatures;
+
+typedef struct VkPhysicalDeviceProtectedMemoryProperties {
+ VkStructureType sType;
+ void* pNext;
+ VkBool32 protectedNoFault;
+} VkPhysicalDeviceProtectedMemoryProperties;
+
+typedef struct VkDeviceQueueInfo2 {
+ VkStructureType sType;
+ const void* pNext;
+ VkDeviceQueueCreateFlags flags;
+ uint32_t queueFamilyIndex;
+ uint32_t queueIndex;
+} VkDeviceQueueInfo2;
+
+typedef struct VkProtectedSubmitInfo {
+ VkStructureType sType;
+ const void* pNext;
+ VkBool32 protectedSubmit;
+} VkProtectedSubmitInfo;
+
+typedef struct VkSamplerYcbcrConversionCreateInfo {
+ VkStructureType sType;
+ const void* pNext;
+ VkFormat format;
+ VkSamplerYcbcrModelConversion ycbcrModel;
+ VkSamplerYcbcrRange ycbcrRange;
+ VkComponentMapping components;
+ VkChromaLocation xChromaOffset;
+ VkChromaLocation yChromaOffset;
+ VkFilter chromaFilter;
+ VkBool32 forceExplicitReconstruction;
+} VkSamplerYcbcrConversionCreateInfo;
+
+typedef struct VkSamplerYcbcrConversionInfo {
+ VkStructureType sType;
+ const void* pNext;
+ VkSamplerYcbcrConversion conversion;
+} VkSamplerYcbcrConversionInfo;
+
+typedef struct VkBindImagePlaneMemoryInfo {
+ VkStructureType sType;
+ const void* pNext;
+ VkImageAspectFlagBits planeAspect;
+} VkBindImagePlaneMemoryInfo;
+
+typedef struct VkImagePlaneMemoryRequirementsInfo {
+ VkStructureType sType;
+ const void* pNext;
+ VkImageAspectFlagBits planeAspect;
+} VkImagePlaneMemoryRequirementsInfo;
+
+typedef struct VkPhysicalDeviceSamplerYcbcrConversionFeatures {
+ VkStructureType sType;
+ void* pNext;
+ VkBool32 samplerYcbcrConversion;
+} VkPhysicalDeviceSamplerYcbcrConversionFeatures;
+
+typedef struct VkSamplerYcbcrConversionImageFormatProperties {
+ VkStructureType sType;
+ void* pNext;
+ uint32_t combinedImageSamplerDescriptorCount;
+} VkSamplerYcbcrConversionImageFormatProperties;
+
+typedef struct VkDescriptorUpdateTemplateEntry {
+ uint32_t dstBinding;
+ uint32_t dstArrayElement;
+ uint32_t descriptorCount;
+ VkDescriptorType descriptorType;
+ size_t offset;
+ size_t stride;
+} VkDescriptorUpdateTemplateEntry;
+
+typedef struct VkDescriptorUpdateTemplateCreateInfo {
+ VkStructureType sType;
+ void* pNext;
+ VkDescriptorUpdateTemplateCreateFlags flags;
+ uint32_t descriptorUpdateEntryCount;
+ const VkDescriptorUpdateTemplateEntry* pDescriptorUpdateEntries;
+ VkDescriptorUpdateTemplateType templateType;
+ VkDescriptorSetLayout descriptorSetLayout;
+ VkPipelineBindPoint pipelineBindPoint;
+ VkPipelineLayout pipelineLayout;
+ uint32_t set;
+} VkDescriptorUpdateTemplateCreateInfo;
+
+typedef struct VkExternalMemoryProperties {
+ VkExternalMemoryFeatureFlags externalMemoryFeatures;
+ VkExternalMemoryHandleTypeFlags exportFromImportedHandleTypes;
+ VkExternalMemoryHandleTypeFlags compatibleHandleTypes;
+} VkExternalMemoryProperties;
+
+typedef struct VkPhysicalDeviceExternalImageFormatInfo {
+ VkStructureType sType;
+ const void* pNext;
+ VkExternalMemoryHandleTypeFlagBits handleType;
+} VkPhysicalDeviceExternalImageFormatInfo;
+
+typedef struct VkExternalImageFormatProperties {
+ VkStructureType sType;
+ void* pNext;
+ VkExternalMemoryProperties externalMemoryProperties;
+} VkExternalImageFormatProperties;
+
+typedef struct VkPhysicalDeviceExternalBufferInfo {
+ VkStructureType sType;
+ const void* pNext;
+ VkBufferCreateFlags flags;
+ VkBufferUsageFlags usage;
+ VkExternalMemoryHandleTypeFlagBits handleType;
+} VkPhysicalDeviceExternalBufferInfo;
+
+typedef struct VkExternalBufferProperties {
+ VkStructureType sType;
+ void* pNext;
+ VkExternalMemoryProperties externalMemoryProperties;
+} VkExternalBufferProperties;
+
+typedef struct VkPhysicalDeviceIDProperties {
+ VkStructureType sType;
+ void* pNext;
+ uint8_t deviceUUID[VK_UUID_SIZE];
+ uint8_t driverUUID[VK_UUID_SIZE];
+ uint8_t deviceLUID[VK_LUID_SIZE];
+ uint32_t deviceNodeMask;
+ VkBool32 deviceLUIDValid;
+} VkPhysicalDeviceIDProperties;
+
+typedef struct VkExternalMemoryImageCreateInfo {
+ VkStructureType sType;
+ const void* pNext;
+ VkExternalMemoryHandleTypeFlags handleTypes;
+} VkExternalMemoryImageCreateInfo;
+
+typedef struct VkExternalMemoryBufferCreateInfo {
+ VkStructureType sType;
+ const void* pNext;
+ VkExternalMemoryHandleTypeFlags handleTypes;
+} VkExternalMemoryBufferCreateInfo;
+
+typedef struct VkExportMemoryAllocateInfo {
+ VkStructureType sType;
+ const void* pNext;
+ VkExternalMemoryHandleTypeFlags handleTypes;
+} VkExportMemoryAllocateInfo;
+
+typedef struct VkPhysicalDeviceExternalFenceInfo {
+ VkStructureType sType;
+ const void* pNext;
+ VkExternalFenceHandleTypeFlagBits handleType;
+} VkPhysicalDeviceExternalFenceInfo;
+
+typedef struct VkExternalFenceProperties {
+ VkStructureType sType;
+ void* pNext;
+ VkExternalFenceHandleTypeFlags exportFromImportedHandleTypes;
+ VkExternalFenceHandleTypeFlags compatibleHandleTypes;
+ VkExternalFenceFeatureFlags externalFenceFeatures;
+} VkExternalFenceProperties;
+
+typedef struct VkExportFenceCreateInfo {
+ VkStructureType sType;
+ const void* pNext;
+ VkExternalFenceHandleTypeFlags handleTypes;
+} VkExportFenceCreateInfo;
+
+typedef struct VkExportSemaphoreCreateInfo {
+ VkStructureType sType;
+ const void* pNext;
+ VkExternalSemaphoreHandleTypeFlags handleTypes;
+} VkExportSemaphoreCreateInfo;
+
+typedef struct VkPhysicalDeviceExternalSemaphoreInfo {
+ VkStructureType sType;
+ const void* pNext;
+ VkExternalSemaphoreHandleTypeFlagBits handleType;
+} VkPhysicalDeviceExternalSemaphoreInfo;
+
+typedef struct VkExternalSemaphoreProperties {
+ VkStructureType sType;
+ void* pNext;
+ VkExternalSemaphoreHandleTypeFlags exportFromImportedHandleTypes;
+ VkExternalSemaphoreHandleTypeFlags compatibleHandleTypes;
+ VkExternalSemaphoreFeatureFlags externalSemaphoreFeatures;
+} VkExternalSemaphoreProperties;
+
+typedef struct VkPhysicalDeviceMaintenance3Properties {
+ VkStructureType sType;
+ void* pNext;
+ uint32_t maxPerSetDescriptors;
+ VkDeviceSize maxMemoryAllocationSize;
+} VkPhysicalDeviceMaintenance3Properties;
+
+typedef struct VkDescriptorSetLayoutSupport {
+ VkStructureType sType;
+ void* pNext;
+ VkBool32 supported;
+} VkDescriptorSetLayoutSupport;
+
+typedef struct VkPhysicalDeviceShaderDrawParameterFeatures {
+ VkStructureType sType;
+ void* pNext;
+ VkBool32 shaderDrawParameters;
+} VkPhysicalDeviceShaderDrawParameterFeatures;
+
+
+typedef VkResult (VKAPI_PTR *PFN_vkEnumerateInstanceVersion)(uint32_t* pApiVersion);
+typedef VkResult (VKAPI_PTR *PFN_vkBindBufferMemory2)(VkDevice device, uint32_t bindInfoCount, const VkBindBufferMemoryInfo* pBindInfos);
+typedef VkResult (VKAPI_PTR *PFN_vkBindImageMemory2)(VkDevice device, uint32_t bindInfoCount, const VkBindImageMemoryInfo* pBindInfos);
+typedef void (VKAPI_PTR *PFN_vkGetDeviceGroupPeerMemoryFeatures)(VkDevice device, uint32_t heapIndex, uint32_t localDeviceIndex, uint32_t remoteDeviceIndex, VkPeerMemoryFeatureFlags* pPeerMemoryFeatures);
+typedef void (VKAPI_PTR *PFN_vkCmdSetDeviceMask)(VkCommandBuffer commandBuffer, uint32_t deviceMask);
+typedef void (VKAPI_PTR *PFN_vkCmdDispatchBase)(VkCommandBuffer commandBuffer, uint32_t baseGroupX, uint32_t baseGroupY, uint32_t baseGroupZ, uint32_t groupCountX, uint32_t groupCountY, uint32_t groupCountZ);
+typedef VkResult (VKAPI_PTR *PFN_vkEnumeratePhysicalDeviceGroups)(VkInstance instance, uint32_t* pPhysicalDeviceGroupCount, VkPhysicalDeviceGroupProperties* pPhysicalDeviceGroupProperties);
+typedef void (VKAPI_PTR *PFN_vkGetImageMemoryRequirements2)(VkDevice device, const VkImageMemoryRequirementsInfo2* pInfo, VkMemoryRequirements2* pMemoryRequirements);
+typedef void (VKAPI_PTR *PFN_vkGetBufferMemoryRequirements2)(VkDevice device, const VkBufferMemoryRequirementsInfo2* pInfo, VkMemoryRequirements2* pMemoryRequirements);
+typedef void (VKAPI_PTR *PFN_vkGetImageSparseMemoryRequirements2)(VkDevice device, const VkImageSparseMemoryRequirementsInfo2* pInfo, uint32_t* pSparseMemoryRequirementCount, VkSparseImageMemoryRequirements2* pSparseMemoryRequirements);
+typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceFeatures2)(VkPhysicalDevice physicalDevice, VkPhysicalDeviceFeatures2* pFeatures);
+typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceProperties2)(VkPhysicalDevice physicalDevice, VkPhysicalDeviceProperties2* pProperties);
+typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceFormatProperties2)(VkPhysicalDevice physicalDevice, VkFormat format, VkFormatProperties2* pFormatProperties);
+typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceImageFormatProperties2)(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceImageFormatInfo2* pImageFormatInfo, VkImageFormatProperties2* pImageFormatProperties);
+typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceQueueFamilyProperties2)(VkPhysicalDevice physicalDevice, uint32_t* pQueueFamilyPropertyCount, VkQueueFamilyProperties2* pQueueFamilyProperties);
+typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceMemoryProperties2)(VkPhysicalDevice physicalDevice, VkPhysicalDeviceMemoryProperties2* pMemoryProperties);
+typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceSparseImageFormatProperties2)(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceSparseImageFormatInfo2* pFormatInfo, uint32_t* pPropertyCount, VkSparseImageFormatProperties2* pProperties);
+typedef void (VKAPI_PTR *PFN_vkTrimCommandPool)(VkDevice device, VkCommandPool commandPool, VkCommandPoolTrimFlags flags);
+typedef void (VKAPI_PTR *PFN_vkGetDeviceQueue2)(VkDevice device, const VkDeviceQueueInfo2* pQueueInfo, VkQueue* pQueue);
+typedef VkResult (VKAPI_PTR *PFN_vkCreateSamplerYcbcrConversion)(VkDevice device, const VkSamplerYcbcrConversionCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSamplerYcbcrConversion* pYcbcrConversion);
+typedef void (VKAPI_PTR *PFN_vkDestroySamplerYcbcrConversion)(VkDevice device, VkSamplerYcbcrConversion ycbcrConversion, const VkAllocationCallbacks* pAllocator);
+typedef VkResult (VKAPI_PTR *PFN_vkCreateDescriptorUpdateTemplate)(VkDevice device, const VkDescriptorUpdateTemplateCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDescriptorUpdateTemplate* pDescriptorUpdateTemplate);
+typedef void (VKAPI_PTR *PFN_vkDestroyDescriptorUpdateTemplate)(VkDevice device, VkDescriptorUpdateTemplate descriptorUpdateTemplate, const VkAllocationCallbacks* pAllocator);
+typedef void (VKAPI_PTR *PFN_vkUpdateDescriptorSetWithTemplate)(VkDevice device, VkDescriptorSet descriptorSet, VkDescriptorUpdateTemplate descriptorUpdateTemplate, const void* pData);
+typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceExternalBufferProperties)(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceExternalBufferInfo* pExternalBufferInfo, VkExternalBufferProperties* pExternalBufferProperties);
+typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceExternalFenceProperties)(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceExternalFenceInfo* pExternalFenceInfo, VkExternalFenceProperties* pExternalFenceProperties);
+typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceExternalSemaphoreProperties)(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceExternalSemaphoreInfo* pExternalSemaphoreInfo, VkExternalSemaphoreProperties* pExternalSemaphoreProperties);
+typedef void (VKAPI_PTR *PFN_vkGetDescriptorSetLayoutSupport)(VkDevice device, const VkDescriptorSetLayoutCreateInfo* pCreateInfo, VkDescriptorSetLayoutSupport* pSupport);
+
+#ifndef VK_NO_PROTOTYPES
+VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceVersion(
+ uint32_t* pApiVersion);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkBindBufferMemory2(
+ VkDevice device,
+ uint32_t bindInfoCount,
+ const VkBindBufferMemoryInfo* pBindInfos);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkBindImageMemory2(
+ VkDevice device,
+ uint32_t bindInfoCount,
+ const VkBindImageMemoryInfo* pBindInfos);
+
+VKAPI_ATTR void VKAPI_CALL vkGetDeviceGroupPeerMemoryFeatures(
+ VkDevice device,
+ uint32_t heapIndex,
+ uint32_t localDeviceIndex,
+ uint32_t remoteDeviceIndex,
+ VkPeerMemoryFeatureFlags* pPeerMemoryFeatures);
+
+VKAPI_ATTR void VKAPI_CALL vkCmdSetDeviceMask(
+ VkCommandBuffer commandBuffer,
+ uint32_t deviceMask);
+
+VKAPI_ATTR void VKAPI_CALL vkCmdDispatchBase(
+ VkCommandBuffer commandBuffer,
+ uint32_t baseGroupX,
+ uint32_t baseGroupY,
+ uint32_t baseGroupZ,
+ uint32_t groupCountX,
+ uint32_t groupCountY,
+ uint32_t groupCountZ);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkEnumeratePhysicalDeviceGroups(
+ VkInstance instance,
+ uint32_t* pPhysicalDeviceGroupCount,
+ VkPhysicalDeviceGroupProperties* pPhysicalDeviceGroupProperties);
+
+VKAPI_ATTR void VKAPI_CALL vkGetImageMemoryRequirements2(
+ VkDevice device,
+ const VkImageMemoryRequirementsInfo2* pInfo,
+ VkMemoryRequirements2* pMemoryRequirements);
+
+VKAPI_ATTR void VKAPI_CALL vkGetBufferMemoryRequirements2(
+ VkDevice device,
+ const VkBufferMemoryRequirementsInfo2* pInfo,
+ VkMemoryRequirements2* pMemoryRequirements);
+
+VKAPI_ATTR void VKAPI_CALL vkGetImageSparseMemoryRequirements2(
+ VkDevice device,
+ const VkImageSparseMemoryRequirementsInfo2* pInfo,
+ uint32_t* pSparseMemoryRequirementCount,
+ VkSparseImageMemoryRequirements2* pSparseMemoryRequirements);
+
+VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceFeatures2(
+ VkPhysicalDevice physicalDevice,
+ VkPhysicalDeviceFeatures2* pFeatures);
+
+VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceProperties2(
+ VkPhysicalDevice physicalDevice,
+ VkPhysicalDeviceProperties2* pProperties);
+
+VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceFormatProperties2(
+ VkPhysicalDevice physicalDevice,
+ VkFormat format,
+ VkFormatProperties2* pFormatProperties);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceImageFormatProperties2(
+ VkPhysicalDevice physicalDevice,
+ const VkPhysicalDeviceImageFormatInfo2* pImageFormatInfo,
+ VkImageFormatProperties2* pImageFormatProperties);
+
+VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceQueueFamilyProperties2(
+ VkPhysicalDevice physicalDevice,
+ uint32_t* pQueueFamilyPropertyCount,
+ VkQueueFamilyProperties2* pQueueFamilyProperties);
+
+VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceMemoryProperties2(
+ VkPhysicalDevice physicalDevice,
+ VkPhysicalDeviceMemoryProperties2* pMemoryProperties);
+
+VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceSparseImageFormatProperties2(
+ VkPhysicalDevice physicalDevice,
+ const VkPhysicalDeviceSparseImageFormatInfo2* pFormatInfo,
+ uint32_t* pPropertyCount,
+ VkSparseImageFormatProperties2* pProperties);
+
+VKAPI_ATTR void VKAPI_CALL vkTrimCommandPool(
+ VkDevice device,
+ VkCommandPool commandPool,
+ VkCommandPoolTrimFlags flags);
+
+VKAPI_ATTR void VKAPI_CALL vkGetDeviceQueue2(
+ VkDevice device,
+ const VkDeviceQueueInfo2* pQueueInfo,
+ VkQueue* pQueue);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkCreateSamplerYcbcrConversion(
+ VkDevice device,
+ const VkSamplerYcbcrConversionCreateInfo* pCreateInfo,
+ const VkAllocationCallbacks* pAllocator,
+ VkSamplerYcbcrConversion* pYcbcrConversion);
+
+VKAPI_ATTR void VKAPI_CALL vkDestroySamplerYcbcrConversion(
+ VkDevice device,
+ VkSamplerYcbcrConversion ycbcrConversion,
+ const VkAllocationCallbacks* pAllocator);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkCreateDescriptorUpdateTemplate(
+ VkDevice device,
+ const VkDescriptorUpdateTemplateCreateInfo* pCreateInfo,
+ const VkAllocationCallbacks* pAllocator,
+ VkDescriptorUpdateTemplate* pDescriptorUpdateTemplate);
+
+VKAPI_ATTR void VKAPI_CALL vkDestroyDescriptorUpdateTemplate(
+ VkDevice device,
+ VkDescriptorUpdateTemplate descriptorUpdateTemplate,
+ const VkAllocationCallbacks* pAllocator);
+
+VKAPI_ATTR void VKAPI_CALL vkUpdateDescriptorSetWithTemplate(
+ VkDevice device,
+ VkDescriptorSet descriptorSet,
+ VkDescriptorUpdateTemplate descriptorUpdateTemplate,
+ const void* pData);
+
+VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceExternalBufferProperties(
+ VkPhysicalDevice physicalDevice,
+ const VkPhysicalDeviceExternalBufferInfo* pExternalBufferInfo,
+ VkExternalBufferProperties* pExternalBufferProperties);
+
+VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceExternalFenceProperties(
+ VkPhysicalDevice physicalDevice,
+ const VkPhysicalDeviceExternalFenceInfo* pExternalFenceInfo,
+ VkExternalFenceProperties* pExternalFenceProperties);
+
+VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceExternalSemaphoreProperties(
+ VkPhysicalDevice physicalDevice,
+ const VkPhysicalDeviceExternalSemaphoreInfo* pExternalSemaphoreInfo,
+ VkExternalSemaphoreProperties* pExternalSemaphoreProperties);
+
+VKAPI_ATTR void VKAPI_CALL vkGetDescriptorSetLayoutSupport(
+ VkDevice device,
+ const VkDescriptorSetLayoutCreateInfo* pCreateInfo,
+ VkDescriptorSetLayoutSupport* pSupport);
+#endif
+
#define VK_KHR_surface 1
VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkSurfaceKHR)
-#define VK_KHR_SURFACE_SPEC_VERSION 25
+#define VK_KHR_SURFACE_SPEC_VERSION 26
#define VK_KHR_SURFACE_EXTENSION_NAME "VK_KHR_surface"
#define VK_COLORSPACE_SRGB_NONLINEAR_KHR VK_COLOR_SPACE_SRGB_NONLINEAR_KHR
@@ -3550,6 +4395,15 @@
} VkCompositeAlphaFlagBitsKHR;
typedef VkFlags VkCompositeAlphaFlagsKHR;
+typedef enum VkDeviceGroupPresentModeFlagBitsKHR {
+ VK_DEVICE_GROUP_PRESENT_MODE_LOCAL_BIT_KHR = 0x00000001,
+ VK_DEVICE_GROUP_PRESENT_MODE_REMOTE_BIT_KHR = 0x00000002,
+ VK_DEVICE_GROUP_PRESENT_MODE_SUM_BIT_KHR = 0x00000004,
+ VK_DEVICE_GROUP_PRESENT_MODE_LOCAL_MULTI_DEVICE_BIT_KHR = 0x00000008,
+ VK_DEVICE_GROUP_PRESENT_MODE_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF
+} VkDeviceGroupPresentModeFlagBitsKHR;
+typedef VkFlags VkDeviceGroupPresentModeFlagsKHR;
+
typedef struct VkSurfaceCapabilitiesKHR {
uint32_t minImageCount;
uint32_t maxImageCount;
@@ -3608,12 +4462,13 @@
#define VK_KHR_swapchain 1
VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkSwapchainKHR)
-#define VK_KHR_SWAPCHAIN_SPEC_VERSION 68
+#define VK_KHR_SWAPCHAIN_SPEC_VERSION 69
#define VK_KHR_SWAPCHAIN_EXTENSION_NAME "VK_KHR_swapchain"
typedef enum VkSwapchainCreateFlagBitsKHR {
- VK_SWAPCHAIN_CREATE_BIND_SFR_BIT_KHX = 0x00000001,
+ VK_SWAPCHAIN_CREATE_BIND_SFR_BIT_KHR = 0x00000001,
+ VK_SWAPCHAIN_CREATE_PROTECTED_BIT_KHR = 0x00000002,
VK_SWAPCHAIN_CREATE_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF
} VkSwapchainCreateFlagBitsKHR;
typedef VkFlags VkSwapchainCreateFlagsKHR;
@@ -3650,12 +4505,60 @@
VkResult* pResults;
} VkPresentInfoKHR;
+typedef struct VkImageSwapchainCreateInfoKHR {
+ VkStructureType sType;
+ const void* pNext;
+ VkSwapchainKHR swapchain;
+} VkImageSwapchainCreateInfoKHR;
+
+typedef struct VkBindImageMemorySwapchainInfoKHR {
+ VkStructureType sType;
+ const void* pNext;
+ VkSwapchainKHR swapchain;
+ uint32_t imageIndex;
+} VkBindImageMemorySwapchainInfoKHR;
+
+typedef struct VkAcquireNextImageInfoKHR {
+ VkStructureType sType;
+ const void* pNext;
+ VkSwapchainKHR swapchain;
+ uint64_t timeout;
+ VkSemaphore semaphore;
+ VkFence fence;
+ uint32_t deviceMask;
+} VkAcquireNextImageInfoKHR;
+
+typedef struct VkDeviceGroupPresentCapabilitiesKHR {
+ VkStructureType sType;
+ const void* pNext;
+ uint32_t presentMask[VK_MAX_DEVICE_GROUP_SIZE];
+ VkDeviceGroupPresentModeFlagsKHR modes;
+} VkDeviceGroupPresentCapabilitiesKHR;
+
+typedef struct VkDeviceGroupPresentInfoKHR {
+ VkStructureType sType;
+ const void* pNext;
+ uint32_t swapchainCount;
+ const uint32_t* pDeviceMasks;
+ VkDeviceGroupPresentModeFlagBitsKHR mode;
+} VkDeviceGroupPresentInfoKHR;
+
+typedef struct VkDeviceGroupSwapchainCreateInfoKHR {
+ VkStructureType sType;
+ const void* pNext;
+ VkDeviceGroupPresentModeFlagsKHR modes;
+} VkDeviceGroupSwapchainCreateInfoKHR;
+
typedef VkResult (VKAPI_PTR *PFN_vkCreateSwapchainKHR)(VkDevice device, const VkSwapchainCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSwapchainKHR* pSwapchain);
typedef void (VKAPI_PTR *PFN_vkDestroySwapchainKHR)(VkDevice device, VkSwapchainKHR swapchain, const VkAllocationCallbacks* pAllocator);
typedef VkResult (VKAPI_PTR *PFN_vkGetSwapchainImagesKHR)(VkDevice device, VkSwapchainKHR swapchain, uint32_t* pSwapchainImageCount, VkImage* pSwapchainImages);
typedef VkResult (VKAPI_PTR *PFN_vkAcquireNextImageKHR)(VkDevice device, VkSwapchainKHR swapchain, uint64_t timeout, VkSemaphore semaphore, VkFence fence, uint32_t* pImageIndex);
typedef VkResult (VKAPI_PTR *PFN_vkQueuePresentKHR)(VkQueue queue, const VkPresentInfoKHR* pPresentInfo);
+typedef VkResult (VKAPI_PTR *PFN_vkGetDeviceGroupPresentCapabilitiesKHR)(VkDevice device, VkDeviceGroupPresentCapabilitiesKHR* pDeviceGroupPresentCapabilities);
+typedef VkResult (VKAPI_PTR *PFN_vkGetDeviceGroupSurfacePresentModesKHR)(VkDevice device, VkSurfaceKHR surface, VkDeviceGroupPresentModeFlagsKHR* pModes);
+typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDevicePresentRectanglesKHR)(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, uint32_t* pRectCount, VkRect2D* pRects);
+typedef VkResult (VKAPI_PTR *PFN_vkAcquireNextImage2KHR)(VkDevice device, const VkAcquireNextImageInfoKHR* pAcquireInfo, uint32_t* pImageIndex);
#ifndef VK_NO_PROTOTYPES
VKAPI_ATTR VkResult VKAPI_CALL vkCreateSwapchainKHR(
@@ -3686,6 +4589,26 @@
VKAPI_ATTR VkResult VKAPI_CALL vkQueuePresentKHR(
VkQueue queue,
const VkPresentInfoKHR* pPresentInfo);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkGetDeviceGroupPresentCapabilitiesKHR(
+ VkDevice device,
+ VkDeviceGroupPresentCapabilitiesKHR* pDeviceGroupPresentCapabilities);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkGetDeviceGroupSurfacePresentModesKHR(
+ VkDevice device,
+ VkSurfaceKHR surface,
+ VkDeviceGroupPresentModeFlagsKHR* pModes);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDevicePresentRectanglesKHR(
+ VkPhysicalDevice physicalDevice,
+ VkSurfaceKHR surface,
+ uint32_t* pRectCount,
+ VkRect2D* pRects);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkAcquireNextImage2KHR(
+ VkDevice device,
+ const VkAcquireNextImageInfoKHR* pAcquireInfo,
+ uint32_t* pImageIndex);
#endif
#define VK_KHR_display 1
@@ -4048,114 +4971,141 @@
#define VK_KHR_SAMPLER_MIRROR_CLAMP_TO_EDGE_EXTENSION_NAME "VK_KHR_sampler_mirror_clamp_to_edge"
+#define VK_KHR_multiview 1
+typedef VkPhysicalDeviceMultiviewFeatures VkPhysicalDeviceMultiviewFeaturesKHR;
+typedef VkPhysicalDeviceMultiviewProperties VkPhysicalDeviceMultiviewPropertiesKHR;
+typedef VkRenderPassMultiviewCreateInfo VkRenderPassMultiviewCreateInfoKHR;
+
+#define VK_KHR_MULTIVIEW_SPEC_VERSION 1
+#define VK_KHR_MULTIVIEW_EXTENSION_NAME "VK_KHR_multiview"
+#define VK_DEPENDENCY_VIEW_LOCAL_BIT_KHR VK_DEPENDENCY_VIEW_LOCAL_BIT
+#define VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_FEATURES_KHR VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_FEATURES
+#define VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_PROPERTIES_KHR VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_PROPERTIES
+#define VK_STRUCTURE_TYPE_RENDER_PASS_MULTIVIEW_CREATE_INFO_KHR VK_STRUCTURE_TYPE_RENDER_PASS_MULTIVIEW_CREATE_INFO
+
+
#define VK_KHR_get_physical_device_properties2 1
+typedef VkFormatProperties2 VkFormatProperties2KHR;
+typedef VkImageFormatProperties2 VkImageFormatProperties2KHR;
+typedef VkPhysicalDeviceFeatures2 VkPhysicalDeviceFeatures2KHR;
+typedef VkPhysicalDeviceImageFormatInfo2 VkPhysicalDeviceImageFormatInfo2KHR;
+typedef VkPhysicalDeviceMemoryProperties2 VkPhysicalDeviceMemoryProperties2KHR;
+typedef VkPhysicalDeviceProperties2 VkPhysicalDeviceProperties2KHR;
+typedef VkPhysicalDeviceSparseImageFormatInfo2 VkPhysicalDeviceSparseImageFormatInfo2KHR;
+typedef VkQueueFamilyProperties2 VkQueueFamilyProperties2KHR;
+typedef VkSparseImageFormatProperties2 VkSparseImageFormatProperties2KHR;
+
#define VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION 1
#define VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME "VK_KHR_get_physical_device_properties2"
+#define VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2
+#define VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2_KHR VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2
+#define VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2_KHR VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2
+#define VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2_KHR VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2
+#define VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_PROPERTIES_2_KHR VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_PROPERTIES_2
+#define VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2_KHR VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2
+#define VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SPARSE_IMAGE_FORMAT_INFO_2_KHR VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SPARSE_IMAGE_FORMAT_INFO_2
+#define VK_STRUCTURE_TYPE_QUEUE_FAMILY_PROPERTIES_2_KHR VK_STRUCTURE_TYPE_QUEUE_FAMILY_PROPERTIES_2
+#define VK_STRUCTURE_TYPE_SPARSE_IMAGE_FORMAT_PROPERTIES_2_KHR VK_STRUCTURE_TYPE_SPARSE_IMAGE_FORMAT_PROPERTIES_2
-typedef struct VkPhysicalDeviceFeatures2KHR {
- VkStructureType sType;
- void* pNext;
- VkPhysicalDeviceFeatures features;
-} VkPhysicalDeviceFeatures2KHR;
-
-typedef struct VkPhysicalDeviceProperties2KHR {
- VkStructureType sType;
- void* pNext;
- VkPhysicalDeviceProperties properties;
-} VkPhysicalDeviceProperties2KHR;
-
-typedef struct VkFormatProperties2KHR {
- VkStructureType sType;
- void* pNext;
- VkFormatProperties formatProperties;
-} VkFormatProperties2KHR;
-
-typedef struct VkImageFormatProperties2KHR {
- VkStructureType sType;
- void* pNext;
- VkImageFormatProperties imageFormatProperties;
-} VkImageFormatProperties2KHR;
-
-typedef struct VkPhysicalDeviceImageFormatInfo2KHR {
- VkStructureType sType;
- const void* pNext;
- VkFormat format;
- VkImageType type;
- VkImageTiling tiling;
- VkImageUsageFlags usage;
- VkImageCreateFlags flags;
-} VkPhysicalDeviceImageFormatInfo2KHR;
-
-typedef struct VkQueueFamilyProperties2KHR {
- VkStructureType sType;
- void* pNext;
- VkQueueFamilyProperties queueFamilyProperties;
-} VkQueueFamilyProperties2KHR;
-
-typedef struct VkPhysicalDeviceMemoryProperties2KHR {
- VkStructureType sType;
- void* pNext;
- VkPhysicalDeviceMemoryProperties memoryProperties;
-} VkPhysicalDeviceMemoryProperties2KHR;
-
-typedef struct VkSparseImageFormatProperties2KHR {
- VkStructureType sType;
- void* pNext;
- VkSparseImageFormatProperties properties;
-} VkSparseImageFormatProperties2KHR;
-
-typedef struct VkPhysicalDeviceSparseImageFormatInfo2KHR {
- VkStructureType sType;
- const void* pNext;
- VkFormat format;
- VkImageType type;
- VkSampleCountFlagBits samples;
- VkImageUsageFlags usage;
- VkImageTiling tiling;
-} VkPhysicalDeviceSparseImageFormatInfo2KHR;
-
-
-typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceFeatures2KHR)(VkPhysicalDevice physicalDevice, VkPhysicalDeviceFeatures2KHR* pFeatures);
-typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceProperties2KHR)(VkPhysicalDevice physicalDevice, VkPhysicalDeviceProperties2KHR* pProperties);
-typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceFormatProperties2KHR)(VkPhysicalDevice physicalDevice, VkFormat format, VkFormatProperties2KHR* pFormatProperties);
-typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceImageFormatProperties2KHR)(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceImageFormatInfo2KHR* pImageFormatInfo, VkImageFormatProperties2KHR* pImageFormatProperties);
-typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceQueueFamilyProperties2KHR)(VkPhysicalDevice physicalDevice, uint32_t* pQueueFamilyPropertyCount, VkQueueFamilyProperties2KHR* pQueueFamilyProperties);
-typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceMemoryProperties2KHR)(VkPhysicalDevice physicalDevice, VkPhysicalDeviceMemoryProperties2KHR* pMemoryProperties);
-typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceSparseImageFormatProperties2KHR)(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceSparseImageFormatInfo2KHR* pFormatInfo, uint32_t* pPropertyCount, VkSparseImageFormatProperties2KHR* pProperties);
+typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceFeatures2KHR)(VkPhysicalDevice physicalDevice, VkPhysicalDeviceFeatures2* pFeatures);
+typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceFormatProperties2KHR)(VkPhysicalDevice physicalDevice, VkFormat format, VkFormatProperties2* pFormatProperties);
+typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceImageFormatProperties2KHR)(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceImageFormatInfo2* pImageFormatInfo, VkImageFormatProperties2* pImageFormatProperties);
+typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceMemoryProperties2KHR)(VkPhysicalDevice physicalDevice, VkPhysicalDeviceMemoryProperties2* pMemoryProperties);
+typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceProperties2KHR)(VkPhysicalDevice physicalDevice, VkPhysicalDeviceProperties2* pProperties);
+typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceQueueFamilyProperties2KHR)(VkPhysicalDevice physicalDevice, uint32_t* pQueueFamilyPropertyCount, VkQueueFamilyProperties2* pQueueFamilyProperties);
+typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceSparseImageFormatProperties2KHR)(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceSparseImageFormatInfo2* pFormatInfo, uint32_t* pPropertyCount, VkSparseImageFormatProperties2* pProperties);
#ifndef VK_NO_PROTOTYPES
VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceFeatures2KHR(
VkPhysicalDevice physicalDevice,
- VkPhysicalDeviceFeatures2KHR* pFeatures);
-
-VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceProperties2KHR(
- VkPhysicalDevice physicalDevice,
- VkPhysicalDeviceProperties2KHR* pProperties);
+ VkPhysicalDeviceFeatures2* pFeatures);
VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceFormatProperties2KHR(
VkPhysicalDevice physicalDevice,
VkFormat format,
- VkFormatProperties2KHR* pFormatProperties);
+ VkFormatProperties2* pFormatProperties);
VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceImageFormatProperties2KHR(
VkPhysicalDevice physicalDevice,
- const VkPhysicalDeviceImageFormatInfo2KHR* pImageFormatInfo,
- VkImageFormatProperties2KHR* pImageFormatProperties);
+ const VkPhysicalDeviceImageFormatInfo2* pImageFormatInfo,
+ VkImageFormatProperties2* pImageFormatProperties);
+
+VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceMemoryProperties2KHR(
+ VkPhysicalDevice physicalDevice,
+ VkPhysicalDeviceMemoryProperties2* pMemoryProperties);
+
+VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceProperties2KHR(
+ VkPhysicalDevice physicalDevice,
+ VkPhysicalDeviceProperties2* pProperties);
VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceQueueFamilyProperties2KHR(
VkPhysicalDevice physicalDevice,
uint32_t* pQueueFamilyPropertyCount,
- VkQueueFamilyProperties2KHR* pQueueFamilyProperties);
-
-VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceMemoryProperties2KHR(
- VkPhysicalDevice physicalDevice,
- VkPhysicalDeviceMemoryProperties2KHR* pMemoryProperties);
+ VkQueueFamilyProperties2* pQueueFamilyProperties);
VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceSparseImageFormatProperties2KHR(
VkPhysicalDevice physicalDevice,
- const VkPhysicalDeviceSparseImageFormatInfo2KHR* pFormatInfo,
+ const VkPhysicalDeviceSparseImageFormatInfo2* pFormatInfo,
uint32_t* pPropertyCount,
- VkSparseImageFormatProperties2KHR* pProperties);
+ VkSparseImageFormatProperties2* pProperties);
+#endif
+
+#define VK_KHR_device_group 1
+typedef VkDeviceGroupBindSparseInfo VkDeviceGroupBindSparseInfoKHR;
+typedef VkDeviceGroupCommandBufferBeginInfo VkDeviceGroupCommandBufferBeginInfoKHR;
+typedef VkDeviceGroupRenderPassBeginInfo VkDeviceGroupRenderPassBeginInfoKHR;
+typedef VkDeviceGroupSubmitInfo VkDeviceGroupSubmitInfoKHR;
+typedef VkMemoryAllocateFlagBits VkMemoryAllocateFlagBitsKHR;
+typedef VkMemoryAllocateFlagsInfo VkMemoryAllocateFlagsInfoKHR;
+typedef VkMemoryAllocateFlags VkMemoryAllocateFlagsKHR;
+typedef VkPeerMemoryFeatureFlagBits VkPeerMemoryFeatureFlagBitsKHR;
+typedef VkPeerMemoryFeatureFlags VkPeerMemoryFeatureFlagsKHR;
+typedef VkBindBufferMemoryDeviceGroupInfo VkBindBufferMemoryDeviceGroupInfoKHR;
+typedef VkBindImageMemoryDeviceGroupInfo VkBindImageMemoryDeviceGroupInfoKHR;
+
+#define VK_KHR_DEVICE_GROUP_SPEC_VERSION 2
+#define VK_KHR_DEVICE_GROUP_EXTENSION_NAME "VK_KHR_device_group"
+#define VK_DEPENDENCY_DEVICE_GROUP_BIT_KHR VK_DEPENDENCY_DEVICE_GROUP_BIT
+#define VK_MEMORY_ALLOCATE_DEVICE_MASK_BIT_KHR VK_MEMORY_ALLOCATE_DEVICE_MASK_BIT
+#define VK_PEER_MEMORY_FEATURE_COPY_DST_BIT_KHR VK_PEER_MEMORY_FEATURE_COPY_DST_BIT
+#define VK_PEER_MEMORY_FEATURE_COPY_SRC_BIT_KHR VK_PEER_MEMORY_FEATURE_COPY_SRC_BIT
+#define VK_PEER_MEMORY_FEATURE_GENERIC_DST_BIT_KHR VK_PEER_MEMORY_FEATURE_GENERIC_DST_BIT
+#define VK_PEER_MEMORY_FEATURE_GENERIC_SRC_BIT_KHR VK_PEER_MEMORY_FEATURE_GENERIC_SRC_BIT
+#define VK_PIPELINE_CREATE_DISPATCH_BASE_KHR VK_PIPELINE_CREATE_DISPATCH_BASE
+#define VK_PIPELINE_CREATE_VIEW_INDEX_FROM_DEVICE_INDEX_BIT_KHR VK_PIPELINE_CREATE_VIEW_INDEX_FROM_DEVICE_INDEX_BIT
+#define VK_STRUCTURE_TYPE_DEVICE_GROUP_BIND_SPARSE_INFO_KHR VK_STRUCTURE_TYPE_DEVICE_GROUP_BIND_SPARSE_INFO
+#define VK_STRUCTURE_TYPE_DEVICE_GROUP_COMMAND_BUFFER_BEGIN_INFO_KHR VK_STRUCTURE_TYPE_DEVICE_GROUP_COMMAND_BUFFER_BEGIN_INFO
+#define VK_STRUCTURE_TYPE_DEVICE_GROUP_RENDER_PASS_BEGIN_INFO_KHR VK_STRUCTURE_TYPE_DEVICE_GROUP_RENDER_PASS_BEGIN_INFO
+#define VK_STRUCTURE_TYPE_DEVICE_GROUP_SUBMIT_INFO_KHR VK_STRUCTURE_TYPE_DEVICE_GROUP_SUBMIT_INFO
+#define VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_FLAGS_INFO_KHR VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_FLAGS_INFO
+#define VK_IMAGE_CREATE_BIND_SFR_BIT_KHR VK_IMAGE_CREATE_BIND_SFR_BIT
+#define VK_STRUCTURE_TYPE_BIND_BUFFER_MEMORY_DEVICE_GROUP_INFO_KHR VK_STRUCTURE_TYPE_BIND_BUFFER_MEMORY_DEVICE_GROUP_INFO
+#define VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_DEVICE_GROUP_INFO_KHR VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_DEVICE_GROUP_INFO
+
+typedef void (VKAPI_PTR *PFN_vkCmdDispatchBaseKHR)(VkCommandBuffer commandBuffer, uint32_t baseGroupX, uint32_t baseGroupY, uint32_t baseGroupZ, uint32_t groupCountX, uint32_t groupCountY, uint32_t groupCountZ);
+typedef void (VKAPI_PTR *PFN_vkCmdSetDeviceMaskKHR)(VkCommandBuffer commandBuffer, uint32_t deviceMask);
+typedef void (VKAPI_PTR *PFN_vkGetDeviceGroupPeerMemoryFeaturesKHR)(VkDevice device, uint32_t heapIndex, uint32_t localDeviceIndex, uint32_t remoteDeviceIndex, VkPeerMemoryFeatureFlags* pPeerMemoryFeatures);
+
+#ifndef VK_NO_PROTOTYPES
+VKAPI_ATTR void VKAPI_CALL vkCmdDispatchBaseKHR(
+ VkCommandBuffer commandBuffer,
+ uint32_t baseGroupX,
+ uint32_t baseGroupY,
+ uint32_t baseGroupZ,
+ uint32_t groupCountX,
+ uint32_t groupCountY,
+ uint32_t groupCountZ);
+
+VKAPI_ATTR void VKAPI_CALL vkCmdSetDeviceMaskKHR(
+ VkCommandBuffer commandBuffer,
+ uint32_t deviceMask);
+
+VKAPI_ATTR void VKAPI_CALL vkGetDeviceGroupPeerMemoryFeaturesKHR(
+ VkDevice device,
+ uint32_t heapIndex,
+ uint32_t localDeviceIndex,
+ uint32_t remoteDeviceIndex,
+ VkPeerMemoryFeatureFlags* pPeerMemoryFeatures);
#endif
#define VK_KHR_shader_draw_parameters 1
@@ -4164,121 +5114,96 @@
#define VK_KHR_maintenance1 1
+typedef VkCommandPoolTrimFlags VkCommandPoolTrimFlagsKHR;
+
#define VK_KHR_MAINTENANCE1_SPEC_VERSION 1
#define VK_KHR_MAINTENANCE1_EXTENSION_NAME "VK_KHR_maintenance1"
+#define VK_ERROR_OUT_OF_POOL_MEMORY_KHR VK_ERROR_OUT_OF_POOL_MEMORY
+#define VK_FORMAT_FEATURE_TRANSFER_DST_BIT_KHR VK_FORMAT_FEATURE_TRANSFER_DST_BIT
+#define VK_FORMAT_FEATURE_TRANSFER_SRC_BIT_KHR VK_FORMAT_FEATURE_TRANSFER_SRC_BIT
+#define VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT_KHR VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT
-typedef VkFlags VkCommandPoolTrimFlagsKHR;
-
-typedef void (VKAPI_PTR *PFN_vkTrimCommandPoolKHR)(VkDevice device, VkCommandPool commandPool, VkCommandPoolTrimFlagsKHR flags);
+typedef void (VKAPI_PTR *PFN_vkTrimCommandPoolKHR)(VkDevice device, VkCommandPool commandPool, VkCommandPoolTrimFlags flags);
#ifndef VK_NO_PROTOTYPES
VKAPI_ATTR void VKAPI_CALL vkTrimCommandPoolKHR(
VkDevice device,
VkCommandPool commandPool,
- VkCommandPoolTrimFlagsKHR flags);
+ VkCommandPoolTrimFlags flags);
+#endif
+
+#define VK_KHR_device_group_creation 1
+typedef VkDeviceGroupDeviceCreateInfo VkDeviceGroupDeviceCreateInfoKHR;
+typedef VkPhysicalDeviceGroupProperties VkPhysicalDeviceGroupPropertiesKHR;
+
+#define VK_KHR_DEVICE_GROUP_CREATION_SPEC_VERSION 1
+#define VK_KHR_DEVICE_GROUP_CREATION_EXTENSION_NAME "VK_KHR_device_group_creation"
+#define VK_MAX_DEVICE_GROUP_SIZE_KHR VK_MAX_DEVICE_GROUP_SIZE
+#define VK_MEMORY_HEAP_MULTI_INSTANCE_BIT_KHR VK_MEMORY_HEAP_MULTI_INSTANCE_BIT
+#define VK_STRUCTURE_TYPE_DEVICE_GROUP_DEVICE_CREATE_INFO_KHR VK_STRUCTURE_TYPE_DEVICE_GROUP_DEVICE_CREATE_INFO
+#define VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GROUP_PROPERTIES_KHR VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GROUP_PROPERTIES
+
+typedef VkResult (VKAPI_PTR *PFN_vkEnumeratePhysicalDeviceGroupsKHR)(VkInstance instance, uint32_t* pPhysicalDeviceGroupCount, VkPhysicalDeviceGroupProperties* pPhysicalDeviceGroupProperties);
+
+#ifndef VK_NO_PROTOTYPES
+VKAPI_ATTR VkResult VKAPI_CALL vkEnumeratePhysicalDeviceGroupsKHR(
+ VkInstance instance,
+ uint32_t* pPhysicalDeviceGroupCount,
+ VkPhysicalDeviceGroupProperties* pPhysicalDeviceGroupProperties);
#endif
#define VK_KHR_external_memory_capabilities 1
-#define VK_LUID_SIZE_KHR 8
+typedef VkExternalBufferProperties VkExternalBufferPropertiesKHR;
+typedef VkExternalImageFormatProperties VkExternalImageFormatPropertiesKHR;
+typedef VkExternalMemoryFeatureFlagBits VkExternalMemoryFeatureFlagBitsKHR;
+typedef VkExternalMemoryFeatureFlags VkExternalMemoryFeatureFlagsKHR;
+typedef VkExternalMemoryHandleTypeFlagBits VkExternalMemoryHandleTypeFlagBitsKHR;
+typedef VkExternalMemoryHandleTypeFlags VkExternalMemoryHandleTypeFlagsKHR;
+typedef VkExternalMemoryProperties VkExternalMemoryPropertiesKHR;
+typedef VkPhysicalDeviceExternalBufferInfo VkPhysicalDeviceExternalBufferInfoKHR;
+typedef VkPhysicalDeviceExternalImageFormatInfo VkPhysicalDeviceExternalImageFormatInfoKHR;
+typedef VkPhysicalDeviceIDProperties VkPhysicalDeviceIDPropertiesKHR;
+
#define VK_KHR_EXTERNAL_MEMORY_CAPABILITIES_SPEC_VERSION 1
#define VK_KHR_EXTERNAL_MEMORY_CAPABILITIES_EXTENSION_NAME "VK_KHR_external_memory_capabilities"
+#define VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT_KHR VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT
+#define VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT_KHR VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT
+#define VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT_KHR VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT
+#define VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_BIT_KHR VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_BIT
+#define VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_KMT_BIT_KHR VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_KMT_BIT
+#define VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_HEAP_BIT_KHR VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_HEAP_BIT
+#define VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_RESOURCE_BIT_KHR VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_RESOURCE_BIT
+#define VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT_KHR VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT
+#define VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT_KHR VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT
+#define VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT_KHR VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT
+#define VK_LUID_SIZE_KHR VK_LUID_SIZE
+#define VK_STRUCTURE_TYPE_EXTERNAL_BUFFER_PROPERTIES_KHR VK_STRUCTURE_TYPE_EXTERNAL_BUFFER_PROPERTIES
+#define VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES_KHR VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES
+#define VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_BUFFER_INFO_KHR VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_BUFFER_INFO
+#define VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO_KHR VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO
+#define VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ID_PROPERTIES_KHR VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ID_PROPERTIES
-
-typedef enum VkExternalMemoryHandleTypeFlagBitsKHR {
- VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT_KHR = 0x00000001,
- VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT_KHR = 0x00000002,
- VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT_KHR = 0x00000004,
- VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_BIT_KHR = 0x00000008,
- VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_KMT_BIT_KHR = 0x00000010,
- VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_HEAP_BIT_KHR = 0x00000020,
- VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_RESOURCE_BIT_KHR = 0x00000040,
- VK_EXTERNAL_MEMORY_HANDLE_TYPE_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF
-} VkExternalMemoryHandleTypeFlagBitsKHR;
-typedef VkFlags VkExternalMemoryHandleTypeFlagsKHR;
-
-typedef enum VkExternalMemoryFeatureFlagBitsKHR {
- VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT_KHR = 0x00000001,
- VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT_KHR = 0x00000002,
- VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT_KHR = 0x00000004,
- VK_EXTERNAL_MEMORY_FEATURE_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF
-} VkExternalMemoryFeatureFlagBitsKHR;
-typedef VkFlags VkExternalMemoryFeatureFlagsKHR;
-
-typedef struct VkExternalMemoryPropertiesKHR {
- VkExternalMemoryFeatureFlagsKHR externalMemoryFeatures;
- VkExternalMemoryHandleTypeFlagsKHR exportFromImportedHandleTypes;
- VkExternalMemoryHandleTypeFlagsKHR compatibleHandleTypes;
-} VkExternalMemoryPropertiesKHR;
-
-typedef struct VkPhysicalDeviceExternalImageFormatInfoKHR {
- VkStructureType sType;
- const void* pNext;
- VkExternalMemoryHandleTypeFlagBitsKHR handleType;
-} VkPhysicalDeviceExternalImageFormatInfoKHR;
-
-typedef struct VkExternalImageFormatPropertiesKHR {
- VkStructureType sType;
- void* pNext;
- VkExternalMemoryPropertiesKHR externalMemoryProperties;
-} VkExternalImageFormatPropertiesKHR;
-
-typedef struct VkPhysicalDeviceExternalBufferInfoKHR {
- VkStructureType sType;
- const void* pNext;
- VkBufferCreateFlags flags;
- VkBufferUsageFlags usage;
- VkExternalMemoryHandleTypeFlagBitsKHR handleType;
-} VkPhysicalDeviceExternalBufferInfoKHR;
-
-typedef struct VkExternalBufferPropertiesKHR {
- VkStructureType sType;
- void* pNext;
- VkExternalMemoryPropertiesKHR externalMemoryProperties;
-} VkExternalBufferPropertiesKHR;
-
-typedef struct VkPhysicalDeviceIDPropertiesKHR {
- VkStructureType sType;
- void* pNext;
- uint8_t deviceUUID[VK_UUID_SIZE];
- uint8_t driverUUID[VK_UUID_SIZE];
- uint8_t deviceLUID[VK_LUID_SIZE_KHR];
- uint32_t deviceNodeMask;
- VkBool32 deviceLUIDValid;
-} VkPhysicalDeviceIDPropertiesKHR;
-
-
-typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceExternalBufferPropertiesKHR)(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceExternalBufferInfoKHR* pExternalBufferInfo, VkExternalBufferPropertiesKHR* pExternalBufferProperties);
+typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceExternalBufferPropertiesKHR)(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceExternalBufferInfo* pExternalBufferInfo, VkExternalBufferProperties* pExternalBufferProperties);
#ifndef VK_NO_PROTOTYPES
VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceExternalBufferPropertiesKHR(
VkPhysicalDevice physicalDevice,
- const VkPhysicalDeviceExternalBufferInfoKHR* pExternalBufferInfo,
- VkExternalBufferPropertiesKHR* pExternalBufferProperties);
+ const VkPhysicalDeviceExternalBufferInfo* pExternalBufferInfo,
+ VkExternalBufferProperties* pExternalBufferProperties);
#endif
#define VK_KHR_external_memory 1
+typedef VkExportMemoryAllocateInfo VkExportMemoryAllocateInfoKHR;
+typedef VkExternalMemoryBufferCreateInfo VkExternalMemoryBufferCreateInfoKHR;
+typedef VkExternalMemoryImageCreateInfo VkExternalMemoryImageCreateInfoKHR;
+
#define VK_KHR_EXTERNAL_MEMORY_SPEC_VERSION 1
#define VK_KHR_EXTERNAL_MEMORY_EXTENSION_NAME "VK_KHR_external_memory"
-#define VK_QUEUE_FAMILY_EXTERNAL_KHR (~0U-1)
-
-typedef struct VkExternalMemoryImageCreateInfoKHR {
- VkStructureType sType;
- const void* pNext;
- VkExternalMemoryHandleTypeFlagsKHR handleTypes;
-} VkExternalMemoryImageCreateInfoKHR;
-
-typedef struct VkExternalMemoryBufferCreateInfoKHR {
- VkStructureType sType;
- const void* pNext;
- VkExternalMemoryHandleTypeFlagsKHR handleTypes;
-} VkExternalMemoryBufferCreateInfoKHR;
-
-typedef struct VkExportMemoryAllocateInfoKHR {
- VkStructureType sType;
- const void* pNext;
- VkExternalMemoryHandleTypeFlagsKHR handleTypes;
-} VkExportMemoryAllocateInfoKHR;
-
+#define VK_ERROR_INVALID_EXTERNAL_HANDLE_KHR VK_ERROR_INVALID_EXTERNAL_HANDLE
+#define VK_QUEUE_FAMILY_EXTERNAL_KHR VK_QUEUE_FAMILY_EXTERNAL
+#define VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO_KHR VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO
+#define VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_BUFFER_CREATE_INFO_KHR VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_BUFFER_CREATE_INFO
+#define VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO_KHR VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO
#ifdef VK_USE_PLATFORM_WIN32_KHR
@@ -4287,11 +5212,11 @@
#define VK_KHR_EXTERNAL_MEMORY_WIN32_EXTENSION_NAME "VK_KHR_external_memory_win32"
typedef struct VkImportMemoryWin32HandleInfoKHR {
- VkStructureType sType;
- const void* pNext;
- VkExternalMemoryHandleTypeFlagBitsKHR handleType;
- HANDLE handle;
- LPCWSTR name;
+ VkStructureType sType;
+ const void* pNext;
+ VkExternalMemoryHandleTypeFlagBits handleType;
+ HANDLE handle;
+ LPCWSTR name;
} VkImportMemoryWin32HandleInfoKHR;
typedef struct VkExportMemoryWin32HandleInfoKHR {
@@ -4309,15 +5234,15 @@
} VkMemoryWin32HandlePropertiesKHR;
typedef struct VkMemoryGetWin32HandleInfoKHR {
- VkStructureType sType;
- const void* pNext;
- VkDeviceMemory memory;
- VkExternalMemoryHandleTypeFlagBitsKHR handleType;
+ VkStructureType sType;
+ const void* pNext;
+ VkDeviceMemory memory;
+ VkExternalMemoryHandleTypeFlagBits handleType;
} VkMemoryGetWin32HandleInfoKHR;
typedef VkResult (VKAPI_PTR *PFN_vkGetMemoryWin32HandleKHR)(VkDevice device, const VkMemoryGetWin32HandleInfoKHR* pGetWin32HandleInfo, HANDLE* pHandle);
-typedef VkResult (VKAPI_PTR *PFN_vkGetMemoryWin32HandlePropertiesKHR)(VkDevice device, VkExternalMemoryHandleTypeFlagBitsKHR handleType, HANDLE handle, VkMemoryWin32HandlePropertiesKHR* pMemoryWin32HandleProperties);
+typedef VkResult (VKAPI_PTR *PFN_vkGetMemoryWin32HandlePropertiesKHR)(VkDevice device, VkExternalMemoryHandleTypeFlagBits handleType, HANDLE handle, VkMemoryWin32HandlePropertiesKHR* pMemoryWin32HandleProperties);
#ifndef VK_NO_PROTOTYPES
VKAPI_ATTR VkResult VKAPI_CALL vkGetMemoryWin32HandleKHR(
@@ -4327,7 +5252,7 @@
VKAPI_ATTR VkResult VKAPI_CALL vkGetMemoryWin32HandlePropertiesKHR(
VkDevice device,
- VkExternalMemoryHandleTypeFlagBitsKHR handleType,
+ VkExternalMemoryHandleTypeFlagBits handleType,
HANDLE handle,
VkMemoryWin32HandlePropertiesKHR* pMemoryWin32HandleProperties);
#endif
@@ -4338,10 +5263,10 @@
#define VK_KHR_EXTERNAL_MEMORY_FD_EXTENSION_NAME "VK_KHR_external_memory_fd"
typedef struct VkImportMemoryFdInfoKHR {
- VkStructureType sType;
- const void* pNext;
- VkExternalMemoryHandleTypeFlagBitsKHR handleType;
- int fd;
+ VkStructureType sType;
+ const void* pNext;
+ VkExternalMemoryHandleTypeFlagBits handleType;
+ int fd;
} VkImportMemoryFdInfoKHR;
typedef struct VkMemoryFdPropertiesKHR {
@@ -4351,15 +5276,15 @@
} VkMemoryFdPropertiesKHR;
typedef struct VkMemoryGetFdInfoKHR {
- VkStructureType sType;
- const void* pNext;
- VkDeviceMemory memory;
- VkExternalMemoryHandleTypeFlagBitsKHR handleType;
+ VkStructureType sType;
+ const void* pNext;
+ VkDeviceMemory memory;
+ VkExternalMemoryHandleTypeFlagBits handleType;
} VkMemoryGetFdInfoKHR;
typedef VkResult (VKAPI_PTR *PFN_vkGetMemoryFdKHR)(VkDevice device, const VkMemoryGetFdInfoKHR* pGetFdInfo, int* pFd);
-typedef VkResult (VKAPI_PTR *PFN_vkGetMemoryFdPropertiesKHR)(VkDevice device, VkExternalMemoryHandleTypeFlagBitsKHR handleType, int fd, VkMemoryFdPropertiesKHR* pMemoryFdProperties);
+typedef VkResult (VKAPI_PTR *PFN_vkGetMemoryFdPropertiesKHR)(VkDevice device, VkExternalMemoryHandleTypeFlagBits handleType, int fd, VkMemoryFdPropertiesKHR* pMemoryFdProperties);
#ifndef VK_NO_PROTOTYPES
VKAPI_ATTR VkResult VKAPI_CALL vkGetMemoryFdKHR(
@@ -4369,7 +5294,7 @@
VKAPI_ATTR VkResult VKAPI_CALL vkGetMemoryFdPropertiesKHR(
VkDevice device,
- VkExternalMemoryHandleTypeFlagBitsKHR handleType,
+ VkExternalMemoryHandleTypeFlagBits handleType,
int fd,
VkMemoryFdPropertiesKHR* pMemoryFdProperties);
#endif
@@ -4395,68 +5320,43 @@
#endif /* VK_USE_PLATFORM_WIN32_KHR */
#define VK_KHR_external_semaphore_capabilities 1
+typedef VkExternalSemaphoreFeatureFlagBits VkExternalSemaphoreFeatureFlagBitsKHR;
+typedef VkExternalSemaphoreFeatureFlags VkExternalSemaphoreFeatureFlagsKHR;
+typedef VkExternalSemaphoreHandleTypeFlagBits VkExternalSemaphoreHandleTypeFlagBitsKHR;
+typedef VkExternalSemaphoreHandleTypeFlags VkExternalSemaphoreHandleTypeFlagsKHR;
+typedef VkExternalSemaphoreProperties VkExternalSemaphorePropertiesKHR;
+typedef VkPhysicalDeviceExternalSemaphoreInfo VkPhysicalDeviceExternalSemaphoreInfoKHR;
+
#define VK_KHR_EXTERNAL_SEMAPHORE_CAPABILITIES_SPEC_VERSION 1
#define VK_KHR_EXTERNAL_SEMAPHORE_CAPABILITIES_EXTENSION_NAME "VK_KHR_external_semaphore_capabilities"
+#define VK_EXTERNAL_SEMAPHORE_FEATURE_EXPORTABLE_BIT_KHR VK_EXTERNAL_SEMAPHORE_FEATURE_EXPORTABLE_BIT
+#define VK_EXTERNAL_SEMAPHORE_FEATURE_IMPORTABLE_BIT_KHR VK_EXTERNAL_SEMAPHORE_FEATURE_IMPORTABLE_BIT
+#define VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_D3D12_FENCE_BIT_KHR VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_D3D12_FENCE_BIT
+#define VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT_KHR VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT
+#define VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT_KHR VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT
+#define VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT_KHR VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT
+#define VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT_KHR VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT
+#define VK_STRUCTURE_TYPE_EXTERNAL_SEMAPHORE_PROPERTIES_KHR VK_STRUCTURE_TYPE_EXTERNAL_SEMAPHORE_PROPERTIES
+#define VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_SEMAPHORE_INFO_KHR VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_SEMAPHORE_INFO
-
-typedef enum VkExternalSemaphoreHandleTypeFlagBitsKHR {
- VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT_KHR = 0x00000001,
- VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT_KHR = 0x00000002,
- VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT_KHR = 0x00000004,
- VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_D3D12_FENCE_BIT_KHR = 0x00000008,
- VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT_KHR = 0x00000010,
- VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF
-} VkExternalSemaphoreHandleTypeFlagBitsKHR;
-typedef VkFlags VkExternalSemaphoreHandleTypeFlagsKHR;
-
-typedef enum VkExternalSemaphoreFeatureFlagBitsKHR {
- VK_EXTERNAL_SEMAPHORE_FEATURE_EXPORTABLE_BIT_KHR = 0x00000001,
- VK_EXTERNAL_SEMAPHORE_FEATURE_IMPORTABLE_BIT_KHR = 0x00000002,
- VK_EXTERNAL_SEMAPHORE_FEATURE_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF
-} VkExternalSemaphoreFeatureFlagBitsKHR;
-typedef VkFlags VkExternalSemaphoreFeatureFlagsKHR;
-
-typedef struct VkPhysicalDeviceExternalSemaphoreInfoKHR {
- VkStructureType sType;
- const void* pNext;
- VkExternalSemaphoreHandleTypeFlagBitsKHR handleType;
-} VkPhysicalDeviceExternalSemaphoreInfoKHR;
-
-typedef struct VkExternalSemaphorePropertiesKHR {
- VkStructureType sType;
- void* pNext;
- VkExternalSemaphoreHandleTypeFlagsKHR exportFromImportedHandleTypes;
- VkExternalSemaphoreHandleTypeFlagsKHR compatibleHandleTypes;
- VkExternalSemaphoreFeatureFlagsKHR externalSemaphoreFeatures;
-} VkExternalSemaphorePropertiesKHR;
-
-
-typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceExternalSemaphorePropertiesKHR)(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceExternalSemaphoreInfoKHR* pExternalSemaphoreInfo, VkExternalSemaphorePropertiesKHR* pExternalSemaphoreProperties);
+typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceExternalSemaphorePropertiesKHR)(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceExternalSemaphoreInfo* pExternalSemaphoreInfo, VkExternalSemaphoreProperties* pExternalSemaphoreProperties);
#ifndef VK_NO_PROTOTYPES
VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceExternalSemaphorePropertiesKHR(
VkPhysicalDevice physicalDevice,
- const VkPhysicalDeviceExternalSemaphoreInfoKHR* pExternalSemaphoreInfo,
- VkExternalSemaphorePropertiesKHR* pExternalSemaphoreProperties);
+ const VkPhysicalDeviceExternalSemaphoreInfo* pExternalSemaphoreInfo,
+ VkExternalSemaphoreProperties* pExternalSemaphoreProperties);
#endif
#define VK_KHR_external_semaphore 1
+typedef VkExportSemaphoreCreateInfo VkExportSemaphoreCreateInfoKHR;
+typedef VkSemaphoreImportFlagBits VkSemaphoreImportFlagBitsKHR;
+typedef VkSemaphoreImportFlags VkSemaphoreImportFlagsKHR;
+
#define VK_KHR_EXTERNAL_SEMAPHORE_SPEC_VERSION 1
#define VK_KHR_EXTERNAL_SEMAPHORE_EXTENSION_NAME "VK_KHR_external_semaphore"
-
-
-typedef enum VkSemaphoreImportFlagBitsKHR {
- VK_SEMAPHORE_IMPORT_TEMPORARY_BIT_KHR = 0x00000001,
- VK_SEMAPHORE_IMPORT_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF
-} VkSemaphoreImportFlagBitsKHR;
-typedef VkFlags VkSemaphoreImportFlagsKHR;
-
-typedef struct VkExportSemaphoreCreateInfoKHR {
- VkStructureType sType;
- const void* pNext;
- VkExternalSemaphoreHandleTypeFlagsKHR handleTypes;
-} VkExportSemaphoreCreateInfoKHR;
-
+#define VK_SEMAPHORE_IMPORT_TEMPORARY_BIT_KHR VK_SEMAPHORE_IMPORT_TEMPORARY_BIT
+#define VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_CREATE_INFO_KHR VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_CREATE_INFO
#ifdef VK_USE_PLATFORM_WIN32_KHR
@@ -4465,13 +5365,13 @@
#define VK_KHR_EXTERNAL_SEMAPHORE_WIN32_EXTENSION_NAME "VK_KHR_external_semaphore_win32"
typedef struct VkImportSemaphoreWin32HandleInfoKHR {
- VkStructureType sType;
- const void* pNext;
- VkSemaphore semaphore;
- VkSemaphoreImportFlagsKHR flags;
- VkExternalSemaphoreHandleTypeFlagBitsKHR handleType;
- HANDLE handle;
- LPCWSTR name;
+ VkStructureType sType;
+ const void* pNext;
+ VkSemaphore semaphore;
+ VkSemaphoreImportFlags flags;
+ VkExternalSemaphoreHandleTypeFlagBits handleType;
+ HANDLE handle;
+ LPCWSTR name;
} VkImportSemaphoreWin32HandleInfoKHR;
typedef struct VkExportSemaphoreWin32HandleInfoKHR {
@@ -4492,10 +5392,10 @@
} VkD3D12FenceSubmitInfoKHR;
typedef struct VkSemaphoreGetWin32HandleInfoKHR {
- VkStructureType sType;
- const void* pNext;
- VkSemaphore semaphore;
- VkExternalSemaphoreHandleTypeFlagBitsKHR handleType;
+ VkStructureType sType;
+ const void* pNext;
+ VkSemaphore semaphore;
+ VkExternalSemaphoreHandleTypeFlagBits handleType;
} VkSemaphoreGetWin32HandleInfoKHR;
@@ -4519,19 +5419,19 @@
#define VK_KHR_EXTERNAL_SEMAPHORE_FD_EXTENSION_NAME "VK_KHR_external_semaphore_fd"
typedef struct VkImportSemaphoreFdInfoKHR {
- VkStructureType sType;
- const void* pNext;
- VkSemaphore semaphore;
- VkSemaphoreImportFlagsKHR flags;
- VkExternalSemaphoreHandleTypeFlagBitsKHR handleType;
- int fd;
+ VkStructureType sType;
+ const void* pNext;
+ VkSemaphore semaphore;
+ VkSemaphoreImportFlags flags;
+ VkExternalSemaphoreHandleTypeFlagBits handleType;
+ int fd;
} VkImportSemaphoreFdInfoKHR;
typedef struct VkSemaphoreGetFdInfoKHR {
- VkStructureType sType;
- const void* pNext;
- VkSemaphore semaphore;
- VkExternalSemaphoreHandleTypeFlagBitsKHR handleType;
+ VkStructureType sType;
+ const void* pNext;
+ VkSemaphore semaphore;
+ VkExternalSemaphoreHandleTypeFlagBits handleType;
} VkSemaphoreGetFdInfoKHR;
@@ -4550,7 +5450,7 @@
#endif
#define VK_KHR_push_descriptor 1
-#define VK_KHR_PUSH_DESCRIPTOR_SPEC_VERSION 1
+#define VK_KHR_PUSH_DESCRIPTOR_SPEC_VERSION 2
#define VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME "VK_KHR_push_descriptor"
typedef struct VkPhysicalDevicePushDescriptorPropertiesKHR {
@@ -4561,6 +5461,7 @@
typedef void (VKAPI_PTR *PFN_vkCmdPushDescriptorSetKHR)(VkCommandBuffer commandBuffer, VkPipelineBindPoint pipelineBindPoint, VkPipelineLayout layout, uint32_t set, uint32_t descriptorWriteCount, const VkWriteDescriptorSet* pDescriptorWrites);
+typedef void (VKAPI_PTR *PFN_vkCmdPushDescriptorSetWithTemplateKHR)(VkCommandBuffer commandBuffer, VkDescriptorUpdateTemplate descriptorUpdateTemplate, VkPipelineLayout layout, uint32_t set, const void* pData);
#ifndef VK_NO_PROTOTYPES
VKAPI_ATTR void VKAPI_CALL vkCmdPushDescriptorSetKHR(
@@ -4570,21 +5471,21 @@
uint32_t set,
uint32_t descriptorWriteCount,
const VkWriteDescriptorSet* pDescriptorWrites);
+
+VKAPI_ATTR void VKAPI_CALL vkCmdPushDescriptorSetWithTemplateKHR(
+ VkCommandBuffer commandBuffer,
+ VkDescriptorUpdateTemplate descriptorUpdateTemplate,
+ VkPipelineLayout layout,
+ uint32_t set,
+ const void* pData);
#endif
#define VK_KHR_16bit_storage 1
+typedef VkPhysicalDevice16BitStorageFeatures VkPhysicalDevice16BitStorageFeaturesKHR;
+
#define VK_KHR_16BIT_STORAGE_SPEC_VERSION 1
#define VK_KHR_16BIT_STORAGE_EXTENSION_NAME "VK_KHR_16bit_storage"
-
-typedef struct VkPhysicalDevice16BitStorageFeaturesKHR {
- VkStructureType sType;
- void* pNext;
- VkBool32 storageBuffer16BitAccess;
- VkBool32 uniformAndStorageBuffer16BitAccess;
- VkBool32 storagePushConstant16;
- VkBool32 storageInputOutput16;
-} VkPhysicalDevice16BitStorageFeaturesKHR;
-
+#define VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_16BIT_STORAGE_FEATURES_KHR VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_16BIT_STORAGE_FEATURES
#define VK_KHR_incremental_present 1
@@ -4612,74 +5513,39 @@
#define VK_KHR_descriptor_update_template 1
-VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkDescriptorUpdateTemplateKHR)
+typedef VkDescriptorUpdateTemplateCreateFlags VkDescriptorUpdateTemplateCreateFlagsKHR;
+typedef VkDescriptorUpdateTemplateCreateInfo VkDescriptorUpdateTemplateCreateInfoKHR;
+typedef VkDescriptorUpdateTemplateEntry VkDescriptorUpdateTemplateEntryKHR;
+typedef VkDescriptorUpdateTemplate VkDescriptorUpdateTemplateKHR;
+typedef VkDescriptorUpdateTemplateType VkDescriptorUpdateTemplateTypeKHR;
#define VK_KHR_DESCRIPTOR_UPDATE_TEMPLATE_SPEC_VERSION 1
#define VK_KHR_DESCRIPTOR_UPDATE_TEMPLATE_EXTENSION_NAME "VK_KHR_descriptor_update_template"
+#define VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET_KHR VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET
+#define VK_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_KHR VK_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE
+#define VK_STRUCTURE_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_CREATE_INFO_KHR VK_STRUCTURE_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_CREATE_INFO
+#define VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_KHR_EXT VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_EXT
-
-typedef enum VkDescriptorUpdateTemplateTypeKHR {
- VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET_KHR = 0,
- VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_PUSH_DESCRIPTORS_KHR = 1,
- VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_BEGIN_RANGE_KHR = VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET_KHR,
- VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_END_RANGE_KHR = VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_PUSH_DESCRIPTORS_KHR,
- VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_RANGE_SIZE_KHR = (VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_PUSH_DESCRIPTORS_KHR - VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET_KHR + 1),
- VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_MAX_ENUM_KHR = 0x7FFFFFFF
-} VkDescriptorUpdateTemplateTypeKHR;
-
-typedef VkFlags VkDescriptorUpdateTemplateCreateFlagsKHR;
-
-typedef struct VkDescriptorUpdateTemplateEntryKHR {
- uint32_t dstBinding;
- uint32_t dstArrayElement;
- uint32_t descriptorCount;
- VkDescriptorType descriptorType;
- size_t offset;
- size_t stride;
-} VkDescriptorUpdateTemplateEntryKHR;
-
-typedef struct VkDescriptorUpdateTemplateCreateInfoKHR {
- VkStructureType sType;
- void* pNext;
- VkDescriptorUpdateTemplateCreateFlagsKHR flags;
- uint32_t descriptorUpdateEntryCount;
- const VkDescriptorUpdateTemplateEntryKHR* pDescriptorUpdateEntries;
- VkDescriptorUpdateTemplateTypeKHR templateType;
- VkDescriptorSetLayout descriptorSetLayout;
- VkPipelineBindPoint pipelineBindPoint;
- VkPipelineLayout pipelineLayout;
- uint32_t set;
-} VkDescriptorUpdateTemplateCreateInfoKHR;
-
-
-typedef VkResult (VKAPI_PTR *PFN_vkCreateDescriptorUpdateTemplateKHR)(VkDevice device, const VkDescriptorUpdateTemplateCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDescriptorUpdateTemplateKHR* pDescriptorUpdateTemplate);
-typedef void (VKAPI_PTR *PFN_vkDestroyDescriptorUpdateTemplateKHR)(VkDevice device, VkDescriptorUpdateTemplateKHR descriptorUpdateTemplate, const VkAllocationCallbacks* pAllocator);
-typedef void (VKAPI_PTR *PFN_vkUpdateDescriptorSetWithTemplateKHR)(VkDevice device, VkDescriptorSet descriptorSet, VkDescriptorUpdateTemplateKHR descriptorUpdateTemplate, const void* pData);
-typedef void (VKAPI_PTR *PFN_vkCmdPushDescriptorSetWithTemplateKHR)(VkCommandBuffer commandBuffer, VkDescriptorUpdateTemplateKHR descriptorUpdateTemplate, VkPipelineLayout layout, uint32_t set, const void* pData);
+typedef VkResult (VKAPI_PTR *PFN_vkCreateDescriptorUpdateTemplateKHR)(VkDevice device, const VkDescriptorUpdateTemplateCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDescriptorUpdateTemplate* pDescriptorUpdateTemplate);
+typedef void (VKAPI_PTR *PFN_vkDestroyDescriptorUpdateTemplateKHR)(VkDevice device, VkDescriptorUpdateTemplate descriptorUpdateTemplate, const VkAllocationCallbacks* pAllocator);
+typedef void (VKAPI_PTR *PFN_vkUpdateDescriptorSetWithTemplateKHR)(VkDevice device, VkDescriptorSet descriptorSet, VkDescriptorUpdateTemplate descriptorUpdateTemplate, const void* pData);
#ifndef VK_NO_PROTOTYPES
VKAPI_ATTR VkResult VKAPI_CALL vkCreateDescriptorUpdateTemplateKHR(
VkDevice device,
- const VkDescriptorUpdateTemplateCreateInfoKHR* pCreateInfo,
+ const VkDescriptorUpdateTemplateCreateInfo* pCreateInfo,
const VkAllocationCallbacks* pAllocator,
- VkDescriptorUpdateTemplateKHR* pDescriptorUpdateTemplate);
+ VkDescriptorUpdateTemplate* pDescriptorUpdateTemplate);
VKAPI_ATTR void VKAPI_CALL vkDestroyDescriptorUpdateTemplateKHR(
VkDevice device,
- VkDescriptorUpdateTemplateKHR descriptorUpdateTemplate,
+ VkDescriptorUpdateTemplate descriptorUpdateTemplate,
const VkAllocationCallbacks* pAllocator);
VKAPI_ATTR void VKAPI_CALL vkUpdateDescriptorSetWithTemplateKHR(
VkDevice device,
VkDescriptorSet descriptorSet,
- VkDescriptorUpdateTemplateKHR descriptorUpdateTemplate,
- const void* pData);
-
-VKAPI_ATTR void VKAPI_CALL vkCmdPushDescriptorSetWithTemplateKHR(
- VkCommandBuffer commandBuffer,
- VkDescriptorUpdateTemplateKHR descriptorUpdateTemplate,
- VkPipelineLayout layout,
- uint32_t set,
+ VkDescriptorUpdateTemplate descriptorUpdateTemplate,
const void* pData);
#endif
@@ -4703,67 +5569,42 @@
#endif
#define VK_KHR_external_fence_capabilities 1
+typedef VkExternalFenceFeatureFlagBits VkExternalFenceFeatureFlagBitsKHR;
+typedef VkExternalFenceFeatureFlags VkExternalFenceFeatureFlagsKHR;
+typedef VkExternalFenceHandleTypeFlagBits VkExternalFenceHandleTypeFlagBitsKHR;
+typedef VkExternalFenceHandleTypeFlags VkExternalFenceHandleTypeFlagsKHR;
+typedef VkExternalFenceProperties VkExternalFencePropertiesKHR;
+typedef VkPhysicalDeviceExternalFenceInfo VkPhysicalDeviceExternalFenceInfoKHR;
+
#define VK_KHR_EXTERNAL_FENCE_CAPABILITIES_SPEC_VERSION 1
#define VK_KHR_EXTERNAL_FENCE_CAPABILITIES_EXTENSION_NAME "VK_KHR_external_fence_capabilities"
+#define VK_EXTERNAL_FENCE_FEATURE_EXPORTABLE_BIT_KHR VK_EXTERNAL_FENCE_FEATURE_EXPORTABLE_BIT
+#define VK_EXTERNAL_FENCE_FEATURE_IMPORTABLE_BIT_KHR VK_EXTERNAL_FENCE_FEATURE_IMPORTABLE_BIT
+#define VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_FD_BIT_KHR VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_FD_BIT
+#define VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_BIT_KHR VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_BIT
+#define VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT_KHR VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT
+#define VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT_KHR VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT
+#define VK_STRUCTURE_TYPE_EXTERNAL_FENCE_PROPERTIES_KHR VK_STRUCTURE_TYPE_EXTERNAL_FENCE_PROPERTIES
+#define VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_FENCE_INFO_KHR VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_FENCE_INFO
-
-typedef enum VkExternalFenceHandleTypeFlagBitsKHR {
- VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_FD_BIT_KHR = 0x00000001,
- VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_BIT_KHR = 0x00000002,
- VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT_KHR = 0x00000004,
- VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT_KHR = 0x00000008,
- VK_EXTERNAL_FENCE_HANDLE_TYPE_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF
-} VkExternalFenceHandleTypeFlagBitsKHR;
-typedef VkFlags VkExternalFenceHandleTypeFlagsKHR;
-
-typedef enum VkExternalFenceFeatureFlagBitsKHR {
- VK_EXTERNAL_FENCE_FEATURE_EXPORTABLE_BIT_KHR = 0x00000001,
- VK_EXTERNAL_FENCE_FEATURE_IMPORTABLE_BIT_KHR = 0x00000002,
- VK_EXTERNAL_FENCE_FEATURE_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF
-} VkExternalFenceFeatureFlagBitsKHR;
-typedef VkFlags VkExternalFenceFeatureFlagsKHR;
-
-typedef struct VkPhysicalDeviceExternalFenceInfoKHR {
- VkStructureType sType;
- const void* pNext;
- VkExternalFenceHandleTypeFlagBitsKHR handleType;
-} VkPhysicalDeviceExternalFenceInfoKHR;
-
-typedef struct VkExternalFencePropertiesKHR {
- VkStructureType sType;
- void* pNext;
- VkExternalFenceHandleTypeFlagsKHR exportFromImportedHandleTypes;
- VkExternalFenceHandleTypeFlagsKHR compatibleHandleTypes;
- VkExternalFenceFeatureFlagsKHR externalFenceFeatures;
-} VkExternalFencePropertiesKHR;
-
-
-typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceExternalFencePropertiesKHR)(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceExternalFenceInfoKHR* pExternalFenceInfo, VkExternalFencePropertiesKHR* pExternalFenceProperties);
+typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceExternalFencePropertiesKHR)(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceExternalFenceInfo* pExternalFenceInfo, VkExternalFenceProperties* pExternalFenceProperties);
#ifndef VK_NO_PROTOTYPES
VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceExternalFencePropertiesKHR(
VkPhysicalDevice physicalDevice,
- const VkPhysicalDeviceExternalFenceInfoKHR* pExternalFenceInfo,
- VkExternalFencePropertiesKHR* pExternalFenceProperties);
+ const VkPhysicalDeviceExternalFenceInfo* pExternalFenceInfo,
+ VkExternalFenceProperties* pExternalFenceProperties);
#endif
#define VK_KHR_external_fence 1
+typedef VkExportFenceCreateInfo VkExportFenceCreateInfoKHR;
+typedef VkFenceImportFlagBits VkFenceImportFlagBitsKHR;
+typedef VkFenceImportFlags VkFenceImportFlagsKHR;
+
#define VK_KHR_EXTERNAL_FENCE_SPEC_VERSION 1
#define VK_KHR_EXTERNAL_FENCE_EXTENSION_NAME "VK_KHR_external_fence"
-
-
-typedef enum VkFenceImportFlagBitsKHR {
- VK_FENCE_IMPORT_TEMPORARY_BIT_KHR = 0x00000001,
- VK_FENCE_IMPORT_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF
-} VkFenceImportFlagBitsKHR;
-typedef VkFlags VkFenceImportFlagsKHR;
-
-typedef struct VkExportFenceCreateInfoKHR {
- VkStructureType sType;
- const void* pNext;
- VkExternalFenceHandleTypeFlagsKHR handleTypes;
-} VkExportFenceCreateInfoKHR;
-
+#define VK_FENCE_IMPORT_TEMPORARY_BIT_KHR VK_FENCE_IMPORT_TEMPORARY_BIT
+#define VK_STRUCTURE_TYPE_EXPORT_FENCE_CREATE_INFO_KHR VK_STRUCTURE_TYPE_EXPORT_FENCE_CREATE_INFO
#ifdef VK_USE_PLATFORM_WIN32_KHR
@@ -4772,13 +5613,13 @@
#define VK_KHR_EXTERNAL_FENCE_WIN32_EXTENSION_NAME "VK_KHR_external_fence_win32"
typedef struct VkImportFenceWin32HandleInfoKHR {
- VkStructureType sType;
- const void* pNext;
- VkFence fence;
- VkFenceImportFlagsKHR flags;
- VkExternalFenceHandleTypeFlagBitsKHR handleType;
- HANDLE handle;
- LPCWSTR name;
+ VkStructureType sType;
+ const void* pNext;
+ VkFence fence;
+ VkFenceImportFlags flags;
+ VkExternalFenceHandleTypeFlagBits handleType;
+ HANDLE handle;
+ LPCWSTR name;
} VkImportFenceWin32HandleInfoKHR;
typedef struct VkExportFenceWin32HandleInfoKHR {
@@ -4790,10 +5631,10 @@
} VkExportFenceWin32HandleInfoKHR;
typedef struct VkFenceGetWin32HandleInfoKHR {
- VkStructureType sType;
- const void* pNext;
- VkFence fence;
- VkExternalFenceHandleTypeFlagBitsKHR handleType;
+ VkStructureType sType;
+ const void* pNext;
+ VkFence fence;
+ VkExternalFenceHandleTypeFlagBits handleType;
} VkFenceGetWin32HandleInfoKHR;
@@ -4817,19 +5658,19 @@
#define VK_KHR_EXTERNAL_FENCE_FD_EXTENSION_NAME "VK_KHR_external_fence_fd"
typedef struct VkImportFenceFdInfoKHR {
- VkStructureType sType;
- const void* pNext;
- VkFence fence;
- VkFenceImportFlagsKHR flags;
- VkExternalFenceHandleTypeFlagBitsKHR handleType;
- int fd;
+ VkStructureType sType;
+ const void* pNext;
+ VkFence fence;
+ VkFenceImportFlags flags;
+ VkExternalFenceHandleTypeFlagBits handleType;
+ int fd;
} VkImportFenceFdInfoKHR;
typedef struct VkFenceGetFdInfoKHR {
- VkStructureType sType;
- const void* pNext;
- VkFence fence;
- VkExternalFenceHandleTypeFlagBitsKHR handleType;
+ VkStructureType sType;
+ const void* pNext;
+ VkFence fence;
+ VkExternalFenceHandleTypeFlagBits handleType;
} VkFenceGetFdInfoKHR;
@@ -4848,59 +5689,28 @@
#endif
#define VK_KHR_maintenance2 1
+typedef VkImageViewUsageCreateInfo VkImageViewUsageCreateInfoKHR;
+typedef VkInputAttachmentAspectReference VkInputAttachmentAspectReferenceKHR;
+typedef VkPhysicalDevicePointClippingProperties VkPhysicalDevicePointClippingPropertiesKHR;
+typedef VkPipelineTessellationDomainOriginStateCreateInfo VkPipelineTessellationDomainOriginStateCreateInfoKHR;
+typedef VkPointClippingBehavior VkPointClippingBehaviorKHR;
+typedef VkRenderPassInputAttachmentAspectCreateInfo VkRenderPassInputAttachmentAspectCreateInfoKHR;
+typedef VkTessellationDomainOrigin VkTessellationDomainOriginKHR;
+
#define VK_KHR_MAINTENANCE2_SPEC_VERSION 1
#define VK_KHR_MAINTENANCE2_EXTENSION_NAME "VK_KHR_maintenance2"
-
-
-typedef enum VkPointClippingBehaviorKHR {
- VK_POINT_CLIPPING_BEHAVIOR_ALL_CLIP_PLANES_KHR = 0,
- VK_POINT_CLIPPING_BEHAVIOR_USER_CLIP_PLANES_ONLY_KHR = 1,
- VK_POINT_CLIPPING_BEHAVIOR_BEGIN_RANGE_KHR = VK_POINT_CLIPPING_BEHAVIOR_ALL_CLIP_PLANES_KHR,
- VK_POINT_CLIPPING_BEHAVIOR_END_RANGE_KHR = VK_POINT_CLIPPING_BEHAVIOR_USER_CLIP_PLANES_ONLY_KHR,
- VK_POINT_CLIPPING_BEHAVIOR_RANGE_SIZE_KHR = (VK_POINT_CLIPPING_BEHAVIOR_USER_CLIP_PLANES_ONLY_KHR - VK_POINT_CLIPPING_BEHAVIOR_ALL_CLIP_PLANES_KHR + 1),
- VK_POINT_CLIPPING_BEHAVIOR_MAX_ENUM_KHR = 0x7FFFFFFF
-} VkPointClippingBehaviorKHR;
-
-typedef enum VkTessellationDomainOriginKHR {
- VK_TESSELLATION_DOMAIN_ORIGIN_UPPER_LEFT_KHR = 0,
- VK_TESSELLATION_DOMAIN_ORIGIN_LOWER_LEFT_KHR = 1,
- VK_TESSELLATION_DOMAIN_ORIGIN_BEGIN_RANGE_KHR = VK_TESSELLATION_DOMAIN_ORIGIN_UPPER_LEFT_KHR,
- VK_TESSELLATION_DOMAIN_ORIGIN_END_RANGE_KHR = VK_TESSELLATION_DOMAIN_ORIGIN_LOWER_LEFT_KHR,
- VK_TESSELLATION_DOMAIN_ORIGIN_RANGE_SIZE_KHR = (VK_TESSELLATION_DOMAIN_ORIGIN_LOWER_LEFT_KHR - VK_TESSELLATION_DOMAIN_ORIGIN_UPPER_LEFT_KHR + 1),
- VK_TESSELLATION_DOMAIN_ORIGIN_MAX_ENUM_KHR = 0x7FFFFFFF
-} VkTessellationDomainOriginKHR;
-
-typedef struct VkPhysicalDevicePointClippingPropertiesKHR {
- VkStructureType sType;
- void* pNext;
- VkPointClippingBehaviorKHR pointClippingBehavior;
-} VkPhysicalDevicePointClippingPropertiesKHR;
-
-typedef struct VkInputAttachmentAspectReferenceKHR {
- uint32_t subpass;
- uint32_t inputAttachmentIndex;
- VkImageAspectFlags aspectMask;
-} VkInputAttachmentAspectReferenceKHR;
-
-typedef struct VkRenderPassInputAttachmentAspectCreateInfoKHR {
- VkStructureType sType;
- const void* pNext;
- uint32_t aspectReferenceCount;
- const VkInputAttachmentAspectReferenceKHR* pAspectReferences;
-} VkRenderPassInputAttachmentAspectCreateInfoKHR;
-
-typedef struct VkImageViewUsageCreateInfoKHR {
- VkStructureType sType;
- const void* pNext;
- VkImageUsageFlags usage;
-} VkImageViewUsageCreateInfoKHR;
-
-typedef struct VkPipelineTessellationDomainOriginStateCreateInfoKHR {
- VkStructureType sType;
- const void* pNext;
- VkTessellationDomainOriginKHR domainOrigin;
-} VkPipelineTessellationDomainOriginStateCreateInfoKHR;
-
+#define VK_IMAGE_CREATE_BLOCK_TEXEL_VIEW_COMPATIBLE_BIT_KHR VK_IMAGE_CREATE_BLOCK_TEXEL_VIEW_COMPATIBLE_BIT
+#define VK_IMAGE_CREATE_EXTENDED_USAGE_BIT_KHR VK_IMAGE_CREATE_EXTENDED_USAGE_BIT
+#define VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL_KHR VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL
+#define VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL_KHR VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL
+#define VK_POINT_CLIPPING_BEHAVIOR_ALL_CLIP_PLANES_KHR VK_POINT_CLIPPING_BEHAVIOR_ALL_CLIP_PLANES
+#define VK_POINT_CLIPPING_BEHAVIOR_USER_CLIP_PLANES_ONLY_KHR VK_POINT_CLIPPING_BEHAVIOR_USER_CLIP_PLANES_ONLY
+#define VK_STRUCTURE_TYPE_IMAGE_VIEW_USAGE_CREATE_INFO_KHR VK_STRUCTURE_TYPE_IMAGE_VIEW_USAGE_CREATE_INFO
+#define VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_POINT_CLIPPING_PROPERTIES_KHR VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_POINT_CLIPPING_PROPERTIES
+#define VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_DOMAIN_ORIGIN_STATE_CREATE_INFO_KHR VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_DOMAIN_ORIGIN_STATE_CREATE_INFO
+#define VK_STRUCTURE_TYPE_RENDER_PASS_INPUT_ATTACHMENT_ASPECT_CREATE_INFO_KHR VK_STRUCTURE_TYPE_RENDER_PASS_INPUT_ATTACHMENT_ASPECT_CREATE_INFO
+#define VK_TESSELLATION_DOMAIN_ORIGIN_LOWER_LEFT_KHR VK_TESSELLATION_DOMAIN_ORIGIN_LOWER_LEFT
+#define VK_TESSELLATION_DOMAIN_ORIGIN_UPPER_LEFT_KHR VK_TESSELLATION_DOMAIN_ORIGIN_UPPER_LEFT
#define VK_KHR_get_surface_capabilities2 1
@@ -4943,36 +5753,21 @@
#endif
#define VK_KHR_variable_pointers 1
+typedef VkPhysicalDeviceVariablePointerFeatures VkPhysicalDeviceVariablePointerFeaturesKHR;
+
#define VK_KHR_VARIABLE_POINTERS_SPEC_VERSION 1
#define VK_KHR_VARIABLE_POINTERS_EXTENSION_NAME "VK_KHR_variable_pointers"
-
-typedef struct VkPhysicalDeviceVariablePointerFeaturesKHR {
- VkStructureType sType;
- void* pNext;
- VkBool32 variablePointersStorageBuffer;
- VkBool32 variablePointers;
-} VkPhysicalDeviceVariablePointerFeaturesKHR;
-
+#define VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VARIABLE_POINTER_FEATURES_KHR VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VARIABLE_POINTER_FEATURES
#define VK_KHR_dedicated_allocation 1
+typedef VkMemoryDedicatedAllocateInfo VkMemoryDedicatedAllocateInfoKHR;
+typedef VkMemoryDedicatedRequirements VkMemoryDedicatedRequirementsKHR;
+
#define VK_KHR_DEDICATED_ALLOCATION_SPEC_VERSION 3
#define VK_KHR_DEDICATED_ALLOCATION_EXTENSION_NAME "VK_KHR_dedicated_allocation"
-
-typedef struct VkMemoryDedicatedRequirementsKHR {
- VkStructureType sType;
- void* pNext;
- VkBool32 prefersDedicatedAllocation;
- VkBool32 requiresDedicatedAllocation;
-} VkMemoryDedicatedRequirementsKHR;
-
-typedef struct VkMemoryDedicatedAllocateInfoKHR {
- VkStructureType sType;
- const void* pNext;
- VkImage image;
- VkBuffer buffer;
-} VkMemoryDedicatedAllocateInfoKHR;
-
+#define VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO_KHR VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO
+#define VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS_KHR VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS
#define VK_KHR_storage_buffer_storage_class 1
@@ -4986,60 +5781,40 @@
#define VK_KHR_get_memory_requirements2 1
+typedef VkBufferMemoryRequirementsInfo2 VkBufferMemoryRequirementsInfo2KHR;
+typedef VkImageMemoryRequirementsInfo2 VkImageMemoryRequirementsInfo2KHR;
+typedef VkImageSparseMemoryRequirementsInfo2 VkImageSparseMemoryRequirementsInfo2KHR;
+typedef VkMemoryRequirements2 VkMemoryRequirements2KHR;
+typedef VkSparseImageMemoryRequirements2 VkSparseImageMemoryRequirements2KHR;
+
#define VK_KHR_GET_MEMORY_REQUIREMENTS_2_SPEC_VERSION 1
#define VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME "VK_KHR_get_memory_requirements2"
+#define VK_STRUCTURE_TYPE_BUFFER_MEMORY_REQUIREMENTS_INFO_2_KHR VK_STRUCTURE_TYPE_BUFFER_MEMORY_REQUIREMENTS_INFO_2
+#define VK_STRUCTURE_TYPE_IMAGE_MEMORY_REQUIREMENTS_INFO_2_KHR VK_STRUCTURE_TYPE_IMAGE_MEMORY_REQUIREMENTS_INFO_2
+#define VK_STRUCTURE_TYPE_IMAGE_SPARSE_MEMORY_REQUIREMENTS_INFO_2_KHR VK_STRUCTURE_TYPE_IMAGE_SPARSE_MEMORY_REQUIREMENTS_INFO_2
+#define VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2_KHR VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2
+#define VK_STRUCTURE_TYPE_SPARSE_IMAGE_MEMORY_REQUIREMENTS_2_KHR VK_STRUCTURE_TYPE_SPARSE_IMAGE_MEMORY_REQUIREMENTS_2
-typedef struct VkBufferMemoryRequirementsInfo2KHR {
- VkStructureType sType;
- const void* pNext;
- VkBuffer buffer;
-} VkBufferMemoryRequirementsInfo2KHR;
-
-typedef struct VkImageMemoryRequirementsInfo2KHR {
- VkStructureType sType;
- const void* pNext;
- VkImage image;
-} VkImageMemoryRequirementsInfo2KHR;
-
-typedef struct VkImageSparseMemoryRequirementsInfo2KHR {
- VkStructureType sType;
- const void* pNext;
- VkImage image;
-} VkImageSparseMemoryRequirementsInfo2KHR;
-
-typedef struct VkMemoryRequirements2KHR {
- VkStructureType sType;
- void* pNext;
- VkMemoryRequirements memoryRequirements;
-} VkMemoryRequirements2KHR;
-
-typedef struct VkSparseImageMemoryRequirements2KHR {
- VkStructureType sType;
- void* pNext;
- VkSparseImageMemoryRequirements memoryRequirements;
-} VkSparseImageMemoryRequirements2KHR;
-
-
-typedef void (VKAPI_PTR *PFN_vkGetImageMemoryRequirements2KHR)(VkDevice device, const VkImageMemoryRequirementsInfo2KHR* pInfo, VkMemoryRequirements2KHR* pMemoryRequirements);
-typedef void (VKAPI_PTR *PFN_vkGetBufferMemoryRequirements2KHR)(VkDevice device, const VkBufferMemoryRequirementsInfo2KHR* pInfo, VkMemoryRequirements2KHR* pMemoryRequirements);
-typedef void (VKAPI_PTR *PFN_vkGetImageSparseMemoryRequirements2KHR)(VkDevice device, const VkImageSparseMemoryRequirementsInfo2KHR* pInfo, uint32_t* pSparseMemoryRequirementCount, VkSparseImageMemoryRequirements2KHR* pSparseMemoryRequirements);
+typedef void (VKAPI_PTR *PFN_vkGetBufferMemoryRequirements2KHR)(VkDevice device, const VkBufferMemoryRequirementsInfo2* pInfo, VkMemoryRequirements2* pMemoryRequirements);
+typedef void (VKAPI_PTR *PFN_vkGetImageMemoryRequirements2KHR)(VkDevice device, const VkImageMemoryRequirementsInfo2* pInfo, VkMemoryRequirements2* pMemoryRequirements);
+typedef void (VKAPI_PTR *PFN_vkGetImageSparseMemoryRequirements2KHR)(VkDevice device, const VkImageSparseMemoryRequirementsInfo2* pInfo, uint32_t* pSparseMemoryRequirementCount, VkSparseImageMemoryRequirements2* pSparseMemoryRequirements);
#ifndef VK_NO_PROTOTYPES
-VKAPI_ATTR void VKAPI_CALL vkGetImageMemoryRequirements2KHR(
- VkDevice device,
- const VkImageMemoryRequirementsInfo2KHR* pInfo,
- VkMemoryRequirements2KHR* pMemoryRequirements);
-
VKAPI_ATTR void VKAPI_CALL vkGetBufferMemoryRequirements2KHR(
VkDevice device,
- const VkBufferMemoryRequirementsInfo2KHR* pInfo,
- VkMemoryRequirements2KHR* pMemoryRequirements);
+ const VkBufferMemoryRequirementsInfo2* pInfo,
+ VkMemoryRequirements2* pMemoryRequirements);
+
+VKAPI_ATTR void VKAPI_CALL vkGetImageMemoryRequirements2KHR(
+ VkDevice device,
+ const VkImageMemoryRequirementsInfo2* pInfo,
+ VkMemoryRequirements2* pMemoryRequirements);
VKAPI_ATTR void VKAPI_CALL vkGetImageSparseMemoryRequirements2KHR(
VkDevice device,
- const VkImageSparseMemoryRequirementsInfo2KHR* pInfo,
+ const VkImageSparseMemoryRequirementsInfo2* pInfo,
uint32_t* pSparseMemoryRequirementCount,
- VkSparseImageMemoryRequirements2KHR* pSparseMemoryRequirements);
+ VkSparseImageMemoryRequirements2* pSparseMemoryRequirements);
#endif
#define VK_KHR_image_format_list 1
@@ -5056,142 +5831,145 @@
#define VK_KHR_sampler_ycbcr_conversion 1
-VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkSamplerYcbcrConversionKHR)
+typedef VkBindImagePlaneMemoryInfo VkBindImagePlaneMemoryInfoKHR;
+typedef VkChromaLocation VkChromaLocationKHR;
+typedef VkImagePlaneMemoryRequirementsInfo VkImagePlaneMemoryRequirementsInfoKHR;
+typedef VkPhysicalDeviceSamplerYcbcrConversionFeatures VkPhysicalDeviceSamplerYcbcrConversionFeaturesKHR;
+typedef VkSamplerYcbcrConversionCreateInfo VkSamplerYcbcrConversionCreateInfoKHR;
+typedef VkSamplerYcbcrConversionImageFormatProperties VkSamplerYcbcrConversionImageFormatPropertiesKHR;
+typedef VkSamplerYcbcrConversionInfo VkSamplerYcbcrConversionInfoKHR;
+typedef VkSamplerYcbcrConversion VkSamplerYcbcrConversionKHR;
+typedef VkSamplerYcbcrModelConversion VkSamplerYcbcrModelConversionKHR;
+typedef VkSamplerYcbcrRange VkSamplerYcbcrRangeKHR;
#define VK_KHR_SAMPLER_YCBCR_CONVERSION_SPEC_VERSION 1
#define VK_KHR_SAMPLER_YCBCR_CONVERSION_EXTENSION_NAME "VK_KHR_sampler_ycbcr_conversion"
+#define VK_CHROMA_LOCATION_COSITED_EVEN_KHR VK_CHROMA_LOCATION_COSITED_EVEN
+#define VK_CHROMA_LOCATION_MIDPOINT_KHR VK_CHROMA_LOCATION_MIDPOINT
+#define VK_DEBUG_REPORT_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION_KHR_EXT VK_DEBUG_REPORT_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION_EXT
+#define VK_FORMAT_B10X6G10X6R10X6G10X6_422_UNORM_4PACK16_KHR VK_FORMAT_B10X6G10X6R10X6G10X6_422_UNORM_4PACK16
+#define VK_FORMAT_B12X4G12X4R12X4G12X4_422_UNORM_4PACK16_KHR VK_FORMAT_B12X4G12X4R12X4G12X4_422_UNORM_4PACK16
+#define VK_FORMAT_B16G16R16G16_422_UNORM_KHR VK_FORMAT_B16G16R16G16_422_UNORM
+#define VK_FORMAT_B8G8R8G8_422_UNORM_KHR VK_FORMAT_B8G8R8G8_422_UNORM
+#define VK_FORMAT_FEATURE_COSITED_CHROMA_SAMPLES_BIT_KHR VK_FORMAT_FEATURE_COSITED_CHROMA_SAMPLES_BIT
+#define VK_FORMAT_FEATURE_DISJOINT_BIT_KHR VK_FORMAT_FEATURE_DISJOINT_BIT
+#define VK_FORMAT_FEATURE_MIDPOINT_CHROMA_SAMPLES_BIT_KHR VK_FORMAT_FEATURE_MIDPOINT_CHROMA_SAMPLES_BIT
+#define VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_BIT_KHR VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_BIT
+#define VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_FORCEABLE_BIT_KHR VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_FORCEABLE_BIT
+#define VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_LINEAR_FILTER_BIT_KHR VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_LINEAR_FILTER_BIT
+#define VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_SEPARATE_RECONSTRUCTION_FILTER_BIT_KHR VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_SEPARATE_RECONSTRUCTION_FILTER_BIT
+#define VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_420_UNORM_3PACK16_KHR VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_420_UNORM_3PACK16
+#define VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_422_UNORM_3PACK16_KHR VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_422_UNORM_3PACK16
+#define VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_444_UNORM_3PACK16_KHR VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_444_UNORM_3PACK16
+#define VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16_KHR VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16
+#define VK_FORMAT_G10X6_B10X6R10X6_2PLANE_422_UNORM_3PACK16_KHR VK_FORMAT_G10X6_B10X6R10X6_2PLANE_422_UNORM_3PACK16
+#define VK_FORMAT_G10X6B10X6G10X6R10X6_422_UNORM_4PACK16_KHR VK_FORMAT_G10X6B10X6G10X6R10X6_422_UNORM_4PACK16
+#define VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_420_UNORM_3PACK16_KHR VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_420_UNORM_3PACK16
+#define VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_422_UNORM_3PACK16_KHR VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_422_UNORM_3PACK16
+#define VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_444_UNORM_3PACK16_KHR VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_444_UNORM_3PACK16
+#define VK_FORMAT_G12X4_B12X4R12X4_2PLANE_420_UNORM_3PACK16_KHR VK_FORMAT_G12X4_B12X4R12X4_2PLANE_420_UNORM_3PACK16
+#define VK_FORMAT_G12X4_B12X4R12X4_2PLANE_422_UNORM_3PACK16_KHR VK_FORMAT_G12X4_B12X4R12X4_2PLANE_422_UNORM_3PACK16
+#define VK_FORMAT_G12X4B12X4G12X4R12X4_422_UNORM_4PACK16_KHR VK_FORMAT_G12X4B12X4G12X4R12X4_422_UNORM_4PACK16
+#define VK_FORMAT_G16_B16_R16_3PLANE_420_UNORM_KHR VK_FORMAT_G16_B16_R16_3PLANE_420_UNORM
+#define VK_FORMAT_G16_B16_R16_3PLANE_422_UNORM_KHR VK_FORMAT_G16_B16_R16_3PLANE_422_UNORM
+#define VK_FORMAT_G16_B16_R16_3PLANE_444_UNORM_KHR VK_FORMAT_G16_B16_R16_3PLANE_444_UNORM
+#define VK_FORMAT_G16_B16R16_2PLANE_420_UNORM_KHR VK_FORMAT_G16_B16R16_2PLANE_420_UNORM
+#define VK_FORMAT_G16_B16R16_2PLANE_422_UNORM_KHR VK_FORMAT_G16_B16R16_2PLANE_422_UNORM
+#define VK_FORMAT_G16B16G16R16_422_UNORM_KHR VK_FORMAT_G16B16G16R16_422_UNORM
+#define VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM_KHR VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM
+#define VK_FORMAT_G8_B8_R8_3PLANE_422_UNORM_KHR VK_FORMAT_G8_B8_R8_3PLANE_422_UNORM
+#define VK_FORMAT_G8_B8_R8_3PLANE_444_UNORM_KHR VK_FORMAT_G8_B8_R8_3PLANE_444_UNORM
+#define VK_FORMAT_G8_B8R8_2PLANE_420_UNORM_KHR VK_FORMAT_G8_B8R8_2PLANE_420_UNORM
+#define VK_FORMAT_G8_B8R8_2PLANE_422_UNORM_KHR VK_FORMAT_G8_B8R8_2PLANE_422_UNORM
+#define VK_FORMAT_G8B8G8R8_422_UNORM_KHR VK_FORMAT_G8B8G8R8_422_UNORM
+#define VK_FORMAT_R10X6_UNORM_PACK16_KHR VK_FORMAT_R10X6_UNORM_PACK16
+#define VK_FORMAT_R10X6G10X6_UNORM_2PACK16_KHR VK_FORMAT_R10X6G10X6_UNORM_2PACK16
+#define VK_FORMAT_R10X6G10X6B10X6A10X6_UNORM_4PACK16_KHR VK_FORMAT_R10X6G10X6B10X6A10X6_UNORM_4PACK16
+#define VK_FORMAT_R12X4_UNORM_PACK16_KHR VK_FORMAT_R12X4_UNORM_PACK16
+#define VK_FORMAT_R12X4G12X4_UNORM_2PACK16_KHR VK_FORMAT_R12X4G12X4_UNORM_2PACK16
+#define VK_FORMAT_R12X4G12X4B12X4A12X4_UNORM_4PACK16_KHR VK_FORMAT_R12X4G12X4B12X4A12X4_UNORM_4PACK16
+#define VK_IMAGE_ASPECT_PLANE_0_BIT_KHR VK_IMAGE_ASPECT_PLANE_0_BIT
+#define VK_IMAGE_ASPECT_PLANE_1_BIT_KHR VK_IMAGE_ASPECT_PLANE_1_BIT
+#define VK_IMAGE_ASPECT_PLANE_2_BIT_KHR VK_IMAGE_ASPECT_PLANE_2_BIT
+#define VK_IMAGE_CREATE_DISJOINT_BIT_KHR VK_IMAGE_CREATE_DISJOINT_BIT
+#define VK_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION_KHR VK_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION
+#define VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY_KHR VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY
+#define VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_2020_KHR VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_2020
+#define VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_601_KHR VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_601
+#define VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_709_KHR VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_709
+#define VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_IDENTITY_KHR VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_IDENTITY
+#define VK_SAMPLER_YCBCR_RANGE_ITU_FULL_KHR VK_SAMPLER_YCBCR_RANGE_ITU_FULL
+#define VK_SAMPLER_YCBCR_RANGE_ITU_NARROW_KHR VK_SAMPLER_YCBCR_RANGE_ITU_NARROW
+#define VK_STRUCTURE_TYPE_BIND_IMAGE_PLANE_MEMORY_INFO_KHR VK_STRUCTURE_TYPE_BIND_IMAGE_PLANE_MEMORY_INFO
+#define VK_STRUCTURE_TYPE_IMAGE_PLANE_MEMORY_REQUIREMENTS_INFO_KHR VK_STRUCTURE_TYPE_IMAGE_PLANE_MEMORY_REQUIREMENTS_INFO
+#define VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_YCBCR_CONVERSION_FEATURES_KHR VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_YCBCR_CONVERSION_FEATURES
+#define VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_CREATE_INFO_KHR VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_CREATE_INFO
+#define VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_IMAGE_FORMAT_PROPERTIES_KHR VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_IMAGE_FORMAT_PROPERTIES
+#define VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_INFO_KHR VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_INFO
-
-typedef enum VkSamplerYcbcrModelConversionKHR {
- VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY_KHR = 0,
- VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_IDENTITY_KHR = 1,
- VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_709_KHR = 2,
- VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_601_KHR = 3,
- VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_2020_KHR = 4,
- VK_SAMPLER_YCBCR_MODEL_CONVERSION_BEGIN_RANGE_KHR = VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY_KHR,
- VK_SAMPLER_YCBCR_MODEL_CONVERSION_END_RANGE_KHR = VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_2020_KHR,
- VK_SAMPLER_YCBCR_MODEL_CONVERSION_RANGE_SIZE_KHR = (VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_2020_KHR - VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY_KHR + 1),
- VK_SAMPLER_YCBCR_MODEL_CONVERSION_MAX_ENUM_KHR = 0x7FFFFFFF
-} VkSamplerYcbcrModelConversionKHR;
-
-typedef enum VkSamplerYcbcrRangeKHR {
- VK_SAMPLER_YCBCR_RANGE_ITU_FULL_KHR = 0,
- VK_SAMPLER_YCBCR_RANGE_ITU_NARROW_KHR = 1,
- VK_SAMPLER_YCBCR_RANGE_BEGIN_RANGE_KHR = VK_SAMPLER_YCBCR_RANGE_ITU_FULL_KHR,
- VK_SAMPLER_YCBCR_RANGE_END_RANGE_KHR = VK_SAMPLER_YCBCR_RANGE_ITU_NARROW_KHR,
- VK_SAMPLER_YCBCR_RANGE_RANGE_SIZE_KHR = (VK_SAMPLER_YCBCR_RANGE_ITU_NARROW_KHR - VK_SAMPLER_YCBCR_RANGE_ITU_FULL_KHR + 1),
- VK_SAMPLER_YCBCR_RANGE_MAX_ENUM_KHR = 0x7FFFFFFF
-} VkSamplerYcbcrRangeKHR;
-
-typedef enum VkChromaLocationKHR {
- VK_CHROMA_LOCATION_COSITED_EVEN_KHR = 0,
- VK_CHROMA_LOCATION_MIDPOINT_KHR = 1,
- VK_CHROMA_LOCATION_BEGIN_RANGE_KHR = VK_CHROMA_LOCATION_COSITED_EVEN_KHR,
- VK_CHROMA_LOCATION_END_RANGE_KHR = VK_CHROMA_LOCATION_MIDPOINT_KHR,
- VK_CHROMA_LOCATION_RANGE_SIZE_KHR = (VK_CHROMA_LOCATION_MIDPOINT_KHR - VK_CHROMA_LOCATION_COSITED_EVEN_KHR + 1),
- VK_CHROMA_LOCATION_MAX_ENUM_KHR = 0x7FFFFFFF
-} VkChromaLocationKHR;
-
-typedef struct VkSamplerYcbcrConversionCreateInfoKHR {
- VkStructureType sType;
- const void* pNext;
- VkFormat format;
- VkSamplerYcbcrModelConversionKHR ycbcrModel;
- VkSamplerYcbcrRangeKHR ycbcrRange;
- VkComponentMapping components;
- VkChromaLocationKHR xChromaOffset;
- VkChromaLocationKHR yChromaOffset;
- VkFilter chromaFilter;
- VkBool32 forceExplicitReconstruction;
-} VkSamplerYcbcrConversionCreateInfoKHR;
-
-typedef struct VkSamplerYcbcrConversionInfoKHR {
- VkStructureType sType;
- const void* pNext;
- VkSamplerYcbcrConversionKHR conversion;
-} VkSamplerYcbcrConversionInfoKHR;
-
-typedef struct VkBindImagePlaneMemoryInfoKHR {
- VkStructureType sType;
- const void* pNext;
- VkImageAspectFlagBits planeAspect;
-} VkBindImagePlaneMemoryInfoKHR;
-
-typedef struct VkImagePlaneMemoryRequirementsInfoKHR {
- VkStructureType sType;
- const void* pNext;
- VkImageAspectFlagBits planeAspect;
-} VkImagePlaneMemoryRequirementsInfoKHR;
-
-typedef struct VkPhysicalDeviceSamplerYcbcrConversionFeaturesKHR {
- VkStructureType sType;
- void* pNext;
- VkBool32 samplerYcbcrConversion;
-} VkPhysicalDeviceSamplerYcbcrConversionFeaturesKHR;
-
-typedef struct VkSamplerYcbcrConversionImageFormatPropertiesKHR {
- VkStructureType sType;
- void* pNext;
- uint32_t combinedImageSamplerDescriptorCount;
-} VkSamplerYcbcrConversionImageFormatPropertiesKHR;
-
-
-typedef VkResult (VKAPI_PTR *PFN_vkCreateSamplerYcbcrConversionKHR)(VkDevice device, const VkSamplerYcbcrConversionCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSamplerYcbcrConversionKHR* pYcbcrConversion);
-typedef void (VKAPI_PTR *PFN_vkDestroySamplerYcbcrConversionKHR)(VkDevice device, VkSamplerYcbcrConversionKHR ycbcrConversion, const VkAllocationCallbacks* pAllocator);
+typedef VkResult (VKAPI_PTR *PFN_vkCreateSamplerYcbcrConversionKHR)(VkDevice device, const VkSamplerYcbcrConversionCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSamplerYcbcrConversion* pYcbcrConversion);
+typedef void (VKAPI_PTR *PFN_vkDestroySamplerYcbcrConversionKHR)(VkDevice device, VkSamplerYcbcrConversion ycbcrConversion, const VkAllocationCallbacks* pAllocator);
#ifndef VK_NO_PROTOTYPES
VKAPI_ATTR VkResult VKAPI_CALL vkCreateSamplerYcbcrConversionKHR(
VkDevice device,
- const VkSamplerYcbcrConversionCreateInfoKHR* pCreateInfo,
+ const VkSamplerYcbcrConversionCreateInfo* pCreateInfo,
const VkAllocationCallbacks* pAllocator,
- VkSamplerYcbcrConversionKHR* pYcbcrConversion);
+ VkSamplerYcbcrConversion* pYcbcrConversion);
VKAPI_ATTR void VKAPI_CALL vkDestroySamplerYcbcrConversionKHR(
VkDevice device,
- VkSamplerYcbcrConversionKHR ycbcrConversion,
+ VkSamplerYcbcrConversion ycbcrConversion,
const VkAllocationCallbacks* pAllocator);
#endif
#define VK_KHR_bind_memory2 1
+typedef VkBindBufferMemoryInfo VkBindBufferMemoryInfoKHR;
+typedef VkBindImageMemoryInfo VkBindImageMemoryInfoKHR;
+
#define VK_KHR_BIND_MEMORY_2_SPEC_VERSION 1
#define VK_KHR_BIND_MEMORY_2_EXTENSION_NAME "VK_KHR_bind_memory2"
+#define VK_IMAGE_CREATE_ALIAS_BIT_KHR VK_IMAGE_CREATE_ALIAS_BIT
+#define VK_STRUCTURE_TYPE_BIND_BUFFER_MEMORY_INFO_KHR VK_STRUCTURE_TYPE_BIND_BUFFER_MEMORY_INFO
+#define VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_INFO_KHR VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_INFO
-typedef struct VkBindBufferMemoryInfoKHR {
- VkStructureType sType;
- const void* pNext;
- VkBuffer buffer;
- VkDeviceMemory memory;
- VkDeviceSize memoryOffset;
-} VkBindBufferMemoryInfoKHR;
-
-typedef struct VkBindImageMemoryInfoKHR {
- VkStructureType sType;
- const void* pNext;
- VkImage image;
- VkDeviceMemory memory;
- VkDeviceSize memoryOffset;
-} VkBindImageMemoryInfoKHR;
-
-
-typedef VkResult (VKAPI_PTR *PFN_vkBindBufferMemory2KHR)(VkDevice device, uint32_t bindInfoCount, const VkBindBufferMemoryInfoKHR* pBindInfos);
-typedef VkResult (VKAPI_PTR *PFN_vkBindImageMemory2KHR)(VkDevice device, uint32_t bindInfoCount, const VkBindImageMemoryInfoKHR* pBindInfos);
+typedef VkResult (VKAPI_PTR *PFN_vkBindBufferMemory2KHR)(VkDevice device, uint32_t bindInfoCount, const VkBindBufferMemoryInfo* pBindInfos);
+typedef VkResult (VKAPI_PTR *PFN_vkBindImageMemory2KHR)(VkDevice device, uint32_t bindInfoCount, const VkBindImageMemoryInfo* pBindInfos);
#ifndef VK_NO_PROTOTYPES
VKAPI_ATTR VkResult VKAPI_CALL vkBindBufferMemory2KHR(
VkDevice device,
uint32_t bindInfoCount,
- const VkBindBufferMemoryInfoKHR* pBindInfos);
+ const VkBindBufferMemoryInfo* pBindInfos);
VKAPI_ATTR VkResult VKAPI_CALL vkBindImageMemory2KHR(
VkDevice device,
uint32_t bindInfoCount,
- const VkBindImageMemoryInfoKHR* pBindInfos);
+ const VkBindImageMemoryInfo* pBindInfos);
+#endif
+
+#define VK_KHR_maintenance3 1
+typedef VkDescriptorSetLayoutSupport VkDescriptorSetLayoutSupportKHR;
+typedef VkPhysicalDeviceMaintenance3Properties VkPhysicalDeviceMaintenance3PropertiesKHR;
+
+#define VK_KHR_MAINTENANCE3_SPEC_VERSION 1
+#define VK_KHR_MAINTENANCE3_EXTENSION_NAME "VK_KHR_maintenance3"
+#define VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_SUPPORT_KHR VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_SUPPORT
+#define VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_3_PROPERTIES_KHR VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_3_PROPERTIES
+
+typedef void (VKAPI_PTR *PFN_vkGetDescriptorSetLayoutSupportKHR)(VkDevice device, const VkDescriptorSetLayoutCreateInfo* pCreateInfo, VkDescriptorSetLayoutSupport* pSupport);
+
+#ifndef VK_NO_PROTOTYPES
+VKAPI_ATTR void VKAPI_CALL vkGetDescriptorSetLayoutSupportKHR(
+ VkDevice device,
+ const VkDescriptorSetLayoutCreateInfo* pCreateInfo,
+ VkDescriptorSetLayoutSupport* pSupport);
#endif
#define VK_EXT_debug_report 1
VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkDebugReportCallbackEXT)
-#define VK_EXT_DEBUG_REPORT_SPEC_VERSION 8
+#define VK_EXT_DEBUG_REPORT_SPEC_VERSION 9
#define VK_EXT_DEBUG_REPORT_EXTENSION_NAME "VK_EXT_debug_report"
#define VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT
#define VK_DEBUG_REPORT_OBJECT_TYPE_DEBUG_REPORT_EXT VK_DEBUG_REPORT_OBJECT_TYPE_DEBUG_REPORT_CALLBACK_EXT_EXT
@@ -5232,8 +6010,8 @@
VK_DEBUG_REPORT_OBJECT_TYPE_OBJECT_TABLE_NVX_EXT = 31,
VK_DEBUG_REPORT_OBJECT_TYPE_INDIRECT_COMMANDS_LAYOUT_NVX_EXT = 32,
VK_DEBUG_REPORT_OBJECT_TYPE_VALIDATION_CACHE_EXT = 33,
- VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_KHR_EXT = 1000085000,
- VK_DEBUG_REPORT_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION_KHR_EXT = 1000156000,
+ VK_DEBUG_REPORT_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION_EXT = 1000156000,
+ VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_EXT = 1000085000,
VK_DEBUG_REPORT_OBJECT_TYPE_BEGIN_RANGE_EXT = VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT,
VK_DEBUG_REPORT_OBJECT_TYPE_END_RANGE_EXT = VK_DEBUG_REPORT_OBJECT_TYPE_VALIDATION_CACHE_EXT,
VK_DEBUG_REPORT_OBJECT_TYPE_RANGE_SIZE_EXT = (VK_DEBUG_REPORT_OBJECT_TYPE_VALIDATION_CACHE_EXT - VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT + 1),
@@ -5486,38 +6264,6 @@
-#define VK_KHX_multiview 1
-#define VK_KHX_MULTIVIEW_SPEC_VERSION 1
-#define VK_KHX_MULTIVIEW_EXTENSION_NAME "VK_KHX_multiview"
-
-typedef struct VkRenderPassMultiviewCreateInfoKHX {
- VkStructureType sType;
- const void* pNext;
- uint32_t subpassCount;
- const uint32_t* pViewMasks;
- uint32_t dependencyCount;
- const int32_t* pViewOffsets;
- uint32_t correlationMaskCount;
- const uint32_t* pCorrelationMasks;
-} VkRenderPassMultiviewCreateInfoKHX;
-
-typedef struct VkPhysicalDeviceMultiviewFeaturesKHX {
- VkStructureType sType;
- void* pNext;
- VkBool32 multiview;
- VkBool32 multiviewGeometryShader;
- VkBool32 multiviewTessellationShader;
-} VkPhysicalDeviceMultiviewFeaturesKHX;
-
-typedef struct VkPhysicalDeviceMultiviewPropertiesKHX {
- VkStructureType sType;
- void* pNext;
- uint32_t maxMultiviewViewCount;
- uint32_t maxMultiviewInstanceIndex;
-} VkPhysicalDeviceMultiviewPropertiesKHX;
-
-
-
#define VK_IMG_format_pvrtc 1
#define VK_IMG_FORMAT_PVRTC_SPEC_VERSION 1
#define VK_IMG_FORMAT_PVRTC_EXTENSION_NAME "VK_IMG_format_pvrtc"
@@ -5636,186 +6382,6 @@
#endif /* VK_USE_PLATFORM_WIN32_KHR */
-#define VK_KHX_device_group 1
-#define VK_KHX_DEVICE_GROUP_SPEC_VERSION 2
-#define VK_KHX_DEVICE_GROUP_EXTENSION_NAME "VK_KHX_device_group"
-#define VK_MAX_DEVICE_GROUP_SIZE_KHX 32
-
-
-typedef enum VkPeerMemoryFeatureFlagBitsKHX {
- VK_PEER_MEMORY_FEATURE_COPY_SRC_BIT_KHX = 0x00000001,
- VK_PEER_MEMORY_FEATURE_COPY_DST_BIT_KHX = 0x00000002,
- VK_PEER_MEMORY_FEATURE_GENERIC_SRC_BIT_KHX = 0x00000004,
- VK_PEER_MEMORY_FEATURE_GENERIC_DST_BIT_KHX = 0x00000008,
- VK_PEER_MEMORY_FEATURE_FLAG_BITS_MAX_ENUM_KHX = 0x7FFFFFFF
-} VkPeerMemoryFeatureFlagBitsKHX;
-typedef VkFlags VkPeerMemoryFeatureFlagsKHX;
-
-typedef enum VkMemoryAllocateFlagBitsKHX {
- VK_MEMORY_ALLOCATE_DEVICE_MASK_BIT_KHX = 0x00000001,
- VK_MEMORY_ALLOCATE_FLAG_BITS_MAX_ENUM_KHX = 0x7FFFFFFF
-} VkMemoryAllocateFlagBitsKHX;
-typedef VkFlags VkMemoryAllocateFlagsKHX;
-
-typedef enum VkDeviceGroupPresentModeFlagBitsKHX {
- VK_DEVICE_GROUP_PRESENT_MODE_LOCAL_BIT_KHX = 0x00000001,
- VK_DEVICE_GROUP_PRESENT_MODE_REMOTE_BIT_KHX = 0x00000002,
- VK_DEVICE_GROUP_PRESENT_MODE_SUM_BIT_KHX = 0x00000004,
- VK_DEVICE_GROUP_PRESENT_MODE_LOCAL_MULTI_DEVICE_BIT_KHX = 0x00000008,
- VK_DEVICE_GROUP_PRESENT_MODE_FLAG_BITS_MAX_ENUM_KHX = 0x7FFFFFFF
-} VkDeviceGroupPresentModeFlagBitsKHX;
-typedef VkFlags VkDeviceGroupPresentModeFlagsKHX;
-
-typedef struct VkMemoryAllocateFlagsInfoKHX {
- VkStructureType sType;
- const void* pNext;
- VkMemoryAllocateFlagsKHX flags;
- uint32_t deviceMask;
-} VkMemoryAllocateFlagsInfoKHX;
-
-typedef struct VkDeviceGroupRenderPassBeginInfoKHX {
- VkStructureType sType;
- const void* pNext;
- uint32_t deviceMask;
- uint32_t deviceRenderAreaCount;
- const VkRect2D* pDeviceRenderAreas;
-} VkDeviceGroupRenderPassBeginInfoKHX;
-
-typedef struct VkDeviceGroupCommandBufferBeginInfoKHX {
- VkStructureType sType;
- const void* pNext;
- uint32_t deviceMask;
-} VkDeviceGroupCommandBufferBeginInfoKHX;
-
-typedef struct VkDeviceGroupSubmitInfoKHX {
- VkStructureType sType;
- const void* pNext;
- uint32_t waitSemaphoreCount;
- const uint32_t* pWaitSemaphoreDeviceIndices;
- uint32_t commandBufferCount;
- const uint32_t* pCommandBufferDeviceMasks;
- uint32_t signalSemaphoreCount;
- const uint32_t* pSignalSemaphoreDeviceIndices;
-} VkDeviceGroupSubmitInfoKHX;
-
-typedef struct VkDeviceGroupBindSparseInfoKHX {
- VkStructureType sType;
- const void* pNext;
- uint32_t resourceDeviceIndex;
- uint32_t memoryDeviceIndex;
-} VkDeviceGroupBindSparseInfoKHX;
-
-typedef struct VkBindBufferMemoryDeviceGroupInfoKHX {
- VkStructureType sType;
- const void* pNext;
- uint32_t deviceIndexCount;
- const uint32_t* pDeviceIndices;
-} VkBindBufferMemoryDeviceGroupInfoKHX;
-
-typedef struct VkBindImageMemoryDeviceGroupInfoKHX {
- VkStructureType sType;
- const void* pNext;
- uint32_t deviceIndexCount;
- const uint32_t* pDeviceIndices;
- uint32_t SFRRectCount;
- const VkRect2D* pSFRRects;
-} VkBindImageMemoryDeviceGroupInfoKHX;
-
-typedef struct VkDeviceGroupPresentCapabilitiesKHX {
- VkStructureType sType;
- const void* pNext;
- uint32_t presentMask[VK_MAX_DEVICE_GROUP_SIZE_KHX];
- VkDeviceGroupPresentModeFlagsKHX modes;
-} VkDeviceGroupPresentCapabilitiesKHX;
-
-typedef struct VkImageSwapchainCreateInfoKHX {
- VkStructureType sType;
- const void* pNext;
- VkSwapchainKHR swapchain;
-} VkImageSwapchainCreateInfoKHX;
-
-typedef struct VkBindImageMemorySwapchainInfoKHX {
- VkStructureType sType;
- const void* pNext;
- VkSwapchainKHR swapchain;
- uint32_t imageIndex;
-} VkBindImageMemorySwapchainInfoKHX;
-
-typedef struct VkAcquireNextImageInfoKHX {
- VkStructureType sType;
- const void* pNext;
- VkSwapchainKHR swapchain;
- uint64_t timeout;
- VkSemaphore semaphore;
- VkFence fence;
- uint32_t deviceMask;
-} VkAcquireNextImageInfoKHX;
-
-typedef struct VkDeviceGroupPresentInfoKHX {
- VkStructureType sType;
- const void* pNext;
- uint32_t swapchainCount;
- const uint32_t* pDeviceMasks;
- VkDeviceGroupPresentModeFlagBitsKHX mode;
-} VkDeviceGroupPresentInfoKHX;
-
-typedef struct VkDeviceGroupSwapchainCreateInfoKHX {
- VkStructureType sType;
- const void* pNext;
- VkDeviceGroupPresentModeFlagsKHX modes;
-} VkDeviceGroupSwapchainCreateInfoKHX;
-
-
-typedef void (VKAPI_PTR *PFN_vkGetDeviceGroupPeerMemoryFeaturesKHX)(VkDevice device, uint32_t heapIndex, uint32_t localDeviceIndex, uint32_t remoteDeviceIndex, VkPeerMemoryFeatureFlagsKHX* pPeerMemoryFeatures);
-typedef void (VKAPI_PTR *PFN_vkCmdSetDeviceMaskKHX)(VkCommandBuffer commandBuffer, uint32_t deviceMask);
-typedef void (VKAPI_PTR *PFN_vkCmdDispatchBaseKHX)(VkCommandBuffer commandBuffer, uint32_t baseGroupX, uint32_t baseGroupY, uint32_t baseGroupZ, uint32_t groupCountX, uint32_t groupCountY, uint32_t groupCountZ);
-typedef VkResult (VKAPI_PTR *PFN_vkGetDeviceGroupPresentCapabilitiesKHX)(VkDevice device, VkDeviceGroupPresentCapabilitiesKHX* pDeviceGroupPresentCapabilities);
-typedef VkResult (VKAPI_PTR *PFN_vkGetDeviceGroupSurfacePresentModesKHX)(VkDevice device, VkSurfaceKHR surface, VkDeviceGroupPresentModeFlagsKHX* pModes);
-typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDevicePresentRectanglesKHX)(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, uint32_t* pRectCount, VkRect2D* pRects);
-typedef VkResult (VKAPI_PTR *PFN_vkAcquireNextImage2KHX)(VkDevice device, const VkAcquireNextImageInfoKHX* pAcquireInfo, uint32_t* pImageIndex);
-
-#ifndef VK_NO_PROTOTYPES
-VKAPI_ATTR void VKAPI_CALL vkGetDeviceGroupPeerMemoryFeaturesKHX(
- VkDevice device,
- uint32_t heapIndex,
- uint32_t localDeviceIndex,
- uint32_t remoteDeviceIndex,
- VkPeerMemoryFeatureFlagsKHX* pPeerMemoryFeatures);
-
-VKAPI_ATTR void VKAPI_CALL vkCmdSetDeviceMaskKHX(
- VkCommandBuffer commandBuffer,
- uint32_t deviceMask);
-
-VKAPI_ATTR void VKAPI_CALL vkCmdDispatchBaseKHX(
- VkCommandBuffer commandBuffer,
- uint32_t baseGroupX,
- uint32_t baseGroupY,
- uint32_t baseGroupZ,
- uint32_t groupCountX,
- uint32_t groupCountY,
- uint32_t groupCountZ);
-
-VKAPI_ATTR VkResult VKAPI_CALL vkGetDeviceGroupPresentCapabilitiesKHX(
- VkDevice device,
- VkDeviceGroupPresentCapabilitiesKHX* pDeviceGroupPresentCapabilities);
-
-VKAPI_ATTR VkResult VKAPI_CALL vkGetDeviceGroupSurfacePresentModesKHX(
- VkDevice device,
- VkSurfaceKHR surface,
- VkDeviceGroupPresentModeFlagsKHX* pModes);
-
-VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDevicePresentRectanglesKHX(
- VkPhysicalDevice physicalDevice,
- VkSurfaceKHR surface,
- uint32_t* pRectCount,
- VkRect2D* pRects);
-
-VKAPI_ATTR VkResult VKAPI_CALL vkAcquireNextImage2KHX(
- VkDevice device,
- const VkAcquireNextImageInfoKHX* pAcquireInfo,
- uint32_t* pImageIndex);
-#endif
-
#define VK_EXT_validation_flags 1
#define VK_EXT_VALIDATION_FLAGS_SPEC_VERSION 1
#define VK_EXT_VALIDATION_FLAGS_EXTENSION_NAME "VK_EXT_validation_flags"
@@ -5875,35 +6441,6 @@
#define VK_EXT_SHADER_SUBGROUP_VOTE_EXTENSION_NAME "VK_EXT_shader_subgroup_vote"
-#define VK_KHX_device_group_creation 1
-#define VK_KHX_DEVICE_GROUP_CREATION_SPEC_VERSION 1
-#define VK_KHX_DEVICE_GROUP_CREATION_EXTENSION_NAME "VK_KHX_device_group_creation"
-
-typedef struct VkPhysicalDeviceGroupPropertiesKHX {
- VkStructureType sType;
- void* pNext;
- uint32_t physicalDeviceCount;
- VkPhysicalDevice physicalDevices[VK_MAX_DEVICE_GROUP_SIZE_KHX];
- VkBool32 subsetAllocation;
-} VkPhysicalDeviceGroupPropertiesKHX;
-
-typedef struct VkDeviceGroupDeviceCreateInfoKHX {
- VkStructureType sType;
- const void* pNext;
- uint32_t physicalDeviceCount;
- const VkPhysicalDevice* pPhysicalDevices;
-} VkDeviceGroupDeviceCreateInfoKHX;
-
-
-typedef VkResult (VKAPI_PTR *PFN_vkEnumeratePhysicalDeviceGroupsKHX)(VkInstance instance, uint32_t* pPhysicalDeviceGroupCount, VkPhysicalDeviceGroupPropertiesKHX* pPhysicalDeviceGroupProperties);
-
-#ifndef VK_NO_PROTOTYPES
-VKAPI_ATTR VkResult VKAPI_CALL vkEnumeratePhysicalDeviceGroupsKHX(
- VkInstance instance,
- uint32_t* pPhysicalDeviceGroupCount,
- VkPhysicalDeviceGroupPropertiesKHX* pPhysicalDeviceGroupProperties);
-#endif
-
#define VK_NVX_device_generated_commands 1
VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkObjectTableNVX)
VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkIndirectCommandsLayoutNVX)
diff --git a/vulkan/libvulkan/Android.bp b/vulkan/libvulkan/Android.bp
index 5f9b357..b55fa27 100644
--- a/vulkan/libvulkan/Android.bp
+++ b/vulkan/libvulkan/Android.bp
@@ -80,6 +80,7 @@
"libcutils",
"libz",
"libnativewindow",
+ "android.hardware.graphics.common@1.0",
],
static_libs: ["libgrallocusage"],
}
diff --git a/vulkan/libvulkan/api.cpp b/vulkan/libvulkan/api.cpp
index e05ca5a..d840786 100644
--- a/vulkan/libvulkan/api.cpp
+++ b/vulkan/libvulkan/api.cpp
@@ -1280,5 +1280,10 @@
physicalDevice, nullptr, pPropertyCount, pProperties);
}
+VkResult EnumerateInstanceVersion(uint32_t* pApiVersion) {
+ *pApiVersion = VK_API_VERSION_1_1;
+ return VK_SUCCESS;
+}
+
} // namespace api
} // namespace vulkan
diff --git a/vulkan/libvulkan/api.h b/vulkan/libvulkan/api.h
index ded7d17..416cba0 100644
--- a/vulkan/libvulkan/api.h
+++ b/vulkan/libvulkan/api.h
@@ -33,6 +33,7 @@
VKAPI_ATTR VkResult EnumerateInstanceExtensionProperties(const char* pLayerName, uint32_t* pPropertyCount, VkExtensionProperties* pProperties);
VKAPI_ATTR VkResult EnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t* pPropertyCount, VkLayerProperties* pProperties);
VKAPI_ATTR VkResult EnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice, const char* pLayerName, uint32_t* pPropertyCount, VkExtensionProperties* pProperties);
+VKAPI_ATTR VkResult EnumerateInstanceVersion(uint32_t* pApiVersion);
// clang-format on
inline InstanceData& GetData(VkInstance instance) {
diff --git a/vulkan/libvulkan/api_gen.cpp b/vulkan/libvulkan/api_gen.cpp
index 8dd55f4..2aa1d5a 100644
--- a/vulkan/libvulkan/api_gen.cpp
+++ b/vulkan/libvulkan/api_gen.cpp
@@ -103,6 +103,26 @@
return VK_SUCCESS;
}
+VKAPI_ATTR VkResult disabledGetDeviceGroupPresentCapabilitiesKHR(VkDevice device, VkDeviceGroupPresentCapabilitiesKHR*) {
+ driver::Logger(device).Err(device, "VK_KHR_swapchain not enabled. Exported vkGetDeviceGroupPresentCapabilitiesKHR not executed.");
+ return VK_SUCCESS;
+}
+
+VKAPI_ATTR VkResult disabledGetDeviceGroupSurfacePresentModesKHR(VkDevice device, VkSurfaceKHR, VkDeviceGroupPresentModeFlagsKHR*) {
+ driver::Logger(device).Err(device, "VK_KHR_swapchain not enabled. Exported vkGetDeviceGroupSurfacePresentModesKHR not executed.");
+ return VK_SUCCESS;
+}
+
+VKAPI_ATTR VkResult disabledGetPhysicalDevicePresentRectanglesKHR(VkPhysicalDevice physicalDevice, VkSurfaceKHR, uint32_t*, VkRect2D*) {
+ driver::Logger(physicalDevice).Err(physicalDevice, "VK_KHR_swapchain not enabled. Exported vkGetPhysicalDevicePresentRectanglesKHR not executed.");
+ return VK_SUCCESS;
+}
+
+VKAPI_ATTR VkResult disabledAcquireNextImage2KHR(VkDevice device, const VkAcquireNextImageInfoKHR*, uint32_t*) {
+ driver::Logger(device).Err(device, "VK_KHR_swapchain not enabled. Exported vkAcquireNextImage2KHR not executed.");
+ return VK_SUCCESS;
+}
+
VKAPI_ATTR VkResult disabledCreateAndroidSurfaceKHR(VkInstance instance, const VkAndroidSurfaceCreateInfoKHR*, const VkAllocationCallbacks*, VkSurfaceKHR*) {
driver::Logger(instance).Err(instance, "VK_KHR_android_surface not enabled. Exported vkCreateAndroidSurfaceKHR not executed.");
return VK_SUCCESS;
@@ -132,11 +152,23 @@
INIT_PROC(true, instance, CreateDevice);
INIT_PROC(true, instance, EnumerateDeviceExtensionProperties);
INIT_PROC(true, instance, GetPhysicalDeviceSparseImageFormatProperties);
+ INIT_PROC(false, instance, EnumeratePhysicalDeviceGroups);
+ INIT_PROC(false, instance, GetPhysicalDeviceFeatures2);
+ INIT_PROC(false, instance, GetPhysicalDeviceProperties2);
+ INIT_PROC(false, instance, GetPhysicalDeviceFormatProperties2);
+ INIT_PROC(false, instance, GetPhysicalDeviceImageFormatProperties2);
+ INIT_PROC(false, instance, GetPhysicalDeviceQueueFamilyProperties2);
+ INIT_PROC(false, instance, GetPhysicalDeviceMemoryProperties2);
+ INIT_PROC(false, instance, GetPhysicalDeviceSparseImageFormatProperties2);
+ INIT_PROC(false, instance, GetPhysicalDeviceExternalBufferProperties);
+ INIT_PROC(false, instance, GetPhysicalDeviceExternalFenceProperties);
+ INIT_PROC(false, instance, GetPhysicalDeviceExternalSemaphoreProperties);
INIT_PROC_EXT(KHR_surface, true, instance, DestroySurfaceKHR);
INIT_PROC_EXT(KHR_surface, true, instance, GetPhysicalDeviceSurfaceSupportKHR);
INIT_PROC_EXT(KHR_surface, true, instance, GetPhysicalDeviceSurfaceCapabilitiesKHR);
INIT_PROC_EXT(KHR_surface, true, instance, GetPhysicalDeviceSurfaceFormatsKHR);
INIT_PROC_EXT(KHR_surface, true, instance, GetPhysicalDeviceSurfacePresentModesKHR);
+ INIT_PROC_EXT(KHR_swapchain, false, instance, GetPhysicalDevicePresentRectanglesKHR);
INIT_PROC_EXT(KHR_android_surface, true, instance, CreateAndroidSurfaceKHR);
// clang-format on
@@ -272,11 +304,30 @@
INIT_PROC(true, dev, CmdNextSubpass);
INIT_PROC(true, dev, CmdEndRenderPass);
INIT_PROC(true, dev, CmdExecuteCommands);
+ INIT_PROC(false, dev, BindBufferMemory2);
+ INIT_PROC(false, dev, BindImageMemory2);
+ INIT_PROC(false, dev, GetDeviceGroupPeerMemoryFeatures);
+ INIT_PROC(false, dev, CmdSetDeviceMask);
+ INIT_PROC(false, dev, CmdDispatchBase);
+ INIT_PROC(false, dev, GetImageMemoryRequirements2);
+ INIT_PROC(false, dev, GetBufferMemoryRequirements2);
+ INIT_PROC(false, dev, GetImageSparseMemoryRequirements2);
+ INIT_PROC(false, dev, TrimCommandPool);
+ INIT_PROC(false, dev, GetDeviceQueue2);
+ INIT_PROC(false, dev, CreateSamplerYcbcrConversion);
+ INIT_PROC(false, dev, DestroySamplerYcbcrConversion);
+ INIT_PROC(false, dev, CreateDescriptorUpdateTemplate);
+ INIT_PROC(false, dev, DestroyDescriptorUpdateTemplate);
+ INIT_PROC(false, dev, UpdateDescriptorSetWithTemplate);
+ INIT_PROC(false, dev, GetDescriptorSetLayoutSupport);
INIT_PROC_EXT(KHR_swapchain, true, dev, CreateSwapchainKHR);
INIT_PROC_EXT(KHR_swapchain, true, dev, DestroySwapchainKHR);
INIT_PROC_EXT(KHR_swapchain, true, dev, GetSwapchainImagesKHR);
INIT_PROC_EXT(KHR_swapchain, true, dev, AcquireNextImageKHR);
INIT_PROC_EXT(KHR_swapchain, true, dev, QueuePresentKHR);
+ INIT_PROC_EXT(KHR_swapchain, false, dev, GetDeviceGroupPresentCapabilitiesKHR);
+ INIT_PROC_EXT(KHR_swapchain, false, dev, GetDeviceGroupSurfacePresentModesKHR);
+ INIT_PROC_EXT(KHR_swapchain, false, dev, AcquireNextImage2KHR);
// clang-format on
return success;
@@ -416,6 +467,33 @@
VKAPI_ATTR void CmdNextSubpass(VkCommandBuffer commandBuffer, VkSubpassContents contents);
VKAPI_ATTR void CmdEndRenderPass(VkCommandBuffer commandBuffer);
VKAPI_ATTR void CmdExecuteCommands(VkCommandBuffer commandBuffer, uint32_t commandBufferCount, const VkCommandBuffer* pCommandBuffers);
+VKAPI_ATTR VkResult BindBufferMemory2(VkDevice device, uint32_t bindInfoCount, const VkBindBufferMemoryInfo* pBindInfos);
+VKAPI_ATTR VkResult BindImageMemory2(VkDevice device, uint32_t bindInfoCount, const VkBindImageMemoryInfo* pBindInfos);
+VKAPI_ATTR void GetDeviceGroupPeerMemoryFeatures(VkDevice device, uint32_t heapIndex, uint32_t localDeviceIndex, uint32_t remoteDeviceIndex, VkPeerMemoryFeatureFlags* pPeerMemoryFeatures);
+VKAPI_ATTR void CmdSetDeviceMask(VkCommandBuffer commandBuffer, uint32_t deviceMask);
+VKAPI_ATTR void CmdDispatchBase(VkCommandBuffer commandBuffer, uint32_t baseGroupX, uint32_t baseGroupY, uint32_t baseGroupZ, uint32_t groupCountX, uint32_t groupCountY, uint32_t groupCountZ);
+VKAPI_ATTR VkResult EnumeratePhysicalDeviceGroups(VkInstance instance, uint32_t* pPhysicalDeviceGroupCount, VkPhysicalDeviceGroupProperties* pPhysicalDeviceGroupProperties);
+VKAPI_ATTR void GetImageMemoryRequirements2(VkDevice device, const VkImageMemoryRequirementsInfo2* pInfo, VkMemoryRequirements2* pMemoryRequirements);
+VKAPI_ATTR void GetBufferMemoryRequirements2(VkDevice device, const VkBufferMemoryRequirementsInfo2* pInfo, VkMemoryRequirements2* pMemoryRequirements);
+VKAPI_ATTR void GetImageSparseMemoryRequirements2(VkDevice device, const VkImageSparseMemoryRequirementsInfo2* pInfo, uint32_t* pSparseMemoryRequirementCount, VkSparseImageMemoryRequirements2* pSparseMemoryRequirements);
+VKAPI_ATTR void GetPhysicalDeviceFeatures2(VkPhysicalDevice physicalDevice, VkPhysicalDeviceFeatures2* pFeatures);
+VKAPI_ATTR void GetPhysicalDeviceProperties2(VkPhysicalDevice physicalDevice, VkPhysicalDeviceProperties2* pProperties);
+VKAPI_ATTR void GetPhysicalDeviceFormatProperties2(VkPhysicalDevice physicalDevice, VkFormat format, VkFormatProperties2* pFormatProperties);
+VKAPI_ATTR VkResult GetPhysicalDeviceImageFormatProperties2(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceImageFormatInfo2* pImageFormatInfo, VkImageFormatProperties2* pImageFormatProperties);
+VKAPI_ATTR void GetPhysicalDeviceQueueFamilyProperties2(VkPhysicalDevice physicalDevice, uint32_t* pQueueFamilyPropertyCount, VkQueueFamilyProperties2* pQueueFamilyProperties);
+VKAPI_ATTR void GetPhysicalDeviceMemoryProperties2(VkPhysicalDevice physicalDevice, VkPhysicalDeviceMemoryProperties2* pMemoryProperties);
+VKAPI_ATTR void GetPhysicalDeviceSparseImageFormatProperties2(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceSparseImageFormatInfo2* pFormatInfo, uint32_t* pPropertyCount, VkSparseImageFormatProperties2* pProperties);
+VKAPI_ATTR void TrimCommandPool(VkDevice device, VkCommandPool commandPool, VkCommandPoolTrimFlags flags);
+VKAPI_ATTR void GetDeviceQueue2(VkDevice device, const VkDeviceQueueInfo2* pQueueInfo, VkQueue* pQueue);
+VKAPI_ATTR VkResult CreateSamplerYcbcrConversion(VkDevice device, const VkSamplerYcbcrConversionCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSamplerYcbcrConversion* pYcbcrConversion);
+VKAPI_ATTR void DestroySamplerYcbcrConversion(VkDevice device, VkSamplerYcbcrConversion ycbcrConversion, const VkAllocationCallbacks* pAllocator);
+VKAPI_ATTR VkResult CreateDescriptorUpdateTemplate(VkDevice device, const VkDescriptorUpdateTemplateCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDescriptorUpdateTemplate* pDescriptorUpdateTemplate);
+VKAPI_ATTR void DestroyDescriptorUpdateTemplate(VkDevice device, VkDescriptorUpdateTemplate descriptorUpdateTemplate, const VkAllocationCallbacks* pAllocator);
+VKAPI_ATTR void UpdateDescriptorSetWithTemplate(VkDevice device, VkDescriptorSet descriptorSet, VkDescriptorUpdateTemplate descriptorUpdateTemplate, const void* pData);
+VKAPI_ATTR void GetPhysicalDeviceExternalBufferProperties(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceExternalBufferInfo* pExternalBufferInfo, VkExternalBufferProperties* pExternalBufferProperties);
+VKAPI_ATTR void GetPhysicalDeviceExternalFenceProperties(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceExternalFenceInfo* pExternalFenceInfo, VkExternalFenceProperties* pExternalFenceProperties);
+VKAPI_ATTR void GetPhysicalDeviceExternalSemaphoreProperties(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceExternalSemaphoreInfo* pExternalSemaphoreInfo, VkExternalSemaphoreProperties* pExternalSemaphoreProperties);
+VKAPI_ATTR void GetDescriptorSetLayoutSupport(VkDevice device, const VkDescriptorSetLayoutCreateInfo* pCreateInfo, VkDescriptorSetLayoutSupport* pSupport);
VKAPI_ATTR void DestroySurfaceKHR(VkInstance instance, VkSurfaceKHR surface, const VkAllocationCallbacks* pAllocator);
VKAPI_ATTR VkResult GetPhysicalDeviceSurfaceSupportKHR(VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex, VkSurfaceKHR surface, VkBool32* pSupported);
VKAPI_ATTR VkResult GetPhysicalDeviceSurfaceCapabilitiesKHR(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, VkSurfaceCapabilitiesKHR* pSurfaceCapabilities);
@@ -426,6 +504,10 @@
VKAPI_ATTR VkResult GetSwapchainImagesKHR(VkDevice device, VkSwapchainKHR swapchain, uint32_t* pSwapchainImageCount, VkImage* pSwapchainImages);
VKAPI_ATTR VkResult AcquireNextImageKHR(VkDevice device, VkSwapchainKHR swapchain, uint64_t timeout, VkSemaphore semaphore, VkFence fence, uint32_t* pImageIndex);
VKAPI_ATTR VkResult QueuePresentKHR(VkQueue queue, const VkPresentInfoKHR* pPresentInfo);
+VKAPI_ATTR VkResult GetDeviceGroupPresentCapabilitiesKHR(VkDevice device, VkDeviceGroupPresentCapabilitiesKHR* pDeviceGroupPresentCapabilities);
+VKAPI_ATTR VkResult GetDeviceGroupSurfacePresentModesKHR(VkDevice device, VkSurfaceKHR surface, VkDeviceGroupPresentModeFlagsKHR* pModes);
+VKAPI_ATTR VkResult GetPhysicalDevicePresentRectanglesKHR(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, uint32_t* pRectCount, VkRect2D* pRects);
+VKAPI_ATTR VkResult AcquireNextImage2KHR(VkDevice device, const VkAcquireNextImageInfoKHR* pAcquireInfo, uint32_t* pImageIndex);
VKAPI_ATTR VkResult CreateAndroidSurfaceKHR(VkInstance instance, const VkAndroidSurfaceCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface);
VKAPI_ATTR VkResult EnumeratePhysicalDevices(VkInstance instance, uint32_t* pPhysicalDeviceCount, VkPhysicalDevice* pPhysicalDevices) {
@@ -451,29 +533,41 @@
"vkEnumerateDeviceLayerProperties",
"vkEnumerateInstanceExtensionProperties",
"vkEnumerateInstanceLayerProperties",
- "vkEnumeratePhysicalDeviceGroupsKHX",
+ "vkEnumerateInstanceVersion",
+ "vkEnumeratePhysicalDeviceGroups",
+ "vkEnumeratePhysicalDeviceGroupsKHR",
"vkEnumeratePhysicalDevices",
"vkGetInstanceProcAddr",
+ "vkGetPhysicalDeviceExternalBufferProperties",
"vkGetPhysicalDeviceExternalBufferPropertiesKHR",
+ "vkGetPhysicalDeviceExternalFenceProperties",
"vkGetPhysicalDeviceExternalFencePropertiesKHR",
"vkGetPhysicalDeviceExternalImageFormatPropertiesNV",
+ "vkGetPhysicalDeviceExternalSemaphoreProperties",
"vkGetPhysicalDeviceExternalSemaphorePropertiesKHR",
"vkGetPhysicalDeviceFeatures",
+ "vkGetPhysicalDeviceFeatures2",
"vkGetPhysicalDeviceFeatures2KHR",
"vkGetPhysicalDeviceFormatProperties",
+ "vkGetPhysicalDeviceFormatProperties2",
"vkGetPhysicalDeviceFormatProperties2KHR",
"vkGetPhysicalDeviceGeneratedCommandsPropertiesNVX",
"vkGetPhysicalDeviceImageFormatProperties",
+ "vkGetPhysicalDeviceImageFormatProperties2",
"vkGetPhysicalDeviceImageFormatProperties2KHR",
"vkGetPhysicalDeviceMemoryProperties",
+ "vkGetPhysicalDeviceMemoryProperties2",
"vkGetPhysicalDeviceMemoryProperties2KHR",
"vkGetPhysicalDeviceMultisamplePropertiesEXT",
- "vkGetPhysicalDevicePresentRectanglesKHX",
+ "vkGetPhysicalDevicePresentRectanglesKHR",
"vkGetPhysicalDeviceProperties",
+ "vkGetPhysicalDeviceProperties2",
"vkGetPhysicalDeviceProperties2KHR",
"vkGetPhysicalDeviceQueueFamilyProperties",
+ "vkGetPhysicalDeviceQueueFamilyProperties2",
"vkGetPhysicalDeviceQueueFamilyProperties2KHR",
"vkGetPhysicalDeviceSparseImageFormatProperties",
+ "vkGetPhysicalDeviceSparseImageFormatProperties2",
"vkGetPhysicalDeviceSparseImageFormatProperties2KHR",
"vkGetPhysicalDeviceSurfaceCapabilities2KHR",
"vkGetPhysicalDeviceSurfaceCapabilitiesKHR",
@@ -508,6 +602,7 @@
if (strcmp(pName, "vkCreateInstance") == 0) return reinterpret_cast<PFN_vkVoidFunction>(CreateInstance);
if (strcmp(pName, "vkEnumerateInstanceLayerProperties") == 0) return reinterpret_cast<PFN_vkVoidFunction>(EnumerateInstanceLayerProperties);
if (strcmp(pName, "vkEnumerateInstanceExtensionProperties") == 0) return reinterpret_cast<PFN_vkVoidFunction>(EnumerateInstanceExtensionProperties);
+ if (strcmp(pName, "vkEnumerateInstanceVersion") == 0) return reinterpret_cast<PFN_vkVoidFunction>(EnumerateInstanceVersion);
ALOGE("invalid vkGetInstanceProcAddr(VK_NULL_HANDLE, \"%s\") call", pName);
return nullptr;
@@ -517,13 +612,16 @@
const char* name;
PFN_vkVoidFunction proc;
} hooks[] = {
+ { "vkAcquireNextImage2KHR", reinterpret_cast<PFN_vkVoidFunction>(AcquireNextImage2KHR) },
{ "vkAcquireNextImageKHR", reinterpret_cast<PFN_vkVoidFunction>(AcquireNextImageKHR) },
{ "vkAllocateCommandBuffers", reinterpret_cast<PFN_vkVoidFunction>(AllocateCommandBuffers) },
{ "vkAllocateDescriptorSets", reinterpret_cast<PFN_vkVoidFunction>(AllocateDescriptorSets) },
{ "vkAllocateMemory", reinterpret_cast<PFN_vkVoidFunction>(AllocateMemory) },
{ "vkBeginCommandBuffer", reinterpret_cast<PFN_vkVoidFunction>(BeginCommandBuffer) },
{ "vkBindBufferMemory", reinterpret_cast<PFN_vkVoidFunction>(BindBufferMemory) },
+ { "vkBindBufferMemory2", reinterpret_cast<PFN_vkVoidFunction>(BindBufferMemory2) },
{ "vkBindImageMemory", reinterpret_cast<PFN_vkVoidFunction>(BindImageMemory) },
+ { "vkBindImageMemory2", reinterpret_cast<PFN_vkVoidFunction>(BindImageMemory2) },
{ "vkCmdBeginQuery", reinterpret_cast<PFN_vkVoidFunction>(CmdBeginQuery) },
{ "vkCmdBeginRenderPass", reinterpret_cast<PFN_vkVoidFunction>(CmdBeginRenderPass) },
{ "vkCmdBindDescriptorSets", reinterpret_cast<PFN_vkVoidFunction>(CmdBindDescriptorSets) },
@@ -540,6 +638,7 @@
{ "vkCmdCopyImageToBuffer", reinterpret_cast<PFN_vkVoidFunction>(CmdCopyImageToBuffer) },
{ "vkCmdCopyQueryPoolResults", reinterpret_cast<PFN_vkVoidFunction>(CmdCopyQueryPoolResults) },
{ "vkCmdDispatch", reinterpret_cast<PFN_vkVoidFunction>(CmdDispatch) },
+ { "vkCmdDispatchBase", reinterpret_cast<PFN_vkVoidFunction>(CmdDispatchBase) },
{ "vkCmdDispatchIndirect", reinterpret_cast<PFN_vkVoidFunction>(CmdDispatchIndirect) },
{ "vkCmdDraw", reinterpret_cast<PFN_vkVoidFunction>(CmdDraw) },
{ "vkCmdDrawIndexed", reinterpret_cast<PFN_vkVoidFunction>(CmdDrawIndexed) },
@@ -558,6 +657,7 @@
{ "vkCmdSetBlendConstants", reinterpret_cast<PFN_vkVoidFunction>(CmdSetBlendConstants) },
{ "vkCmdSetDepthBias", reinterpret_cast<PFN_vkVoidFunction>(CmdSetDepthBias) },
{ "vkCmdSetDepthBounds", reinterpret_cast<PFN_vkVoidFunction>(CmdSetDepthBounds) },
+ { "vkCmdSetDeviceMask", reinterpret_cast<PFN_vkVoidFunction>(CmdSetDeviceMask) },
{ "vkCmdSetEvent", reinterpret_cast<PFN_vkVoidFunction>(CmdSetEvent) },
{ "vkCmdSetLineWidth", reinterpret_cast<PFN_vkVoidFunction>(CmdSetLineWidth) },
{ "vkCmdSetScissor", reinterpret_cast<PFN_vkVoidFunction>(CmdSetScissor) },
@@ -574,6 +674,7 @@
{ "vkCreateComputePipelines", reinterpret_cast<PFN_vkVoidFunction>(CreateComputePipelines) },
{ "vkCreateDescriptorPool", reinterpret_cast<PFN_vkVoidFunction>(CreateDescriptorPool) },
{ "vkCreateDescriptorSetLayout", reinterpret_cast<PFN_vkVoidFunction>(CreateDescriptorSetLayout) },
+ { "vkCreateDescriptorUpdateTemplate", reinterpret_cast<PFN_vkVoidFunction>(CreateDescriptorUpdateTemplate) },
{ "vkCreateDevice", reinterpret_cast<PFN_vkVoidFunction>(CreateDevice) },
{ "vkCreateEvent", reinterpret_cast<PFN_vkVoidFunction>(CreateEvent) },
{ "vkCreateFence", reinterpret_cast<PFN_vkVoidFunction>(CreateFence) },
@@ -587,6 +688,7 @@
{ "vkCreateQueryPool", reinterpret_cast<PFN_vkVoidFunction>(CreateQueryPool) },
{ "vkCreateRenderPass", reinterpret_cast<PFN_vkVoidFunction>(CreateRenderPass) },
{ "vkCreateSampler", reinterpret_cast<PFN_vkVoidFunction>(CreateSampler) },
+ { "vkCreateSamplerYcbcrConversion", reinterpret_cast<PFN_vkVoidFunction>(CreateSamplerYcbcrConversion) },
{ "vkCreateSemaphore", reinterpret_cast<PFN_vkVoidFunction>(CreateSemaphore) },
{ "vkCreateShaderModule", reinterpret_cast<PFN_vkVoidFunction>(CreateShaderModule) },
{ "vkCreateSwapchainKHR", reinterpret_cast<PFN_vkVoidFunction>(CreateSwapchainKHR) },
@@ -595,6 +697,7 @@
{ "vkDestroyCommandPool", reinterpret_cast<PFN_vkVoidFunction>(DestroyCommandPool) },
{ "vkDestroyDescriptorPool", reinterpret_cast<PFN_vkVoidFunction>(DestroyDescriptorPool) },
{ "vkDestroyDescriptorSetLayout", reinterpret_cast<PFN_vkVoidFunction>(DestroyDescriptorSetLayout) },
+ { "vkDestroyDescriptorUpdateTemplate", reinterpret_cast<PFN_vkVoidFunction>(DestroyDescriptorUpdateTemplate) },
{ "vkDestroyDevice", reinterpret_cast<PFN_vkVoidFunction>(DestroyDevice) },
{ "vkDestroyEvent", reinterpret_cast<PFN_vkVoidFunction>(DestroyEvent) },
{ "vkDestroyFence", reinterpret_cast<PFN_vkVoidFunction>(DestroyFence) },
@@ -608,6 +711,7 @@
{ "vkDestroyQueryPool", reinterpret_cast<PFN_vkVoidFunction>(DestroyQueryPool) },
{ "vkDestroyRenderPass", reinterpret_cast<PFN_vkVoidFunction>(DestroyRenderPass) },
{ "vkDestroySampler", reinterpret_cast<PFN_vkVoidFunction>(DestroySampler) },
+ { "vkDestroySamplerYcbcrConversion", reinterpret_cast<PFN_vkVoidFunction>(DestroySamplerYcbcrConversion) },
{ "vkDestroySemaphore", reinterpret_cast<PFN_vkVoidFunction>(DestroySemaphore) },
{ "vkDestroyShaderModule", reinterpret_cast<PFN_vkVoidFunction>(DestroyShaderModule) },
{ "vkDestroySwapchainKHR", reinterpret_cast<PFN_vkVoidFunction>(DestroySwapchainKHR) },
@@ -617,18 +721,27 @@
{ "vkEnumerateDeviceLayerProperties", reinterpret_cast<PFN_vkVoidFunction>(EnumerateDeviceLayerProperties) },
{ "vkEnumerateInstanceExtensionProperties", nullptr },
{ "vkEnumerateInstanceLayerProperties", nullptr },
+ { "vkEnumerateInstanceVersion", nullptr },
{ "vkFlushMappedMemoryRanges", reinterpret_cast<PFN_vkVoidFunction>(FlushMappedMemoryRanges) },
{ "vkFreeCommandBuffers", reinterpret_cast<PFN_vkVoidFunction>(FreeCommandBuffers) },
{ "vkFreeDescriptorSets", reinterpret_cast<PFN_vkVoidFunction>(FreeDescriptorSets) },
{ "vkFreeMemory", reinterpret_cast<PFN_vkVoidFunction>(FreeMemory) },
{ "vkGetBufferMemoryRequirements", reinterpret_cast<PFN_vkVoidFunction>(GetBufferMemoryRequirements) },
+ { "vkGetBufferMemoryRequirements2", reinterpret_cast<PFN_vkVoidFunction>(GetBufferMemoryRequirements2) },
+ { "vkGetDescriptorSetLayoutSupport", reinterpret_cast<PFN_vkVoidFunction>(GetDescriptorSetLayoutSupport) },
+ { "vkGetDeviceGroupPeerMemoryFeatures", reinterpret_cast<PFN_vkVoidFunction>(GetDeviceGroupPeerMemoryFeatures) },
+ { "vkGetDeviceGroupPresentCapabilitiesKHR", reinterpret_cast<PFN_vkVoidFunction>(GetDeviceGroupPresentCapabilitiesKHR) },
+ { "vkGetDeviceGroupSurfacePresentModesKHR", reinterpret_cast<PFN_vkVoidFunction>(GetDeviceGroupSurfacePresentModesKHR) },
{ "vkGetDeviceMemoryCommitment", reinterpret_cast<PFN_vkVoidFunction>(GetDeviceMemoryCommitment) },
{ "vkGetDeviceProcAddr", reinterpret_cast<PFN_vkVoidFunction>(GetDeviceProcAddr) },
{ "vkGetDeviceQueue", reinterpret_cast<PFN_vkVoidFunction>(GetDeviceQueue) },
+ { "vkGetDeviceQueue2", reinterpret_cast<PFN_vkVoidFunction>(GetDeviceQueue2) },
{ "vkGetEventStatus", reinterpret_cast<PFN_vkVoidFunction>(GetEventStatus) },
{ "vkGetFenceStatus", reinterpret_cast<PFN_vkVoidFunction>(GetFenceStatus) },
{ "vkGetImageMemoryRequirements", reinterpret_cast<PFN_vkVoidFunction>(GetImageMemoryRequirements) },
+ { "vkGetImageMemoryRequirements2", reinterpret_cast<PFN_vkVoidFunction>(GetImageMemoryRequirements2) },
{ "vkGetImageSparseMemoryRequirements", reinterpret_cast<PFN_vkVoidFunction>(GetImageSparseMemoryRequirements) },
+ { "vkGetImageSparseMemoryRequirements2", reinterpret_cast<PFN_vkVoidFunction>(GetImageSparseMemoryRequirements2) },
{ "vkGetImageSubresourceLayout", reinterpret_cast<PFN_vkVoidFunction>(GetImageSubresourceLayout) },
{ "vkGetInstanceProcAddr", reinterpret_cast<PFN_vkVoidFunction>(GetInstanceProcAddr) },
{ "vkGetPipelineCacheData", reinterpret_cast<PFN_vkVoidFunction>(GetPipelineCacheData) },
@@ -648,7 +761,9 @@
{ "vkResetEvent", reinterpret_cast<PFN_vkVoidFunction>(ResetEvent) },
{ "vkResetFences", reinterpret_cast<PFN_vkVoidFunction>(ResetFences) },
{ "vkSetEvent", reinterpret_cast<PFN_vkVoidFunction>(SetEvent) },
+ { "vkTrimCommandPool", reinterpret_cast<PFN_vkVoidFunction>(TrimCommandPool) },
{ "vkUnmapMemory", reinterpret_cast<PFN_vkVoidFunction>(UnmapMemory) },
+ { "vkUpdateDescriptorSetWithTemplate", reinterpret_cast<PFN_vkVoidFunction>(UpdateDescriptorSetWithTemplate) },
{ "vkUpdateDescriptorSets", reinterpret_cast<PFN_vkVoidFunction>(UpdateDescriptorSets) },
{ "vkWaitForFences", reinterpret_cast<PFN_vkVoidFunction>(WaitForFences) },
};
@@ -1174,6 +1289,114 @@
GetData(commandBuffer).dispatch.CmdExecuteCommands(commandBuffer, commandBufferCount, pCommandBuffers);
}
+VKAPI_ATTR VkResult BindBufferMemory2(VkDevice device, uint32_t bindInfoCount, const VkBindBufferMemoryInfo* pBindInfos) {
+ return GetData(device).dispatch.BindBufferMemory2(device, bindInfoCount, pBindInfos);
+}
+
+VKAPI_ATTR VkResult BindImageMemory2(VkDevice device, uint32_t bindInfoCount, const VkBindImageMemoryInfo* pBindInfos) {
+ return GetData(device).dispatch.BindImageMemory2(device, bindInfoCount, pBindInfos);
+}
+
+VKAPI_ATTR void GetDeviceGroupPeerMemoryFeatures(VkDevice device, uint32_t heapIndex, uint32_t localDeviceIndex, uint32_t remoteDeviceIndex, VkPeerMemoryFeatureFlags* pPeerMemoryFeatures) {
+ GetData(device).dispatch.GetDeviceGroupPeerMemoryFeatures(device, heapIndex, localDeviceIndex, remoteDeviceIndex, pPeerMemoryFeatures);
+}
+
+VKAPI_ATTR void CmdSetDeviceMask(VkCommandBuffer commandBuffer, uint32_t deviceMask) {
+ GetData(commandBuffer).dispatch.CmdSetDeviceMask(commandBuffer, deviceMask);
+}
+
+VKAPI_ATTR void CmdDispatchBase(VkCommandBuffer commandBuffer, uint32_t baseGroupX, uint32_t baseGroupY, uint32_t baseGroupZ, uint32_t groupCountX, uint32_t groupCountY, uint32_t groupCountZ) {
+ GetData(commandBuffer).dispatch.CmdDispatchBase(commandBuffer, baseGroupX, baseGroupY, baseGroupZ, groupCountX, groupCountY, groupCountZ);
+}
+
+VKAPI_ATTR VkResult EnumeratePhysicalDeviceGroups(VkInstance instance, uint32_t* pPhysicalDeviceGroupCount, VkPhysicalDeviceGroupProperties* pPhysicalDeviceGroupProperties) {
+ return GetData(instance).dispatch.EnumeratePhysicalDeviceGroups(instance, pPhysicalDeviceGroupCount, pPhysicalDeviceGroupProperties);
+}
+
+VKAPI_ATTR void GetImageMemoryRequirements2(VkDevice device, const VkImageMemoryRequirementsInfo2* pInfo, VkMemoryRequirements2* pMemoryRequirements) {
+ GetData(device).dispatch.GetImageMemoryRequirements2(device, pInfo, pMemoryRequirements);
+}
+
+VKAPI_ATTR void GetBufferMemoryRequirements2(VkDevice device, const VkBufferMemoryRequirementsInfo2* pInfo, VkMemoryRequirements2* pMemoryRequirements) {
+ GetData(device).dispatch.GetBufferMemoryRequirements2(device, pInfo, pMemoryRequirements);
+}
+
+VKAPI_ATTR void GetImageSparseMemoryRequirements2(VkDevice device, const VkImageSparseMemoryRequirementsInfo2* pInfo, uint32_t* pSparseMemoryRequirementCount, VkSparseImageMemoryRequirements2* pSparseMemoryRequirements) {
+ GetData(device).dispatch.GetImageSparseMemoryRequirements2(device, pInfo, pSparseMemoryRequirementCount, pSparseMemoryRequirements);
+}
+
+VKAPI_ATTR void GetPhysicalDeviceFeatures2(VkPhysicalDevice physicalDevice, VkPhysicalDeviceFeatures2* pFeatures) {
+ GetData(physicalDevice).dispatch.GetPhysicalDeviceFeatures2(physicalDevice, pFeatures);
+}
+
+VKAPI_ATTR void GetPhysicalDeviceProperties2(VkPhysicalDevice physicalDevice, VkPhysicalDeviceProperties2* pProperties) {
+ GetData(physicalDevice).dispatch.GetPhysicalDeviceProperties2(physicalDevice, pProperties);
+}
+
+VKAPI_ATTR void GetPhysicalDeviceFormatProperties2(VkPhysicalDevice physicalDevice, VkFormat format, VkFormatProperties2* pFormatProperties) {
+ GetData(physicalDevice).dispatch.GetPhysicalDeviceFormatProperties2(physicalDevice, format, pFormatProperties);
+}
+
+VKAPI_ATTR VkResult GetPhysicalDeviceImageFormatProperties2(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceImageFormatInfo2* pImageFormatInfo, VkImageFormatProperties2* pImageFormatProperties) {
+ return GetData(physicalDevice).dispatch.GetPhysicalDeviceImageFormatProperties2(physicalDevice, pImageFormatInfo, pImageFormatProperties);
+}
+
+VKAPI_ATTR void GetPhysicalDeviceQueueFamilyProperties2(VkPhysicalDevice physicalDevice, uint32_t* pQueueFamilyPropertyCount, VkQueueFamilyProperties2* pQueueFamilyProperties) {
+ GetData(physicalDevice).dispatch.GetPhysicalDeviceQueueFamilyProperties2(physicalDevice, pQueueFamilyPropertyCount, pQueueFamilyProperties);
+}
+
+VKAPI_ATTR void GetPhysicalDeviceMemoryProperties2(VkPhysicalDevice physicalDevice, VkPhysicalDeviceMemoryProperties2* pMemoryProperties) {
+ GetData(physicalDevice).dispatch.GetPhysicalDeviceMemoryProperties2(physicalDevice, pMemoryProperties);
+}
+
+VKAPI_ATTR void GetPhysicalDeviceSparseImageFormatProperties2(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceSparseImageFormatInfo2* pFormatInfo, uint32_t* pPropertyCount, VkSparseImageFormatProperties2* pProperties) {
+ GetData(physicalDevice).dispatch.GetPhysicalDeviceSparseImageFormatProperties2(physicalDevice, pFormatInfo, pPropertyCount, pProperties);
+}
+
+VKAPI_ATTR void TrimCommandPool(VkDevice device, VkCommandPool commandPool, VkCommandPoolTrimFlags flags) {
+ GetData(device).dispatch.TrimCommandPool(device, commandPool, flags);
+}
+
+VKAPI_ATTR void GetDeviceQueue2(VkDevice device, const VkDeviceQueueInfo2* pQueueInfo, VkQueue* pQueue) {
+ GetData(device).dispatch.GetDeviceQueue2(device, pQueueInfo, pQueue);
+}
+
+VKAPI_ATTR VkResult CreateSamplerYcbcrConversion(VkDevice device, const VkSamplerYcbcrConversionCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSamplerYcbcrConversion* pYcbcrConversion) {
+ return GetData(device).dispatch.CreateSamplerYcbcrConversion(device, pCreateInfo, pAllocator, pYcbcrConversion);
+}
+
+VKAPI_ATTR void DestroySamplerYcbcrConversion(VkDevice device, VkSamplerYcbcrConversion ycbcrConversion, const VkAllocationCallbacks* pAllocator) {
+ GetData(device).dispatch.DestroySamplerYcbcrConversion(device, ycbcrConversion, pAllocator);
+}
+
+VKAPI_ATTR VkResult CreateDescriptorUpdateTemplate(VkDevice device, const VkDescriptorUpdateTemplateCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDescriptorUpdateTemplate* pDescriptorUpdateTemplate) {
+ return GetData(device).dispatch.CreateDescriptorUpdateTemplate(device, pCreateInfo, pAllocator, pDescriptorUpdateTemplate);
+}
+
+VKAPI_ATTR void DestroyDescriptorUpdateTemplate(VkDevice device, VkDescriptorUpdateTemplate descriptorUpdateTemplate, const VkAllocationCallbacks* pAllocator) {
+ GetData(device).dispatch.DestroyDescriptorUpdateTemplate(device, descriptorUpdateTemplate, pAllocator);
+}
+
+VKAPI_ATTR void UpdateDescriptorSetWithTemplate(VkDevice device, VkDescriptorSet descriptorSet, VkDescriptorUpdateTemplate descriptorUpdateTemplate, const void* pData) {
+ GetData(device).dispatch.UpdateDescriptorSetWithTemplate(device, descriptorSet, descriptorUpdateTemplate, pData);
+}
+
+VKAPI_ATTR void GetPhysicalDeviceExternalBufferProperties(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceExternalBufferInfo* pExternalBufferInfo, VkExternalBufferProperties* pExternalBufferProperties) {
+ GetData(physicalDevice).dispatch.GetPhysicalDeviceExternalBufferProperties(physicalDevice, pExternalBufferInfo, pExternalBufferProperties);
+}
+
+VKAPI_ATTR void GetPhysicalDeviceExternalFenceProperties(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceExternalFenceInfo* pExternalFenceInfo, VkExternalFenceProperties* pExternalFenceProperties) {
+ GetData(physicalDevice).dispatch.GetPhysicalDeviceExternalFenceProperties(physicalDevice, pExternalFenceInfo, pExternalFenceProperties);
+}
+
+VKAPI_ATTR void GetPhysicalDeviceExternalSemaphoreProperties(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceExternalSemaphoreInfo* pExternalSemaphoreInfo, VkExternalSemaphoreProperties* pExternalSemaphoreProperties) {
+ GetData(physicalDevice).dispatch.GetPhysicalDeviceExternalSemaphoreProperties(physicalDevice, pExternalSemaphoreInfo, pExternalSemaphoreProperties);
+}
+
+VKAPI_ATTR void GetDescriptorSetLayoutSupport(VkDevice device, const VkDescriptorSetLayoutCreateInfo* pCreateInfo, VkDescriptorSetLayoutSupport* pSupport) {
+ GetData(device).dispatch.GetDescriptorSetLayoutSupport(device, pCreateInfo, pSupport);
+}
+
VKAPI_ATTR void DestroySurfaceKHR(VkInstance instance, VkSurfaceKHR surface, const VkAllocationCallbacks* pAllocator) {
GetData(instance).dispatch.DestroySurfaceKHR(instance, surface, pAllocator);
}
@@ -1214,6 +1437,22 @@
return GetData(queue).dispatch.QueuePresentKHR(queue, pPresentInfo);
}
+VKAPI_ATTR VkResult GetDeviceGroupPresentCapabilitiesKHR(VkDevice device, VkDeviceGroupPresentCapabilitiesKHR* pDeviceGroupPresentCapabilities) {
+ return GetData(device).dispatch.GetDeviceGroupPresentCapabilitiesKHR(device, pDeviceGroupPresentCapabilities);
+}
+
+VKAPI_ATTR VkResult GetDeviceGroupSurfacePresentModesKHR(VkDevice device, VkSurfaceKHR surface, VkDeviceGroupPresentModeFlagsKHR* pModes) {
+ return GetData(device).dispatch.GetDeviceGroupSurfacePresentModesKHR(device, surface, pModes);
+}
+
+VKAPI_ATTR VkResult GetPhysicalDevicePresentRectanglesKHR(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, uint32_t* pRectCount, VkRect2D* pRects) {
+ return GetData(physicalDevice).dispatch.GetPhysicalDevicePresentRectanglesKHR(physicalDevice, surface, pRectCount, pRects);
+}
+
+VKAPI_ATTR VkResult AcquireNextImage2KHR(VkDevice device, const VkAcquireNextImageInfoKHR* pAcquireInfo, uint32_t* pImageIndex) {
+ return GetData(device).dispatch.AcquireNextImage2KHR(device, pAcquireInfo, pImageIndex);
+}
+
VKAPI_ATTR VkResult CreateAndroidSurfaceKHR(VkInstance instance, const VkAndroidSurfaceCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface) {
return GetData(instance).dispatch.CreateAndroidSurfaceKHR(instance, pCreateInfo, pAllocator, pSurface);
}
@@ -1914,6 +2153,146 @@
}
__attribute__((visibility("default")))
+VKAPI_ATTR VkResult vkEnumerateInstanceVersion(uint32_t* pApiVersion) {
+ return vulkan::api::EnumerateInstanceVersion(pApiVersion);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR VkResult vkBindBufferMemory2(VkDevice device, uint32_t bindInfoCount, const VkBindBufferMemoryInfo* pBindInfos) {
+ return vulkan::api::BindBufferMemory2(device, bindInfoCount, pBindInfos);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR VkResult vkBindImageMemory2(VkDevice device, uint32_t bindInfoCount, const VkBindImageMemoryInfo* pBindInfos) {
+ return vulkan::api::BindImageMemory2(device, bindInfoCount, pBindInfos);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkGetDeviceGroupPeerMemoryFeatures(VkDevice device, uint32_t heapIndex, uint32_t localDeviceIndex, uint32_t remoteDeviceIndex, VkPeerMemoryFeatureFlags* pPeerMemoryFeatures) {
+ vulkan::api::GetDeviceGroupPeerMemoryFeatures(device, heapIndex, localDeviceIndex, remoteDeviceIndex, pPeerMemoryFeatures);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkCmdSetDeviceMask(VkCommandBuffer commandBuffer, uint32_t deviceMask) {
+ vulkan::api::CmdSetDeviceMask(commandBuffer, deviceMask);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkCmdDispatchBase(VkCommandBuffer commandBuffer, uint32_t baseGroupX, uint32_t baseGroupY, uint32_t baseGroupZ, uint32_t groupCountX, uint32_t groupCountY, uint32_t groupCountZ) {
+ vulkan::api::CmdDispatchBase(commandBuffer, baseGroupX, baseGroupY, baseGroupZ, groupCountX, groupCountY, groupCountZ);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR VkResult vkEnumeratePhysicalDeviceGroups(VkInstance instance, uint32_t* pPhysicalDeviceGroupCount, VkPhysicalDeviceGroupProperties* pPhysicalDeviceGroupProperties) {
+ return vulkan::api::EnumeratePhysicalDeviceGroups(instance, pPhysicalDeviceGroupCount, pPhysicalDeviceGroupProperties);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkGetImageMemoryRequirements2(VkDevice device, const VkImageMemoryRequirementsInfo2* pInfo, VkMemoryRequirements2* pMemoryRequirements) {
+ vulkan::api::GetImageMemoryRequirements2(device, pInfo, pMemoryRequirements);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkGetBufferMemoryRequirements2(VkDevice device, const VkBufferMemoryRequirementsInfo2* pInfo, VkMemoryRequirements2* pMemoryRequirements) {
+ vulkan::api::GetBufferMemoryRequirements2(device, pInfo, pMemoryRequirements);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkGetImageSparseMemoryRequirements2(VkDevice device, const VkImageSparseMemoryRequirementsInfo2* pInfo, uint32_t* pSparseMemoryRequirementCount, VkSparseImageMemoryRequirements2* pSparseMemoryRequirements) {
+ vulkan::api::GetImageSparseMemoryRequirements2(device, pInfo, pSparseMemoryRequirementCount, pSparseMemoryRequirements);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkGetPhysicalDeviceFeatures2(VkPhysicalDevice physicalDevice, VkPhysicalDeviceFeatures2* pFeatures) {
+ vulkan::api::GetPhysicalDeviceFeatures2(physicalDevice, pFeatures);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkGetPhysicalDeviceProperties2(VkPhysicalDevice physicalDevice, VkPhysicalDeviceProperties2* pProperties) {
+ vulkan::api::GetPhysicalDeviceProperties2(physicalDevice, pProperties);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkGetPhysicalDeviceFormatProperties2(VkPhysicalDevice physicalDevice, VkFormat format, VkFormatProperties2* pFormatProperties) {
+ vulkan::api::GetPhysicalDeviceFormatProperties2(physicalDevice, format, pFormatProperties);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR VkResult vkGetPhysicalDeviceImageFormatProperties2(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceImageFormatInfo2* pImageFormatInfo, VkImageFormatProperties2* pImageFormatProperties) {
+ return vulkan::api::GetPhysicalDeviceImageFormatProperties2(physicalDevice, pImageFormatInfo, pImageFormatProperties);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkGetPhysicalDeviceQueueFamilyProperties2(VkPhysicalDevice physicalDevice, uint32_t* pQueueFamilyPropertyCount, VkQueueFamilyProperties2* pQueueFamilyProperties) {
+ vulkan::api::GetPhysicalDeviceQueueFamilyProperties2(physicalDevice, pQueueFamilyPropertyCount, pQueueFamilyProperties);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkGetPhysicalDeviceMemoryProperties2(VkPhysicalDevice physicalDevice, VkPhysicalDeviceMemoryProperties2* pMemoryProperties) {
+ vulkan::api::GetPhysicalDeviceMemoryProperties2(physicalDevice, pMemoryProperties);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkGetPhysicalDeviceSparseImageFormatProperties2(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceSparseImageFormatInfo2* pFormatInfo, uint32_t* pPropertyCount, VkSparseImageFormatProperties2* pProperties) {
+ vulkan::api::GetPhysicalDeviceSparseImageFormatProperties2(physicalDevice, pFormatInfo, pPropertyCount, pProperties);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkTrimCommandPool(VkDevice device, VkCommandPool commandPool, VkCommandPoolTrimFlags flags) {
+ vulkan::api::TrimCommandPool(device, commandPool, flags);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkGetDeviceQueue2(VkDevice device, const VkDeviceQueueInfo2* pQueueInfo, VkQueue* pQueue) {
+ vulkan::api::GetDeviceQueue2(device, pQueueInfo, pQueue);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR VkResult vkCreateSamplerYcbcrConversion(VkDevice device, const VkSamplerYcbcrConversionCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSamplerYcbcrConversion* pYcbcrConversion) {
+ return vulkan::api::CreateSamplerYcbcrConversion(device, pCreateInfo, pAllocator, pYcbcrConversion);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkDestroySamplerYcbcrConversion(VkDevice device, VkSamplerYcbcrConversion ycbcrConversion, const VkAllocationCallbacks* pAllocator) {
+ vulkan::api::DestroySamplerYcbcrConversion(device, ycbcrConversion, pAllocator);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR VkResult vkCreateDescriptorUpdateTemplate(VkDevice device, const VkDescriptorUpdateTemplateCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDescriptorUpdateTemplate* pDescriptorUpdateTemplate) {
+ return vulkan::api::CreateDescriptorUpdateTemplate(device, pCreateInfo, pAllocator, pDescriptorUpdateTemplate);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkDestroyDescriptorUpdateTemplate(VkDevice device, VkDescriptorUpdateTemplate descriptorUpdateTemplate, const VkAllocationCallbacks* pAllocator) {
+ vulkan::api::DestroyDescriptorUpdateTemplate(device, descriptorUpdateTemplate, pAllocator);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkUpdateDescriptorSetWithTemplate(VkDevice device, VkDescriptorSet descriptorSet, VkDescriptorUpdateTemplate descriptorUpdateTemplate, const void* pData) {
+ vulkan::api::UpdateDescriptorSetWithTemplate(device, descriptorSet, descriptorUpdateTemplate, pData);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkGetPhysicalDeviceExternalBufferProperties(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceExternalBufferInfo* pExternalBufferInfo, VkExternalBufferProperties* pExternalBufferProperties) {
+ vulkan::api::GetPhysicalDeviceExternalBufferProperties(physicalDevice, pExternalBufferInfo, pExternalBufferProperties);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkGetPhysicalDeviceExternalFenceProperties(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceExternalFenceInfo* pExternalFenceInfo, VkExternalFenceProperties* pExternalFenceProperties) {
+ vulkan::api::GetPhysicalDeviceExternalFenceProperties(physicalDevice, pExternalFenceInfo, pExternalFenceProperties);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkGetPhysicalDeviceExternalSemaphoreProperties(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceExternalSemaphoreInfo* pExternalSemaphoreInfo, VkExternalSemaphoreProperties* pExternalSemaphoreProperties) {
+ vulkan::api::GetPhysicalDeviceExternalSemaphoreProperties(physicalDevice, pExternalSemaphoreInfo, pExternalSemaphoreProperties);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkGetDescriptorSetLayoutSupport(VkDevice device, const VkDescriptorSetLayoutCreateInfo* pCreateInfo, VkDescriptorSetLayoutSupport* pSupport) {
+ vulkan::api::GetDescriptorSetLayoutSupport(device, pCreateInfo, pSupport);
+}
+
+__attribute__((visibility("default")))
VKAPI_ATTR void vkDestroySurfaceKHR(VkInstance instance, VkSurfaceKHR surface, const VkAllocationCallbacks* pAllocator) {
vulkan::api::DestroySurfaceKHR(instance, surface, pAllocator);
}
@@ -1964,6 +2343,26 @@
}
__attribute__((visibility("default")))
+VKAPI_ATTR VkResult vkGetDeviceGroupPresentCapabilitiesKHR(VkDevice device, VkDeviceGroupPresentCapabilitiesKHR* pDeviceGroupPresentCapabilities) {
+ return vulkan::api::GetDeviceGroupPresentCapabilitiesKHR(device, pDeviceGroupPresentCapabilities);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR VkResult vkGetDeviceGroupSurfacePresentModesKHR(VkDevice device, VkSurfaceKHR surface, VkDeviceGroupPresentModeFlagsKHR* pModes) {
+ return vulkan::api::GetDeviceGroupSurfacePresentModesKHR(device, surface, pModes);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR VkResult vkGetPhysicalDevicePresentRectanglesKHR(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, uint32_t* pRectCount, VkRect2D* pRects) {
+ return vulkan::api::GetPhysicalDevicePresentRectanglesKHR(physicalDevice, surface, pRectCount, pRects);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR VkResult vkAcquireNextImage2KHR(VkDevice device, const VkAcquireNextImageInfoKHR* pAcquireInfo, uint32_t* pImageIndex) {
+ return vulkan::api::AcquireNextImage2KHR(device, pAcquireInfo, pImageIndex);
+}
+
+__attribute__((visibility("default")))
VKAPI_ATTR VkResult vkCreateAndroidSurfaceKHR(VkInstance instance, const VkAndroidSurfaceCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface) {
return vulkan::api::CreateAndroidSurfaceKHR(instance, pCreateInfo, pAllocator, pSurface);
}
diff --git a/vulkan/libvulkan/api_gen.h b/vulkan/libvulkan/api_gen.h
index 3e50fda..939dc73 100644
--- a/vulkan/libvulkan/api_gen.h
+++ b/vulkan/libvulkan/api_gen.h
@@ -40,11 +40,23 @@
PFN_vkCreateDevice CreateDevice;
PFN_vkEnumerateDeviceExtensionProperties EnumerateDeviceExtensionProperties;
PFN_vkGetPhysicalDeviceSparseImageFormatProperties GetPhysicalDeviceSparseImageFormatProperties;
+ PFN_vkEnumeratePhysicalDeviceGroups EnumeratePhysicalDeviceGroups;
+ PFN_vkGetPhysicalDeviceFeatures2 GetPhysicalDeviceFeatures2;
+ PFN_vkGetPhysicalDeviceProperties2 GetPhysicalDeviceProperties2;
+ PFN_vkGetPhysicalDeviceFormatProperties2 GetPhysicalDeviceFormatProperties2;
+ PFN_vkGetPhysicalDeviceImageFormatProperties2 GetPhysicalDeviceImageFormatProperties2;
+ PFN_vkGetPhysicalDeviceQueueFamilyProperties2 GetPhysicalDeviceQueueFamilyProperties2;
+ PFN_vkGetPhysicalDeviceMemoryProperties2 GetPhysicalDeviceMemoryProperties2;
+ PFN_vkGetPhysicalDeviceSparseImageFormatProperties2 GetPhysicalDeviceSparseImageFormatProperties2;
+ PFN_vkGetPhysicalDeviceExternalBufferProperties GetPhysicalDeviceExternalBufferProperties;
+ PFN_vkGetPhysicalDeviceExternalFenceProperties GetPhysicalDeviceExternalFenceProperties;
+ PFN_vkGetPhysicalDeviceExternalSemaphoreProperties GetPhysicalDeviceExternalSemaphoreProperties;
PFN_vkDestroySurfaceKHR DestroySurfaceKHR;
PFN_vkGetPhysicalDeviceSurfaceSupportKHR GetPhysicalDeviceSurfaceSupportKHR;
PFN_vkGetPhysicalDeviceSurfaceCapabilitiesKHR GetPhysicalDeviceSurfaceCapabilitiesKHR;
PFN_vkGetPhysicalDeviceSurfaceFormatsKHR GetPhysicalDeviceSurfaceFormatsKHR;
PFN_vkGetPhysicalDeviceSurfacePresentModesKHR GetPhysicalDeviceSurfacePresentModesKHR;
+ PFN_vkGetPhysicalDevicePresentRectanglesKHR GetPhysicalDevicePresentRectanglesKHR;
PFN_vkCreateAndroidSurfaceKHR CreateAndroidSurfaceKHR;
// clang-format on
};
@@ -172,11 +184,30 @@
PFN_vkCmdNextSubpass CmdNextSubpass;
PFN_vkCmdEndRenderPass CmdEndRenderPass;
PFN_vkCmdExecuteCommands CmdExecuteCommands;
+ PFN_vkBindBufferMemory2 BindBufferMemory2;
+ PFN_vkBindImageMemory2 BindImageMemory2;
+ PFN_vkGetDeviceGroupPeerMemoryFeatures GetDeviceGroupPeerMemoryFeatures;
+ PFN_vkCmdSetDeviceMask CmdSetDeviceMask;
+ PFN_vkCmdDispatchBase CmdDispatchBase;
+ PFN_vkGetImageMemoryRequirements2 GetImageMemoryRequirements2;
+ PFN_vkGetBufferMemoryRequirements2 GetBufferMemoryRequirements2;
+ PFN_vkGetImageSparseMemoryRequirements2 GetImageSparseMemoryRequirements2;
+ PFN_vkTrimCommandPool TrimCommandPool;
+ PFN_vkGetDeviceQueue2 GetDeviceQueue2;
+ PFN_vkCreateSamplerYcbcrConversion CreateSamplerYcbcrConversion;
+ PFN_vkDestroySamplerYcbcrConversion DestroySamplerYcbcrConversion;
+ PFN_vkCreateDescriptorUpdateTemplate CreateDescriptorUpdateTemplate;
+ PFN_vkDestroyDescriptorUpdateTemplate DestroyDescriptorUpdateTemplate;
+ PFN_vkUpdateDescriptorSetWithTemplate UpdateDescriptorSetWithTemplate;
+ PFN_vkGetDescriptorSetLayoutSupport GetDescriptorSetLayoutSupport;
PFN_vkCreateSwapchainKHR CreateSwapchainKHR;
PFN_vkDestroySwapchainKHR DestroySwapchainKHR;
PFN_vkGetSwapchainImagesKHR GetSwapchainImagesKHR;
PFN_vkAcquireNextImageKHR AcquireNextImageKHR;
PFN_vkQueuePresentKHR QueuePresentKHR;
+ PFN_vkGetDeviceGroupPresentCapabilitiesKHR GetDeviceGroupPresentCapabilitiesKHR;
+ PFN_vkGetDeviceGroupSurfacePresentModesKHR GetDeviceGroupSurfacePresentModesKHR;
+ PFN_vkAcquireNextImage2KHR AcquireNextImage2KHR;
// clang-format on
};
diff --git a/vulkan/libvulkan/code-generator.tmpl b/vulkan/libvulkan/code-generator.tmpl
index cb2d26a..3b48e08 100644
--- a/vulkan/libvulkan/code-generator.tmpl
+++ b/vulkan/libvulkan/code-generator.tmpl
@@ -419,7 +419,7 @@
INIT_PROC(§
{{end}}
- {{if GetAnnotation $ "optional"}}false{{else}}true{{end}}, §
+ {{if GetAnnotation $ "optional"}}false{{else if GetAnnotation $ "vulkan1_1"}}false{{else}}true{{end}}, §
{{if (Macro "IsInstanceDispatched" $)}}
instance, §
@@ -733,7 +733,9 @@
{{ if eq $.Name "vkCreateInstance"}}true
{{else if eq $.Name "vkCreateDevice"}}true
{{else if eq $.Name "vkEnumeratePhysicalDevices"}}true
+ {{else if eq $.Name "vkEnumeratePhysicalDeviceGroups"}}true
{{else if eq $.Name "vkGetDeviceQueue"}}true
+ {{else if eq $.Name "vkGetDeviceQueue2"}}true
{{else if eq $.Name "vkAllocateCommandBuffers"}}true
{{/* Destroy functions of dispatchable objects */}}
@@ -958,6 +960,7 @@
{{/* Create functions of dispatchable objects */}}
{{ if eq $.Name "vkCreateDevice"}}true
{{else if eq $.Name "vkGetDeviceQueue"}}true
+ {{else if eq $.Name "vkGetDeviceQueue2"}}true
{{else if eq $.Name "vkAllocateCommandBuffers"}}true
{{/* Destroy functions of dispatchable objects */}}
@@ -969,6 +972,7 @@
{{/* We cache physical devices in loader.cpp */}}
{{else if eq $.Name "vkEnumeratePhysicalDevices"}}true
+ {{else if eq $.Name "vkEnumeratePhysicalDeviceGroups"}}true
{{else if eq $.Name "vkGetInstanceProcAddr"}}true
{{else if eq $.Name "vkGetDeviceProcAddr"}}true
diff --git a/vulkan/libvulkan/driver.cpp b/vulkan/libvulkan/driver.cpp
index 947a2f7..ade0bde 100644
--- a/vulkan/libvulkan/driver.cpp
+++ b/vulkan/libvulkan/driver.cpp
@@ -880,19 +880,6 @@
const VkAllocationCallbacks& data_allocator =
(pAllocator) ? *pAllocator : GetDefaultAllocator();
- if (pCreateInfo->pApplicationInfo &&
- pCreateInfo->pApplicationInfo->apiVersion >= VK_MAKE_VERSION(1, 1, 0)) {
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wold-style-cast"
- ALOGI(
- "Requested Vulkan instance version %d.%d is greater than max "
- "supported version (1.0)",
- VK_VERSION_MAJOR(pCreateInfo->pApplicationInfo->apiVersion),
- VK_VERSION_MINOR(pCreateInfo->pApplicationInfo->apiVersion));
-#pragma clang diagnostic pop
- return VK_ERROR_INCOMPATIBLE_DRIVER;
- }
-
CreateInfoWrapper wrapper(*pCreateInfo, data_allocator);
VkResult result = wrapper.Validate();
if (result != VK_SUCCESS)
@@ -1056,6 +1043,28 @@
return result;
}
+VkResult EnumeratePhysicalDeviceGroups(
+ VkInstance instance,
+ uint32_t* pPhysicalDeviceGroupCount,
+ VkPhysicalDeviceGroupProperties* pPhysicalDeviceGroupProperties) {
+ const auto& data = GetData(instance);
+
+ VkResult result = data.driver.EnumeratePhysicalDeviceGroups(
+ instance, pPhysicalDeviceGroupCount, pPhysicalDeviceGroupProperties);
+ if ((result == VK_SUCCESS || result == VK_INCOMPLETE) &&
+ *pPhysicalDeviceGroupCount && pPhysicalDeviceGroupProperties) {
+ for (uint32_t i = 0; i < *pPhysicalDeviceGroupCount; i++) {
+ for (uint32_t j = 0;
+ j < pPhysicalDeviceGroupProperties->physicalDeviceCount; j++) {
+ SetData(pPhysicalDeviceGroupProperties->physicalDevices[j],
+ data);
+ }
+ }
+ }
+
+ return result;
+}
+
void GetDeviceQueue(VkDevice device,
uint32_t queueFamilyIndex,
uint32_t queueIndex,
@@ -1066,6 +1075,15 @@
SetData(*pQueue, data);
}
+void GetDeviceQueue2(VkDevice device,
+ const VkDeviceQueueInfo2* pQueueInfo,
+ VkQueue* pQueue) {
+ const auto& data = GetData(device);
+
+ data.driver.GetDeviceQueue2(device, pQueueInfo, pQueue);
+ SetData(*pQueue, data);
+}
+
VKAPI_ATTR VkResult
AllocateCommandBuffers(VkDevice device,
const VkCommandBufferAllocateInfo* pAllocateInfo,
diff --git a/vulkan/libvulkan/driver.h b/vulkan/libvulkan/driver.h
index 7f8ae98..57c956d 100644
--- a/vulkan/libvulkan/driver.h
+++ b/vulkan/libvulkan/driver.h
@@ -126,7 +126,10 @@
VKAPI_ATTR void DestroyDevice(VkDevice device, const VkAllocationCallbacks* pAllocator);
VKAPI_ATTR VkResult EnumeratePhysicalDevices(VkInstance instance, uint32_t* pPhysicalDeviceCount, VkPhysicalDevice* pPhysicalDevices);
+VKAPI_ATTR VkResult EnumeratePhysicalDeviceGroups(VkInstance instance, uint32_t* pPhysicalDeviceGroupCount, VkPhysicalDeviceGroupProperties* pPhysicalDeviceGroupProperties);
+
VKAPI_ATTR void GetDeviceQueue(VkDevice device, uint32_t queueFamilyIndex, uint32_t queueIndex, VkQueue* pQueue);
+VKAPI_ATTR void GetDeviceQueue2(VkDevice device, const VkDeviceQueueInfo2* pQueueInfo, VkQueue* pQueue);
VKAPI_ATTR VkResult AllocateCommandBuffers(VkDevice device, const VkCommandBufferAllocateInfo* pAllocateInfo, VkCommandBuffer* pCommandBuffers);
// clang-format on
diff --git a/vulkan/libvulkan/driver_gen.cpp b/vulkan/libvulkan/driver_gen.cpp
index 82b464e..c6e8a7a 100644
--- a/vulkan/libvulkan/driver_gen.cpp
+++ b/vulkan/libvulkan/driver_gen.cpp
@@ -75,6 +75,33 @@
}
}
+VKAPI_ATTR VkResult checkedGetDeviceGroupPresentCapabilitiesKHR(VkDevice device, VkDeviceGroupPresentCapabilitiesKHR* pDeviceGroupPresentCapabilities) {
+ if (GetData(device).hook_extensions[ProcHook::KHR_swapchain]) {
+ return GetDeviceGroupPresentCapabilitiesKHR(device, pDeviceGroupPresentCapabilities);
+ } else {
+ Logger(device).Err(device, "VK_KHR_swapchain not enabled. vkGetDeviceGroupPresentCapabilitiesKHR not executed.");
+ return VK_SUCCESS;
+ }
+}
+
+VKAPI_ATTR VkResult checkedGetDeviceGroupSurfacePresentModesKHR(VkDevice device, VkSurfaceKHR surface, VkDeviceGroupPresentModeFlagsKHR* pModes) {
+ if (GetData(device).hook_extensions[ProcHook::KHR_swapchain]) {
+ return GetDeviceGroupSurfacePresentModesKHR(device, surface, pModes);
+ } else {
+ Logger(device).Err(device, "VK_KHR_swapchain not enabled. vkGetDeviceGroupSurfacePresentModesKHR not executed.");
+ return VK_SUCCESS;
+ }
+}
+
+VKAPI_ATTR VkResult checkedAcquireNextImage2KHR(VkDevice device, const VkAcquireNextImageInfoKHR* pAcquireInfo, uint32_t* pImageIndex) {
+ if (GetData(device).hook_extensions[ProcHook::KHR_swapchain]) {
+ return AcquireNextImage2KHR(device, pAcquireInfo, pImageIndex);
+ } else {
+ Logger(device).Err(device, "VK_KHR_swapchain not enabled. vkAcquireNextImage2KHR not executed.");
+ return VK_SUCCESS;
+ }
+}
+
VKAPI_ATTR VkResult checkedGetRefreshCycleDurationGOOGLE(VkDevice device, VkSwapchainKHR swapchain, VkRefreshCycleDurationGOOGLE* pDisplayTimingProperties) {
if (GetData(device).hook_extensions[ProcHook::GOOGLE_display_timing]) {
return GetRefreshCycleDurationGOOGLE(device, swapchain, pDisplayTimingProperties);
@@ -122,6 +149,13 @@
nullptr,
},
{
+ "vkAcquireNextImage2KHR",
+ ProcHook::DEVICE,
+ ProcHook::KHR_swapchain,
+ reinterpret_cast<PFN_vkVoidFunction>(AcquireNextImage2KHR),
+ reinterpret_cast<PFN_vkVoidFunction>(checkedAcquireNextImage2KHR),
+ },
+ {
"vkAcquireNextImageKHR",
ProcHook::DEVICE,
ProcHook::KHR_swapchain,
@@ -227,6 +261,13 @@
nullptr,
},
{
+ "vkEnumeratePhysicalDeviceGroups",
+ ProcHook::INSTANCE,
+ ProcHook::EXTENSION_CORE,
+ reinterpret_cast<PFN_vkVoidFunction>(EnumeratePhysicalDeviceGroups),
+ nullptr,
+ },
+ {
"vkEnumeratePhysicalDevices",
ProcHook::INSTANCE,
ProcHook::EXTENSION_CORE,
@@ -234,6 +275,20 @@
nullptr,
},
{
+ "vkGetDeviceGroupPresentCapabilitiesKHR",
+ ProcHook::DEVICE,
+ ProcHook::KHR_swapchain,
+ reinterpret_cast<PFN_vkVoidFunction>(GetDeviceGroupPresentCapabilitiesKHR),
+ reinterpret_cast<PFN_vkVoidFunction>(checkedGetDeviceGroupPresentCapabilitiesKHR),
+ },
+ {
+ "vkGetDeviceGroupSurfacePresentModesKHR",
+ ProcHook::DEVICE,
+ ProcHook::KHR_swapchain,
+ reinterpret_cast<PFN_vkVoidFunction>(GetDeviceGroupSurfacePresentModesKHR),
+ reinterpret_cast<PFN_vkVoidFunction>(checkedGetDeviceGroupSurfacePresentModesKHR),
+ },
+ {
"vkGetDeviceProcAddr",
ProcHook::DEVICE,
ProcHook::EXTENSION_CORE,
@@ -248,6 +303,13 @@
nullptr,
},
{
+ "vkGetDeviceQueue2",
+ ProcHook::DEVICE,
+ ProcHook::EXTENSION_CORE,
+ reinterpret_cast<PFN_vkVoidFunction>(GetDeviceQueue2),
+ nullptr,
+ },
+ {
"vkGetInstanceProcAddr",
ProcHook::INSTANCE,
ProcHook::EXTENSION_CORE,
@@ -262,6 +324,13 @@
reinterpret_cast<PFN_vkVoidFunction>(checkedGetPastPresentationTimingGOOGLE),
},
{
+ "vkGetPhysicalDevicePresentRectanglesKHR",
+ ProcHook::INSTANCE,
+ ProcHook::KHR_swapchain,
+ reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDevicePresentRectanglesKHR),
+ nullptr,
+ },
+ {
"vkGetPhysicalDeviceSurfaceCapabilities2KHR",
ProcHook::INSTANCE,
ProcHook::KHR_get_surface_capabilities2,
@@ -423,6 +492,7 @@
INIT_PROC(true, instance, GetPhysicalDeviceProperties);
INIT_PROC(true, instance, CreateDevice);
INIT_PROC(true, instance, EnumerateDeviceExtensionProperties);
+ INIT_PROC(false, instance, EnumeratePhysicalDeviceGroups);
INIT_PROC_EXT(EXT_debug_report, true, instance, CreateDebugReportCallbackEXT);
INIT_PROC_EXT(EXT_debug_report, true, instance, DestroyDebugReportCallbackEXT);
INIT_PROC_EXT(EXT_debug_report, true, instance, DebugReportMessageEXT);
@@ -445,6 +515,7 @@
INIT_PROC(true, dev, CreateImage);
INIT_PROC(true, dev, DestroyImage);
INIT_PROC(true, dev, AllocateCommandBuffers);
+ INIT_PROC(false, dev, GetDeviceQueue2);
INIT_PROC_EXT(ANDROID_native_buffer, false, dev, GetSwapchainGrallocUsageANDROID);
INIT_PROC_EXT(ANDROID_native_buffer, false, dev, GetSwapchainGrallocUsage2ANDROID);
INIT_PROC_EXT(ANDROID_native_buffer, true, dev, AcquireImageANDROID);
diff --git a/vulkan/libvulkan/driver_gen.h b/vulkan/libvulkan/driver_gen.h
index 3b26a80..646662f 100644
--- a/vulkan/libvulkan/driver_gen.h
+++ b/vulkan/libvulkan/driver_gen.h
@@ -67,6 +67,7 @@
PFN_vkGetPhysicalDeviceProperties GetPhysicalDeviceProperties;
PFN_vkCreateDevice CreateDevice;
PFN_vkEnumerateDeviceExtensionProperties EnumerateDeviceExtensionProperties;
+ PFN_vkEnumeratePhysicalDeviceGroups EnumeratePhysicalDeviceGroups;
PFN_vkCreateDebugReportCallbackEXT CreateDebugReportCallbackEXT;
PFN_vkDestroyDebugReportCallbackEXT DestroyDebugReportCallbackEXT;
PFN_vkDebugReportMessageEXT DebugReportMessageEXT;
@@ -82,6 +83,7 @@
PFN_vkCreateImage CreateImage;
PFN_vkDestroyImage DestroyImage;
PFN_vkAllocateCommandBuffers AllocateCommandBuffers;
+ PFN_vkGetDeviceQueue2 GetDeviceQueue2;
PFN_vkGetSwapchainGrallocUsageANDROID GetSwapchainGrallocUsageANDROID;
PFN_vkGetSwapchainGrallocUsage2ANDROID GetSwapchainGrallocUsage2ANDROID;
PFN_vkAcquireImageANDROID AcquireImageANDROID;
diff --git a/vulkan/libvulkan/stubhal.cpp b/vulkan/libvulkan/stubhal.cpp
index 2926268..726e854 100644
--- a/vulkan/libvulkan/stubhal.cpp
+++ b/vulkan/libvulkan/stubhal.cpp
@@ -97,7 +97,7 @@
return VK_SUCCESS;
}
-VKAPI_ATTR PFN_vkVoidFunction GetInstanceProcAddr(VkInstance /*instance*/,
+VKAPI_ATTR PFN_vkVoidFunction GetInstanceProcAddr(VkInstance instance,
const char* name) {
if (strcmp(name, "vkCreateInstance") == 0)
return reinterpret_cast<PFN_vkVoidFunction>(CreateInstance);
@@ -110,7 +110,9 @@
return reinterpret_cast<PFN_vkVoidFunction>(EnumeratePhysicalDevices);
if (strcmp(name, "vkGetInstanceProcAddr") == 0)
return reinterpret_cast<PFN_vkVoidFunction>(GetInstanceProcAddr);
-
+ // Per the spec, return NULL if instance is NULL.
+ if (!instance)
+ return nullptr;
// 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);
diff --git a/vulkan/libvulkan/swapchain.cpp b/vulkan/libvulkan/swapchain.cpp
index 665a32b..03e6ee0 100644
--- a/vulkan/libvulkan/swapchain.cpp
+++ b/vulkan/libvulkan/swapchain.cpp
@@ -23,9 +23,12 @@
#include <utils/StrongPointer.h>
#include <utils/Vector.h>
#include <system/window.h>
+#include <android/hardware/graphics/common/1.0/types.h>
#include "driver.h"
+using android::hardware::graphics::common::V1_0::BufferUsage;
+
// 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.
@@ -771,6 +774,77 @@
}
VKAPI_ATTR
+VkResult GetDeviceGroupPresentCapabilitiesKHR(
+ VkDevice,
+ VkDeviceGroupPresentCapabilitiesKHR* pDeviceGroupPresentCapabilities) {
+ ALOGV_IF(pDeviceGroupPresentCapabilities->sType !=
+ VK_STRUCTURE_TYPE_DEVICE_GROUP_PRESENT_CAPABILITIES_KHR,
+ "vkGetDeviceGroupPresentCapabilitiesKHR: invalid "
+ "VkDeviceGroupPresentCapabilitiesKHR structure type %d",
+ pDeviceGroupPresentCapabilities->sType);
+
+ memset(pDeviceGroupPresentCapabilities->presentMask, 0,
+ sizeof(pDeviceGroupPresentCapabilities->presentMask));
+
+ // assume device group of size 1
+ pDeviceGroupPresentCapabilities->presentMask[0] = 1 << 0;
+ pDeviceGroupPresentCapabilities->modes =
+ VK_DEVICE_GROUP_PRESENT_MODE_LOCAL_BIT_KHR;
+
+ return VK_SUCCESS;
+}
+
+VKAPI_ATTR
+VkResult GetDeviceGroupSurfacePresentModesKHR(
+ VkDevice,
+ VkSurfaceKHR,
+ VkDeviceGroupPresentModeFlagsKHR* pModes) {
+ *pModes = VK_DEVICE_GROUP_PRESENT_MODE_LOCAL_BIT_KHR;
+ return VK_SUCCESS;
+}
+
+VKAPI_ATTR
+VkResult GetPhysicalDevicePresentRectanglesKHR(VkPhysicalDevice,
+ VkSurfaceKHR surface,
+ uint32_t* pRectCount,
+ VkRect2D* pRects) {
+ if (!pRects) {
+ *pRectCount = 1;
+ } else {
+ uint32_t count = std::min(*pRectCount, 1u);
+ bool incomplete = *pRectCount < 1;
+
+ *pRectCount = count;
+
+ if (incomplete) {
+ return VK_INCOMPLETE;
+ }
+
+ int err;
+ ANativeWindow* window = SurfaceFromHandle(surface)->window.get();
+
+ int width = 0, height = 0;
+ err = window->query(window, NATIVE_WINDOW_DEFAULT_WIDTH, &width);
+ if (err != 0) {
+ ALOGE("NATIVE_WINDOW_DEFAULT_WIDTH query failed: %s (%d)",
+ strerror(-err), err);
+ }
+ err = window->query(window, NATIVE_WINDOW_DEFAULT_HEIGHT, &height);
+ if (err != 0) {
+ ALOGE("NATIVE_WINDOW_DEFAULT_WIDTH query failed: %s (%d)",
+ strerror(-err), err);
+ }
+
+ // TODO: Return something better than "whole window"
+ pRects[0].offset.x = 0;
+ pRects[0].offset.y = 0;
+ pRects[0].extent = VkExtent2D{static_cast<uint32_t>(width),
+ static_cast<uint32_t>(height)};
+ }
+ return VK_SUCCESS;
+}
+
+VKAPI_ATTR
VkResult CreateSwapchainKHR(VkDevice device,
const VkSwapchainCreateInfoKHR* create_info,
const VkAllocationCallbacks* allocator,
@@ -996,7 +1070,7 @@
return VK_ERROR_SURFACE_LOST_KHR;
}
- int gralloc_usage = 0;
+ int32_t legacy_usage = 0;
if (dispatch.GetSwapchainGrallocUsage2ANDROID) {
uint64_t consumer_usage, producer_usage;
result = dispatch.GetSwapchainGrallocUsage2ANDROID(
@@ -1006,18 +1080,25 @@
ALOGE("vkGetSwapchainGrallocUsage2ANDROID failed: %d", result);
return VK_ERROR_SURFACE_LOST_KHR;
}
- gralloc_usage =
+ legacy_usage =
android_convertGralloc1To0Usage(producer_usage, consumer_usage);
} else if (dispatch.GetSwapchainGrallocUsageANDROID) {
result = dispatch.GetSwapchainGrallocUsageANDROID(
device, create_info->imageFormat, create_info->imageUsage,
- &gralloc_usage);
+ &legacy_usage);
if (result != VK_SUCCESS) {
ALOGE("vkGetSwapchainGrallocUsageANDROID failed: %d", result);
return VK_ERROR_SURFACE_LOST_KHR;
}
}
- err = native_window_set_usage(surface.window.get(), uint64_t(gralloc_usage));
+ uint64_t native_usage = static_cast<uint64_t>(legacy_usage);
+
+ bool createProtectedSwapchain = false;
+ if (create_info->flags & VK_SWAPCHAIN_CREATE_PROTECTED_BIT_KHR) {
+ createProtectedSwapchain = true;
+ native_usage |= BufferUsage::PROTECTED;
+ }
+ err = native_window_set_usage(surface.window.get(), native_usage);
if (err != 0) {
// TODO(jessehall): Improve error reporting. Can we enumerate possible
// errors and translate them to valid Vulkan result codes?
@@ -1065,7 +1146,7 @@
.samples = VK_SAMPLE_COUNT_1_BIT,
.tiling = VK_IMAGE_TILING_OPTIMAL,
.usage = create_info->imageUsage,
- .flags = 0,
+ .flags = createProtectedSwapchain ? VK_IMAGE_CREATE_PROTECTED_BIT : 0u,
.sharingMode = create_info->imageSharingMode,
.queueFamilyIndexCount = create_info->queueFamilyIndexCount,
.pQueueFamilyIndices = create_info->pQueueFamilyIndices,
@@ -1273,6 +1354,17 @@
return VK_SUCCESS;
}
+VKAPI_ATTR
+VkResult AcquireNextImage2KHR(VkDevice device,
+ const VkAcquireNextImageInfoKHR* pAcquireInfo,
+ uint32_t* pImageIndex) {
+ // TODO: this should actually be the other way around and this function
+ // should handle any additional structures that get passed in
+ return AcquireNextImageKHR(device, pAcquireInfo->swapchain,
+ pAcquireInfo->timeout, pAcquireInfo->semaphore,
+ pAcquireInfo->fence, pImageIndex);
+}
+
static VkResult WorstPresentResult(VkResult a, VkResult b) {
// See the error ranking for vkQueuePresentKHR at the end of section 29.6
// (in spec version 1.0.14).
diff --git a/vulkan/libvulkan/swapchain.h b/vulkan/libvulkan/swapchain.h
index e3cf624..ed5718c 100644
--- a/vulkan/libvulkan/swapchain.h
+++ b/vulkan/libvulkan/swapchain.h
@@ -29,11 +29,15 @@
VKAPI_ATTR VkResult GetPhysicalDeviceSurfaceCapabilitiesKHR(VkPhysicalDevice pdev, VkSurfaceKHR surface, VkSurfaceCapabilitiesKHR* capabilities);
VKAPI_ATTR VkResult GetPhysicalDeviceSurfaceFormatsKHR(VkPhysicalDevice pdev, VkSurfaceKHR surface_handle, uint32_t* count, VkSurfaceFormatKHR* formats);
VKAPI_ATTR VkResult GetPhysicalDeviceSurfacePresentModesKHR(VkPhysicalDevice pdev, VkSurfaceKHR surface, uint32_t* count, VkPresentModeKHR* modes);
+VKAPI_ATTR VkResult GetDeviceGroupPresentCapabilitiesKHR(VkDevice device, VkDeviceGroupPresentCapabilitiesKHR* pDeviceGroupPresentCapabilities);
+VKAPI_ATTR VkResult GetDeviceGroupSurfacePresentModesKHR(VkDevice device, VkSurfaceKHR surface, VkDeviceGroupPresentModeFlagsKHR* pModes);
+VKAPI_ATTR VkResult GetPhysicalDevicePresentRectanglesKHR(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, uint32_t* pRectCount, VkRect2D* pRects);
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);
+VKAPI_ATTR VkResult AcquireNextImage2KHR(VkDevice device, const VkAcquireNextImageInfoKHR* pAcquireInfo, uint32_t* pImageIndex);
VKAPI_ATTR VkResult GetRefreshCycleDurationGOOGLE(VkDevice device, VkSwapchainKHR swapchain, VkRefreshCycleDurationGOOGLE* pDisplayTimingProperties);
VKAPI_ATTR VkResult GetPastPresentationTimingGOOGLE(VkDevice device, VkSwapchainKHR swapchain, uint32_t* pPresentationTimingCount, VkPastPresentationTimingGOOGLE* pPresentationTimings);
VKAPI_ATTR VkResult GetSwapchainStatusKHR(VkDevice device, VkSwapchainKHR swapchain);
diff --git a/vulkan/nulldrv/null_driver.cpp b/vulkan/nulldrv/null_driver.cpp
index b4ca42c..4647a80 100644
--- a/vulkan/nulldrv/null_driver.cpp
+++ b/vulkan/nulldrv/null_driver.cpp
@@ -16,6 +16,7 @@
#include <hardware/hwvulkan.h>
+#include <errno.h>
#include <inttypes.h>
#include <stdlib.h>
#include <string.h>
@@ -258,6 +259,12 @@
// Global
VKAPI_ATTR
+VkResult EnumerateInstanceVersion(uint32_t* pApiVersion) {
+ *pApiVersion = VK_API_VERSION_1_1;
+ return VK_SUCCESS;
+}
+
+VKAPI_ATTR
VkResult EnumerateInstanceExtensionProperties(
const char* layer_name,
uint32_t* count,
@@ -1474,6 +1481,93 @@
void DebugReportMessageEXT(VkInstance instance, VkDebugReportFlagsEXT flags, VkDebugReportObjectTypeEXT objectType, uint64_t object, size_t location, int32_t messageCode, const char* pLayerPrefix, const char* pMessage) {
}
+VkResult BindBufferMemory2(VkDevice device, uint32_t bindInfoCount, const VkBindBufferMemoryInfo* pBindInfos) {
+ return VK_SUCCESS;
+}
+
+VkResult BindImageMemory2(VkDevice device, uint32_t bindInfoCount, const VkBindImageMemoryInfo* pBindInfos) {
+ return VK_SUCCESS;
+}
+
+void GetDeviceGroupPeerMemoryFeatures(VkDevice device, uint32_t heapIndex, uint32_t localDeviceIndex, uint32_t remoteDeviceIndex, VkPeerMemoryFeatureFlags* pPeerMemoryFeatures) {
+}
+
+void CmdSetDeviceMask(VkCommandBuffer commandBuffer, uint32_t deviceMask) {
+}
+
+void CmdDispatchBase(VkCommandBuffer commandBuffer, uint32_t baseGroupX, uint32_t baseGroupY, uint32_t baseGroupZ, uint32_t groupCountX, uint32_t groupCountY, uint32_t groupCountZ) {
+}
+
+VkResult EnumeratePhysicalDeviceGroups(VkInstance instance, uint32_t* pPhysicalDeviceGroupCount, VkPhysicalDeviceGroupProperties* pPhysicalDeviceGroupProperties) {
+ return VK_SUCCESS;
+}
+
+void GetImageMemoryRequirements2(VkDevice device, const VkImageMemoryRequirementsInfo2* pInfo, VkMemoryRequirements2* pMemoryRequirements) {
+}
+
+void GetBufferMemoryRequirements2(VkDevice device, const VkBufferMemoryRequirementsInfo2* pInfo, VkMemoryRequirements2* pMemoryRequirements) {
+}
+
+void GetImageSparseMemoryRequirements2(VkDevice device, const VkImageSparseMemoryRequirementsInfo2* pInfo, uint32_t* pSparseMemoryRequirementCount, VkSparseImageMemoryRequirements2* pSparseMemoryRequirements) {
+}
+
+void GetPhysicalDeviceFeatures2(VkPhysicalDevice physicalDevice, VkPhysicalDeviceFeatures2* pFeatures) {
+}
+
+void GetPhysicalDeviceProperties2(VkPhysicalDevice physicalDevice, VkPhysicalDeviceProperties2* pProperties) {
+}
+
+void GetPhysicalDeviceFormatProperties2(VkPhysicalDevice physicalDevice, VkFormat format, VkFormatProperties2* pFormatProperties) {
+}
+
+VkResult GetPhysicalDeviceImageFormatProperties2(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceImageFormatInfo2* pImageFormatInfo, VkImageFormatProperties2* pImageFormatProperties) {
+ return VK_SUCCESS;
+}
+
+void GetPhysicalDeviceQueueFamilyProperties2(VkPhysicalDevice physicalDevice, uint32_t* pQueueFamilyPropertyCount, VkQueueFamilyProperties2* pQueueFamilyProperties) {
+}
+
+void GetPhysicalDeviceMemoryProperties2(VkPhysicalDevice physicalDevice, VkPhysicalDeviceMemoryProperties2* pMemoryProperties) {
+}
+
+void GetPhysicalDeviceSparseImageFormatProperties2(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceSparseImageFormatInfo2* pFormatInfo, uint32_t* pPropertyCount, VkSparseImageFormatProperties2* pProperties) {
+}
+
+void TrimCommandPool(VkDevice device, VkCommandPool commandPool, VkCommandPoolTrimFlags flags) {
+}
+
+void GetDeviceQueue2(VkDevice device, const VkDeviceQueueInfo2* pQueueInfo, VkQueue* pQueue) {
+}
+
+VkResult CreateSamplerYcbcrConversion(VkDevice device, const VkSamplerYcbcrConversionCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSamplerYcbcrConversion* pYcbcrConversion) {
+ return VK_SUCCESS;
+}
+
+void DestroySamplerYcbcrConversion(VkDevice device, VkSamplerYcbcrConversion ycbcrConversion, const VkAllocationCallbacks* pAllocator) {
+}
+
+VkResult CreateDescriptorUpdateTemplate(VkDevice device, const VkDescriptorUpdateTemplateCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDescriptorUpdateTemplate* pDescriptorUpdateTemplate) {
+ return VK_SUCCESS;
+}
+
+void DestroyDescriptorUpdateTemplate(VkDevice device, VkDescriptorUpdateTemplate descriptorUpdateTemplate, const VkAllocationCallbacks* pAllocator) {
+}
+
+void UpdateDescriptorSetWithTemplate(VkDevice device, VkDescriptorSet descriptorSet, VkDescriptorUpdateTemplate descriptorUpdateTemplate, const void* pData) {
+}
+
+void GetPhysicalDeviceExternalBufferProperties(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceExternalBufferInfo* pExternalBufferInfo, VkExternalBufferProperties* pExternalBufferProperties) {
+}
+
+void GetPhysicalDeviceExternalFenceProperties(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceExternalFenceInfo* pExternalFenceInfo, VkExternalFenceProperties* pExternalFenceProperties) {
+}
+
+void GetPhysicalDeviceExternalSemaphoreProperties(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceExternalSemaphoreInfo* pExternalSemaphoreInfo, VkExternalSemaphoreProperties* pExternalSemaphoreProperties) {
+}
+
+void GetDescriptorSetLayoutSupport(VkDevice device, const VkDescriptorSetLayoutCreateInfo* pCreateInfo, VkDescriptorSetLayoutSupport* pSupport) {
+}
+
#pragma clang diagnostic pop
// clang-format on
diff --git a/vulkan/nulldrv/null_driver_gen.cpp b/vulkan/nulldrv/null_driver_gen.cpp
index 25ee65a..92b7468 100644
--- a/vulkan/nulldrv/null_driver_gen.cpp
+++ b/vulkan/nulldrv/null_driver_gen.cpp
@@ -49,6 +49,7 @@
{"vkCreateInstance", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCreateInstance>(CreateInstance))},
{"vkEnumerateInstanceExtensionProperties", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkEnumerateInstanceExtensionProperties>(EnumerateInstanceExtensionProperties))},
{"vkEnumerateInstanceLayerProperties", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkEnumerateInstanceLayerProperties>(EnumerateInstanceLayerProperties))},
+ {"vkEnumerateInstanceVersion", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkEnumerateInstanceVersion>(EnumerateInstanceVersion))},
// clang-format on
};
@@ -60,7 +61,9 @@
{"vkAllocateMemory", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkAllocateMemory>(AllocateMemory))},
{"vkBeginCommandBuffer", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkBeginCommandBuffer>(BeginCommandBuffer))},
{"vkBindBufferMemory", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkBindBufferMemory>(BindBufferMemory))},
+ {"vkBindBufferMemory2", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkBindBufferMemory2>(BindBufferMemory2))},
{"vkBindImageMemory", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkBindImageMemory>(BindImageMemory))},
+ {"vkBindImageMemory2", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkBindImageMemory2>(BindImageMemory2))},
{"vkCmdBeginQuery", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCmdBeginQuery>(CmdBeginQuery))},
{"vkCmdBeginRenderPass", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCmdBeginRenderPass>(CmdBeginRenderPass))},
{"vkCmdBindDescriptorSets", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCmdBindDescriptorSets>(CmdBindDescriptorSets))},
@@ -77,6 +80,7 @@
{"vkCmdCopyImageToBuffer", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCmdCopyImageToBuffer>(CmdCopyImageToBuffer))},
{"vkCmdCopyQueryPoolResults", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCmdCopyQueryPoolResults>(CmdCopyQueryPoolResults))},
{"vkCmdDispatch", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCmdDispatch>(CmdDispatch))},
+ {"vkCmdDispatchBase", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCmdDispatchBase>(CmdDispatchBase))},
{"vkCmdDispatchIndirect", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCmdDispatchIndirect>(CmdDispatchIndirect))},
{"vkCmdDraw", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCmdDraw>(CmdDraw))},
{"vkCmdDrawIndexed", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCmdDrawIndexed>(CmdDrawIndexed))},
@@ -95,6 +99,7 @@
{"vkCmdSetBlendConstants", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCmdSetBlendConstants>(CmdSetBlendConstants))},
{"vkCmdSetDepthBias", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCmdSetDepthBias>(CmdSetDepthBias))},
{"vkCmdSetDepthBounds", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCmdSetDepthBounds>(CmdSetDepthBounds))},
+ {"vkCmdSetDeviceMask", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCmdSetDeviceMask>(CmdSetDeviceMask))},
{"vkCmdSetEvent", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCmdSetEvent>(CmdSetEvent))},
{"vkCmdSetLineWidth", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCmdSetLineWidth>(CmdSetLineWidth))},
{"vkCmdSetScissor", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCmdSetScissor>(CmdSetScissor))},
@@ -112,6 +117,7 @@
{"vkCreateDebugReportCallbackEXT", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCreateDebugReportCallbackEXT>(CreateDebugReportCallbackEXT))},
{"vkCreateDescriptorPool", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCreateDescriptorPool>(CreateDescriptorPool))},
{"vkCreateDescriptorSetLayout", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCreateDescriptorSetLayout>(CreateDescriptorSetLayout))},
+ {"vkCreateDescriptorUpdateTemplate", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCreateDescriptorUpdateTemplate>(CreateDescriptorUpdateTemplate))},
{"vkCreateDevice", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCreateDevice>(CreateDevice))},
{"vkCreateEvent", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCreateEvent>(CreateEvent))},
{"vkCreateFence", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCreateFence>(CreateFence))},
@@ -125,6 +131,7 @@
{"vkCreateQueryPool", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCreateQueryPool>(CreateQueryPool))},
{"vkCreateRenderPass", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCreateRenderPass>(CreateRenderPass))},
{"vkCreateSampler", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCreateSampler>(CreateSampler))},
+ {"vkCreateSamplerYcbcrConversion", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCreateSamplerYcbcrConversion>(CreateSamplerYcbcrConversion))},
{"vkCreateSemaphore", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCreateSemaphore>(CreateSemaphore))},
{"vkCreateShaderModule", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCreateShaderModule>(CreateShaderModule))},
{"vkDebugReportMessageEXT", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkDebugReportMessageEXT>(DebugReportMessageEXT))},
@@ -134,6 +141,7 @@
{"vkDestroyDebugReportCallbackEXT", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkDestroyDebugReportCallbackEXT>(DestroyDebugReportCallbackEXT))},
{"vkDestroyDescriptorPool", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkDestroyDescriptorPool>(DestroyDescriptorPool))},
{"vkDestroyDescriptorSetLayout", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkDestroyDescriptorSetLayout>(DestroyDescriptorSetLayout))},
+ {"vkDestroyDescriptorUpdateTemplate", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkDestroyDescriptorUpdateTemplate>(DestroyDescriptorUpdateTemplate))},
{"vkDestroyDevice", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkDestroyDevice>(DestroyDevice))},
{"vkDestroyEvent", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkDestroyEvent>(DestroyEvent))},
{"vkDestroyFence", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkDestroyFence>(DestroyFence))},
@@ -147,6 +155,7 @@
{"vkDestroyQueryPool", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkDestroyQueryPool>(DestroyQueryPool))},
{"vkDestroyRenderPass", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkDestroyRenderPass>(DestroyRenderPass))},
{"vkDestroySampler", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkDestroySampler>(DestroySampler))},
+ {"vkDestroySamplerYcbcrConversion", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkDestroySamplerYcbcrConversion>(DestroySamplerYcbcrConversion))},
{"vkDestroySemaphore", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkDestroySemaphore>(DestroySemaphore))},
{"vkDestroyShaderModule", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkDestroyShaderModule>(DestroyShaderModule))},
{"vkDeviceWaitIdle", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkDeviceWaitIdle>(DeviceWaitIdle))},
@@ -155,34 +164,52 @@
{"vkEnumerateDeviceLayerProperties", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkEnumerateDeviceLayerProperties>(EnumerateDeviceLayerProperties))},
{"vkEnumerateInstanceExtensionProperties", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkEnumerateInstanceExtensionProperties>(EnumerateInstanceExtensionProperties))},
{"vkEnumerateInstanceLayerProperties", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkEnumerateInstanceLayerProperties>(EnumerateInstanceLayerProperties))},
+ {"vkEnumerateInstanceVersion", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkEnumerateInstanceVersion>(EnumerateInstanceVersion))},
+ {"vkEnumeratePhysicalDeviceGroups", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkEnumeratePhysicalDeviceGroups>(EnumeratePhysicalDeviceGroups))},
{"vkEnumeratePhysicalDevices", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkEnumeratePhysicalDevices>(EnumeratePhysicalDevices))},
{"vkFlushMappedMemoryRanges", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkFlushMappedMemoryRanges>(FlushMappedMemoryRanges))},
{"vkFreeCommandBuffers", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkFreeCommandBuffers>(FreeCommandBuffers))},
{"vkFreeDescriptorSets", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkFreeDescriptorSets>(FreeDescriptorSets))},
{"vkFreeMemory", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkFreeMemory>(FreeMemory))},
{"vkGetBufferMemoryRequirements", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkGetBufferMemoryRequirements>(GetBufferMemoryRequirements))},
+ {"vkGetBufferMemoryRequirements2", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkGetBufferMemoryRequirements2>(GetBufferMemoryRequirements2))},
+ {"vkGetDescriptorSetLayoutSupport", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkGetDescriptorSetLayoutSupport>(GetDescriptorSetLayoutSupport))},
+ {"vkGetDeviceGroupPeerMemoryFeatures", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkGetDeviceGroupPeerMemoryFeatures>(GetDeviceGroupPeerMemoryFeatures))},
{"vkGetDeviceMemoryCommitment", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkGetDeviceMemoryCommitment>(GetDeviceMemoryCommitment))},
{"vkGetDeviceProcAddr", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkGetDeviceProcAddr>(GetDeviceProcAddr))},
{"vkGetDeviceQueue", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkGetDeviceQueue>(GetDeviceQueue))},
+ {"vkGetDeviceQueue2", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkGetDeviceQueue2>(GetDeviceQueue2))},
{"vkGetEventStatus", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkGetEventStatus>(GetEventStatus))},
{"vkGetFenceStatus", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkGetFenceStatus>(GetFenceStatus))},
{"vkGetImageMemoryRequirements", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkGetImageMemoryRequirements>(GetImageMemoryRequirements))},
+ {"vkGetImageMemoryRequirements2", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkGetImageMemoryRequirements2>(GetImageMemoryRequirements2))},
{"vkGetImageSparseMemoryRequirements", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkGetImageSparseMemoryRequirements>(GetImageSparseMemoryRequirements))},
+ {"vkGetImageSparseMemoryRequirements2", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkGetImageSparseMemoryRequirements2>(GetImageSparseMemoryRequirements2))},
{"vkGetImageSubresourceLayout", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkGetImageSubresourceLayout>(GetImageSubresourceLayout))},
{"vkGetInstanceProcAddr", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkGetInstanceProcAddr>(GetInstanceProcAddr))},
+ {"vkGetPhysicalDeviceExternalBufferProperties", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkGetPhysicalDeviceExternalBufferProperties>(GetPhysicalDeviceExternalBufferProperties))},
+ {"vkGetPhysicalDeviceExternalFenceProperties", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkGetPhysicalDeviceExternalFenceProperties>(GetPhysicalDeviceExternalFenceProperties))},
+ {"vkGetPhysicalDeviceExternalSemaphoreProperties", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkGetPhysicalDeviceExternalSemaphoreProperties>(GetPhysicalDeviceExternalSemaphoreProperties))},
{"vkGetPhysicalDeviceFeatures", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkGetPhysicalDeviceFeatures>(GetPhysicalDeviceFeatures))},
+ {"vkGetPhysicalDeviceFeatures2", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkGetPhysicalDeviceFeatures2>(GetPhysicalDeviceFeatures2))},
{"vkGetPhysicalDeviceFeatures2KHR", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkGetPhysicalDeviceFeatures2KHR>(GetPhysicalDeviceFeatures2KHR))},
{"vkGetPhysicalDeviceFormatProperties", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkGetPhysicalDeviceFormatProperties>(GetPhysicalDeviceFormatProperties))},
+ {"vkGetPhysicalDeviceFormatProperties2", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkGetPhysicalDeviceFormatProperties2>(GetPhysicalDeviceFormatProperties2))},
{"vkGetPhysicalDeviceFormatProperties2KHR", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkGetPhysicalDeviceFormatProperties2KHR>(GetPhysicalDeviceFormatProperties2KHR))},
{"vkGetPhysicalDeviceImageFormatProperties", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkGetPhysicalDeviceImageFormatProperties>(GetPhysicalDeviceImageFormatProperties))},
+ {"vkGetPhysicalDeviceImageFormatProperties2", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkGetPhysicalDeviceImageFormatProperties2>(GetPhysicalDeviceImageFormatProperties2))},
{"vkGetPhysicalDeviceImageFormatProperties2KHR", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkGetPhysicalDeviceImageFormatProperties2KHR>(GetPhysicalDeviceImageFormatProperties2KHR))},
{"vkGetPhysicalDeviceMemoryProperties", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkGetPhysicalDeviceMemoryProperties>(GetPhysicalDeviceMemoryProperties))},
+ {"vkGetPhysicalDeviceMemoryProperties2", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkGetPhysicalDeviceMemoryProperties2>(GetPhysicalDeviceMemoryProperties2))},
{"vkGetPhysicalDeviceMemoryProperties2KHR", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkGetPhysicalDeviceMemoryProperties2KHR>(GetPhysicalDeviceMemoryProperties2KHR))},
{"vkGetPhysicalDeviceProperties", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkGetPhysicalDeviceProperties>(GetPhysicalDeviceProperties))},
+ {"vkGetPhysicalDeviceProperties2", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkGetPhysicalDeviceProperties2>(GetPhysicalDeviceProperties2))},
{"vkGetPhysicalDeviceProperties2KHR", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkGetPhysicalDeviceProperties2KHR>(GetPhysicalDeviceProperties2KHR))},
{"vkGetPhysicalDeviceQueueFamilyProperties", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkGetPhysicalDeviceQueueFamilyProperties>(GetPhysicalDeviceQueueFamilyProperties))},
+ {"vkGetPhysicalDeviceQueueFamilyProperties2", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkGetPhysicalDeviceQueueFamilyProperties2>(GetPhysicalDeviceQueueFamilyProperties2))},
{"vkGetPhysicalDeviceQueueFamilyProperties2KHR", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkGetPhysicalDeviceQueueFamilyProperties2KHR>(GetPhysicalDeviceQueueFamilyProperties2KHR))},
{"vkGetPhysicalDeviceSparseImageFormatProperties", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkGetPhysicalDeviceSparseImageFormatProperties>(GetPhysicalDeviceSparseImageFormatProperties))},
+ {"vkGetPhysicalDeviceSparseImageFormatProperties2", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkGetPhysicalDeviceSparseImageFormatProperties2>(GetPhysicalDeviceSparseImageFormatProperties2))},
{"vkGetPhysicalDeviceSparseImageFormatProperties2KHR", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkGetPhysicalDeviceSparseImageFormatProperties2KHR>(GetPhysicalDeviceSparseImageFormatProperties2KHR))},
{"vkGetPipelineCacheData", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkGetPipelineCacheData>(GetPipelineCacheData))},
{"vkGetQueryPoolResults", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkGetQueryPoolResults>(GetQueryPoolResults))},
@@ -202,7 +229,9 @@
{"vkResetEvent", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkResetEvent>(ResetEvent))},
{"vkResetFences", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkResetFences>(ResetFences))},
{"vkSetEvent", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkSetEvent>(SetEvent))},
+ {"vkTrimCommandPool", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkTrimCommandPool>(TrimCommandPool))},
{"vkUnmapMemory", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkUnmapMemory>(UnmapMemory))},
+ {"vkUpdateDescriptorSetWithTemplate", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkUpdateDescriptorSetWithTemplate>(UpdateDescriptorSetWithTemplate))},
{"vkUpdateDescriptorSets", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkUpdateDescriptorSets>(UpdateDescriptorSets))},
{"vkWaitForFences", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkWaitForFences>(WaitForFences))},
// clang-format on
diff --git a/vulkan/nulldrv/null_driver_gen.h b/vulkan/nulldrv/null_driver_gen.h
index 8a9a963..c6ad537 100644
--- a/vulkan/nulldrv/null_driver_gen.h
+++ b/vulkan/nulldrv/null_driver_gen.h
@@ -165,6 +165,34 @@
VKAPI_ATTR void CmdNextSubpass(VkCommandBuffer commandBuffer, VkSubpassContents contents);
VKAPI_ATTR void CmdEndRenderPass(VkCommandBuffer commandBuffer);
VKAPI_ATTR void CmdExecuteCommands(VkCommandBuffer commandBuffer, uint32_t commandBufferCount, const VkCommandBuffer* pCommandBuffers);
+VKAPI_ATTR VkResult EnumerateInstanceVersion(uint32_t* pApiVersion);
+VKAPI_ATTR VkResult BindBufferMemory2(VkDevice device, uint32_t bindInfoCount, const VkBindBufferMemoryInfo* pBindInfos);
+VKAPI_ATTR VkResult BindImageMemory2(VkDevice device, uint32_t bindInfoCount, const VkBindImageMemoryInfo* pBindInfos);
+VKAPI_ATTR void GetDeviceGroupPeerMemoryFeatures(VkDevice device, uint32_t heapIndex, uint32_t localDeviceIndex, uint32_t remoteDeviceIndex, VkPeerMemoryFeatureFlags* pPeerMemoryFeatures);
+VKAPI_ATTR void CmdSetDeviceMask(VkCommandBuffer commandBuffer, uint32_t deviceMask);
+VKAPI_ATTR void CmdDispatchBase(VkCommandBuffer commandBuffer, uint32_t baseGroupX, uint32_t baseGroupY, uint32_t baseGroupZ, uint32_t groupCountX, uint32_t groupCountY, uint32_t groupCountZ);
+VKAPI_ATTR VkResult EnumeratePhysicalDeviceGroups(VkInstance instance, uint32_t* pPhysicalDeviceGroupCount, VkPhysicalDeviceGroupProperties* pPhysicalDeviceGroupProperties);
+VKAPI_ATTR void GetImageMemoryRequirements2(VkDevice device, const VkImageMemoryRequirementsInfo2* pInfo, VkMemoryRequirements2* pMemoryRequirements);
+VKAPI_ATTR void GetBufferMemoryRequirements2(VkDevice device, const VkBufferMemoryRequirementsInfo2* pInfo, VkMemoryRequirements2* pMemoryRequirements);
+VKAPI_ATTR void GetImageSparseMemoryRequirements2(VkDevice device, const VkImageSparseMemoryRequirementsInfo2* pInfo, uint32_t* pSparseMemoryRequirementCount, VkSparseImageMemoryRequirements2* pSparseMemoryRequirements);
+VKAPI_ATTR void GetPhysicalDeviceFeatures2(VkPhysicalDevice physicalDevice, VkPhysicalDeviceFeatures2* pFeatures);
+VKAPI_ATTR void GetPhysicalDeviceProperties2(VkPhysicalDevice physicalDevice, VkPhysicalDeviceProperties2* pProperties);
+VKAPI_ATTR void GetPhysicalDeviceFormatProperties2(VkPhysicalDevice physicalDevice, VkFormat format, VkFormatProperties2* pFormatProperties);
+VKAPI_ATTR VkResult GetPhysicalDeviceImageFormatProperties2(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceImageFormatInfo2* pImageFormatInfo, VkImageFormatProperties2* pImageFormatProperties);
+VKAPI_ATTR void GetPhysicalDeviceQueueFamilyProperties2(VkPhysicalDevice physicalDevice, uint32_t* pQueueFamilyPropertyCount, VkQueueFamilyProperties2* pQueueFamilyProperties);
+VKAPI_ATTR void GetPhysicalDeviceMemoryProperties2(VkPhysicalDevice physicalDevice, VkPhysicalDeviceMemoryProperties2* pMemoryProperties);
+VKAPI_ATTR void GetPhysicalDeviceSparseImageFormatProperties2(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceSparseImageFormatInfo2* pFormatInfo, uint32_t* pPropertyCount, VkSparseImageFormatProperties2* pProperties);
+VKAPI_ATTR void TrimCommandPool(VkDevice device, VkCommandPool commandPool, VkCommandPoolTrimFlags flags);
+VKAPI_ATTR void GetDeviceQueue2(VkDevice device, const VkDeviceQueueInfo2* pQueueInfo, VkQueue* pQueue);
+VKAPI_ATTR VkResult CreateSamplerYcbcrConversion(VkDevice device, const VkSamplerYcbcrConversionCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSamplerYcbcrConversion* pYcbcrConversion);
+VKAPI_ATTR void DestroySamplerYcbcrConversion(VkDevice device, VkSamplerYcbcrConversion ycbcrConversion, const VkAllocationCallbacks* pAllocator);
+VKAPI_ATTR VkResult CreateDescriptorUpdateTemplate(VkDevice device, const VkDescriptorUpdateTemplateCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDescriptorUpdateTemplate* pDescriptorUpdateTemplate);
+VKAPI_ATTR void DestroyDescriptorUpdateTemplate(VkDevice device, VkDescriptorUpdateTemplate descriptorUpdateTemplate, const VkAllocationCallbacks* pAllocator);
+VKAPI_ATTR void UpdateDescriptorSetWithTemplate(VkDevice device, VkDescriptorSet descriptorSet, VkDescriptorUpdateTemplate descriptorUpdateTemplate, const void* pData);
+VKAPI_ATTR void GetPhysicalDeviceExternalBufferProperties(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceExternalBufferInfo* pExternalBufferInfo, VkExternalBufferProperties* pExternalBufferProperties);
+VKAPI_ATTR void GetPhysicalDeviceExternalFenceProperties(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceExternalFenceInfo* pExternalFenceInfo, VkExternalFenceProperties* pExternalFenceProperties);
+VKAPI_ATTR void GetPhysicalDeviceExternalSemaphoreProperties(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceExternalSemaphoreInfo* pExternalSemaphoreInfo, VkExternalSemaphoreProperties* pExternalSemaphoreProperties);
+VKAPI_ATTR void GetDescriptorSetLayoutSupport(VkDevice device, const VkDescriptorSetLayoutCreateInfo* pCreateInfo, VkDescriptorSetLayoutSupport* pSupport);
VKAPI_ATTR VkResult GetSwapchainGrallocUsageANDROID(VkDevice device, VkFormat format, VkImageUsageFlags imageUsage, int32_t* grallocUsage);
VKAPI_ATTR VkResult GetSwapchainGrallocUsage2ANDROID(VkDevice device, VkFormat format, VkImageUsageFlags imageUsage, VkSwapchainImageUsageFlagsANDROID swapchainImageUsage, uint64_t* grallocConsumerUsage, uint64_t* grallocProducerUsage);
VKAPI_ATTR VkResult AcquireImageANDROID(VkDevice device, VkImage image, int nativeFenceFd, VkSemaphore semaphore, VkFence fence);